blattlauslr
Goto Top

Letzte While-Schleife wird nicht abgearbeitet

Hallo zusammen.

Ich habe hier ein Quellcode der mir etwas graue Haare beschert.

Die erste While-Schleife funktioniert anstandslos, jedoch die zweite wird nicht abgearbeitet, weshalb auch immer:
import RPi.GPIO as GPIO
import time

P_BUTTON_ALARM = 12
P_BUTTON_PI = 13
P_LED_ALARM_AUS = 19
P_LED_ALARM_AN = 20
P_LED_PI_AN = 21
ZEIT=3

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(P_BUTTON_ALARM, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_BUTTON_PI, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_LED_ALARM_AN, GPIO.OUT)
    GPIO.setup(P_LED_ALARM_AUS, GPIO.OUT)
    GPIO.setup(P_LED_PI_AN, GPIO.OUT)

setup()
isLedOn = False
isButtonReady = True

while True:
    if isButtonReady and GPIO.input(P_BUTTON_ALARM) == GPIO.LOW:
        isButtonReady = False
        if not isLedOn:
            isLedOn = True
            time.sleep(5.00)
            import os
            os.system("sudo service motion start")  
            time.sleep(1.00)
            GPIO.output(P_LED_ALARM_AN, GPIO.HIGH)
            GPIO.output(P_LED_ALARM_AUS, GPIO.LOW)            
        else:
            isLedOn = False
            import os
            os.system("sudo service motion stop")  
            time.sleep(1.00)
            GPIO.output(P_LED_ALARM_AN, GPIO.LOW)
            GPIO.output(P_LED_ALARM_AUS, GPIO.HIGH)
    if GPIO.input(P_BUTTON_ALARM) == GPIO.HIGH:
        isButtonReady = True
    time.sleep(0.01)

while True:
    GPIO.output(P_LED_PI_AN, GPIO.HIGH)
    time.sleep(0.2)
    if GPIO.input(P_BUTTON_PI) == False:
        print "TASTER UNBETAETIGT"  
        pressed_time=time.time()
        while GPIO.input(P_BUTTON_PI) == False:
            time.sleep(0.2)

        pressed_time=time.time()-pressed_time
        print "TASTER BETAETIGT %d" % pressed_time  
        if pressed_time<ZEIT:
            print "REBOOT"  
            import os
            os.system("sudo reboot")  
        else:
            print "SHUTDOWN"  
            import os
            os.system("sudo shutdown -h now")  

GPIO.cleanup()

Teste ich nur die zweite While-Schleife:
import RPi.GPIO as GPIO
import time

P_BUTTON_PI = 13
P_LED_PI_AN = 21
ZEIT=3

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(P_BUTTON_PI, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_LED_PI_AN, GPIO.OUT)

setup()
isLedOn = False
isButtonReady = True

while True:
    GPIO.output(P_LED_PI_AN, GPIO.HIGH)
    time.sleep(0.2)
    if GPIO.input(P_BUTTON_PI) == False:
        print "TASTER UNBETAETIGT"  
        pressed_time=time.time()
        while GPIO.input(P_BUTTON_PI) == False:
            time.sleep(0.2)

        pressed_time=time.time()-pressed_time
        print "TASTER BETAETIGT %d" % pressed_time  
        if pressed_time<ZEIT:
            print "REBOOT"  
            import os
            os.system("sudo reboot")  
        else:
            print "SHUTDOWN"  
            import os
            os.system("sudo shutdown -h now")  

GPIO.cleanup()

...fährt mir der Raspberry Pi sofort herunter, obwohl die Taster-Zeit-Abfrage funktioniert!
Und weshalb funktionieren nicht beide Schleifen nacheinander in einem Skript?

Kann jemand den eingeschlichenen Fehler entdecken bzw. mich auf den richtigen Lösungsansatz führen?

Vielen Dank.

Content-Key: 393889

Url: https://administrator.de/contentid/393889

Printed on: April 19, 2024 at 09:04 o'clock

Mitglied: 137846
137846 Nov 25, 2018 updated at 15:57:30 (UTC)
Goto Top
Moin.
Und weshalb funktionieren nicht beide Schleifen nacheinander in einem Skript?
Weil die erste Schleife ja nie verlassen wird, kann der Code nie deine zweite Schleife erreichen, deshalb! Code wird immer noch zeilenweise abgearbeitet, d.h. wenn der Code in die erste Schleife einsteigt und sich in dieser keine Abbruchbedingung befindet wird Python diese Schleife natürlich endlos fortführen und deine zweite Schleife wird so also niemals erreicht, klar? Also entweder aus der Schleife eine Funktion machen und diese aus der ersten heraus aufrufen oder den Code der zweite Schleife mit in die erste integrieren.

Gruß A.
Member: maretz
maretz Nov 25, 2018 at 17:06:33 (UTC)
Goto Top
was du möchtest wären threads (oder wie auch immer das identische in py heissen mag). Dann läuft das auch parallel (mehr oder minder, aber zumindest parallel genug für deine Anwendung).
Member: Lochkartenstanzer
Lochkartenstanzer Nov 26, 2018 updated at 05:37:00 (UTC)
Goto Top
Moin,

Wenn die erste Schleife keine Abbruchbedingung hat, kommt das Programm auch nie un die zweite Schleife.

Du mußt die Schleifen etweder zusammenlegen oder Threading benutzen.

lks
Member: SlainteMhath
SlainteMhath Nov 26, 2018 at 07:43:40 (UTC)
Goto Top
Moin,

die GPIO-Lib sollte doch Callbacks unterstützen. D.h. eine Funktion die aufgerufen wird, wenn der Taster betätigt wird, egal wo sich dein Code gerade befindet.

Jop... 5 Sek auf Google... https://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry ...

lg,
Slainte
Member: Penny.Cilin
Penny.Cilin Nov 26, 2018 at 08:00:12 (UTC)
Goto Top
Hallo,

alternative kann er die beiden While Schleifen kombinieren, bzw. seine Logik überarbeiten.
Ich weiß nicht, ob es in Python ein
select...case
gibt. Damit könnte man es lösen.

Gruss Penny.
Member: BlattlausLR
BlattlausLR Nov 26, 2018 at 08:46:26 (UTC)
Goto Top
Guten Morgen.

Zuerst ein herzliches Dankeschön für die Anteilnahme meiner Fragestellung. face-smile

Da ich mir den Quellcode aus dem Internet zusammenkopiert habe und auch relativ wenig Kenntnis über Python verfüge, werde ich dem Ansatz von "Lochkartenstanzer" folgen und testen.

Ich habe mir den Quellcode nach bestem Wissen angepasst und werde ihn heute Abend zu Hause mal testen und überraschen was letzten Endes beim ausführen passiert. face-wink

Werde mich heute Abend nochmals zu Wort melden.

import RPi.GPIO as GPIO
import threading
import time

P_BUTTON_ALARM = 12
P_BUTTON_PI = 13
P_LED_ALARM_AUS = 19
P_LED_ALARM_AN = 20
P_LED_PI_AN = 21
ZEIT=3

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(P_BUTTON_ALARM, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_BUTTON_PI, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_LED_ALARM_AN, GPIO.OUT)
    GPIO.setup(P_LED_ALARM_AUS, GPIO.OUT)
    GPIO.setup(P_LED_PI_AN, GPIO.OUT)

setup()
isLedOn = False
isButtonReady = True

def ALARM():
	while True:
		if isButtonReady and GPIO.input(P_BUTTON_ALARM) == GPIO.LOW:
			isButtonReady = False
			if not isLedOn:
				isLedOn = True
				time.sleep(5.00)
				import os
				os.system("sudo service motion start")  
				time.sleep(1.00)
				GPIO.output(P_LED_ALARM_AN, GPIO.HIGH)
				GPIO.output(P_LED_ALARM_AUS, GPIO.LOW)            
			else:
				isLedOn = False
				import os
				os.system("sudo service motion stop")  
				time.sleep(1.00)
				GPIO.output(P_LED_ALARM_AN, GPIO.LOW)
				GPIO.output(P_LED_ALARM_AUS, GPIO.HIGH)
		if GPIO.input(P_BUTTON_ALARM) == GPIO.HIGH:
			isButtonReady = True
		time.sleep(0.01)

def PI():
	while True:
		GPIO.output(P_LED_PI_AN, GPIO.HIGH)
		time.sleep(0.2)
		if GPIO.input(P_BUTTON_PI) == False:
			print ("TASTER UNBETAETIGT")  
			pressed_time=time.time()
			while GPIO.input(P_BUTTON_PI) == False:
				time.sleep(0.2)

			pressed_time=time.time()-pressed_time
			print ("TASTER BETAETIGT %d" % pressed_time)  
			if pressed_time<ZEIT:
				print ("REBOOT")  
				import os
				os.system("sudo reboot")  
			else:
				print ("SHUTDOWN")  
				import os
				os.system("sudo shutdown -h now")  

threading.Thread(target=ALARM).start()
threading.Thread(target=PI).start()
			
GPIO.cleanup()
Member: BlattlausLR
BlattlausLR Nov 26, 2018 at 17:51:16 (UTC)
Goto Top
Hallo zusammen,

ich habe nun den oben genannten Quellcode etwas abgeändert und auf Funktion getestet...
import RPi.GPIO as GPIO
import threading
import time

P_BUTTON_ALARM = 12
P_BUTTON_PI = 13
P_LED_ALARM_AUS = 19
P_LED_ALARM_AN = 20
P_LED_PI_AN = 21
ZEIT=3

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(P_BUTTON_ALARM, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_BUTTON_PI, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_LED_ALARM_AN, GPIO.OUT)
    GPIO.setup(P_LED_ALARM_AUS, GPIO.OUT)
    GPIO.setup(P_LED_PI_AN, GPIO.OUT)

setup()
isLedOn = False
isButtonReady = True

def ALARM():
	global isLedOn
	global isButtonReady
		if isButtonReady and GPIO.input(P_BUTTON_ALARM) == GPIO.LOW:
			isButtonReady = False
			if not isLedOn:
				isLedOn = True
				time.sleep(5.00)
				import os
				os.system("sudo service motion start")  
				time.sleep(1.00)
				GPIO.output(P_LED_ALARM_AN, GPIO.HIGH)
				GPIO.output(P_LED_ALARM_AUS, GPIO.LOW)            
			else:
				isLedOn = False
				import os
				os.system("sudo service motion stop")  
				time.sleep(1.00)
				GPIO.output(P_LED_ALARM_AN, GPIO.LOW)
				GPIO.output(P_LED_ALARM_AUS, GPIO.HIGH)
		if GPIO.input(P_BUTTON_ALARM) == GPIO.HIGH:
			isButtonReady = True
		time.sleep(0.01)

def PI():
	while True:
		GPIO.output(P_LED_PI_AN, GPIO.HIGH)
		time.sleep(0.2)
		if GPIO.input(P_BUTTON_PI) == False:
			print ("TASTER UNBETAETIGT")  
			pressed_time=time.time()
			while GPIO.input(P_BUTTON_PI) == False:
				time.sleep(0.2)

			pressed_time=time.time()-pressed_time
			print ("TASTER BETAETIGT %d" % pressed_time)  
			if pressed_time<ZEIT:
				print ("REBOOT")  
				import os
				os.system("sudo reboot")  
			else:
				print ("SHUTDOWN")  
				import os
				os.system("sudo shutdown -h now")  

threading.Thread(target=ALARM).start()
threading.Thread(target=PI).start()
			
GPIO.cleanup()


...es wird mir folgendes ausgegeben:
sudo python /home/pi/Desktop/Pi-Share/Sicherungen/Skripte/TasterLED1.py
  File "/home/pi/Desktop/Pi-Share/Sicherungen/Skripte/TasterLED1.py", line 28  
    if isButtonReady and GPIO.input(P_BUTTON_ALARM) == GPIO.LOW:
    ^
IndentationError: unexpected indent

Wäre jemand so freundlich und würde mir mitteilen was dies genau zu bedeuten hat?
Ich hatte gelesen, dass "unexpected indent" etwas mit der Syntax bzw. der Einrückung Pythons zu tun hat, aber wo um Himmels Willen soll der Fehler liegen, ich kann nichts entdecken...

Vielen Dank für Ratschläge. face-smile
Member: SlainteMhath
SlainteMhath Nov 27, 2018 at 07:33:51 (UTC)
Goto Top
Wäre jemand so freundlich und würde mir mitteilen was dies genau zu bedeuten hat?
An der Stelle ist deine Einrückung falsch - das if muss auf gleicher "Höhe" sein wie das "global" in der Zeile zuvir
Member: BlattlausLR
BlattlausLR Nov 27, 2018 updated at 08:20:49 (UTC)
Goto Top
Guten Morgen SlainteMhath,

danke für deinen Hinweis, habe es auch gleich mal abgeändert und getestet, allerdings wird die Ausgabe nun unübersichtlicher für mich:
import RPi.GPIO as GPIO
import threading
import time

P_BUTTON_ALARM = 12
P_BUTTON_PI = 13
P_LED_ALARM_AUS = 19
P_LED_ALARM_AN = 20
P_LED_PI_AN = 21
ZEIT=3

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    GPIO.setup(P_BUTTON_ALARM, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_BUTTON_PI, GPIO.IN, GPIO.PUD_UP)
    GPIO.setup(P_LED_ALARM_AN, GPIO.OUT)
    GPIO.setup(P_LED_ALARM_AUS, GPIO.OUT)
    GPIO.setup(P_LED_PI_AN, GPIO.OUT)

setup()
isLedOn = False
isButtonReady = True

def ALARM():
	global isLedOn
	global isButtonReady
	if isButtonReady and GPIO.input(P_BUTTON_ALARM) == GPIO.LOW:
		isButtonReady = False
		if not isLedOn:
			isLedOn = True
			time.sleep(5.00)
			import os
			os.system("sudo service motion start")  
			time.sleep(1.00)
			GPIO.output(P_LED_ALARM_AN, GPIO.HIGH)
			GPIO.output(P_LED_ALARM_AUS, GPIO.LOW)            
		else:
			isLedOn = False
			import os
			os.system("sudo service motion stop")  
			time.sleep(1.00)
			GPIO.output(P_LED_ALARM_AN, GPIO.LOW)
			GPIO.output(P_LED_ALARM_AUS, GPIO.HIGH)
	if GPIO.input(P_BUTTON_ALARM) == GPIO.HIGH:
		isButtonReady = True
	time.sleep(0.01)

def PI():
	while True:
		GPIO.output(P_LED_PI_AN, GPIO.HIGH)
		time.sleep(0.2)
		if GPIO.input(P_BUTTON_PI) == False:
			print ("TASTER UNBETAETIGT")  
			pressed_time=time.time()
			while GPIO.input(P_BUTTON_PI) == False:
				time.sleep(0.2)

			pressed_time=time.time()-pressed_time
			print ("TASTER BETAETIGT %d" % pressed_time)  
			if pressed_time<ZEIT:
				print ("REBOOT")  
				import os
				os.system("sudo reboot")  
			else:
				print ("SHUTDOWN")  
				import os
				os.system("sudo shutdown -h now")  

threading.Thread(target=ALARM).start()
threading.Thread(target=PI).start()

GPIO.cleanup()

Ausgabe:
sudo python /home/pi/Desktop/Pi-Share/Sicherungen/Skripte/TasterLED.py
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner  
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run  
    self.__target(*self.__args, **self.__kwargs)
  File "/home/pi/Desktop/Pi-Share/Sicherungen/Skripte/TasterLED.py", line 53, in PI  
    if GPIO.input(P_BUTTON_PI) == False:
RuntimeError: Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM)

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner  
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run  
    self.__target(*self.__args, **self.__kwargs)
  File "/home/pi/Desktop/Pi-Share/Sicherungen/Skripte/TasterLED.py", line 36, in ALARM  
    GPIO.output(P_LED_ALARM_AN, GPIO.HIGH)
RuntimeError: Please set pin numbering mode using GPIO.setmode(GPIO.BOARD) or GPIO.setmode(GPIO.BCM)

Was hat dies zu bedeuten?

GPIO.setmode(GPIO.BCM) ist doch in Zeile 13 bereits enthalten...
Member: SlainteMhath
SlainteMhath Nov 27, 2018 at 09:32:39 (UTC)
Goto Top
Naja, wirst du wohl pro thread machen müssen... Wie gesagt, ich würde das mit Callbacks/Interrupts machen, nicht mir Threads - siehe mein Link weiter oben.
Member: maretz
maretz Nov 27, 2018 at 11:32:52 (UTC)
Goto Top
Was auch generell besser wäre - ehrlich gesagt hatte ich oben nich mal geguckt was in den Schleifen selbst gemacht wird sondern nur 2x "While (true)" gesehen, damit is dann klar warum die zweite nich erreicht wird... Dies kann man eben nur per Thread parallel laufen lassen...

Wenn ich aber im Code noch Taster o.ä. habe die idR. nen Event/Interrupt/whatever auslösen ist es natürlich generell besser dieses auch zu beachten. Denn natürlich kann man sagen "frage alle 5 ms nach wie der Status des Buttons ist" - kostet aber rechenzeit und je nach Einstellung würde man auch Events verpassen (derjenige war extrem schnell und hat nur für 2ms gedrückt...).
Member: Lochkartenstanzer
Lochkartenstanzer Nov 27, 2018 at 11:36:46 (UTC)
Goto Top
Zitat von @maretz:

Was auch generell besser wäre - ehrlich gesagt hatte ich oben nich mal geguckt was in den Schleifen selbst gemacht wird sondern nur 2x "While (true)" gesehen, damit is dann klar warum die zweite nich erreicht wird... Dies kann man eben nur per Thread parallel laufen lassen...

Ging mir genauso, deswegen hatte ich Threads vorgeschlagen. ob Threads oder eine "große" Schleife in diesem Fall das richtige sind, steht auf einem anderen Blatt. Interrupts mit passenden Service-Routinen sind zwar prinzipiell für eine Tastenabfrage geschickter, aber nicht jeder Programmierer kommt damit zurecht. face-smile

lks
Member: BlattlausLR
BlattlausLR Nov 27, 2018 at 21:54:04 (UTC)
Goto Top
Guten Abend.

Da ich mich wie bereits erwähnt in Python nicht wirklich auskenne und mir das zu kompliziert erscheint, habe ich mich dazu entschieden zwei einzelne Dateien anstatt einer anzulegen und über /etc/rc.local beim Systemstart zu starten.

Die erste Datei funktioniert soweit, in der über ein Taster zwei Serviceanwendungen ausgeführt werden.

Allerdings habe ich noch ein Problem bei der zweiten Datei, wo über ein Taster ein reboot bzw. shutdown ausgeführt werden soll. ( Taster kürzer als 3 Sekunden betätigt = reboot / Taster länger als 3 Sekunden betätigt shutdown)

Mit meinem derzeitigen Quellcode wird stets shutdown ausgeführt und das unabhängig wie lange die Taste betätigt wird, im Prinzip sofort!?
Kann mich jemand zum Fehler führen?

Vielen Dank. face-smile

import RPi.GPIO as GPIO
import time

P_BUTTON_PI = 13
P_LED_PI_AN = 21
ZEIT=3

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(P_BUTTON_PI, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(P_LED_PI_AN, GPIO.OUT)

while True:
	GPIO.output(P_LED_PI_AN, GPIO.HIGH)
	time.sleep(0.2)
	if GPIO.input(P_BUTTON_PI) == False:
		pressed_time=time.time()
		while GPIO.input(P_BUTTON_PI) == False:
			time.sleep(0.2)

		pressed_time=time.time()-pressed_time
		if pressed_time<ZEIT:
			time.sleep(3.0)
			import os
			os.system("sudo reboot")  
		else:
			time.sleep(3.0)
			import os
			os.system("sudo shutdown -h now")  

GPIO.cleanup()
Member: SlainteMhath
SlainteMhath Nov 28, 2018 at 08:13:12 (UTC)
Goto Top
Google anwerfen - und Interrupts verwenden .)

z.B. https://raspberrypi.stackexchange.com/questions/63512/how-can-i-detect-h ...