Drehschalter an GPIO Abfragen

Registriere dich jetzt, um exklusive Vorteile zu genießen! Als registriertes Mitglied kannst du Inhalte herunterladen und profitierst von einem werbefreien Forum.
Mach mit und werde Teil unserer Community!
  • Servus,


    ich möchte an der GPIO einen Drehschalter anschliessen und dessen Position abfragen.


    PIN / GPIO / Anschluss

    29 / GPIO5 / Schaltstellung 1 / Audio-Datei 1

    31 / GPIO6 / Schaltstellung 2 / Audio-Datei 2

    33 / GPIO13 / Schaltstellung 3 / Audio-Datei 3

    35 / GPIO19 / Schaltstellung 4 / Audio-Datei 4

    36 / GPIO16 / Schaltstellung 5 / Audio-Datei 5

    0 / 0 / Schaltstellung 6 / KEINE AUSWAHL-Nullstellung

    39 / GND / Masse für den Schalter


    Funktion:

    Mit dem Drehschalter wird eine von Fünf Audio-Datei ausgewählt. Dann kann diese Datei per separatem Button abgespielt werden. Mit einem weiteren Taster kann die Datei neu Aufgenommen werden - Quasi 5 verschiedenen Anrufbeantworter-Ansagen, wenn man so will ;)


    Die Buttons sind kein Thema. Aber wie kann ich sinnvoll in Python den Drehschalter abfragen? Ich kenne aus PHP die Switch-Anweisung und habe gelesen, dass man die in Python mit "match ... case" nutzen kann. Aber bei switch/match ginge es ja darum, EINE Variable auf FÜNF verschiedene Zustände zu prüfen.


    Hier muss ich fünf GPIOs (von welchen immer nur einer aktiv sein kann) auf Aktivität, sprich auf Masse) überprüfen.

    Wie kann ich das am sinnvollsten in Python anstellen?

  • DJ1NG Das sind halt einfach fünf Taster von denen immer nur einer gedrückt ist. Frag die der Reihe nach in einer Schleife ab, dann siehst Du ja welcher aktiv ist. Wenn man den Umweg über eine ganze Zahl gehen will, ist `enumerate()` hilfreich. Wenn man sich die Indirektion sparen will, die `zip()`-Funktion.


    ``match``/``case`` ist nicht für so simple Fälle wie ``switch``/``case`` in PHP! Wenn man das „pattern matching“ nicht tatsächlich verwendet um Namen an Werte zu binden, sollte man kein ``match`` verwenden. Das ist dann einfach ein ``if``/``elif``/…-Konstrukt wenn man aus irgendwelchen Gründen keine Schleife schreiben kann. Was man hier aber problemlos machen kann. Und selbst wenn man keine Schleife schreiben kann, lohnt es sich zu schauen ob man das nicht über ein Wörterbuch lösen könnte. Oder eine Liste, falls die Schlüssel aufsteigende ganze Zahlen sind.


    Nachtrag: Auch wenn da nur ein GPIO high sein kann, würde ich trotzdem Code schreiben der alle ausliest und diese Bedingung auch *prüft* und mindestens eine Protokollausgabe macht falls die Bedingung verletzt ist.

    Tradition is just peer pressure from dead people.

  • Moinsen,

    Verstehe ich das richtig ? Wenn der Wiedergabe Button betätigt wird, soll zuvor geprüft werden, welche Schalterstellung diese Drehschalter hat um dann eine entsprechende Audiodatei auszuwählen ?

    Die Bedienung ist so: Drehschalter auf entsprechende Auswahl stellen, Playback oder Record-Button drücken.


    Damit hast Du das richtig erfasst: Wenn z.B. Playback gedrückt wird, muss der Drehschalter ausgelesen und die passende Audio-Datei in den Player schoben werden.

  • Hi DJ1NG ,


    die softwaremäßige Auswertung der GPIO-Pins hat Dir ja __blackjack__ schon skizziert.


    Da es sich hier um ein Audioprojekt handelt, empfehle ich Dir dringend, die I2S-Pins nicht zu verwenden:
    Pin 12 (GPIO18) = PCM_CLK

    Pin 35 (GPIO19) = PCM_FS

    Pin 38 (GPIO20) = PCM_DIN

    Pin 40 (GPIO21) = PCM_DOUT

    Diese Pins sind für eine Audiowiedergabe per I2S (PWM) durch den RPi notwendig. Werden diese Pins anderweitig verwendet, so stehen sie nicht mehr für I2S zur Verfügung und man sperrt damit für dieses Projekt alle DAC-Soundkarten für den RPi wie z.B. den Hifiberry DAC+ grundsätzlich aus!

  • Moinsen,


    Ich würde hier einen anderen Weg gehen, um nicht nur GPIOs einzusparen, sondern auch um mir aufwendige Abfragen zu ersparen. Dazu nimmt man einen PCF8574 8 Bit Port Expander.
    Dieser verfügt über 8 Ein- bzw. Ausgänge, welche man ganz einfach und nach belieben belegen kann.
    Wenn man nun das Statusregister via I²C ausliest erhält man einen Wert zwischen 0 und 255 je nach dem welcher / welche Ports geschaltet sind. in deinem Fall mit 5 aktiven Stellungen [1,2,4,8,16] weil eine Vermischung nicht auftritt. Diesen Zahlwert kannst du wie von __blackjack__ vorgeschlagen einem DICT mit den Angaben der Musiktitel ( String) direkt zuordnen.

    Code
    playlist = {'0' : None,
                '1' : '/home/pi/playtitle1.wav',
                '2' : '/home/pi/playtitle2.wav',
                '4' : '/home/pi/playtitle3.wav',
                '8' : '/home/pi/playtitle4.wav',
                '16': '/home/pi/playtitle5.wav'}

    Dazu musst du mit der Initiierung des PCF8574 alle Ports auf Eingang setzen, das geschieht in dem du an die Adresse dieses I²C Slaves den Wert 0xff sendest. Damit werden alle 8 Ports auf Eingang gesetzt. Wenn du nun diese I²C Adresse abfragst, bekommst du den Zahlenwert entsprechend des geschalteten Zustandes zurück. Diesen Wert kannst du direkt in Verbindung mit diesem DICT
    playtitle = playlist[str(pcf8574.read_byte(i2c_address))]

    deiner Wiedergabe-Routine übergeben.

    Franky

    Edited once, last by Franky07 ().

  • Ich würde die Button von Abspielen oder Aufnehmen prüfen und eine entsprechende Funktion dazu erstellen. Die GPIO hätte ich auch mittels Dictionarie an die Audio-Dateien gebunden und würde dieses Dict ähnlich wie in diesem Beispiel auslesen und statt eine Funktion aufzurufen, mit if button.is_pressed: direkt abfragen.


    Zumindst wäre das mein Ansatz.

  • Es gibt noch die Variante, den Schalter an eine Widerstandsreihe (Multi-Spannungsteiler) anzuschließen, so dass man je nach Schalterstellung unterschiedliche Spannungen mit einem ADC auslesen kann. Dann genügt ein GPIO. 5 gleich große Widerstände in Reihe zwischen 3,3 V und GND, die 6 Schalt-Pins des Drehschalters an die Endpunkte und die Verbindungen zwischen den Widerständen und den Ausgang des Drehschalters an einen ADC.


    Allerdings ist das für einen Pi nix, weil der bekanntlich keinen ADC hat. ADC nachrüsten braucht auch wieder mindestens 2 GPIOs.

    Mit nem Pico würde das gehen. Und Audio könnte der wohl prinzipiell auch, wenn ich mich nicht irre.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Moinsen,

    Es gibt noch die Variante, den Schalter an eine Widerstandsreihe (Multi-Spannungsteiler) anzuschließen, so dass man je nach Schalterstellung unterschiedliche Spannungen mit einem ADC auslesen kann. Dann genügt ein GPIO. 5 gleich große Widerstände in Reihe zwischen 3,3 V und GND, die 6 Schalt-Pins des Drehschalters an die Endpunkte und die Verbindungen zwischen den Widerständen und den Ausgang des Drehschalters an einen ADC.

    In der absolut konsequenten Reduzierung der Controller Ressourcen einen ATiny13, welcher über einen ADC Eingang verfügt, via Serial() mit der Außenwelt kommunizieren kann, und damit einen MP3 Player ansteuern kann, und auch für einen Play-Taster wäre noch ein Pin frei ;)

    Franky

  • franky Warum Zeichenketten als Schlüssel? Man könnte eine Zweierpotenz >0 aber auch einfach in eine Zahl zwischen 0 und 4 umrechnen statt sich da mit literalen Zweierpotenzen herumschlagen zu müssen:

    Python
    if value:
        index = int(math.log2(value))
        filename = f"home/pi/playtitle{index + 1}.wav"

    Und falls die Dateinamen unterschiedlicher sind/sich nicht einfach in der Nummer im Namen unterscheiden, kann man `index` als Index in eine Liste/Sequenz mit Dateinamen verwenden.

    Tradition is just peer pressure from dead people.

  • Moinsen,

    In der absolut konsequenten Reduzierung der Controller Ressourcen einen ATiny13, welcher über einen ADC Eingang verfügt, via Serial() mit der Außenwelt kommunizieren kann, und damit einen MP3 Player ansteuern kann, und auch für einen Play-Taster wäre noch ein Pin frei ;)

    Definitif ist ein Raspberry Pi jedenfalls für eine Funktion mit 5 Recordings und Abspielauswahl unterfordert. Warum nicht gleich einen Xeon mit 20 Kernen...
    Die Aufgabe dürfte tatsächlich mit einem Pico oder ESP32 lösbar sein - billiger und robuster - dafür vielleicht ein wenig aufwändiger. Wenn man mal einen Anrufbeantworter aufschraubt, wird man da drin sicher keinen Pi finden. Wer allerdings schon Schwierigkeiten mit der Abfrage von fünf GPIO-Pins hat, dürfte mit filigraneren Lösungen überfordert sein.

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

  • Moinsen

    Man könnte eine Zweierpotenz >0 aber auch einfach in eine Zahl zwischen 0 und 4 umrechnen statt sich da mit literalen Zweierpotenzen herumschlagen zu müssen:

    Viele Wege führen nach Rom :bravo2:

    Da keiner von uns wissen kann, wie der TO seine Sounddateien organisiert, sollte sich doch der TO für eine Variante entscheiden, welche ihm am liebsten ist. Ich hatte ja auch geschrieben, das ich keinesfalls so viele GPIOs wegen so einem "dußligen" Drehschalter opfern würde.
    Und ob man wirklich ein ganzes PI dafür braucht, wenn man sich im Bereich Hardware und Zubehör umsieht, siehe #9 , ist gleich die nächste Frage !?
    In der Erweiterung wie Sinnvoll ist es, weil man nur die eine Programmiersprache Python beherrscht, überhaupt eine solche Controllereinheit ( Pi, µC , PICO usw ) zu verwenden, oder den aufgezeigten MP3 Player gleich direkt ansteuert, ohne das man erst eine Software erstellen muss, das sollte der TO für sich selbst beantworten. Rein für die Aufgabe anhand einer Schalterstellung welche sich mittels Binärzahlen ( Zweipotenzen ) darstellen läßt, einen solchen Aufwand zu betreiben, erst ein System wie ein PI hochzufahren ( Wir wissen leider alle nicht ob es die einzige Aufgabe des PIs sein wird ) stellt sich für hier ohnehin in Frage. Dazu fehlen viele Hintergrundinformationen, inwieweit dieses System eine Dauerverfügbarkeit haben muss, und welche Re-boot Zeiten im Falle des Falle - z.B. eines Stromausfalles / -unterbrechung angestrebt werden. Jetzt wieder, wen auch mit einem Ansatz des Spekulativen muss man sich nur die vorherigen Posts des TOs zu Gemüte führen. Wenn dann auch noch Beeinflussungen durch Funkanlagen /-geräte ins Spiel kommen, wäre dieser Ansatz einer PI- basierten Lösung wohl die ungeeigneste Variante zu welcher ich greifen würde. Viel zu empfindlich, viel zu langsam in der Re-Boot Phase, und eine durchaus schlechtere elektromagnetische Unempfindlichkeit. Aber wie gesagt, man kann sich hierzu selber Gedanken machen, auch weitreichendere - ob das mit dem tatsächlichen Aufbau / Funktion im Zusammenhang steht wissen wir alle nicht. :gk1:

    Franky

  • Moinsen

    Die Aufgabe dürfte tatsächlich mit einem Pico oder ESP32 lösbar sein - billiger und robuster - dafür vielleicht ein wenig aufwändiger.

    Wie definiert man Aufwand ?
    Spannungsversorgung 5 Volt ist bei allen Systemen annähern gleich, nur der benötigte Strom macht die Sache einfacher oder teurer ;)
    Ein PICO bekommt man für ca. 5 Euro, eine TINY für 1,30 € ( aber man braucht noch einen Programmer ) aber rein vom Strom reden wir hier von unter 50 mA für die Controllereinheit.
    Ob nun ein ESP8266 oder ESP32 welche auch ( wenn man mal ALI und CO weglässt ) so in diesem Preissegment liegen nutzen könnte, ja ? Klar kann ein ESP32 direkt von einer SD-Card ( dann aber auch nicht in Python ) eine MP3 Datei über den I²S Bus zu einem Digitalverstärker durchleiten. Nur ist der Strombedarf ein anderer. Möglichkeiten gibt es sicherlich viele.
    Dabei sollte erst einmal geklärt werden, oder vom TO bekannt gegeben werden, ob diese "einfache" Aufgabe die einzigste Aufgabe ist, welche das PI übernehmen soll ?
    Klar der PICO mit seinen 2 HW-UARTs kann hier auch noch die Steuerung eines anderen Gerätes übernehmen, falls das ganze mit den vorherigen Nachfragen um elektromagnetische Festigkeit eines Zeros mit Funkgeräten in Verbindung stehen sollte.

    Theoretisch würde dieser Drehschalter und dieser MP3 Player mit einem Logikgatter vollkommen zureichen, wenn man soweit das System einschrumpfen möchte und auf SW verzichten möchte. An diesen MP3 Player kann man problemlos Dank LineOut jeden Verstärker fast jeder Leistungsklasse anschließen.

    Franky

    1. Jemand kommt mit einer einfachen Frage.
    2. Jemand anderes kommt mit der Idee, dass man aus den Eingängen einen Integer erstellt und ein Mapping mit den entsprechenden Zahlen als Keys zu definieren. (ist z.B. nützlich, wenn man eine binäre Eingabe hat)
    3. Dann möchte jemand, dem OP mitteilen, dass sein RPi doch viel zu gut/teuer für das Projekt ist. (auch das mag richtig sein, demotiviert den OP aber sicherlich auch)
    4. Der nächste meinte ironisch, dass man ja mit math.log2 rechnen kann.
    5. Nachfolgend wieder ein Einwurf, dass man das doch mit einem ESP32 auch lösen könnte.


    Würde jemand strikt nach allen Anweisungen hier im Thread 1:1 vorgehen, so würde das Projekt erst in 1000 Jahren fertig werden.



    Was soll jemand denken, der nach einfachen Lösung sucht und das hier alles liest? Welche Wirkung hat das?


    Sinnvoll ist es, die Eingänge erst dann abzufragen, wenn eine Play-Taste gedrückt wird.

    Richtig ist auch, zu prüfen, ob zwei oder mehr Eingänge aktiv sind.


    Die Zuordnung würde ich so machen, dass der Pin (int) als Key und den Pfad zum Audio als str.

    Beispiel mit zwei Eingängen:

    Code
    pin2audio = {
        29: "/home/pi/Audio/sound1.wav"
        31: "/home/pi/Audio/sound2.wav"
    }

    Wie man dann weiter vorgeht, hängt davon ab, welche Bibliothek/Modul man nutzt, um die GPIOs auszulesen.

    Die meisten Anfänger landen bei RPi.GPIO da dieses Modul in sämtlichen Anleitungen vorkommt.

    Dann wird fast immer gpiozero vorgeschlagen, dass mehr Pythonisch ist und eine bessere Abstraktion hat.


    Beispiel für RPI.GPIO



    Ähnliches Beispiel mit gpiozero:


    Macht es nicht komplizierter, als es sein muss.

    Bei meinem Beispiel könnte man z.B. kritisieren, dass ich das dict beim zweiten Beispiel neu zuweise.

    Ja, man kann auch Button() 5 Mal schreiben, wenn man damit zufriedener ist.

    Man könnte auch einen Basispfad für die Audio-Dateien vorgeben und die Dateiendung auslassen und dann wieder kombinieren.


    usw...