Script führt If-Bedingung fälschlicherweise aus

  • Liebes Forum,


    ich bastel gerade an einer Fotobox und an sich klappt alles super. Mittels GPIO-Taster starte ich einen LED-Countdown und mache mehrere Fotos, die anschließend zusammengefügt und im Display angezeigt werden. Soweit, so gut. Mittels eines weiteren Tasters soll nun die Anzeige im Display beendet werden. Die Taster lese ich per If-Bedingung in einer Endlosschleife aus. Im Falle des Start-Taster funktioniert das wunderbar. Die Anweisung zum Schließen wird aber immer ausgeführt, unabhängig vom Taster-Zustand. Hier mein Code (In der Mitte fehlen ein paar Funktionen, die mit der Funktionalität des IF jedoch nichts zu tun haben):



    Außerdem anbei noch die Schaltung. Ich habe drei Mal geprüft, ob ich alles korrekt verkabelt habe und bin mir eigentlich ziemlich sicher, dass ich auf dem Steckbrett alles genau so habe, wie im Schaltplan. Ich habe auch schonmal zwischen Pin 3 und 5 gewechselt, das Ergebnis ist das gleiche: Sobald ich das Skript starte, kommt eine Fehlermeldung, dass kein pqiv-Prozess läuft. Er führt also die IF-Anweisung aus.


    Habt ihr irgendeine Idee, ob mit dem Code etwas nicht stimmt? :s


    Danke und Gruß
    Tim

  • Lass dir doch einfach mal im Sekundendtakt die Werte von GPIO.input(3) bzw GPIO.input(5) ausgeben. Wirst sehen, dass die schwimmen. Was du brauchst, ist ein definiertes Signal, wenn der Schalter offen ist. Dazu gibt es Pull-up/down Widerstände, hat der Pi sogar integriert, müssen nur aktiviert werden. Da du, bei gedrücktem Schalter LOW lesen willst(sog. active low), musst du das Signal bei nicht gedrücktem Schalter gegen HIGH bzw 3V3 ziehen -> PullUp.


    Außerdem: Im Kreis mit Pin 3 wird der Strom nicht begrenzt. Hier solltest du noch einen Widerstand einfügen.

  • Hi,
    ich kann zwar kein Python, aber:


    1. Du setzt den Pin ja nicht initial auf HIGH ... da ist das Signal beim Start des Programms undefiniert. Das ist/war natürlich Unfug ... sorry ... :blush:
    2. Möglicherweise bricht Dir auch die Spannung ein. Du hast 8 LEDs die jeweils je 8 mA Strom ziehen. Das macht nur für die LEDs schon 64 mA ...


    btw.: es ist Quatsch, dass eine bedingte Anweisung "fälschlicherweise" ausgeführt wird. Wenn die Anweisung durchlaufen wird, dann ist auch die Bedingung erfüllt (warum auch immer). Also: der Fehler sitzt meistens vor dem Bildschirm und der Rechner tut immer das, was Du ihm sagst. Der hat kein Eigenleben ;)


    cu,
    -ds-

  • Hallo Tim,



    hmm, mir graust es, wenn jemand einen als Output definierten GPIO-Pin abfragt, um an den Status des Pins heranzukommen.


    Du setzt mit einem Befehl einen Ausgang auf HIGH oder LOW. Der Zustand ergibt sich aus dem Programm-Code, einem Status, einer Variablen oder dergleichen.


    Einen Status eines GPIO-Pins abzufragen, liest diesen GPIO-Pin aus. Das Ergebnis ist ein Pegel (LOW < 0,8 V, HIGH > 1,3 V), der davon abhängt, was da physikalisch, elektrotechnisch auf der Schaltung abgeht.


    Bei Deiner Schaltung hast Du über P1-18 und P1-19 LED (als Ausgang) und Taster (als Eingang) verbunden. Das heißt, der Pegel, der an der LED anliegt, liegt auch am Taster-Pin an (ohne dass der jetzt betätigt wird oder nicht). Ein Betätigen des Tasters muss dann nicht unbedingt zu einem HIGH-Pegel führen (wie Du es erwartest). Das könnte auch ein LOW ergeben...


    Stilistisch reiner wäre es, eine Status-Variable zu setzen, wenn die LED leuchtet. Und dann auch diese Variable zu verwenden, wenn Du den Taster-Zustand abfragst.


    Für Testzwecke würde ich die beiden Afragen trennen. Dein Programm muss erkennen, ob der Taster gedrückt wurde - unabhängig vom Zustand der LED. Und Dein Programm soll erkennen, ob der Taster bei leuchtender LED gedrückt wurde.


    Wegen des pqiv: Das Teil wird geschlossen, wenn die Bedingung erfüllt ist (warum und wann auch immer). Wenn die Bedingung das nächste Mal erfüllt ist, dann versucht es natürlich, wieder pqiv zu killen - was nicht möglich ist, weil das dann schon lange nicht mehr läuft. Insofern ist dann auch die Fehlermeldung berechtigt und auch verdammt sinnvoll!


    Auch hier musst Du eine Status-Variable setzen, wenn pqiv das erste Mal gekillt wurde. Ein zweites Mal muss es das dann nicht mehr. Tot ist tot. Mehr als tot geht nicht. Vielleicht noch mausetot. Aber so weit kann der RPi nicht unterscheiden.


    Beste Grüße


    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    • Icon-Tutorials (IDE: Geany) - GPIO-Library - µController-Programmierung in Icon! - ser. Devices - kein Support per PM / Konversation

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Edited once, last by Andreas ().


  • hmm, mir graust es, wenn jemand einen als Output definierten GPIO-Pin abfragt, um an den Status des Pins heranzukommen.


    mir graust es noch mehr, viel umständlicher kann man das ganze nicht aufbauen...


    Allerdings funktioniert alles wie es soll, du hast halt die Sache falsch aufgebaut :cool:


    Du fragst Pin 5 auf Low ab und wenn ich mir das Pinout des Pis so anschaue liegt bei mir auf Pin 6 dauerhaft auf GND
    Damit ist R9 wenn der Schalter offen ist ein Pull-Down nach GND, Pin 5 sieht also ständig Low, daher wird auch die Verzweigung aufgerufen.


    Bitte baue doch das ganze anständig auf, auch wenn es mit der Korrektur des Fehlers funktionieren sollte....


    lg kobold254


  • ... Du fragst Pin 5 auf Low ab und wenn ich mir das Pinout des Pis so anschaue liegt bei mir auf Pin 6 dauerhaft auf GND ...


    Da hast Du vollkommen recht ... ist mir jetzt gar nicht aufgefallen.
    :wallbash: manchmal sieht man den Baum vor lauter Wald nicht ...


    cu,
    -ds-

  • Vielen Dank schonmal für die Antworten,


    ein vorweg: An sich sollte die Abfrage auf GPIO.HIGH testen. Ich habe nur mal zu Testzwecken GPIO.LOW eingesetzt und das ist dann hier rien gerutscht... Nun im Einzelnen:


    @[font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Berlin_pi : [/font]Interrupts werde ich mir mal anschauen, das scheint eine sinnvolle Lösung zu sein.


    @[font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]KrawallKurt : [/font]Die Pull-Up-Widerstände habe ich doch in der Schaltung, 10k. Habe gelesen, dass man sich auf die internen nicht verlassen sollte und das ganze besser mit zusätzlichen Widerständen löst. Und beides ist unnötig, bzw. unsinnig, oder?


    @[font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]dreamshader: Wie kann ich denn dein Input beim Programmstart auf High oder Low setzen? Ich dachte, das ginge nur mit Outputs?! Dass das Problem vor dem PC sitzt ist mir klar. Ich habe eben nach einem Titel gesucht, der mein Problem beschreibt. Und ich denke, es ist beim Lesen des Titels ungefähr klar, was mein Anliegen ist, oder? [/font]


    @[font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Andreas: Die Idee, den Output auf diese Weise auszulesen habe ich im Internet gefunden und es funktioniert problemlos. Gibt es denn (abgesehen von "stilistisch nicht so schönem Code") einen Grund für dein Grauen? Ich dachte mir, ich spare mir einfach die Variable... Und zwischen Pin 18 und 19 ist ja ein 10k Widerstand (bzw. sogar 10k + 220). Das funktioniert auch alles. Auch die Fehlermeldung ist natürlich richtig! Eine Abfrage, ob pqiv überhaupt geöffnet ist, kann ich natürlich noch einfügen. Aber mein Problem ist ja, dass ich den Taster nicht vernünftig ausgelesen bekomme und deshalb das Programm pqiv schließen will, obwohl es nicht soll.[/font]


    @[font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]kobold254 : Was ist denn daran umständlich? Die Alternative mit einer Statusvariable wäre ja mehr Code, also "umständlicher". Die LED steht für die Zustand "bereit", ich benutze also quasi den GPIO-Zustand als Statusvariable. Ich bin Python-Anfänger und ändere meinen Code gerne, würde aber gerne verstehen, warum es so wie ich es mache umständlich oder unsauber ist. Meinst du mit dem falschen Aufbau meinen Code, meinen Schaltplan oder meinen tatsächlichen Aufbau auf dem Steckbrett? Letzteren hast du ja nicht gesehen...[/font]


    [font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Ich habe das ganze jetzt mal kolossal reduziert auf folgenden Code:[/font]


    [font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]

    Python
    #!/usr/bin/python[/font][/color][color=#333333][font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]# benoetigte Module importieren[/font][/color]import timeimport RPi.GPIO as GPIO# RPi.GPIO Layout verwenden (wie Pin-Nummern)GPIO.setmode(GPIO.BOARD)GPIO.setwarnings(True)GPIO.cleanup()# Pins definieren und "Bereit"-LED einschalteninput_list = [3,5,18]GPIO.setup(input_list, GPIO.IN)GPIO.while 1:    print "pin  3 ="+str(GPIO.input(3))    print "Pin  5 ="+str(GPIO.input(5))    print "Pin 18 ="+str(GPIO.input(18))[color=#333333][font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]    time.sleep(1)

    [/font][/color]


    [font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Ergebnis: Pin 3 und 5 stehen auf 1, Pin 18 auf 0. Betätige ich den Taster von Pin 18, schaltet dieser temporär auf 1. Betätige ich den Taster von Pin 5 tut sich nichts. Das erklärt dann auch, warum meine Schleife immer ausgeführt wird.
    [/font]


    [font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Anschließend habe ich dann - um eine falsche Verkabelung doch auszuschließen - die Kabel nochmal komplett abgezogen und das Skript nochmal gestartet. Ergebnis ist das selbe wie oben. Es scheint also, als müsste ich die Input-Pins tatsächlich irgendwie erstmal auf 0 setzen?! Oder ist wohl mein Board defekt?[/font]


    [font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Danke und Gruß[/font]
    [font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]Tim[/font]


  • aber: Pin 5 ist SCL des I2C-Bus, und der hat einen physikalischen Pullup von 1k8 Ohm ;)


    Treffer! Habe es jetzt mit Pin 7 probiert und das funktioniert problemlos. Dachte, es wird wohl nicht am Pin liegen, weil ich es ja bereits mit Pin 3 und 5 probiert hatte. Aber das sind blöderweise beides I2C-Pins. Mit Pin 7 jetzt geht es, Problem gelöst.


    :danke_ATDE:

  • Naja ... Du kannst Pin 3 und 5 schon verwenden. Du musst halt dann auf Masse durchschalten.
    Aber schön, dass es jetzt klappt :thumbs1:
    Ich würde aber trotzdem den Strom der LEDs mal im Auge behalten ... über 60 mA sind kein Pappenstil. Evtl. den Vorwiderstand verdoppeln ( das sollte bei uh LEDs auch locker reichen ).


    cu,
    -ds-

  • @[font="Source Sans Pro, Tahoma, Helvetica Neue, Arial, sans-serif"]kobold254 : Was ist denn daran umständlich? Die Alternative mit einer Statusvariable wäre ja mehr Code, also "umständlicher". Die LED steht für die Zustand "bereit", ich benutze also quasi den GPIO-Zustand als Statusvariable. Ich bin Python-Anfänger und ändere meinen Code gerne, würde aber gerne verstehen, warum es so wie ich es mache umständlich oder unsauber ist. Meinst du mit dem falschen Aufbau meinen Code, meinen Schaltplan oder meinen tatsächlichen Aufbau auf dem Steckbrett? Letzteren hast du ja nicht gesehen...[/font]


    Es spricht nichts dagegen einen Output einzulesen, entweder verwendet Linux intern ein Flag oder du bekommst
    einen Registerinhalt vom Output, direkt "abgefragt" wird dieser nicht, sodass es keine Probleme gibt.


    Unschön ist dein Schaltplan, den man wesentlich überschaubarer hätte zeichnen können :P
    Und bitte wenn möglich entweder Pull-Up oder Pull-Down verwenden ansonsten fließt dauerhaft Strom
    (wenn auch nur gering), was absolut unnötig ist :thumbs1:


    kobold254

  • Einen hab' ich im Zusammenhang des Postings von kobold254 auch noch:
    Ich habe mir zur Regel gemacht, die internen (Software-gesteuerten) Pullups/Pulldowns nicht zu verwenden sondern explizit externe Widerstände zu nutzen.
    Die internen Dinger sieht man nur im Programmcode und sie werden deshalb auch gerne mal übersehen ;)


    cu,
    -ds-