pigpio Interrupt - Entprellen + Risingedge?

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Hallo Leute,

    ich bin momentan an einem Datenlogger am Arbeiten. Das Starten des Loggens soll per Taster erfolgen. Nun hab ich die Beispiele aus diesem Beitrag mir angesehen und mich für die pigpio Lib entschieden. Meine Fragen beziehen sich auf den im Beispiel hinterlegten Code.

    Erstes Problem: Ich krieg das Eingangssignal nicht entprellt. Normalerweise sollte das ja mit gpioDelay passieren. Doch diesen kann ich ändern wie ich will, da tut sich eigentlich gar nichts. Wie sag ich also dem Interrupt dass er den GPIO nur alle z.B. 50ms abfragen soll?

    Das andere ist die Flanke, ich möchte ja nur beim Signalwechsel low->high bzw. umgekehrt einen Sprung in die Interruptroutine bekommen. So eine Funktion ist in dieser Lib nur im Python Teil drin, wenn ich nichts übersehen habe.

    Please help.

    Gruß - Markus

    Ok, das mit der Flanke habe ich jetzt gefunden. In der Interrupt Routine kommt der Level - Wert mit. 0 bedeutet fallingedge, 1 risingedge. Hab den Code mal erweitert:

    Code
    void alert(int pin, int level, uint32_t tick)
    {
    		if (level == 0) //falling edge
    		{
    			printf("pin %d - %d\n", pin, level);
    		}
    
    
    }

    Hat sich aber nicht viel geändert. Wenn ich den Taster drücke kommen zwar nur noch Werte mit Level 0, aber auch beim loslassen des Tasters wird mir ein Wert angezeigt. Auch mit Level 0 ???

    Any Idea?

    Einmal editiert, zuletzt von Markus-H (19. Oktober 2014 um 22:07)

  • Hallo,
    bin auch begeisterter User der pigpio lib.

    Les dir mal das ,oder das durch
    wird Dich sicher weiter bringen.

    gruß root

    Einmal editiert, zuletzt von root (19. Oktober 2014 um 22:40)

  • Hi,
    also mit delay kannst Du nix entprellen ... die peaks treten ja trotzdem auf.
    roots Links sind da schon ganz hilfreich, blöderweise ist das interessantere Beispiel für Python.
    Ich würde jetzt so aus dem hohlen Bauch ein Flag setzen, wenn die ISR angetriggert wird - am besten einen Wert mit millis(). Bei jedem Antriggern der Funktion überprüfst Du jetzt, ob der aktuelle millis() Wert abzüglich des zuerst gespeicherten z.B. >= 200 ist ... das wären dann 200 ms. Ist der Wert kleiner, ist es ein Preller und Du tust nix in der ISR. Ist er grösser oder gleich, dann setzt Du den Merker wieder auf 0.
    Ich hoffe, das war verständlich ...
    cu,
    -ds-


  • Ich würde jetzt so aus dem hohlen Bauch ein Flag setzen, wenn die ISR angetriggert wird - am besten einen Wert mit millis(). Bei jedem Antriggern der Funktion überprüfst Du jetzt, ob der aktuelle millis() Wert abzüglich des zuerst gespeicherten z.B. >= 200 ist ... das wären dann 200 ms. Ist der Wert kleiner, ist es ein Preller und Du tust nix in der ISR. Ist er grösser oder gleich, dann setzt Du den Merker wieder auf 0.


    ...sauber...
    ich hätte nen Timer aufgezogen und in der ISR solange der rennt auch nix gemacht, aber
    wozu... ne Zeitdifferenz iss ja'n Timer. :lol:
    man lernt eben nie aus...

  • Naja ... ich weiss ehrlich gesagt nicht, wie sich der RPi da verhalten würde. Für die Arduinos gilt, dass Du innerhalb einer ISR keinen Timer verwenden kannst (weil -> solange du in der ISR bist, sind die Interrupts disabled ... logisch). Bei generischen AVRs hab' ich das aber auch noch nicht ausprobiert.
    cu,
    -ds-


  • Naja ... ich weiss ehrlich gesagt nicht, wie sich der RPi da verhalten würde. Für die Arduinos gilt, dass Du innerhalb einer ISR keinen Timer verwenden kannst (weil -> solange du in der ISR bist, sind die Interrupts disabled ... logisch). Bei generischen AVRs hab' ich das aber auch noch nicht ausprobiert.


    Das ist korrekt,da ich hab mich falsch ausgedrückt.
    Ich würde auch nie nen Timer in der ISR aufziehen.
    Ich meinte: bein ersten Flankenwechsel in der ISR ein Flag setzen.
    In der Hauproutine das Flag abfragen und Timer (wenn nötig) starten...der Rest wie oben.

  • Hi Leutz,

    vielen Dank für die zahlreichen Antworten. Ich habe den code folgendermaßen ergänzt:

    Funktioniert perfekt, einziges Problem ist dass manchmal beim Auslassen der Taste auch ein Drücken erkannt wird (also Level ist auch 0!). Hängt vermutlich mit meinen Tastern zusammen. Eventuell ist auch die Beschaltung nicht gut bzw. gibts ne besser geeignete Variante?


    Gruß - Markus

  • Hi Markus,
    die Verschaltung ist imho ok ... probier einfach das Loslassen ebenfalls zu entprellen ( so ad hoc: else Zweig rein, nur den zaehler setzen ) ...
    Jedenfalls schön, dass es klappt ;) ...

    Viel Spass noch,
    -ds-

  • ich liebe ja die Entprellroutine nach Dannegger, ist zwar AVR aber sollte im PI doch auch irgendwie gehen

    http://www.mikrocontroller.net/topic/tasten-e…len-bulletproof

    ich habe überall die in C

    Interrupt Routine 10ms -> Byte maskiert einlesen (oder Bit und nach Byte schieben)

    abfragen bei Bedarf, muss ja nicht in Echtzeit erfolgen.

    Mir entgeht nie ein Tastendruck, egal wie lange die Hauptroutine grad beschäftigt ist.

    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)


  • Hi Markus,
    die Verschaltung ist imho ok ... probier einfach das Loslassen ebenfalls zu entprellen ( so ad hoc: else Zweig rein, nur den zaehler setzen ) ...
    Jedenfalls schön, dass es klappt ;) ...

    Viel Spass noch,
    -ds-

    Hi,

    das Problem ist imho, dass beim Loslassen auch ein "Drücken" erkannt wird. Siehe Ausgabe Konsole:

    Bei "1" habe ich gedrückt und bei "2" wieder losgelassen. Level ist immer 0. Ich verstehs nicht ganz, liegts vielleicht an disen billigen Printtastern?

    Markus


  • ....Ich verstehs nicht ganz, liegts vielleicht an disen billigen Printtastern?

    nö, ALLE Taster prellen, völlig normal, von daher hilft nur ein retrigerbares Monoflop, ein Timer NE oder TLC 555 oder eine vernünftige Routine.

    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)

  • Hi,

    mal zur grundsätzlichen Vorgehensweise wenn ich die Routine von Danegger am Pi nutzen möchte: Soweit ich das bisher gelesene verstanden habe, müsste ich statt der GPIO-ISR eine eigene ISR setzen. Diese pollt alle 10 ms welche Taster gedrückt wurden. Mein Verständnisproblem bisher ist, dass meines Wissens nach es unter Linux keine Möglichkeit gibt eigene ISR zu nutzen. Richtig? Auf einem AVR ist das ja kein Problem.
    Ein Ansatz wäre mit pigpio z.B. die Funktion gpioSetTimerFunc zu nutzen. Das würde in etwa so aussehen (Beispiel aus dem ARM MP3/AAC Player Projekt):


    Ich könnt mir vorstellen dass es so funktionieren könnte. Ein Problem: Als was definiere ich aber KEY_INPUT? Einen Port wie im AVR (z.B. PIND) gibts ja hier nicht. Da könnt ich nen Schups brauchen, danke.

    Gruß - Markus

    Weitere Überlegung um den KEY_INPUT zu bekommen: Ich definiere eine Variable z.B.
    uint8_t keys;

    In diese Variable schreibe ich die Zustände der GPIOs an denen die Taster hängen. Dies passiert durch die GPIO-ISR (gpioSetAlertFunc).

    Es laufen dann also die ISR-Routine für die GPIO Abfrage und ein Timer der das entprellen übernimmt. Komme ich so ans Ziel?

    Gruß - Markus

    Einmal editiert, zuletzt von Markus-H (21. Oktober 2014 um 11:10)


  • Weitere Überlegung um den KEY_INPUT zu bekommen: Ich definiere eine Variable z.B.
    uint8_t keys;
    In diese Variable schreibe ich die Zustände der GPIOs an denen die Taster hängen. Dies passiert durch die GPIO-ISR (gpioSetAlertFunc).
    Es laufen dann also die ISR-Routine für die GPIO Abfrage und ein Timer der das entprellen übernimmt. Komme ich so ans Ziel?

    ich denke so kann das gehen

    GPIO Abfrage

    ist ja nur ein Bit high oder low, das in ein Byte hier <uint8_t i> geschoben an gewünschter Stelle, das für bis zu 8 GPIO Pins und Tasten und dann mit der normalen "DanneggerRoutine" weiter

    am Arduino oder AVR (jetzt mit einer I2C Tastatur und PCF8574) mache ich das so

    PS. ich habe pullups nach +U und frage deswegen invertiert ~ ab, die Taster ziehen auf low der pullupwiderstand ist bei mir um 1mA also 4,7k an 5V und 3,3k an 3,3V und der PCF8574 bringt seine eigene Quelle mit

    Nach der Abfrage und Auswertung der gewünschten Taste lösche ich das entsprechende Bit wieder

    10ms ISR

    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 (21. Oktober 2014 um 11:38)

  • Hi Leute,

    vielleicht könnt ihr euch das mal anschauen, ich komm da einfach nicht weiter. Eine Abfrage des angschlossenen Tasters mittel get_key_press ergibt immer, dass die Taste nicht gedrückt ist. Laut debug Ausgabe wird das (in diesem Fall) 4. bit korrekt gesetzt:

    Wo könnte der Fehler liegen?

    Gruß - Markus


  • Wo könnte der Fehler liegen?

    Taster nach +3,3V oder nach GND ?

    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)

  • long get_key_press( long key_mask )
    {
    gpioSetTimerFunc(0, 10, 0);


    soll das cli() sein ?

    char get_key_press( char key_mask )
    {
    cli();

    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)

  • Richtig, damit wird der Timer deaktiviert. Eigentlich steht statt der letzten 0 ein "NULL", die 0 ist nur zum testen drin. So stehts zumindest in der Beschreibung der lib:

    Zitat

    The timer may be cancelled by passing NULL as the function


  • Richtig, damit wird der Timer deaktiviert.

    hmm Timer deaktivvieren ist aber was anderes als IRQ sperren :s

    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)

Jetzt mitmachen!

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