Seite 1 von 1
Probleme mit Interrupts
Verfasst: Montag 15. Februar 2021, 16:24
von basti2s
Hallo zusammen,
ich komm gerade nicht klar. Vielleicht könnt ihr mir helfen.
Ich verwende einen RaspberryPi. An den GPIOs ist ein Wahlschalter angeschlossen. Also im Endeffekt ein Drehschalter.
Ich möchte je nach Stellung des Schalters eine bestimmte Funktion ausführen. Der Schalter hat drei Stellungen.
In jeder Funktion befindet sich jedoch eine while Schleife, weshalb ich das ganze über Interrupts realisieren würde.
Das ganze sieht in etwa so aus:
Code: Alles auswählen
import RPi.GPIO as GPIO
GPIO.setmode (GPIO.BOARD)
GPIO.setup (12, GPIO.IN) #Wahlschalter
GPIO.setup (18, GPIO.IN) #Wahlschalter
GPIO.setup (16, GPIO.IN) #Wahlschalter
GPIO.add_event_detect (12, GPIO.RISING, bouncetime = 70) #Einstellen Interrupt
GPIO.add_event_detect (16, GPIO.RISING, bouncetime = 70)
GPIO.add_event_detect (18, GPIO.RISING, bouncetime = 70)
def mode1():
while (1):
print("1")
def mode2():
while (1):
print("8")
def mode3():
while (1):
print("3")
def callback_GPIO(n):
if GPIO.input(12):
mode1()
if GPIO.input(16):
print("wamp")
mode2()
if GPIO.input(18):
mode3()
GPIO.add_event_callback(12, callback_GPIO) #Wenn Interrupt erkannt wurde wird funktion "myCallback" aufgerufen
GPIO.add_event_callback(16, callback_GPIO)
GPIO.add_event_callback(18, callback_GPIO)
mode1()
In der Konsole kommen dann nur komische Werte raus, wenn ich den Schalter drehe. Hier mal ein Ausschnitt:
Code: Alles auswählen
1
1
1
1
1
1
1
1
1
31
31
31
31
3
13
1
13
13
13
1
13
13
31
13
13
13
1
1
3
13
13
31
31
3
1
1
1
3
13
13
13
13
13
1
3
31
1
1
1
1
13
13
1
13
13
3
3
3
3
3
3
3
3
3
3
3
3
3
1
31
1
31
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
31
3
3
3
3
3
3
Was genau mach ich falsch? Wo liegt mein Denkfehler?
Re: Probleme mit Interrupts
Verfasst: Montag 15. Februar 2021, 16:37
von __deets__
Zu denken die callbacks würden immer in einem eigenen Thread gestartet. Es gibt nur EINEN Thread, der für alle IRQs da ist. Und den main Thread. Und was passiert ist ganz einfach: der main Thread printed 1. Und der eine IRQ thread wird von dir in eine Endlosschleife geschickt, die eine 3 printed. Und die kommen jetzt wild durcheinander auf der Konsole an.
Im IRQ darf man nur ganz kurz was machen. Denn sonst hält der nachfolgende auf.
Re: Probleme mit Interrupts
Verfasst: Montag 15. Februar 2021, 17:28
von Sirius3
(1) ist das selbe wie 1 und sollte eigentlich True sein. Was willst du mit den Endlosschleifen bezwecken?
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 00:57
von __blackjack__
@basti2s: Ergänzend: Ich würde `RPi.GPIO` nicht mehr ohne Not verwenden. Es gibt mit dem `gpiozero`-Modul eine bessere, modernere API.
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 07:51
von basti2s
Sirius3 hat geschrieben: Montag 15. Februar 2021, 17:28
(1) ist das selbe wie 1 und sollte eigentlich True sein. Was willst du mit den Endlosschleifen bezwecken?
Ich möchte mit dem Wahlschalter unterschiedliche Modi ausführen. Und in jedem Modi werden halt andere unterprogramme ausgeführt. Die sollen halt dann endlos durchlaufen, bis duch den wahlschalter ein anderer Modus ausgewählt wird.
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 07:55
von __deets__
Das wird so nichts. Denn ohne periodisch zu prüfen, ob der Modus noch stimmt, kannst du etwas, das endlos läuft, per Definition nicht beenden.
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 09:55
von basti2s
Okay. Wäre es denn eine Möglichkeit mit mehreren Threads zu arbeiten?
Also in meinem Main Thread führe ich quasi die Modi1-3 die ganze Zeit aus (unabhängig von der Schalterstellung) und schreibe die Ausgaben in Queues.
Wenn der Schalter verändert wird erfolgt ein Interrupt. In der Callback Funktion wird in eine separate Queue geschrieben, dass der Modus x jetzt aktiv ist.
Der zweite Thread pullt diese Liste und gibt dann die Werte des aktiven Modus aus.
Wäre das eine gute Lösung?
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 10:32
von __deets__
Das klingt falsch. Wenn du alles drei laufen lässt, aber die Ergebnisse von zweien verwerfen willst - wieso lässt du die laufen? Warum kannst du nicht abhängig von dem gewünschten Zustand einfach EIN Ergebnis berechnen, das ausgeben, prüfen, ob der Zustand sich geändert hat, und entsprechend reagieren, und von vorne beginnen?
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 10:40
von basti2s
Genau das hat mich daran auch gestört. Ich habe jetzt folgendes gemacht:
Code: Alles auswählen
import RPi.GPIO as GPIO
GPIO.setmode (GPIO.BOARD)
GPIO.setup (12, GPIO.IN) #Wahlschalter
GPIO.setup (18, GPIO.IN) #Wahlschalter
GPIO.setup (16, GPIO.IN) #Wahlschalter
GPIO.add_event_detect (12, GPIO.RISING, bouncetime = 70) #Einstellen Interrupt
GPIO.add_event_detect (16, GPIO.RISING, bouncetime = 70)
GPIO.add_event_detect (18, GPIO.RISING, bouncetime = 70)
def mode1():
print("1")
def mode2():
print("8")
def mode3():
print("3")
def wahlschalter_callback():
if GPIO.input(12):
mode1()
if GPIO.input(16):
print("wamp")
mode2()
if GPIO.input(18):
mode3()
while (1):
wahlschalter_callback()
GPIO.add_event_callback(12, wahlschalter_callback) #Wenn Interrupt erkannt wurde wird funktion "myCallback" aufgerufen
GPIO.add_event_callback(16, wahlschalter_callback)
GPIO.add_event_callback(18, wahlschalter_callback)
Müsste so doch ertragbar sein?
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 10:54
von __deets__
Nicht. Im. Callback. Dinge. Machen. NUR signalisieren. Wie schon Millionen mal geschrieben, und mehrfach in diesem Thema.
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 13:24
von Sirius3
Die Callbacks werden jetzt ja gar nicht mehr gebraucht und auch nie gesetzt, da die Endlosschleife nie endet.
Re: Probleme mit Interrupts
Verfasst: Dienstag 16. Februar 2021, 13:35
von __blackjack__
Also mal ordentlich ohne Zeug auf Modulebene und mit aufräumen der GPIOs am Programmende, und auf das wesentliche gekürzt der Stand:
Code: Alles auswählen
#!/usr/bin/env python3
from RPi import GPIO # TODO `gpiozero` verwenden.
PIN_TO_TEXT = {12: "1", 16: "wamp\n8", 18: "3"}
def main():
try:
GPIO.setmode(GPIO.BOARD)
GPIO.setup(list(PIN_TO_TEXT), GPIO.IN)
while True:
for pin, text in PIN_TO_TEXT.items():
if GPIO.input(pin):
print(text)
finally:
GPIO.cleanup()
if __name__ == "__main__":
main()
Re: Probleme mit Interrupts
Verfasst: Mittwoch 17. Februar 2021, 08:59
von basti2s
Sirius3 hat geschrieben: Dienstag 16. Februar 2021, 13:24
Die Callbacks werden jetzt ja gar nicht mehr gebraucht und auch nie gesetzt, da die Endlosschleife nie endet.
Ist es nicht der Sinn eines Interrupts, dass er mich aus einer Endlosschleife holt?
Re: Probleme mit Interrupts
Verfasst: Mittwoch 17. Februar 2021, 09:15
von Sirius3
Nein, ein Interrupt unterbricht nur kurz eine Endlosschleife, die danach aber ungerührt weiterläuft, wenn man nicht explizit in der Schleife was macht.
Meine Satz bezieht sich aber auf Dein damals aktuelles Programm, das keine Callbacks mehr benutzt.
Re: Probleme mit Interrupts
Verfasst: Dienstag 23. Februar 2021, 14:12
von basti2s
und wie verhält sich das ganzte mit time.sleep? Ich habe das Gefühl, dass er nach dem Interrupt wieder zurück in das time.sleep springt und dort weiter schläft.
Gibt es denn die Möglichkeit zu definieren, dass nach einem Interrupt nicht wieder in das time.sleep gesprungen wird?
Re: Probleme mit Interrupts
Verfasst: Dienstag 23. Februar 2021, 15:00
von __deets__
Dazu benutzt man eine Queue. Die schläft, entweder für immer, oder mit timeout, bis aus einem IRQ darin ein Element abgelegt wurde. Oder eben der timeout zuschlägt, was früher dran ist.