Forum: Mikrocontroller und Digitale Elektronik Verständnisfrage Debounce nach Peter Dannegger


von Stefan S. (sschultewolter)


Lesenswert?

Hallo,

ich habe eine kurze Verständnisfrage zu Peter Danneggers Debounce Lib 
hier aus dem Forum.

Ich habe auf einem Board 3 Taster, so kommt mir dieser Funktionsumfang 
der Lib sehr entgegen, um nicht unnötig viele Taster zu verbauen.

Folgender Ablauf,

Drücke ich die Taster einmalig kurz, soll in einen entsprechenden 
Set-Modus gewechselt werden.

KEY0 -> Hue
KEY1 -> Saturation
KEY2 -> Value/Brightness

Wird nun die gleiche Taste kurz einmalig wieder gedrückt, so soll der 
Set-Modus wieder abgeschaltet werden, wird jedoch eine andere Taste 
gedrückt, wird in den anderen Modus gewechselt.
1
    static uint8_t progMode = 0;
2
    
3
    if(get_key_short(1<<KEY0)) {
4
      if(progMode == 1)
5
      {
6
        progMode = 0;
7
        uart_puts("PROGMODE_OFF\r\n");
8
      }
9
      else {
10
        progMode = 1;
11
        uart_puts("PROGMODE_HUE\r\n");
12
      }
13
    }
14
    
15
    if(get_key_short(1<<KEY1))
16
    {
17
      if(progMode == 2)
18
      {
19
        progMode = 0;
20
        uart_puts("PROGMODE_OFF\r\n");
21
      }
22
      else {
23
        progMode = 2;
24
        uart_puts("PROGMODE_SAT\r\n");
25
      }
26
    }
27
    
28
    if(get_key_short(1<<KEY2))
29
    {
30
      if(progMode == 3)
31
      {
32
        progMode = 0;
33
        uart_puts("PROGMODE_OFF\r\n");
34
      }
35
      else {
36
        progMode = 3;
37
        uart_puts("PROGMODE_VAL\r\n");
38
      }
39
    }

Die einzelne Erkennung der Tasten funktioniert. Was nun hingegen zu 
Problemem führt ist dieser Teil
1
    switch(progMode)
2
    {
3
      case 1:
4
      if(get_key_rpt(1<<KEY1) && hue > 0) hue--;
5
      else if(get_key_rpt(1<<KEY2 && hue < 359)) hue++;
6
      break;
7
      
8
      case 2:
9
      if(get_key_rpt(1<<KEY1) && saturation > 0) saturation--;
10
      else if(get_key_rpt(1<<KEY1) && saturation < 255) saturation++;
11
      break;
12
      
13
      case 3:
14
      if(get_key_rpt(1<<KEY1) && value > 0) value--;
15
      else if(get_key_rpt(1<<KEY2) && value < 255) value++;
16
      break;
17
    }

Halte ich eine entsprechende Taste gedrückt, wird alles korrekt 
ausgeführt. Lasse ich diese Taste nun los, erfolgt automatisch eine 
Anweisung im oberen Codeabschnitt, wo die Tasten auf kurze Drücke 
dedektiert werden.

Soll heißen in diesem Fall.

Ich drücke KEY0 einmal kurz. So schaltet der setMode in Hue. Nun kann 
ich über KEY1 und KEY2 den Wert in oder dekremtieren. Die Werte 
verändern sich. Nun wird aber beim loslassen der Taste automatisch 
entweder für KEY1 oder KEY die entsprechende Aktion für einen kurzen 
Tastendruck erkannt. Somit bleibt das Programm nicht mehr im setMode für 
Hue, sondern wechselt nach VAL oder SAT.

Die anderen Stellen in Peters Libary habe ich nur minimal abgeändert. 
Ich brauche keinen Timerinterupt alle 10ms, sondern nutze hier den 
millis() auf Timer0, welchen ich in anderen Programmabschnitten nutze. 
Dieser funktioniert auch in den entsprechenden Zeiten
1
    /* Update Debounce-Libary */
2
    static uint32_t lastMillisDebounce = 0;
3
    if(millis() - lastMillisDebounce >= 10)
4
    {
5
      lastMillisDebounce = millis();
6
      debounce_update();
7
    }

Der Wert für REPEAT_MASK steht auf 500ms und REPEAT_NEXT steht bei 10ms.

Kann mir einer sagen, wo genau der Fehler sitzt. Leider sind die 
Funktionen nicht ausführlicher beschrieben in welchen Umfang sie genutzt 
werden können.

von Edi R. (edi_r)


Lesenswert?

Stefan S. schrieb:
>       if(get_key_rpt(1<<KEY1) && hue > 0) hue--;
>       else if(get_key_rpt(1<<KEY2 && hue < 359)) hue++;

Da steht im if-Teil "KEY1" und im else-Teil "KEY2". Bei case 3 ebenso. 
Vielleicht liegt's daran.

Gerade gesehen: Im else-Teil sind die Klammern offenbar falsch gesetzt. 
Ich würde hier schreiben:
1
else if(get_key_rpt(1<<KEY2) && hue < 359) hue++;

: Bearbeitet durch User
von Stefan S. (sschultewolter)


Lesenswert?

Hier hatte sich ein Fehler eingeschlichen
1
     case 2:
2
      if(get_key_rpt(1<<KEY1) && saturation > 0) saturation--;
3
      else if(get_key_rpt(1<<KEY1) && saturation < 255) saturation++;
4
      break;
Da muss es an der 2. Stelle KEY2 heißen. Behebt aber nicht das Problem, 
sondern deckt einen Teil auf, den ich noch nicht gesehen hatte.

Die 2. Anmerkung habe ich ausgebessert. Wenn auch nicht beabsichtigt 
sollte das mit der falschen Klammer denoch gehen.

von W.S. (Gast)


Lesenswert?

Stefan S. schrieb:
> Drücke ich die Taster einmalig kurz, soll in einen entsprechenden
> Set-Modus gewechselt werden.

Du machst es vom Grundsatz her falsch, da du die Tastenerkennung und die 
Auswertung zusammenziehen willst.

Mach es lieber so, daß du zunächst NUR die Tastenerkennung nebst 
Entprellung implementierst und daraus sowas wie Ereignisse (Taste 1 ist 
soeben gedrückt worden) generierst.

Als zweite und davon völlig losgelöste Sache ist dann die Auswertung von 
Ereignissen, also etwa so:
 if EventAvailable
 then
   Get the Event
   if Event = dies then mache dieses
   if Event = jenes then mache jenes
   if Event = unbehandelt then schmeissweg(Event)

und so weiter.
Damit hast du die eigentliche Tastenverwaltung getrennt von der 
Verwaltung deiner Systemzustände - und das ist enorm wichtig, wenn du 
dich nicht in deiner eigenen Firmware verheddern willst.

W.S.

von Stefan S. (sschultewolter)


Lesenswert?

Verstehe aber nicht, warum ich nach dem Loslassen der Taste im RPT-Modus 
immer noch einen Short hinterhergeworfen bekomme.
1
    if(get_key_short(1<<KEY0)) uart_puts("KEY0_SHORT\r\n");
2
    if(get_key_short(1<<KEY1) ) uart_puts("KEY1_SHORT\r\n");
3
    if(get_key_short(1<<KEY2) ) uart_puts("KEY2_SHORT\r\n");
4
    if(get_key_short(1<<KEY3) ) uart_puts("KEY3_SHORT\r\n");
5
    
6
    if(get_key_rpt(1<<KEY0)) uart_puts("KEY0_RPT\r\n");
7
    if(get_key_rpt(1<<KEY1)) uart_puts("KEY1_RPT\r\n");
8
    if(get_key_rpt(1<<KEY2)) uart_puts("KEY2_RTP\r\n");
9
    if(get_key_rpt(1<<KEY3)) uart_puts("KEY3_RTP\r\n");

Drücke ich die 4 Tasten einmal kurz, wird SHORT richtig erkannt. Halte 
ich länger diese Taste gedrückt, erhalte ich logicherweise kein SHORT, 
sondern nur RPT. Lasse ich aber nun eine Taste los, erhalte ich von 
dieser im Abschluss imer einer Short.

von Peter D. (peda)


Lesenswert?

get_key_short darf nur und muß immer zusammen mit get_key_long verwendet 
werden.
Ohne Unterscheidung muß man get_key_press und optional get_key_rpt 
nehmen.

von Peter D. (peda)


Lesenswert?

W.S. schrieb:
> Du machst es vom Grundsatz her falsch, da du die Tastenerkennung und die
> Auswertung zusammenziehen willst.

Das ist quatsch.
Die Erkennung macht der Interrupt und die Auswertung erfolgt davon 
unabhängig in der Mainfunktion.
Das Main muß also nicht nutzlos Zeit verwarten, sondern fragt nur das 
Ereignisflag ab.
Und ein Tastendruck geht nicht verloren, auch wenn das Main mal länger 
braucht als man drückt.

Ich hab mir schon was dabei gedacht, die Entprellung+Flankenerkennung 
und die Auswertung voneinander zu trennen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.