Relais mit Taster schalten

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Freitag 11. Juni 2021, 08:30

Moin,
zum Verständnis schreibe ich euch erstmal was ich überhaupt machen möchte...
Ich habe 2 Pumpen an meinem Pool. Die eine ist die Pumpe am Sandfilter, die andere eine Pumpe pumpt das Wasser durch Solarkollektoren.
Jetzt möchte ich mit (jeweils) einem Taster beim ersten tasten die Pumpe einschalten und beim zweiten tasten die Pumpe wieder ausschalten.

Da ich jetzt eher der Laie und keine Profi bin habe ich natürlch das Internet bemüht um zu schauen wie das Programm aussehen könnte. Dabei bin ich auf "event_detected() function" mit "callback" gestoßen.
Dieses hat auch mit dem ersten Taster mit nur einer Pumpe super funktioniert. Dann habe ich alles für die zweite Pumpe fertig gemacht. Und dann kam das Problem...
Ein Taster funktioniert weiterhin so wie er soll, während der andere undifiniert auf einmal beide Pumpen (Relais) an und aus schaltet.

Ich hoffe bis dahin ist verständlich was mein Problem ist und das mir jemand weiterhelfen kann.

Hier mein Programm:

Code: Alles auswählen

import RPi.GPIO as GPIO
import time
#
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#
taster_1 = 16
taster_2 = 20
pumpe_1 = 26
pumpe_2 = 19
#
GPIO.setup(taster_1, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(pumpe_1, GPIO.OUT)
GPIO.setup(taster_2, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(pumpe_2, GPIO.OUT)
#
pumpe_11 = False
pumpe_22 = False
#
def pumpe01(channel):  
    global pumpe_11
    pumpe_11 = not pumpe_11
    GPIO.output(26, GPIO.HIGH if pumpe_11 else GPIO.LOW)
    print (("Pumpe_1 An: "), pumpe_11)
#
def pumpe02(channel):
    global pumpe_22
    pumpe_22 = not pumpe_22
    GPIO.output(19, GPIO.HIGH if pumpe_22 else GPIO.LOW)
    print (("Pumpe_2 An: "), pumpe_22)
#
GPIO.add_event_detect(taster_1, GPIO.FALLING, callback=pumpe01, bouncetime=200)
GPIO.add_event_detect(taster_2, GPIO.FALLING, callback=pumpe02, bouncetime=200)
#
try:
    while True:
        pass 
#
except KeyboardInterrupt:
    print ("Ctrl-C - quit")
#
finally:
    GPIO.cleanup()
Sirius3
User
Beiträge: 14755
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 11. Juni 2021, 10:19

`as` bei `import` ist dazu da, einen Namen umzubenennen, GPIO wird aber gar nicht umbenannt.
Warnungen sind dazu da, dass man sie behebt, nicht dass man sie ignoriert.
Konstanten werden KOMPLETT_GROSS geschrieben. Und wenn man Konstanten hat, dann benutzt man die auch, statt magischer Zahlenwerte.
Benutze keine globalen Variablen.
Du hast für beide Pumpen quasi identischen Code.
Dass Du mit Deiner while-Schleife die Wohnung heizt, ist nicht so toll.

Code: Alles auswählen

from RPi import GPIO
import time
from queue import Queue

TASTER_TO_PUMPEN_PINS = [
    16: 26,
    20: 19,
]

def initalize():
    queue = Queue()
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(list(TASTER_TO_PUMPEN_PINS.keys()), GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(list(TASTER_TO_PUMPEN_PINS.values()), GPIO.OUT)
    for taster_pin in TASTER_TO_PUMPEN_PINS:
        GPIO.add_event_detect(taster_pin, GPIO.FALLING, callback=queue.put, bouncetime=200)
    return queue

def main():
    try:
        status = dict.fromkeys(TASTER_TO_PUMPEN_PINS, False)
        queue = initialize()
        while True:
            taster_pin = queue.get()
            pumpen_pin = TASTER_TO_PUMPEN_PINS[taster_pin]
            new_status = not status[taster_pin]
            status[taster_pin] = new_status
            GPIO.output(pumpen_pin, GPIO.HIGH if new_status else GPIO.LOW)
            print(f"Pumpe {taster_pin}: {'an' if new_status else 'aus'}")
    except KeyboardInterrupt:
        print("Ctrl-C - quit")
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    main()
Und dass da irgendwelche Taster übersprechen scheint ein Hardware-Problem zu sein.
__deets__
User
Beiträge: 10051
Registriert: Mittwoch 14. Oktober 2015, 14:29

Freitag 11. Juni 2021, 10:37

Wenn alles, was da (auch in Zukunft) passieren soll, dieses umschalten ist, dann solltest du den Pi für etwas anderes verwenden, und einfach einen Kippschalter oder Ähnliches verwenden. Ein so kompliziertes Stück Hard- und Software für ein so simples Unterfangen zu verwenden, ist im Zweifel nur Verschwendung, schlimmstenfalls ein Risiko, weil es abschmiert oder kaputt geht.
Benutzeravatar
hyle
User
Beiträge: 54
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Freitag 11. Juni 2021, 15:23

Falls der RPi doch mehr machen darf als schnödes schalten, dann würde ich gpiozero statt dem RPi.GPIO verwenden.

Code: Alles auswählen

#!/usr/bin/env python3

from gpiozero import OutputDevice, Button
from signal import pause

TASTER_1 = Button(16)
TASTER_2 = Button(20)
PUMPE_1 = OutputDevice(26)
PUMPE_2 = OutputDevice(19)

def main():
    try:
        TASTER_1.when_pressed = PUMPE_1.toggle
        TASTER_2.when_pressed = PUMPE_2.toggle

    except KeyboardInterrupt:
        print ("Ctrl-C - quit")

if __name__ == "__main__":
    main()
    pause()
Mein Code hier ist ungetestet und nicht nicht besonders schick, soll aber hoffentlich zum Verständnis beitragen.
Alles was wir sind ist Sand im Wind Hoschi.
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Samstag 12. Juni 2021, 12:36

Danke erstmal für diese schnelle ausführliche Hilfe.

Wie schon gesagt bin leider eher der Laie was programmiern angeht, nehme aber natürlich immer gerne Ratschläge an.
Ich habe natürlich deinen Code ausprobiert, jedoch bekomme ich jetzt die Fehlermeldung:
Traceback (most recent call last):
File "/home/pi/Desktop/taster_internet.py", line 5
TASTER_TO_PUMPEN_PINS = [16: 26, 20: 19]
^
SyntaxError: invalid syntax
Das "^" steht übrigens eigentlich unter dem Doppelpunkt nach der "16". Wird hier von der Formatierung wohl nicht richtig übernommen.

Habe natürlich auch schon selbst probiert diesen Fehler zu beheben, jedoch bis jetzt ohne Erfolg.


Was das Taster übersprechen angeht glaube ich nicht das es ein Hardwareproblem ist. Ich habe verschiedene Taster probiert, auch an verschiedenen Pins, jedoch immer das gleiche Verhalten gehabt.
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Samstag 12. Juni 2021, 12:39

__deets__ hat geschrieben:
Freitag 11. Juni 2021, 10:37
Wenn alles, was da (auch in Zukunft) passieren soll, dieses umschalten ist, dann solltest du den Pi für etwas anderes verwenden, und einfach einen Kippschalter oder Ähnliches verwenden. Ein so kompliziertes Stück Hard- und Software für ein so simples Unterfangen zu verwenden, ist im Zweifel nur Verschwendung, schlimmstenfalls ein Risiko, weil es abschmiert oder kaputt geht.
Das ist natürlich nicht alles was der "Pi" machen soll...
Es ist jetzt noch eine kleine Erweiterung.
Sirius3
User
Beiträge: 14755
Registriert: Sonntag 21. Oktober 2012, 17:20

Samstag 12. Juni 2021, 12:55

@Kaffebohne: ja das sollte ein Wörterbuch sein.

Code: Alles auswählen

TASTER_TO_PUMPEN_PINS = {
    16: 26,
    20: 19,
}
Benutzeravatar
hyle
User
Beiträge: 54
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Samstag 12. Juni 2021, 13:36

Kaffebohne hat geschrieben:
Samstag 12. Juni 2021, 12:36
Was das Taster übersprechen angeht glaube ich nicht das es ein Hardwareproblem ist. Ich habe verschiedene Taster probiert, auch an verschiedenen Pins, jedoch immer das gleiche Verhalten gehabt.
Wie hast Du die Taster denn angeschlossen?

Wenn Du den / die GPIO mit ...pull_up_down = GPIO.PUD_DOWN gegen GND ziehst und dann noch GPIO.add_event_detect(taster_1, GPIO.FALLING... die fallende Flanke dedektierst, dann gibt es nun mal einen undefinierten Zustand.

Setz den GPIO mal als Pullup pull_up_down = GPIO.PUD_UP. wenn Du schon nicht das einfachere und aktuellere gpiozero verwenden willst.
Alles was wir sind ist Sand im Wind Hoschi.
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Samstag 12. Juni 2021, 15:54

So ich habe jetzt noch mal einiges ausprobiert.
Ich habe den Code von "Sirius3" am laufen (Danke dafür). Das Ergebnis ist genau das gleiche wie bei dem was ich geschrieben habe. Wenn ich den Taster der an den "GPIO16" angeschlossen ist betätige, wird das Relais am "GPIO26" geschaltet. Also so wie es sein soll.
Betätige ich den zweiten Taster an "GPIO20" habe ich wieder das Ergebnis das beide Relais undifiniert geschaltet werden (GPIO26 und GPIO19). Mal schaltet nur ein Relais mal beide gleichzeitig oder auch im wechsel...

Ich habe die Schalter getascht, neu verkabelt, verschiedene GPIO`s versucht und das Ergebnis ist immer das Der Taster bzw. GPIO der im Code als erstes steht ordentlich schaltet, der zweite nicht. Diese habe ich im Code zum Test natürlich auch getauscht...

Und auch mit pull_up_down = GPIO.PUD_DOWN / pull_up_down = GPIO.PUD_UP habe ich es versucht. Aber auch da kein anders Ergebnis.

Mit gpiozero habe ich es auch probiert, jedoch das Programm noch nicht ans laufen bekommen...
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Samstag 12. Juni 2021, 18:08

So, hier noch mal ein update.
Nach langem hin und her probieren, hat es mit der Variante von "hyle" mit gpiozero funktioniert.

So sieht es jetzt aus
#!/usr/bin/env python3
import gpiozero
from gpiozero import LED, Button
from signal import pause

TASTER_1 = Button(2)
TASTER_2 = Button(3)
PUMPE_1 = LED(6)
PUMPE_2 = LED(13)


def main():
try:
TASTER_1.when_pressed = PUMPE_1.toggle
TASTER_2.when_pressed = PUMPE_2.toggle

except KeyboardInterrupt:
print ("Ctrl-C - quit")

if __name__ == "__main__":
main()
pause()
Das einzige was ich jetzt noch hab ist, dass beim beenden mit Ctrl-C folgender Fehler kommt:
Traceback (most recent call last):
File "/home/pi/Desktop/taster.py", line 22, in <module>
pause()
File "/usr/lib/python3/dist-packages/thonny/backend.py", line 380, in signal_handler
raise KeyboardInterrupt("Execution interrupted")
KeyboardInterrupt: Execution interrupted
Und ich verstehe nicht warum die Variante von "Sirius3" nicht funktioniert. :?

Danke für eure Hilfe :D
Benutzeravatar
hyle
User
Beiträge: 54
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Sonntag 13. Juni 2021, 10:00

Kaffebohne hat geschrieben:
Samstag 12. Juni 2021, 18:08
Das einzige was ich jetzt noch hab ist, dass beim beenden mit Ctrl-C folgender Fehler kommt:
Ups, mein Fehler! :roll: Verschiebe pause() in die main()-Funktion unter die Zeile TASTER_2.when_pressed = PUMPE_2.toggle auf die gleiche Einrückungsebene!


Das import gpiozero ist überflüssig, da Du es nicht verwendest.
LED statt OutputDevice kann man in dem Fall zwar auch nutzen, aber für ein Relaise ist "LED" nicht zwangsläufig zutreffend.
Alles was wir sind ist Sand im Wind Hoschi.
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Sonntag 13. Juni 2021, 11:30

hyle hat geschrieben:
Sonntag 13. Juni 2021, 10:00
Kaffebohne hat geschrieben:
Samstag 12. Juni 2021, 18:08
Das einzige was ich jetzt noch hab ist, dass beim beenden mit Ctrl-C folgender Fehler kommt:
Ups, mein Fehler! :roll: Verschiebe pause() in die main()-Funktion unter die Zeile TASTER_2.when_pressed = PUMPE_2.toggle auf die gleiche Einrückungsebene!


Das import gpiozero ist überflüssig, da Du es nicht verwendest.
LED statt OutputDevice kann man in dem Fall zwar auch nutzen, aber für ein Relaise ist "LED" nicht zwangsläufig zutreffend.

Okay, dass mit der Pause werde ich noch mal ändern, danke.

Und mit "OutputDevice" hat es leider nicht funktioniert. Habe dann mal in den "gpiozero docs" nachgelesen und ich vermute das ich noch "DigitalOutputDevice" importieren muss bzw. anstelle von "Import OutputDevice". Dann könnte es damit auch funktionieren.
Benutzeravatar
hyle
User
Beiträge: 54
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Sonntag 13. Juni 2021, 11:53

OutputDevice sollte funktionieren, da hast Du irgeneinen Fehler gemacht. DigitalOutputDevice importieren ist auch nicht nötig, denn das baut zwar alles aufeinander auf, aber die jeweiligen Erweiterungen haben mit dem von Dir gewünschten Ziel nichts zu tun.
OutputDevice
...
This class extends GPIODevice to add facilities common to GPIO output devices: an on() method to switch the device on, a corresponding off() method, and a toggle() method.
ist das was Du willst.
DigitalOutputDevice
...
This class extends OutputDevice with a blink() method which uses an optional background thread to handle toggling the device state without further interaction.
Du willst ja kein blinken und
LED
...
Extends DigitalOutputDevice and represents a light emitting diode (LED).
eine LED soll auch nicht leuchten. :P
Alles was wir sind ist Sand im Wind Hoschi.
Kaffebohne
User
Beiträge: 11
Registriert: Donnerstag 31. Januar 2019, 11:27

Sonntag 13. Juni 2021, 15:26

So, hab jetzt noch mal die beiden Sachen geändert und es läuft auch so wie es soll.

Besten Dank noch mal für die Hilfe hier :)

Falls noch mal jemand einen Taster schalten möchte, hier noch mal mein finaler Code:
#!/usr/bin/env python3
from gpiozero import OutputDevice, Button
from signal import pause

TASTER_FILTERPUMPE = Button(2)
TASTER_SOLARPUMPE = Button(3)
FILTERPUMPE = OutputDevice(6)
SOLARPUMPE = OutputDevice(13)

def main():
try:
TASTER_FILTERPUMPE.when_pressed = FILTERPUMPE.toggle
TASTER_SOLARPUMPE.when_pressed = SOLARPUMPE.toggle
print ("----> Programm gestartet")
pause()
except KeyboardInterrupt:
print ("Ctrl-C - quit")

if __name__ == "__main__":
main()
Antworten