Abfrage Taster am PCF8574 mit dem Pico

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo

    Muss noch mal fragen weil es nicht funktioniert. Die Hardware besteht aus einem Raspberry Pi Pico und 2 x PCF8574. Am ersten PCF sind 8 LEDs angeschlossen. Am zweiten PCF sind 4xTaster und 4 LEDs angeschlossen. Die Taster schalten nach GND. Die LEDs an beiden PCF kann ich ohne Probleme schalten. Das lesen des Tasters funktioniert nicht. Mein Code dazu:

    Es geht dabei nur um die allgemeine Abfrage eines Taster und schalten einer LED.

  • Guten Tag,

    das kann so nicht funktionieren.
    Du setzt im ersten Schritt alle Port auf LOW, und fragst dann einen Taster ab, der den Stromkreis auf Null ziehen soll.
    Für den PCF8574 der sowohl LEDs wie auch Taster angeschlossen hat musst du dazu entweder über BIT-Verschiebung die Ports auf LOW schalten, an denen eine LED angeschlossen ist, oder du schaltest jeden LED Port einzeln auf LOW.
    Mit der Definition als Input hat der Pegel an diesen Taster-Pins High zu sein. Dazu muss man eine externen Pull-Up schalten. In diesem Fall reagiert auch der INT Pin des PCF8574 mit einem to Loow Wechseln, diesen kann man über einen weiteren GPIO mit Pin.IRQ_FALLING() abfragen und den Ausleseprozess der mit den Taster beschalteten Ports starten.
    Mit Polling und der Gewalthammer-Methode alle Port Registereinträge auf LOW zu setzen wird das nie funktionieren. Ich glaube mich erinnern zu können, dass es zu diesem Thema der Nutzung des INT Ports an diesen Portexpandern schon eine sehr umfangreiche Abhandlung u.a. jar gegeben hat.

    es grüßt euer
    Willy

  • Das lesen des Tasters funktioniert nicht.

    muss am Programm liegen, denn wird dein Taster abgefragt wenn er schon längst wieder high ist, falsches Timing, falsche Vorgehensweise!

    Mit INT könnte es funktionieren! das du genau abfragst wenn der INT vom PCF kommt.

    des INT Ports an diesen Portexpandern schon eine sehr umfangreiche Abhandlung u.a. jar gegeben hat.

    mag sein, kann mich nicht mehr erinnern.

    Eines ist klar, gemischte IN / OUT am PCF ist nicht einfach!

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Beitrag von jar (11. Februar 2023 um 12:58)

    Dieser Beitrag wurde gelöscht, Informationen über den Löschvorgang sind nicht verfügbar.
  • stimmt, aber gemischt IN/OUT habe ich nie genutzt, da ist mir das Verhalten vom PCF noch völlig unklar, kann sein das es locker funktioniert oder nicht.

    Tatsache bleibt man muss entprellen also mehrfach abfragen, optimal in einer IRQ von 10ms und den Zustand speichern bis zur Auswertung.

    Code
    https://de.wikipedia.org/wiki/Prellen
    
    https://www.mikrocontroller.net/articles/Entprellung
    
    https://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_(nach_Peter_Dannegger)
    
    https://www.mikrocontroller.net/topic/tasten-entprellen-bulletproof#41628

    der Editor hier nervt!

    Links werden nie richtig eingefügt!

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

    Einmal editiert, zuletzt von jar (11. Februar 2023 um 13:10)

  • Guten Tag,

    Wenn man auf das INT Signal reagiert, also eine I/O Interrupt-Handler aufruft, kann man kurz in der Schleife Pollen, alle betreffenden Ports abfragen, und die 0 oder 1 Werte in einer Tabelle / Liste pro Register erfassen. Das geht sehr bequem, wenn man den PCF8574 nicht über diese Fertig-Bibliothek anspricht, sondern nur die Port Register Zahl ausliest, des jeweilige Port BIT dann durch Bit-Verschiebung zwischen speichert. Damit kann man mit einem Auslesevorgang über den Wert Registerinhalt.copy() nacheinander auf alle möglichen und beliebig belegten Ports zugreifen. Wenn dann nach der Zeit 20 ms ( INT Release ) eine Überzahl an 0 in der Liste des jeweiligen Posts findet, kann man davon zu 99,98 % Wahrscheinlichkeit ausgehen, der Taster an Port XYZ wurde betätigt. Das kann man dann zusammengefasst, als Return zurückgeben.
    Eigentlich überhaupt kein Problem mit der Portvermischung. Man muss halt nur aufpassen, das man keinen Output Port erwischt. Jedoch sollte das mit der Aufgabenstellung Port x bis y für den Input klar definiert sein. Und natürlich darf man nicht diese Input Ports mit einem aktiven LOW überschreiben sonst werden diese zu Output-Ports.

    es grüßt euer
    Willy

  • Wenn man auf das INT Signal reagiert, also eine I/O Interrupt-Handler aufruft, kann man kurz in der Schleife Pollen

    leider nicht mit sleep(1) und nie pollen mit µC oder SoC Tempo

    Mensch will ja nicht in dem Glauben sein in sehr kurzer Zeit ist alles erledigt, vielleicht waren es nur sehr kurze Störeinstahlungen, man muss schon unterscheiden echter Tastendruck, prellen beendet?

    Ein Mensch kann keine Taste im µs Bereich drücken und loslassen also doch eher im Timer ms entprellen, das wäre sauber!

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Guten Tag jar

    so meinte ich das nicht.
    Wenn der INT auf Falling geht, springt man in eine Handler Routine. Diese enthält natürlich keine Sleep Anweisung. Damit kann man mit ticks_ms() eine Startzeit bestimmen, an dem der INT ausgelöst wurde und legt die Verarbeitungs- oder Durchlaufzeit mit:
    while start + 20 > ticks_ms(): fest. Nun kann man die Port Register Summe abfragen. Diesen Wert speichert man in einer Variablen zwischen, und beginnt dann mit Bit-Verschiebung die jeweiligen END-Bits in einer Liste ( LIST ) nacheinander abzuspeichern, je nach dem wie viele Ports als Input genutzt werden sollen, und kehr zum Anfang der While Schleife zurück. Wenn die Zeit aufgelaufen ist hat man entsprechend so viele Listen die Listenlänge ist bekannt, also bildet man die Summe und wertet diese aus.
    Result = (0 if sum(LISTE) / len(LESTE) < 0.5 else 1)
    Wenn nun der Anteil der 0 Bits über 50 % beträgt ( oder jeden anderen Faktor ) wird 0 als gedrückt ausgegeben, ansonsten eine 1, oder jeden anderen Sache die man haben möchte. True und False ist ebenfalls möglich.
    Ich hatte mir das schon einmal statisch zurecht gebastelt, das ließe sich sicherlich auch dynamisch mit einer variablen Anzahl der Input Ports umsetzen.

    es grüßt euer
    Willy

  • so meinte ich das nicht.

    OK dann sehe mein Posting als Ergänzung!

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Guten Tag

    dann sehe mein Posting als Ergänzung!

    Ist der Begriff "Polling" für diese kurze ticks_ms() Schleife etwa unangebracht ? :angel:

    Oder sollte man hier lieber einen neuen Kunstbegriff einführen: "Zeitgesteuerte Durchlaufschleife zur Erfassung von Störimpulsen und Kontaktprellungen " ? :baeh2:

    es grüßt euer
    Willy

  • Wenn man auf das INT Signal reagiert, also eine I/O Interrupt-Handler aufruft, kann man kurz in der Schleife Pollen, alle betreffenden Ports abfragen

    ne aber:

    while low

    ist auch polling

    und das im ns oder µs Bereich bei I2C mit 100kHz also 0,x bis 1,5 µs bei meinen AVR Messungen

    Das ist viel zu schnell um zu entprellen.

    dein Timer ticks_ms() kam erst später und hätte untergehen können gelle?

    Ist der Begriff "Polling" für diese kurze ticks_ms() Schleife etwa unangebracht ?

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • bin raus, bringt ja eh nix

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Warum sollte das nichts bringen?

    Ja es stimmt. Wir haben uns schon darüber unterhalten. Es geht mir hierbei um einfache Abfrage, ohne alles dabei. Da kommt es auch die Zeit nicht draufan oder das prellen. Die Nutzung von Int geht, ist klar. Bloss nicht gleich zu Anfang.

    PCF_Adresse_2.port = 0xf0 # alle LED aus utime.sleep(1)

    Habe es jetzt soweit das die Abfrage des Tasters klappt. 0xf0 ist falsch, muss 0xff sein damit klappt es super. Auch das lesen einer Adresse und schreiben auf einer anderen Adress geht.

  • Spoiler anzeigen

    Ständiges Abfragen == Pollen

    Auf Ereignis Reagieren == Interrupt

    Das Problem ist, dass der Interrupt keine Information darüber gibt, welcher Port eine Zustandsänderung hatte, also muss man alle Ports einmal abfragen. Das würde ich nicht als pollen bezeichnen. Die Abfrage darf auch nicht zu lange dauern, da jederzeit ein erneuter Interrupt kommen könnte. Ich würde den Hardwaremäßig entpellen, damit die CPU nicht stark belastet wird.

    1. Zustandsänderung bei einem der Eingänge des PCF
    2. PCF zieht /INT wird auf LOW
    3. Interrupt-Handler des Microcontrollers wird aufgerufen, der dann die Ports einmal abfragt.
    4. Der neue Zustand wird mit dem alten Zustand verglichen, um z.B. ausschließlich die Ports mit der Zustandsänderung auszugeben

    Aber darum ging es ursprünglich nicht.

    Das Problem liegt eher daran, dass die Taster GND schalten:

    Die Taster schalten nach GND

    Liegt im geöffneten Zustand des Tasters 3.3V am Port an?

    Hier die Doku: https://www.ti.com/lit/ds/symlink/pcf8574.pdf

    Auf Seite 15 ist ein Beispiel. Der VCC ganz unten rechts am Taster ist glaube ich falsch. Das sollte eigentlich GND sein. Der Port 5 wird auf VCC gezogen und es ist wahrscheinlich so vorgesehen, dass am Taster der GND den Port5 auf 0V zieht.

  • Warum sollte das nichts bringen?

    weil ich dich eh auf Ignore gesetzt hatte, wer meine Fragen oder mich ignoriert, das muss ich mir nicht mehr antun, lebt sich viel ruhiger. :danke_ATDE:

    Du kannst ja mal in deinen 228 Beiträgen suchen, bin sicher du findet meine von dir unbeantwortete Frage.

    lasst die PIs & ESPs am Leben !
    Energiesparen:
    Das Gehirn kann in Standby gehen. Abschalten spart aber noch mehr Energie, was immer mehr nutzen. Dieter Nuhr
    (ich kann leider nicht schneller fahren, vor mir fährt ein GTi)

  • Guten Abend liebe Freunde

    Was macht ihr hier bloß ?
    Das Grundverständnis wie jar schon sagte liegt darin, das jedes auch befohlene "to LOW" vom INT quittiert wird !
    achim 9876 nochmals gesagt: Wenn einer der GPIO's des PCF8574 auf Low wechselt löst automatisch der INT des Portexpanders aus. Jetzt muss man wissen, oder in seinem Programm des steuernden Controllers beachten, was ist der Auslöser !
    Wenn du für einen als Output angedachten Pin des PCF8574 eine Port-Register-Setting Befehl sendest, der als Output gedacht ist, also eine LED aktiv ansteuert deswegen kommt deswegen trotzdem ein "aktives" Return über den INT.
    Jetzt kannst du aktiv in der CPU damit Zeit verschwenden um für 20 ms alle Port-Register in der Summe, jedoch als Einzelauswertung abzufragen, oder du bist indem Ablaufthema und der Programmiersprache deiner Wahl so weit fit, das du das Interrupr- Händling im Falle eines aktiven, vom Programmierer gewollten Umschalten des Pegels eines von dir als Ausgang beabsichtigten Ports des PCF8574 unterbindet.
    Das geht mit für den INT überwachenden GPIO via PIN_name.IRQ(handler = None) .
    Damit kannst du euch einen Ausgang auf Low schalten, also eine angeschlossene LED abschalten, der INT-Out des PCF8574 kann reagieren, aber die Auswertung über den GPIO des PICOs welcher zuvor auf "Überwache den Pegelwechsel auf LOW" aktiviert wurde wieder außer Kraft setzt,
    Wenn du einen Output Pin des PCF8574 aktiv beschreibst, also eine Zustands- oder Pegeländerung an einem dieser Ports die aus Ausgang vorgesehen sind benutzt, oder via Programmlauf anweist, dann musst du diesen INT- Interrupt für diese Zeit oder den Moment abschalte, jedoch anschließend gleich wieder aktivieren.

    jar hat schon recht, wenn er sagt der Mischbetrieb ist mit dieser Programmiersprache nicht einfach.
    Das reine Software Entprellen ist nicht das wirkliche Problem, nur das jeder "to Low" Schaltbefehl auf einen Output Port auch zu einer Auslösung des INT führt, der eigentlich dafür gedacht ist, das ein Input- Event einen Pegelwechsel "to Low" auch sofort eine Reaktion des INT Kanals nach sich zieht.

    es grüßt euer
    Willy

  • Noch mal zu meinem Verständnis. Ich verwende einen 10 poligen Wannenstecker mit SCL, SDA, 2x5V, 4xGND, 12V und eine Int Verbindung. Wenn ich ein bischen längeres Kabel brauche, nehme ich 2x2 0,75 geschirmt. Beim Wannenstecker kann ich Int verbinden, beim Kabel nicht.

    Ist den Int zwingend notwendig?

    Teilweise verwende ich 3 x PFC8574, MCP23017 und manchmal auch den PCF8591 (analog) für Joustick Erfassung. Auch gleichzeitig. Wird das denn nicht zuviel? Wie soll die Auswertung erfolgen? Wenn ich z.B. mit Multitasking programmiere spielt die Auswertung eine so grosse Rolle?

    Gibt es einen bevorzugten Pin am Pico für Int? Verwende I2C 0 Pin 0 und 1.

  • Guten Tag,

    Es ist nicht relevant wie dein Aufbau der Verbindungen zum Controller ist, sondern rein wie die Beschaltung ist, und somit wie oder was an welchem Port an den PCF8574 angeschlossen ist.
    Es wurde schon mehrfach und wiederholt ausgesprochen.
    Egal welchen Ausgangszustand eine Port hat, oder er als Input auf High gesetzt wird, um auf einen LOW Event zu triggern, oder ob du selber im Mischbetrieb Input + Output einen solchen Port in der Funktion aus Output auf Low setzt, um damit z.B. eine LED wieder abzuschalten, der INT selber reagiert immer, mit einem für ca. 20 ms anliegenden LOW Event / Impuls, und geht dann wieder in den High zustand. Also mit jeder Pegeländerungen an einem Port auf LOW, gibt der INT einen Impuls ebenfalls als LOW Signal aus.
    Welchen Pin du an deinen µController dem Pico dafür benutzt ist vollkommen egal.

    Python
    def PCF_Abfrage():
        bla bla bla bla 
    
    INT_Pin = Pin(<Pin-Nummer>, Pin.IN, Pin.PULL_UP)
    INT_Pin.IRQ(trigger = Pin.FALLING, handler = PCF_Abfrage)

    Wenn du jetzt einen Output-Port aktiv auf Low setzt, dann musst du mit

    Python
    INT_Pin.IRQ(handler = None) 

    zuvor diese INT-Überwachung abstellen, und nach dem Senden des neuen Registerstaatus dieses wieder wie oben drüber gezeigt ( letzte Zeile ) aktivieren. Was in in "bla bla bla bla" wie machst, das ist deinem Einfallsreichtum überlassen, nur darf dieser Teil keinen Verweilzeit im Sinne eines sleep(), sleep_ms() oder sleep_us() enthalten. Du musst also alles mit ticks_ms() oder ticks_us() machen, um eine zeitlich begrenzte wiederholte Anfrage der Portregister auszuführen.
    Und dieser Abfrageintervall darf ebenso diese schon genannten 20 ms nicht überschreiten. Also wenn du für kein elektromechanisches Entprellen sorgen kannst, geht das nur auf der Software Ebene. Dazu hatte ich schon ein umfangreiche Ausführung gemacht. Beschäftige dich mit dem I²C Protokoll des PCF8574, dazu gibt es ausreichend Material im Internet, wie auch von den Herstellern selber.

    es grüßt euer
    Willy

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!