mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Entprellen nach Peter Dannegger.


Autor: Marc Brexner (drakenfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Liebe Community!

Ich habe eine Frage zur Entprellungs-"Komfort-Routine" von Peter 
Dannegger, siehe hier: 
http://www.mikrocontroller.net/articles/Entprellun...

Ich weiß, es wurde schon oft durchgekaut, jedoch konnte dass alles meine 
Fragen nicht klären. Das Hauptproblem ist, dass ich derzeit keine 
Möglichkeiten habe, auch nur irgendwas auf einem AVR zu testen.
Trotz allem muss ich mehr oder weniger bis Sonntag ein Projekt 
fertigstellen, in dem ich eine Entprellung brauche. An und für sich ist 
die Routine ja auch sehr komfortabel, und ich habe mich sehr gerne dafür 
entschieden.

Jedoch bin ich mir bis heute im Unklaren, was die einzelnen Abfragen 
GANZ GENAU machen, und welche sich stören.

Es gibt ja die 4 Abfragen:
get_key_press
get_key_short
get_key_long
get_key_rpt

Nun, kann ich denn auf einfache Weise, so wie hier
if (get_key_short(1<<KEY0)) {
    // Tue Aktion A
}
else if (get_key_short(1<<KEY0)) {
    // Tue Aktion B
}

zwischen langem Tastendruck und kurzem unterscheiden? Immerhin wartet 
die Routine ja auf das loslassen der Taste, bis ein short-press oder 
long-press erkannt wird. Bekomme ich da Probleme mit dem if/else 
if-Statement?

Und aus dem Source-Code:
// check if a key has been pressed. Each pressed key is reported
// only once

Heißt das, wenn er einmal abgefragt ist, wird er nie wieder als gedrückt 
erkannt, oder wie? Oder nur, bis der ISR-Ablauf wieder durchgerannt ist?


Bitte helft mit ein bißchen, ich komme im Moment kein Stück weiter... :(

Vielen Dank im Vorraus!
Lg Marc

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc Brexner schrieb:

> zwischen langem Tastendruck und kurzem unterscheiden? Immerhin wartet
> die Routine ja auf das loslassen der Taste, bis ein short-press oder
> long-press erkannt wird.

keine einzige der get_... Funktionen wartet auf irgendwas.

> Bekomme ich da Probleme mit dem if/else
> if-Statement?

Nein

> Und aus dem Source-Code:
> // check if a key has been pressed. Each pressed key is reported
> // only once
>
> Heißt das, wenn er einmal abgefragt ist, wird er nie wieder als gedrückt
> erkannt, oder wie?

Es heist genau das was dort steht.
Du drückst auf die Taste und get_key_press liefert für diese Taste 
einmal TRUE. Du drückst erneut auf die Taste und get_key_press liefert 
wieder nur 1mal TRUE

> Bitte helft mit ein bißchen, ich komme im Moment kein Stück weiter... :(

Du machst dir zu viele Sorgen.
Alle get_.... Funktionen liefern dir die Info ob eine Taste 
nieder-gedrückt wurde. So wie auf deinem Keyboard auch. Du drückst die 
Taste 'A' und 1 'a' erscheint in deinem Text. 1 Tastendruck - 1 Aktion.

Im Falle von get_key_short vs. get_key_long klarerweise erst dann, wenn 
die Taste wieder losgelassen wird.

Autor: Marc Brexner (drakenfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nunja, aber sobald einmal get_key_press abgefragt wurde, liefert mir 
get_key_short doch nur noch false?

Ich meine, kann so ein Gebilde denn noch funktionieren?
if (get_key_press(1<<KEY0) || get_key_press(1<<KEY0)) { // Ist mind. ein Taster gedrückt (nicht key_short, sondern key_press! siehe debounce.h)
        if (~clockStatus & (1<<CK3)) { // Wird die Uhr gerade nicht verstellt
          if (get_key_short(1<<KEY0) || get_key_short(1<<KEY1)) {
            if (~clockStatus & (1<<CK0)) { // Ist die Anzeige aus, die ...
              clockStatus |= (1<<CK0); // ... Anzeige eingeschalten
            }
            else { // Ist die Anzeige aus, die ...
              clockStatus &= ~(1<<CK0); // ... Anzeige ausschalten
            }
          }
          if (get_key_long(1<<KEY0)) { // Ist die Taste zum verstellen lange genug gedrückt...
            clockStatus |= (1<<CK3); // ... Modus zum verstellen der Uhr betreten
          }
        }
        else
        {
          if (get_key_short(1<<KEY0)) // Ist Taster 0 gedrückt, wechselt man von H auf M, von M auf S, und von S auf fertig.
          {
            if (clockStatus & (1<<CK4)) {
              clockStatus &= ~(1<<CK4);  // Stunde aus
              clockStatus |= (1<<CK4);  // Minute an
            }
            else if (clockStatus & (1<<CK5)) {
              clockStatus &= ~(1<<CK5);  // Minute aus
              clockStatus |= (1<<CK6);  // Sekunde an
            }
            else if (clockStatus & (1<<CK6))
            {
              clockStatus &= ~(1<<CK6);  // Sekunde aus
              clockStatus &= ~(1<<CK3);  // Bearbeitung beendet
              seconds = displayHours * 3600 + displayMinutes * 60 + displaySeconds;    // Neue Uhrzeit übernehmen
            }
          }
          else if(get_key_short(1<<KEY1) || get_key_press(1<<KEY1) || get_key_rpt(1<<KEY1)) { // Wird Taster 1 gedrückt (oder repeat)
            if (clockStatus & CK4) {
              displayHours++; // Um eine Stunde erhöhen
              if (displayHours == 24) { // Nur bis 23:59:59! -> Maximal 23h
                displayHours = 0;
              }
            }
            else if (clockStatus & CK5) {
              displayMinutes++;  // Um eine Minute erhöhen
              if (displayMinutes == 60) {
                displayMinutes = 0; // Nur bis 23:59:59! -> Maximal 59min
              }
            }
            else if (clockStatus & CK6) {
              displaySeconds++;  // Um eine Sekunde erhöhen (1s)
              if (displaySeconds == 60) {
                displaySeconds = 0; // Nur bis 23:59:59! -> Maximal 59s;
              }
            }
          }
        }
      }

Ich kann es mir nur schwer vorstellen...?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du sollst auch nicht get_key_press mit get_key_short an einem Portpin 
mischen.

get_key_short und get_key_long gehören zusammen.

und

get_key_press und get_key_rpt gehören zusammen.

Also schön brav immer innerhalb einer der beiden 'Familien' bleiben.

In der ISR wird in ein paar Variablen vermerkt, dass eine Taste gedrückt 
wurde. Sobald du die entsprechende Abfrage auf diese Taste machst, wird 
dieser Vermerk für diese Taste gelöscht. D.h. Nach einem get_key_press 
wird dir ein unmittelbar nachfolgender get_key_short immer ein FALSE 
liefern. So schnell kannst du eine Taste gar nicht drückn, dass du das 
in der Zeit dazwischen schaffst.

Autor: Marc Brexner (drakenfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber wie kann ich denn dann meine Steuerung realisieren? Ich wollte 
Taster sparen, indem ich zwischen langen und kurzen Tastendrücken 
unterscheide. Auszug aus dem Handbuch meiner Uhr:

Bedienung:
Taster 0 -> Oberer Taster
Taster 1 -> Unterer Taster
Uhr inaktiv (keine LEDs an):
Taster 0 oder Taster 1 einmal kurz drücken -> Uhr wird eingeschalten
Uhr aktiv (LEDs an):
Taster 0 einmal lange drücken -> Uhr geht in Modus zum Einstellen
Taster 0 oder Taster 1 einmal kurz drücken -> Uhr wird ausgeschalten
Einstellungsmodus (LEDs blinken):
Stunden-anzeige blinkt: Die Stundenanzahl kann nun durch Drücken von 
Taster 1 nun verstellt werden. Wird Taster 1 lange gedrückt, geht er in 
den sogenannten „Repeat-Modus“, und signalisiert alle 200 Millisekunden 
einen Tastendruck für Sie. Durch Drücken von Taster 0 wird die Eingabe 
der Stundenanzahl gespeichert, und Sie können die Minuten einstellen. 
(Die Minuten-Anzeige beginnt zu blinken)
Minuten-Anzeige blinkt: Die Minutenanzahl kann nun durch Drücken von 
Taster 1 nun verstellt werden. Wird Taster 1 lange gedrückt, geht er in 
den sogenannten „Repeat-Modus“, und signalisiert alle 200 Millisekunden 
einen Tastendruck für Sie. Durch Drücken von Taster 0 wird die Eingabe 
der Minutenanzahl gespeichert, und Sie können die Sekunden einstellen. 
(Die Sekunden-Anzeige beginnt zu blinken)
Sekunden-Anzeige blinkt: Die Sekundennzahl kann nun durch Drücken von 
Taster 1 nun verstellt werden. Wird Taster 1 lange gedrückt, geht er in 
den sogenannten „Repeat-Modus“, und signalisiert alle 200 Millisekunden 
einen Tastendruck für Sie. Durch Drücken von Taster 0 wird die Eingabe 
der Sekunden-Anzahl gespeichert, und die von Ihnen eingestellte Uhrzeit 
übernommen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich meine, kann so ein Gebilde denn noch funktionieren?

Nein. So wird das nichts.
Du gehst davon aus, dass die die get_.... Funktionen solange TRUE 
liefern, solange eine Taste gedrückt ist. Genau das tun sie aber nicht 
und genau das ist auch der Witz an der ganzen Sache.

Autor: Marc Brexner (drakenfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm, okay. Jetzt verstehe ich, wie das funktioniert. Nun muss ich nur 
noch überlegen, was ich mache, um je nach aktuellem Modus auf die 
Abfragen zu reagieren...

Irgendwie macht dass das ganze jetzt um einiges schwerer... =/

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marc Brexner schrieb:

> Taster 0 oder Taster 1 einmal kurz drücken -> Uhr wird eingeschalten
> Uhr aktiv (LEDs an):

  if Anzeige == aus )
  {
    if key pressed 0  or key pressed 1
      Anzeige ein
  }

  else
  {
    if key short 0   or  key short 1
      Anzeige aus

    else if key long 0
    {
      // Einstellungsmodus
      while ! key pressed 0
      {
         if  key pressed 1   or  key repeat 1
           Stunden++
      }

      while ! key pressed 0
      {
         if  key pressed 1   or  key repeat 1
           Minuten++
      }

      while ! key pressed 0
      {
         if  key pressed 1   or  key repeat 1
           Sekunden++
      }
    }
  }


> Irgendwie macht dass das ganze jetzt um einiges schwerer... =/
find ich nicht :-)
Ganz im Gegenteil

Autor: Marc Brexner (drakenfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (clockStatus & (1<<CK1)) // Tasterabfrage aktiv, mal sehen was nun zu tun ist
{
if (~TIMSK1 & (1<<OCIE1A)) { // Timer für Tastenabfrage ist inkativ, also ...
  TIMSK1 |= (1<<OCIE1A); // ... aktivieren
}
if (~clockStatus & (1<<CK0)) { // Uhr ist aus
  if (get_key_short(1<<KEY0) || get_key_short(1<<KEY1)) { // Bei kurzem Tastendruck
    clockStatus |= (1<<CK0); // Anzeige einschalten
  }
}
else {
  if (~clockStatus & (1<<CK3)) { // Wenn die Uhrzeit nicht bearbeitet wird
    if (get_key_short(1<<KEY0) || get_key_short(1<<KEY1)) { // Bei kurzem Tastendruck
    // TODO: ALLES AUS damit AVR wieder Energie sparen kann! Diese Anweisung schaltet nur die Anzeige aus!
      clockStatus &= ~(1<<CK0);
    }
    else if (get_key_long(1<<KEY0)) { // Bei langem Tastendruck von Taster 0
      clockStatus |= (1<<CK3); // Einstellungsmodus betreten
    }
  }
  else {
    if (get_key_short(1<<KEY0)) { // Taster 0 wird gedrückt -> Modus umschalten!
      if (clockStatus & (1<<CK4)) {
        clockStatus &= ~(1<<CK4);  // Stunde aus
        clockStatus |= (1<<CK4);  // Minute an
      }
      else if (clockStatus & (1<<CK5)) {
        clockStatus &= ~(1<<CK5);  // Minute aus
        clockStatus |= (1<<CK6);  // Sekunde an
      }
      else if (clockStatus & (1<<CK6)) {
        clockStatus &= ~(1<<CK6);  // Sekunde aus
        clockStatus &= ~(1<<CK3);  // Bearbeitung beendet
        seconds = displayHours * 3600 + displayMinutes * 60 + displaySeconds;    // Neue Uhrzeit übernehmen
      }
    }
    if (get_key_press(1<<KEY1) || get_key_rpt(1<<KEY1)) { // Wird Taster 1 gedrückt oder gehalten aktuelle ausgewähltes "Element" der Uhr hochzählen.
      if (clockStatus & CK4) {
        displayHours++; // Um eine Stunde erhöhen
        if (displayHours == 24) { // Nur bis 23:59:59! -> Maximal 23h
          displayHours = 0;
        }
      }
      else if (clockStatus & CK5) {
        displayMinutes++;  // Um eine Minute erhöhen
        if (displayMinutes == 60) {
          displayMinutes = 0; // Nur bis 23:59:59! -> Maximal 59min
        }
      }
      else if (clockStatus & CK6) {
        displaySeconds++;  // Um eine Sekunde erhöhen (1s)
        if (displaySeconds == 60) {
          displaySeconds = 0; // Nur bis 23:59:59! -> Maximal 59s;
        }
      }
    }
  }
}


Dann hat dieses Gebilde in deinen Augen schon etwas mehr 
durchsetzungskraft, oder? Danke für deinen "Prototypen"! :D

Lg Marc

Autor: Marc Brexner (drakenfly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da ich seit gestern wieder zu Hause bin, habe ich mich gleich 
hingesetzt, und auf meinem Testboard was zusammengesteckt. Dieses von 
mir zuletzt gepostetes "Gebilde" funktioniert - Danke, für eure Hilfe!

Und ein großes Lob an Peters Entprellungs-Code, der funktioniert 
wirklich TOP

Lg Marc

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.