Plenz Geschrieben May 21, 2012 at 21:50 Geschrieben May 21, 2012 at 21:50 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? Zitieren
photron Geschrieben May 22, 2012 at 08:56 Geschrieben May 22, 2012 at 08:56 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. Zitieren
Plenz Geschrieben May 22, 2012 at 09:10 Autor Geschrieben May 22, 2012 at 09:10 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? Zitieren
AuronX Geschrieben May 22, 2012 at 16:30 Geschrieben May 22, 2012 at 16:30 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 Zitieren
Plenz Geschrieben May 22, 2012 at 21:23 Autor Geschrieben May 22, 2012 at 21:23 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? Zitieren
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.