Seite 1 von 1

Pythonprogramm mit GPIO Eingängen

Verfasst: Donnerstag 26. Oktober 2023, 12:39
von CallMeGuardian
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()

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Donnerstag 26. Oktober 2023, 13:06
von __deets__
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.

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Donnerstag 26. Oktober 2023, 13:15
von Sirius3
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?

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Freitag 27. Oktober 2023, 21:04
von hyle
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. 😉

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Freitag 3. November 2023, 08:28
von CallMeGuardian
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?

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Freitag 3. November 2023, 08:30
von CallMeGuardian
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!

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Freitag 3. November 2023, 11:44
von Sirius3
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)

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Freitag 3. November 2023, 11:58
von __deets__
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.

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Samstag 4. November 2023, 23:43
von hyle
__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

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Sonntag 5. November 2023, 09:49
von __deets__
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.

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Montag 6. November 2023, 14:03
von CallMeGuardian
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.

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Montag 6. November 2023, 14:16
von __deets__
Hast du mal die Spannungen an den Pins gemessen, ob das alles ueberhaupt deiner Erwartungshaltung entspricht?

Re: Pythonprogramm mit GPIO Eingängen

Verfasst: Montag 6. November 2023, 14:37
von Sirius3
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?