Interruptroutine in Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
wiesam
User
Beiträge: 5
Registriert: Dienstag 2. Oktober 2018, 06:58

Guten Tag!
Ich entschuldige mich schon jetzt für diese grundlegende Frage, allerdings habe ich schon viel gesucht und nichts zu diesem Thema gefunden.

Ich möchte eine Funktion in meinem Python-Programm durch eine Eingabe - genauer gesagt durch das Drücken eines Tasters - unterbrechen, eine "Interrupt-Routine" abarbeiten und anschließend die vorhergehende Funktion fortsetzen. Da ich von der C-Programmierung komme, denke ich dabei sofort an Interrupts. Vergleichbares habe ich bereits erwähnt in der Pythonprogrammierung noch nicht gefunden.

Vielleicht kann mir da jemand helfen. Danke schon im voraus :)

Grüße
wiesam
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wo geht denn sowas in C? Kenne ich nur von Microcontrollern. Unter normalen OSsen geht sowas jedenfalls nicht. Auch nicht in C.

Das Modul signal könnte für dich interessant sein. Ansonsten erläutere mal etwas genauer deine Problemstellung.
wiesam
User
Beiträge: 5
Registriert: Dienstag 2. Oktober 2018, 06:58

Stimmt. Hab mich wohl zu ungenau ausgedrückt, ich kenne das auch nur von der µC-Programmierung in C. Da es sich hier um einen Roboter handelt, die vermutlich auch mit einem µC angesteuert wird, dachte ich, dass es da etwas ähnliches geben sollte.

Um ganz konkret zu werden, stell ich mal den betroffenen Code-Abschnitt herein.

Code: Alles auswählen

	
def glue(xout, yout, zout, xin, yin, zin, r,c):	
	
	(...)
	
	for x in range(2):
		for y in range(9):
			#jump fast to other gluing points
			dType.SetPTPCommonParams(api, v_fast, a_fast, 1)
			dType.SetPTPCmd(api, 0, xout+(x*x2)+xoff, yout+(y*cell)+yoff, zout+1, r, 1)
			dType.SetPTPCommonParams(api, 20, a_fast, 1)
			dType.SetPTPCmd(api, 0, xout+(x*x2)+xoff, yout+(y*cell)+yoff, zout, r, 1)

			#gluing
			#glue while first glue-rectangle
			#stop gluing while second glue-rectangle
			dType.SetIODO(api, 2, 0, 1)
			dType.SetPTPCommonParams(api, v_glu, a_glu, 1)
			dType.SetPTPCmd(api, 2 , xout+(x*x2)+xoff, yout-xy_arc+(y*cell)+yoff, zout+z_arc, r, 1)
			dType.SetPTPCmd(api, 2 , xout-xy_arc+(x*x2)+xoff, yout+(y*cell)+yoff, zout+(2*z_arc), r, 1)
			dType.SetPTPCmd(api, 2 , xout+(x*x2)+xoff, yout+xy_arc+(y*cell)+yoff, zout+(3*z_arc), r, 1)
			dType.SetPTPCmd(api, 2 , xout+xy_arc+(x*x2)+xoff, yout+(y*cell)+yoff, zout+(4*z_arc), r, 1)
			dType.SetIODO(api, 2, 1, 1)
			dType.SetPTPCmd(api, 2 , xout+(x*x2)+xoff, yout-xy_arc+(y*cell)+yoff, zout+zup, r, 1)
			dType.SetPTPCmd(api, 2 , xout-xy_arc+(x*x2)+xoff, yout+(y*cell)+yoff, zout+zup, r, 1)
			dType.SetPTPCmd(api, 2 , xout+(x*x2)+xoff, yout+xy_arc+(y*cell)+yoff, zout+zup, r, 1)
			dType.SetPTPCmd(api, 2 , xout+xy_arc+(x*x2)+xoff, yout+(y*cell)+yoff, zout+zup, r, 1)
			dType.SetPTPCmd(api, 2 , xout+(x*x2)+xoff, yout-xy_arc+(y*cell)+yoff, zout+zup, r, 1)
			
			
			if(dType.GetIODI(api,  17)[0]==0):
				serv_exit=1
				
				(...)
				
	return serv_exit
Es handelt sich um obenstehendes Unterprogramm. Die Klammer mit den Punkten (...) ersetzt Teile des Codes, die meiner Meinung für die Frage nicht von Bedeutung sind (Variablendefinition, etc.). Die dType-Befehle sind Roboterbefehle (auch nicht so wichtig).

Um auf den Punkt zu kommen: ich will anders als bisher gelöst, die Abarbeitung der for-Schleife im Bereich der if-Anweisung mittels Taster unterbrechen, in ein Unterprogramm (Interrupt-Routine) springen und anschließend soll die for-Schleife im bisherigen Verlauf weiterlaufen. Dabei sollte der Tasterstatus schon während der dType-Befehle abgefragt und in eine Variable geschrieben werden und nicht wie bisher erst in der if-Anweisung.

Ich hoffe das war klar und verständlich ausgedrückt. ;)
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Unterbrechen und wieder weiter laufen lassen geht nicht. Weder in Python, noch in irgendeiner anderen Sprache. Jedenfalls nicht so ohne weiteres. Wie schon erwaehnt, da kann ggf. das Modul "signal" helfen, denn das ist der einzige mir bekannte Mechanismus, mit dem unter Posixen und mit Einschraenkungen auch unter Windows so etwas programmiert werden kann. Allerdings loest das nicht das Problem, wie man dieses Signal abhaengig von dType.GetIODI ausloest.

Da du nicht ausfuehrst, was dType *genau* ist, kann man leider auch nicht verlaesslich eine alternative Herangehensweise empfehlen. Das einzige, was nach bisherigem Kenntnisstand gehen wuerde ist, jede Anweisung im Wechsel mit einer Abfrage aufzurufen. Dazu die if-Anweisung und alles was sie macht in eine Funktion packen, und dann nach dem Schema

Code: Alles auswählen

dType.SetPTPCommonParams(api, v_fast, a_fast, 1)
serv_exit = taster_abfrage(dType, api) 
dType.SetPTPCmd(api, 0, xout+(x*x2)+xoff, yout+(y*cell)+yoff, zout+1, r, 1)
serv_exit = taster_abfrage(dType, api)
...
arbeiten.

Wenn dType hingegen die Abfrage durch einen nebenlaeufigen Thread erlaubt, *dann* kann man etwas parallel ausfuehren lassen. Oder noch besser eine Ereignis-Behandlung bereit stellt. Aber wie schon gesagt, das kann man ohne genauere Kenntnis von dType nicht weiter ausfuehren.
wiesam
User
Beiträge: 5
Registriert: Dienstag 2. Oktober 2018, 06:58

Alles klar, dann wird das Modul "signal" nicht weiterhelfen, wenn ich es nicht abhängig von dType.GetIODI auslösen kann.

Alle Roboterbefehle in der dazugehörigen Entwicklungsumgebung beginnen mit dType. Wie genau diese Befehle arbeiten, weiß ich nicht und der Hersteller beschreibt diese auch nicht näher. Er beschreibt lediglich, dass z.B. dType.GetIODI(api, 17)[0] den IO-Status vom 17. digitalen Eingang auslest.

An die Variante von deinem Code dachte ich auch schon, allerdings wird serv_exit jedes mal überschrieben. Somit berücksichtigt die if-Abfrage nur die letzte Tasterabfrage.

Leider nein. Daran verzweifle ich eben, da der Roboter den Programmcode zyklisch, wie eine SPS abarbeitet und keine parllelen Befehle erlaubt.
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn es darum geht serv_status high zu halten, wenn es das einmal war, dann geht natuerlich auch

Code: Alles auswählen

serv_status = False
while True:
     serv_status |= abfrage()
Dann reicht ein einziges mal den Status auf True zu setzen, und serv_status bleibt so.
wiesam
User
Beiträge: 5
Registriert: Dienstag 2. Oktober 2018, 06:58

Funktioniert das ganze auch, wenn die Abfrage kein True bzw. False ausgibt, sondern stattdessen 0 und 1 also einen Zahlenwert vom Datentyp uint8_t? Wenn ja, wie halte ich serv_status auf 1 bzw. auf 0?
Und was genau macht der Operator |= ?
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ja und

x |= y <=> x = x | y

Und warum das geht kannst du dir mit Stift und Papier mal klar machen fuer verschiedene Werte y.
wiesam
User
Beiträge: 5
Registriert: Dienstag 2. Oktober 2018, 06:58

Klingt alles logisch und funktioniert.
Jetzt sollte der Roboter nur noch eine höhere Rechenleistung haben, damit er auch den IO-Port richtig und in Echtzeit erkennt...
__deets__
User
Beiträge: 14539
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das sollte eigentlich (roboterseitig) eigentlich kein Problem darstellen. Gibt es dafuer keine Dokumentation, in der man sowas mal nachschauen kann?
Antworten