Pythonprogramm mit GPIO Eingängen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
CallMeGuardian
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2023, 16:26

Hallo vielleicht haben manche von euch mein "anderes" Thema zur Verbindungsherstellung zwischen Pi und SPS gesehen. Ich habe mich nach längerer Überlegung für die I/O Steuerung über die GPIO Pins entschieden da so eine Schnittstelle wie NodeRed rausfällt.
Nachdem ich mich über Python bzw. die Python Programmierung informiert habe, habe ich jetzt ein Script geschrieben damit bei der PIN-Abfrage, ein bestimmtes Video gestartet wird.
Leider überspringt er immer wieder Die Abfrage der PINS und Spielt immer "Video 3" ab. Leider hab ich jetzt über 3 Tage versucht es anzupassen, doch habe den Fehler nicht gefunden (Nur das Problem auf "Video 1" verschoben bekommen. Falls jemand vielleicht etwas sieht was ich übersehe würde ich mich sehr freuen wenn ihr mir hierbei einen Denkanstoß geben könntet.
(Ich habe es mit den "Grünen" GPIO Pins gemacht ohne irgendwelche Zusatzfunktionen (BOARD Pins: 12,16,18 und auch einmal als Test mit 36,38,40)

Hier mal das Script:

Code: Alles auswählen

# Import der Bibliotheken
import RPi.GPIO as GPIO
import subprocess
import time

# Laden der GPIO-Pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.IN)
GPIO.setup(16, GPIO.IN)
GPIO.setup(18, GPIO.IN)

# VLC-Player-Befehle
vlc_command = "vlc --fullscreen --no-video-title-show"

while True:
    # Überwachen der GPIO-Pins
    if GPIO.input(12) == GPIO.HIGH:
        # Wenn Signal an Pin 12 erkannt wird, wird Video 1 abgespielt
        subprocess.call(f"{vlc_command} /home/XYZ/Desktop/XYZ/XYZ1.mp4", shell=True)
    elif GPIO.input(16) == GPIO.HIGH:
        # Wenn Signal an Pin 16 erkannt wird, wird Video 2 abgespielt
        subprocess.call(f"{vlc_command} /home/XYZ/Desktop/XYZ/XYZ2.mp4", shell=True)
    elif GPIO.input(18) == GPIO.HIGH:
        # Wenn Signal an Pin 18 erkannt wird, wird Video 3 abgespielt
        subprocess.call(f"{vlc_command} /home/XYZ/Desktop/XYZ/XYZ3.mp4", shell=True)

    # Pause zur Entlastung vom Pi
    time.sleep(0.1)

# Cleanup
GPIO.cleanup()
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Programm ist ja simpel genug, wenn zum Zeitpunkt der Abfrage ein Pin high ist, wird abgespielt. Wenn also immer Video 3 abgespielt wird, ist wohl Pin 3 high. Statt den wahrscheinlich länger laufenden Videos würde ich die Hypothese erstmal mit print-statements prüfen.
Sirius3
User
Beiträge: 17872
Registriert: Sonntag 21. Oktober 2012, 17:20

Kommentare sollten einen Mehrwert bieten, ein "Import der Bobliotheken" for import-Zeilen oder ein "Cleanup" vor dem cleanup-Aufruf sind nicht sehr hilfreich.
`as` bei Import ist dazu da, dass man Namen beim Importieren umbenennen kann, wie `import tkinter as tk` um einen schönen kurzen Namen zu haben, oder `from datetime import datetime as DateTime`, um sich an die Namenskonvention zu halten, Du aber importierst GPIO und nennst es in GPIO um. Das `as` ist also unsinnig, korrekt wäre `from RPi import GPIO as gpio` um sich an die Namenskonvention zu halten.
subprocess.call mit shell=True benutzt man nicht. Kopierten Code möchte man auch nicht haben, statt dessen möchte man Schleifen benutzen.
Man benutzt keine kryptischen Nummern, sondern definiert sich die PIN-Nummern als Konstanten am Anfang der Datei, und man schreibt keine literalen Strings wie Dateinamen mitten in den Code, sondern zieht diese Information auch als Konstanten an den Anfang der Datei. Konstanten schreibt man komplett GROSS.
Um Pins zu überwachen, benutzt man die entpsrechenden Methoden und schreib sich nicht selbst eine Busy-Loop.
cleanup muß verläßlich innerhalb eines finally-Blocks aufgerufen werden:

Code: Alles auswählen

import subprocess
from queue import Queue
from RPi import GPIO as gpio

PIN_TO_VIDEO = {
    12: "/home/XYZ/Desktop/XYZ/XYZ1.mp4",
    16: "/home/XYZ/Desktop/XYZ/XYZ2.mp4",
    18: "/home/XYZ/Desktop/XYZ/XYZ3.mp4",
}
VLC_COMMAND = ["vlc", "--fullscreen", "--no-video-title-show"]

def initialize():
    queue = Queue()
    gpio.setmode(gpio.BOARD)
    for pin in PIN_TO_VIDEO:
        gpio.setup(pin, gpio.IN)
        gpio.add_event_detect(pin, gpio.RISING, callback=queue.put, bouncetime=200)
    return queue

def main():
    try:
        queue = initialize()
        while True:
            pin = queue.get()
            subprocess.call([*VLC_COMMAND, PIN_TO_VIDEO[pin]])
    finally:
        gpio.cleanup()

if __name__ == "__main__":
    main()
Wahrscheinlich ist Pin 18 wirklich der einzige Pin, an dem ein high-Signal anliegt. Wie hast Du denn Deine Taster verschaltet? Hast Du die passenden Pull-Down-Widerstände?
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

Sind für die GPIOs hardwareseitig Pulldown-Widerstände verbaut? Im Skript sind die internen Pulldowns jedenfalls nicht aktiviert. Also nur um diese mögliche Fehlerquelle auszuschließen. Davon abgesehen ist es sinnvoller gegen GND zu schalten, Pullup zu verwenden und auf fallende Flanke zu reagieren. Dieser Weg ist wesentlich zuverlässiger als andersherum.

Um das auch noch anzusprechen: gpiozero ist wesentlich angenehmer und einfacher als RPi.GPIO. 😉
Alles was wir sind ist Sand im Wind Hoschi.
CallMeGuardian
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2023, 16:26

Sirius3 hat geschrieben: Donnerstag 26. Oktober 2023, 13:15
Wahrscheinlich ist Pin 18 wirklich der einzige Pin, an dem ein high-Signal anliegt. Wie hast Du denn Deine Taster verschaltet? Hast Du die passenden Pull-Down-Widerstände?
Danke für die Antwort, das mit den Kommentaren ist verständlich dachte nur sieht ein bisschen besser aus wenn auf allem ein kleiner Kommentar ist, werde ich dann aufjeden fall ändern genauso mit den "as" Befehlen.

Pin 18 ist leider nicht der Einzige PIN an dem ein HIGH-Signal anliegt. Das mit den Pull-Up/Pull-Down Widerständen habe ich das erste mal gehört, ich hatte sie bis jetzt mit 3,3V über ein Schaltnetzteil beschaltet zum Test über eine Breedboard. Hatte gerade mal geschaut wegen den Pull-Widerständen, würdet ihr sagen die internen könne man nutzen oder doch eher auf externe verlassen?
CallMeGuardian
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2023, 16:26

hyle hat geschrieben: Freitag 27. Oktober 2023, 21:04 Sind für die GPIOs hardwareseitig Pulldown-Widerstände verbaut? Im Skript sind die internen Pulldowns jedenfalls nicht aktiviert. Also nur um diese mögliche Fehlerquelle auszuschließen. Davon abgesehen ist es sinnvoller gegen GND zu schalten, Pullup zu verwenden und auf fallende Flanke zu reagieren. Dieser Weg ist wesentlich zuverlässiger als andersherum.

Um das auch noch anzusprechen: gpiozero ist wesentlich angenehmer und einfacher als RPi.GPIO. 😉
Richtig die Pulldown-Widerstände sind leider nicht verbaut bzw nicht aktiviert da ich davon vorher noch nichts gehört hatte, aber ich denke mal genau das ist das Problem :roll:

Wie meinst du das gegen Ground zu schalten? Also anstatt auf 3,3V zu warten, zu warten dass von 3,3V wieder auf 0V fällt oder wie?

Danke schonmal!
Sirius3
User
Beiträge: 17872
Registriert: Sonntag 21. Oktober 2012, 17:20

Hier habe ich auf die schnelle eine Erklärung gefunden: https://www.elektronik-kompendium.de/si ... 006051.htm

Die Änderung für die internen Pull-Down-Widerstände ist trivial:

Code: Alles auswählen

gpio.setup(pin, gpio.IN, pull_up_down = GPIO.PUD_DOWN)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich halte die Pulldowns für einen roten Hering. Die Eingänge werden doch von einer SPS getrieben. Solange das keine Open-collector Ausgänge an der SPS sind, bewirkt ein pullup oder down hier genau gar nichts. Ich bin kein SPS-Kenner, aber das wäre IMHO schon ein eher grober Schnitzer.
Benutzeravatar
hyle
User
Beiträge: 96
Registriert: Sonntag 22. Dezember 2019, 23:19
Wohnort: Leipzig

__deets__ hat geschrieben: Freitag 3. November 2023, 11:58 Ich halte die Pulldowns für einen roten Hering.
Oh! Womit habe ich mir das denn verdient? 🙈

Egal. Es schadet jedenfalls nicht den Status bei einem GPIO als Eingang klar zu definieren, ganz im Gegenteil und die internen Pullup / -down zu aktivieren ist nun wirklich kein Hexenwerk.
Ich kenne mich mit SPS auch nicht aus, hatte aber hier https://de.wikipedia.org/wiki/Speicherp ... _einer_SPS folgendes gelesen:

Einige Beispiele für verschiedene Baugruppen eines modularen Systems:
Zentralbaugruppe (Sitz des Hauptprozessors)
Anschaltungen: Baugruppen zum Anbinden eines Feldbus-Systems
Busmodule (Schraub- oder Crimpklemmen, Alarmierung)
Digitale Eingangskarte (meist Potentialtrennung mittels Optokoppler)
Digitale Ausgangskarte (offener Kollektor oder Relais)
Analoge Eingangskarte
Analoge Ausgangskarte
Alles was wir sind ist Sand im Wind Hoschi.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Klar, gibt es OC Ausgänge. Aber warum dann triggert der dritte Pin? Ohne pull-up dürfte keiner tun. Es schadet auch nicht, die einzuschalten. Aber ich denke eben nicht, dass es das Fehlerbild erklärt. Da muss dann noch was anderes stattfinden.
CallMeGuardian
User
Beiträge: 8
Registriert: Donnerstag 12. Oktober 2023, 16:26

Sirius3 hat geschrieben: Donnerstag 26. Oktober 2023, 13:15 Kommentare sollten einen Mehrwert bieten, ein "Import der Bobliotheken" for import-Zeilen oder ein "Cleanup" vor dem cleanup-Aufruf sind nicht sehr hilfreich.
`as` bei Import ist dazu da, dass man Namen beim Importieren umbenennen kann, wie `import tkinter as tk` um einen schönen kurzen Namen zu haben, oder `from datetime import datetime as DateTime`, um sich an die Namenskonvention zu halten, Du aber importierst GPIO und nennst es in GPIO um. Das `as` ist also unsinnig, korrekt wäre `from RPi import GPIO as gpio` um sich an die Namenskonvention zu halten.
subprocess.call mit shell=True benutzt man nicht. Kopierten Code möchte man auch nicht haben, statt dessen möchte man Schleifen benutzen.
Man benutzt keine kryptischen Nummern, sondern definiert sich die PIN-Nummern als Konstanten am Anfang der Datei, und man schreibt keine literalen Strings wie Dateinamen mitten in den Code, sondern zieht diese Information auch als Konstanten an den Anfang der Datei. Konstanten schreibt man komplett GROSS.
Um Pins zu überwachen, benutzt man die entpsrechenden Methoden und schreib sich nicht selbst eine Busy-Loop.
cleanup muß verläßlich innerhalb eines finally-Blocks aufgerufen werden:

Code: Alles auswählen

import subprocess
from queue import Queue
from RPi import GPIO as gpio

PIN_TO_VIDEO = {
    12: "/home/XYZ/Desktop/XYZ/XYZ1.mp4",
    16: "/home/XYZ/Desktop/XYZ/XYZ2.mp4",
    18: "/home/XYZ/Desktop/XYZ/XYZ3.mp4",
}
VLC_COMMAND = ["vlc", "--fullscreen", "--no-video-title-show"]

def initialize():
    queue = Queue()
    gpio.setmode(gpio.BOARD)
    for pin in PIN_TO_VIDEO:
        gpio.setup(pin, gpio.IN)
        gpio.add_event_detect(pin, gpio.RISING, callback=queue.put, bouncetime=200)
    return queue

def main():
    try:
        queue = initialize()
        while True:
            pin = queue.get()
            subprocess.call([*VLC_COMMAND, PIN_TO_VIDEO[pin]])
    finally:
        gpio.cleanup()

if __name__ == "__main__":
    main()
Wahrscheinlich ist Pin 18 wirklich der einzige Pin, an dem ein high-Signal anliegt. Wie hast Du denn Deine Taster verschaltet? Hast Du die passenden Pull-Down-Widerstände?
Habe gerade das Programm von dir mit den Entsprechenden Pfaden abgeändert also den Pfaden zu den Videos, doch leider immer wenn ich das Script per Python öffne bricht es zusammen bzw. schließt immer direkt wieder. Hab ich irgendwas vergessen? Ich stehe gerade sehr dolle auf dem Schlauch...

Ich hab auch schon probiert die Pull Down widerstände des Pi´s einzuschalten, hat leider am Problem nichts geändert.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du mal die Spannungen an den Pins gemessen, ob das alles ueberhaupt deiner Erwartungshaltung entspricht?
Sirius3
User
Beiträge: 17872
Registriert: Sonntag 21. Oktober 2012, 17:20

Was meinst Du mit schließt sich direkt wieder?
Du startest das Programm von einer Shell aus?
Wie lautet die Fehlermeldung?

Bist Du Dir sicher, das die SPS das richtige Signal liefert?
Antworten