Jump to content

Recommended Posts

Geschrieben

Ich mache nun meine ersten Gehversuche mit Python. Es geht um einen Getriebemotor, dessen Achse sich maximal um +/- 120 Grad verdrehen darf. Die eigentliche Steuerung kommt später, aber für den Fall, dass sie versagt, habe ich schon mal einen Schalter eingebaut, der in beiden Endstellungen betätigt wird. Er hängt an Pin0 eines IO4-Bricklets und dieses an einen DC-Brick, der den Motor steuert.

 

Zum Testen habe ich ein Programm geschrieben, das beim Betätigen des Schalters die Drehrichtung umkehrt:

 

HOST = "localhost"
PORT = 4223
UID_DCo = "9oXWJFxoHoS"  # DC Brick oben
UID_IO4 = "7Qo"          # IO-4 Bricklet

from tinkerforge.ip_connection import IPConnection
from tinkerforge.brick_dc import DC
from tinkerforge.bricklet_io4 import IO4

dco = None
io4 = None
velo = 0

# Callback function for interrupts
def cb_interrupt(interrupt_mask, value_mask):
    vm = value_mask & 1
    if vm < 1:
        velo = dco.get_velocity()
        dco.full_brake()
        dco.set_velocity(velo * -1)

if __name__ == "__main__":
    ipcon = IPConnection(HOST, PORT)        # Create IP connection to brick
    io4 = IO4(UID_IO4)                      # Create device object
    ipcon.add_device(io4)                   # Add device to IP connection
    io4.set_debounce_period(500)
    io4.set_configuration(3, 'i', True)     # Eingang Pin 0 und 1 mit Pull-Up
    io4.set_interrupt(3)                    # Eingang Pin 0 und 1 = Interrupt
    io4.register_callback(io4.CALLBACK_INTERRUPT, cb_interrupt)

    dco = DC(UID_DCo)                       # Create dc brick device object
    ipcon.add_device(dco)                   # Add device to IP connection
    dco.enable()

    dco.set_acceleration(0xFFFF)            # acceleration (FFFF = full)
    velo = 10000                            # Velocity: -32767/32767
    dco.set_velocity(velo)

    raw_input('Press Enter to exit\n') # Use input() in Python 3
    dco.disable()
    ipcon.destroy()

 

Das funktioniert auch so weit ganz gut, der Motor dreht sich brav zwischen den Anschlägen hin und her.

 

Wenn ich jetzt aber die Geschwindigkeit erhöhe, tun sich merkwürdige Dinge auf dem Bildschirm:

 

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Programme\Python\lib\threading.py", line 551, in __bootstrap_inner
    self.run()
  File "C:\Programme\Python\lib\threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 212, in callback_loop
    device.callbacks[function_id](*self.data_to_return(data[4:], form))
  File "C:\Programme\Python\CamStab.py", line 22, in cb_interrupt
    io4.set_configuration(8, 'o', True)     # Ausgang Pin 3
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 76, in func
    return f(self, *args, **kwargs)
  File "build/bdist.linux-x86_64/egg/tinkerforge/bricklet_io4.py", line 87, in set_configuration
    self.ipcon.write(self, IO4.FUNCTION_SET_CONFIGURATION, (pin_mask, direction, value), 'B c ?', '')
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 279, in write
    self.destroy()
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 222, in destroy
    self.join_thread()
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 245, in join_thread
    self.thread_callback.join()
  File "C:\Programme\Python\lib\threading.py", line 654, in join
    raise RuntimeError("cannot join current thread")
RuntimeError: cannot join current thread

 

Was soll ich nun damit anfangen?  :o

Geschrieben

Du hast da einen Bug in den Python Bindings gefunden (cannot join current thread). Der ist jetzt in Version 1.0.11 behoben.

 

Das ist aber nicht dein eigentliches Problem, sondern nur ein Nebeneffekt. Teste doch noch mal bitte mit den aktuellen Python Bindings.

 

Was mir noch in deinem Code auffällt: Du registrierst den Callback für den Interrupt bevor du das DC Brick Objekt erzeugst. Du greifst aber im Callback auf die dco Variable zu. Es kann also passieren dass ein Callback kommt bevor die dco Variable richtig gesetzt wurde. Mit anderen Worten: Änder doch mal bitte die Reihenfolge von

 

    io4.register_callback(io4.CALLBACK_INTERRUPT, cb_interrupt)

    dco = DC(UID_DCo)                       # Create dc brick device object
    ipcon.add_device(dco)                   # Add device to IP connection

 

zu

 

    dco = DC(UID_DCo)                       # Create dc brick device object
    ipcon.add_device(dco)                   # Add device to IP connection

    io4.register_callback(io4.CALLBACK_INTERRUPT, cb_interrupt)

 

einfach um da auf der sicheren Seite zu sein.

 

Oder prüfe im Callback ob dco != None ist bevor du es verwendest.

Geschrieben

Danke, ich werde heute abend die Bindings noch mal runterladen.

 

Wegen des Callbacks mache ich mir keine Sorgen. Das wird doch nur ausgelöst, wenn der Schalter betätigt wird, und das geschieht erst dann, wenn der Motor sich dreht, und der dreht sich erst, wenn die Hauptroutine so weit durchgelaufen ist. Oder irre ich mich?

 

Für mich als Python-Anfänger ist das alles ziemlich verwirrend. Ich versuche immer, diese neuen Begriffe in etwas Bekanntes zu übersetzen: Bindings = Treiber, Callback = Interrupt-Subroutine - kommt das in etwa hin?

Geschrieben
Wegen des Callbacks mache ich mir keine Sorgen. Das wird doch nur ausgelöst, wenn der Schalter betätigt wird, und das geschieht erst dann, wenn der Motor sich dreht, und der dreht sich erst, wenn die Hauptroutine so weit durchgelaufen ist. Oder irre ich mich?

 

Im normalfall hast du recht, aber was wäre wenn ^^

 

Beispiel:

Während des Einschaltens kommt jemand gegen den Schalter (oder der Motor ist während des Einschaltens am Schalter), jetzt kommt der Callback noch WÄHREND du alles initialisierst und durch die nicht initialisierte variable stürzt der callback-thread ab. Jetzt läuft die initialisierung weiter, startet den Motor, aber weil der Callback-Thread tot ist wird nciht auf den Schalter reagiert und alles fängt an zu brennen! (dramatisiert)

 

Kurz: Wenn sich ein Fehler schon Software-seitig ausschließen lässt sollte man ihn schon dort ausschließen.

 

Dein Code entwickelt sich ja auch weiter, manches wird verschoben und kopiert und schon bald hast du vergessen, dass das dort ausnahmsweise in der Reihenfolge ging weil ...

 

LG

Jan

Geschrieben

Nun, wie auch immer - es gibt ein neues (?) Problem. Und zwar möchte ich mir regelmäßig die Stromstärke anzeigen lassen. Ich habe die Zeile

cs = dco.get_current_consumption()

in die Interrupt-Routine eingefügt, soweit funktioniert das Programm noch, aber wenn ich dann noch

print cs

hinzufüge, wird die Subroutine nicht mehr beendet. Ich drücke dann die Enter-Taste, um das Programm abzubrechen, und es erscheint:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Programme\Python\lib\threading.py", line 551, in __bootstrap_inner
    self.run()
  File "C:\Programme\Python\lib\threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 212, in callback_loop
    device.callbacks[function_id](*self.data_to_return(data[4:], form))
  File "C:\Programme\Python\CamStab.py", line 29, in cb_interrupt
    velo = dco.get_velocity()
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 76, in func
    return f(self, *args, **kwargs)
  File "build/bdist.linux-x86_64/egg/tinkerforge/brick_dc.py", line 84, in get_velocity
    return self.ipcon.write(self, DC.FUNCTION_GET_VELOCITY, (), '', 'h')
  File "build/bdist.linux-x86_64/egg/tinkerforge/ip_connection.py", line 291, in write
    raise Error(Error.TIMEOUT, msg)
Error: -1: Did not receive answer for message()in time

Noch ein Bug in den Bindings?

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...