Elegantere Variante gesucht

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Neodog
User
Beiträge: 3
Registriert: Mittwoch 11. Januar 2017, 00:28

Elegantere Variante gesucht

Beitragvon Neodog » Mittwoch 11. Januar 2017, 00:36

Hallo liebes Forum!

Ich bin blutiger Anfänger in Sachen programmieren. (Dafür ist der kleine Raspi ja gedacht) Nachdem ich viele tolle Anleitungen gefunden habe habe ich ein script erstellt welches auch funktioniert. Ich habe jedoch für einen Punkt keine Lösung gefunden.
Als Einführung: Ein Türkontakt (GPIO.input) schaltet ein Relais zum einschalten einer Beleuchtung (GPIO.output) und versendet einen Nachricht via Pushbullet. Die Nachricht soll natürlich nicht in einen permanenten Schleife kommen sonder nur alle x Minuten.

Wenn das Licht eingeschaltet ist dann bleibt es so lange an wie time.sleep definiert ist. Schöner wäre wenn es natürlich sofort bei geschlossenem Kontakt wieder aus geht.


Wie kann ich das eleganter lösen?

  1. #!/usr/bin/python
  2.  import time
  3.  import RPi.GPIO as GPIO
  4.  GPIO.setwarnings(False)
  5.  GPIO.setmode(GPIO.BCM)
  6.  GPIO.setup(27,GPIO.IN)
  7.  GPIO.setup(18,GPIO.OUT)
  8.  
  9.  
  10.  while True:
  11.  
  12.         if not GPIO.input(27):
  13.                 GPIO.output(18, 1) #Licht einschalten
  14.                 import subprocess
  15.                 print "Nachricht versenden, Licht eingeschaltet"
  16.                 subprocess.call ("pushbullet.sh") #Nachricht versenden
  17.                 print "Nachricht wurde versendet"
  18.                 time.sleep(10)
  19.  
  20.         else:
  21.                 GPIO.output(18, 0) #Licht ausschalten
  22.  
Zuletzt geändert von Anonymous am Mittwoch 11. Januar 2017, 10:11, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
sebastian0202
User
Beiträge: 140
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Re: Elegantere Variante gesucht

Beitragvon sebastian0202 » Mittwoch 11. Januar 2017, 08:25

Du könntest in die While-Schleife noch ein time.sleep(1) setzen.
Damit würde die Schleife nur jede Sekunde durchlaufen.

Für das andere Problem kannst du dir eine Variable erstellen (zustand_alt=False).
Dann reagiert er nur, wenn es wirklich eine Zustandänderung gibt.
Vielleicht so:

  1. #PSEUDOCODE
  2. zustand_neu = GPIO.input(27)
  3. zustand_alt = False
  4. while True:
  5.     if zustand_neu != zustand_alt:
  6.         if zustand_neu:
  7.             licht ein
  8.         else:
  9.             licht aus
  10.         zustand_alt = zustand_neu    
  11.     zustand_neu = GPIO.input(27)
  12.     time.sleep(1)
  13.    
Sirius3
User
Beiträge: 6377
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Elegantere Variante gesucht

Beitragvon Sirius3 » Mittwoch 11. Januar 2017, 09:12

@sebastian0202: man will wohl nicht eine Sekunde lang warten, bis das Lich angeht. Schon nach 200ms fragt man sich, ähm, ist das Licht vielleicht kaputt? zustand_neu zwei mal im Code zu setzen ist unnötig, wenn man das am Anfang der Schleife macht.

@Neodog: Warnings sind dazu da, Dich zu warnen. Sollte also eine Warnung stören, solltest Du den Grund und nicht die Meldung abschalten. Es wird immer mit 4 Leerzeichen pro Ebene eingerückt. subprocess.call erwartet eine Liste und keinen String als Argument. Importe sollten immer ganz am Anfang der Datei stehen, damit man auf einen Blick die Abhängigkeiten sieht.

  1. #!/usr/bin/python
  2. import time
  3. import subprocess
  4. import RPi.GPIO as GPIO
  5.  
  6. def switch(state):
  7.     # Licht ein- oder ausschalten
  8.     GPIO.output(18, state)
  9.     if state:
  10.         # Nachricht versenden
  11.         subprocess.call(["pushbullet.sh"])
  12.  
  13. def process():
  14.     old_state = False
  15.     while True:
  16.         new_state = not GPIO.input(27)
  17.         if new_state != old_state :
  18.             switch(new_state)
  19.             old_state = new_state
  20.         time.sleep(0.1)
  21.  
  22. def main():
  23.     try:  
  24.         GPIO.setmode(GPIO.BCM)
  25.         GPIO.setup(27, GPIO.IN)
  26.         GPIO.setup(18, GPIO.OUT)
  27.         process()
  28.     except KeyboardInterrupt:  
  29.         pass
  30.     finally:  
  31.         GPIO.cleanup()
  32.                
  33. if __name__ == '__main__':
  34.     main()
BlackJack

Re: Elegantere Variante gesucht

Beitragvon BlackJack » Mittwoch 11. Januar 2017, 12:03

@Neodog: Ich würde dann noch die ”magischen” Pin-Nummern im Programm durch Konstanten ersetzen, so dass man den Wert nur einmal im Programm stehen hat, und überall wo er benutzt wird, am Namen ablesen kann, was der Pin bedeutet.

Mit `wait_for_edge()` sollte man das „busy waiting“ beseitigen können.

Ungetestet:
  1. #!/usr/bin/env python
  2. import subprocess
  3. import time
  4. from RPi import GPIO
  5.  
  6. LIGHT_PIN = 18
  7. SWITCH_PIN = 27
  8.  
  9.  
  10. def switch(state):
  11.     GPIO.output(LIGHT_PIN, state)
  12.     if state:
  13.         # Nachricht versenden.
  14.         subprocess.call(['pushbullet.sh'])
  15.  
  16.  
  17. def process():
  18.     while True:
  19.         GPIO.wait_for_edge(SWITCH_PIN, GPIO.BOTH)
  20.         switch(not GPIO.input(SWITCH_PIN))
  21.  
  22.  
  23. def main():
  24.     try:  
  25.         GPIO.setmode(GPIO.BCM)
  26.         GPIO.setup(SWITCH_PIN, GPIO.IN)
  27.         GPIO.setup(LIGHT_PIN, GPIO.OUT)
  28.         process()
  29.     except KeyboardInterrupt:  
  30.         pass
  31.     finally:  
  32.         GPIO.cleanup()
  33.              
  34.  
  35. if __name__ == '__main__':
  36.     main()
Neodog
User
Beiträge: 3
Registriert: Mittwoch 11. Januar 2017, 00:28

Re: Elegantere Variante gesucht

Beitragvon Neodog » Mittwoch 11. Januar 2017, 17:27

Vielen Dank für die Antworten!
Und auch danke das keiner "schon mal gegoogelt" oder "benutz die Forensuche" geantwortet hat!

Heute morgen kurz vor ende der Nachtschicht bin ich noch über die steigenden/fallenden Flanken gestolpert. Das habe ich mir jetzt mal genauer angesehen. Was haltet ihr davon wenn man damit die Türkontakte überwacht?
Neodog
User
Beiträge: 3
Registriert: Mittwoch 11. Januar 2017, 00:28

Re: Elegantere Variante gesucht

Beitragvon Neodog » Donnerstag 12. Januar 2017, 02:19

BlackJack hat geschrieben:

Mit `wait_for_edge()` sollte man das „busy waiting“ beseitigen können.

Das hätte ich vor meinem letzten Beitrag besser gegoogelt.
Scheint genau das zu sein was ich brauche.

Ich werde mir eure Tipps und Vorschläge zu Herzen nehmen und das mal anpassen und zur "Kontrolle" hier nochmal posten.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder