Dannegger-Entprellung anpassen

Gast #1751068
Lesenswert?

Hallo zusammen,

ich habe gerade die Dannegger-Super-Entprellung auf meinem uC 
implementiert.
Funktioniert auch gut!

Es ist hier ja so, dass wenn man die Taste drückt, der Tastendruck erst 
registriert wird, wenn man wieder losgelassen hat.

Gibt es eine Möglichkeit, es irgendwie so anzupassen, dass das Programm 
auf den Tastendruck sofort reagiert. Um z.b. bei einem Menü sofort bei 
Tastendruck das nächste Item anzuzeigen, obwohl die Taste noch gedrückt 
ist und trotzdem erst zwischendruch ein loslassen registriert werden 
muss, bevor der nächste Tastendruck erfolgen kann?

Ich persönlich steige durch die Dannegger-Entprellung sowieso nicht 
durch, hab sie genommen, weil sie hier so beliebt ist.
#1751093
Lesenswert?

Vladislav schrieb:
> OK, noch ein Nachtrag: mit get_key_press läufts, wie ich es meine.
> Wofür ist dann get_key_short?

Wenn du zwischen langem und kurzem Tastendruck unterscheiden willst. Wie 
lange eine Taste gedrückt wurde, kannst du logischerweise erst dann 
feststellen, wenn sie wieder losgelassen wurde oder die Zeit für 'langer 
Tastendruck' erreicht ist.
Gast #1751101
Lesenswert?

Sorry Karl-Heinz, das versteh ich grad nicht. Für welche Funktion 
würdest du get_key_short nehmen.

Den get_key_press für Menü rauf und runter und so

Den get_key_long um z.b. beim hochzählen von größeren Werten den Lauf zu 
beschleunigen.

Aber den get_key_short? Hab ich die Funktion grad nicht verstanden.
#1751106
Lesenswert?

Vladislav schrieb:
> Sorry Karl-Heinz, das versteh ich grad nicht. Für welche Funktion
> würdest du get_key_short nehmen.

Ich erfinde jetzt etwas

  einzelner kurzer Tastendruck: ein Zahlenwert erhöht sich um 1
  einzelner langer Tastendruck: selbiger Wert erhöht sich um 100


get_key_press und get_key_long passen nicht zusammen.

Entweder du verwendest  get_key_press
oder du verwendest das Duo  get_key_short / get_key_long

get_key_press ist es egal, wie lange gedrückt wird
nur bei short/long wirkt sich das aus.
Moderator Persönliche Seite #1751150
Lesenswert?

Karl heinz Buchegger schrieb:

>   einzelner kurzer Tastendruck: ein Zahlenwert erhöht sich um 1
>   einzelner langer Tastendruck: selbiger Wert erhöht sich um 100

Ist aber nun gerade ein Fall, bei dem es funktionieren würde. ;-)
Mit dem ersten Tastendruck (Drücken genügt) erhöht man den Wert
um 1.  Nach 500 ms ist die Taste immer noch gedrückt, und man
erhöht erstmal um 99, danach weiter um jeweils 100, wenn sie weiter
gedrückt bleibt.
#1751161
Lesenswert?

Vladislav schrieb:

> Press und long sind 1A, nur short leuchtet mit nicht ein.
> Bei long geht meine LED jetzt an, wenn ich die Taste lange gedrückt
> halte, aber bei short geht sie erst an, wenn ich die Taste dann wieder
> losgelassen hab.

Ja logisch.
Wie soll denn das Programm feststellen ob du mit dem Niederdrücken einer 
Taste jetzt kurz oder lang drücken willst?


In a Nutshell: Wenn du keinen Sinn darin siehst, dann verwends einfach 
nicht :-)

Ich könnte mir auch dieses Szenario vorstellen:
Benutzer hat die Möglichkeit eine Taste zu drücken. DIe Funktionalität 
springt erst dann an, wenn er die Taste loslässt. Bleibt er länger auf 
der Taste, so kann er dadurch die Anforderung 'löschen' und die 
Funktionalität wird nicht ausgeführt.
Gast #1751176
Lesenswert?

Karl heinz Buchegger schrieb:
> In a Nutshell: Wenn du keinen Sinn darin siehst, dann verwends einfach
> nicht :-)

Nein, um Gotteswillen, ich bin grad begeistert und probier ein bisschen 
damit rum.

Wenn ich jetzt aber z.b. eine LED mit REPEAT toggle und eine andere mit 
LONG und REPEAT dabei die ganze zeit gedrückt halte, dann wird aus dem 
LONG ein PRESS ?
Gast #1751247
Lesenswert?

1
if( get_key_short( 1<<KEY1 ))
2
      LED_PORT ^= 1<<LED1;
3
 
4
    if( get_key_long( 1<<KEY1 ))
5
      LED_PORT ^= 1<<LED2;
6
 
7
                                                  // single press and repeat
8
 
9
    if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){
10
      uint8_t i = LED_PORT;
11
 
12
      i = (i & 0x07) | ((i << 1) & 0xF0);
13
      if( i < 0xF0 )
14
        i |= 0x08;
15
      LED_PORT = i;      
16
    }

Du benutzt doch hier auch long alleine.

Ich komm da immernoch nicht so ganz hinter, tut mir leid.
Kannst du mir die einzelnen Funktion vielleicht nochmal eben 
beschreiben, wieso welche nur zusammen mit anderen gehen?

Ich probiere gerade z.b. mittels zweier gleichzeitig gedrückter Tasten 
einen Punkt zurückzuspringen. Aber das will nicht so.

Ich hatte:
1
else if (get_button_press (BUTTON_1 | BUTTON_2))
2
{
3
  item = 0;
4
}
aber das geht nicht, dann springt er auch bei einer zurück und wenn ich:
1
else if (get_button_press (BUTTON_1 | BUTTON_2) == (BUTTON_1 | BUTTON_2))
2
{
3
  item = 0;
4
}
geht das auch nur sporadisch, aber nicht wirklich...


Danke!
Gast #1751250
Lesenswert?

Danke Peter für deine Routine, ihre ausführliche Dokumentation und deine 
Erläuterung der Funktionen an dieser Stelle nochmal.

Hey Vladislav, diese Zeilen oben müssen aus deinem Post verschwunden 
sein...
Gast #1752024
Lesenswert?

Ich verstehe das mit den Kombinationen nicht und darüber hinaus probiere 
ich die ganze Zeit herum, um mit Taste 1 und 2 aus dem Menü einen Punkt 
zurück zu springen. Aber ich bekomme es nicht hin.

Habe mir den Thread zum Entprellen schon durchgelesen...mir ist das auch 
klar, dass der uC nicht wissen kann, ob gleich noch eine zweite taste 
kommt... es klappt halt nur, wenn ich sie wirklich gleichzeitig drücke.

Gibt es dafür keine Lösung?
#1752030
Lesenswert?

Vladislav schrieb:
> Ich verstehe das mit den Kombinationen nicht

Dann vergiss fürs erste die Kombinationen. Man braucht sie nur in 
Sinderfällen.

> und darüber hinaus probiere
> ich die ganze Zeit herum, um mit Taste 1 und 2 aus dem Menü einen Punkt
> zurück zu springen. Aber ich bekomme es nicht hin.

Dann zeig dein Programm

> kommt... es klappt halt nur, wenn ich sie wirklich gleichzeitig drücke.

Eine Menüfuhrung, die darauf beruht, dass der Benutzer 2 Tasten 
gleichzeitig drücken muss, ist meistens sowieso schlecht. Sowas erfreut 
immer wieder die Grobmotoriker.
Spendier deinem Benutzer genügend Tasten oder bau ihm einen Menüpunkt 
'Zurück' ein, dann brauchst du nur 3 Tasten.
Gast #1752038
Lesenswert?

Danke für deine Antwort! Hier mal ein kurzer Auszug vom Menü:
1
case 11:                       // Menuepunkt 1.1
2
{
3
  if (disp_done == FALSE)      // Gibt einmal neuen Inhalt auf Display aus
4
  {
5
    lcd_clear_display ();      // Loesche Display
6
    lcd_jump_to (2,1);         // Untere Zeile, 1. Stelle
7
    lcd_send_string ("MENUE"); // Sende String "Menue"
8
    lcd_jump_to (1,3);         // Obere Zeile, 3. Stelle
9
    lcd_send_num (1, TRUE);    // Sende 1 mit Dezimalpunkt
10
    lcd_send_num (1, FALSE);   // Sende 1 ohne Dezimalpunkt
11
          
12
    disp_done = TRUE;          // Display-Inhalt fertig
13
  }
14
        
15
  if (get_button_press (BUTTON_3)) // Wenn Taste 'OK' gedrueckt
16
  {
17
    disp_done = 0;             // Beim naechsten mal Display beschreiben
18
    item = 12;                 // Menuepunkt auf 1.2 (weiter)
19
  }
20
  else if (get_button_press (BUTTON_1 | BUTTON_2)) // <- PROBLEM HIER!
21
  {
22
    item = 10;                 // Menuepunkt auf 1.0 (zurueck)
23
    disp_done = 0;             // Beim naechsten mal Display beschreiben
24
  }
25
        
26
  break;
27
}

So sieht ein Menüpunkt aus.
Ich habe leider nur drei Tasten, da komm ich nicht drum herum. Daher ist 
meine Tastensteuerung etwas eingeschränkt...

Ich würde daher gerne mit BUTTON_1 und BUTTON_2 gleichzeitig einen Punkt 
zurückspringen, aber nunja, die Problematik ist mir bekannt...der uC 
kann nicht wissen, was kommt.

Es geht halt, wenn ich wirklich gleichzeitig:
1
else if ((get_button_press (BUTTON_1 | BUTTON_2) == (BUTTON_1 | BUTTON_2))
schreibe, aber wirklich gleichzeitig!
#1752054
Lesenswert?

Vladislav schrieb:
> die Problematik ist mir bekannt...der uC
> kann nicht wissen, was kommt.

Dann ist Dein Versuch in etwa so erfolgreich, wie einen Gegenstand nach 
oben fallen lassen zu wollen.

Du mußt Dir erstmal einen Plan machen, welche Betätigungsmöglichkeiten 
Du hast und wie Du sie verwendest.
Einfach drauflos programmieren und merken, da fehlt ne Taste, ist der 
falsche Weg!

Du hast mit 3 Tasten z.B. folgende Möglichkeiten, die von einem MC ohne 
Hellsehen eindeutig erkannt werden können:
1
                            Anzahl Funktionen
2
3 Tasten:                   3
3
Shift + 2 Tasten:           4
4
3 Tasten kurz/lang:         6
5
Shift + 2 Tasten kurz/lang: 8


Peter
Gast #1752075
Lesenswert?

Aber das Problem geht ja weiter:
1
              MENUE_2.1 <-> MENUE_2.2 <-> MENUE_2.3
2
                |
3
MENUE_1.0 <-> MENUE_2.0 <-> MENUE_3.0
4
  /\           ||            ||
5
  ||           ||            ||
6
  \/           \/            \/
7
--------------------------------------
8
|         NORMALES PROGRAMM          |
9
--------------------------------------

Ich kann also vom normalen Programm in den Menüpunkt 1.0 springen und 
von der untersten Ebene überall wieder ins Programm - vorzugsweise mit 
LINKS+RECHTS

Mal angenommen ich bin im Punkt 2.0, dann kann ich mit mit LINKS 
(get_button_press (BUTTON_LINKS) ins Menü 1.0 und mit RECHTS 
(get_button_press (BUTTON_RECHTS) in 3.0

Will ich aber jetzt zurück zum Programm mit gleichzeitigen Druck von 
LINKS+RECHTS, dann nimmt der uC natürlich den normalen Befehl für RECHTS 
oder LINKS...oh man, 3 Tasten sind echt scheisse, aber ich kann das 
nicht ändern.

Was kann ich hier tun? Ich bin echt ratlos!
#1752116
Lesenswert?

Ich glaube , ich würde die Variante "3 Tasten kurz/lang" wählen.

Tastenbeschriftung:  Rechts, Links und Enter.

Programm  -> Menue1.0  : Enter (lang)
Menue X.0 -> Programm  : Enter (lang)
Menue X.0 -> Menue x.0 : Rechts / Links
Menue 2.0 -> Menue 2.1 : Enter
Menue 2.x -> Menue 2.0 : Enter (lang)

usw.
#1752132
Lesenswert?

Vladislav schrieb:

> Will ich aber jetzt zurück zum Programm mit gleichzeitigen Druck

Nochmal:

gleichzeitiges Drücken vom Benutzer zu verlangen ist praktisch IMMER 
Mist!

Denn das kriegt kein Mensch hin.
Irgendeine der beiden Tasten kommt immer früher! Da kannst du als 
Programmierer nichts dagegen tun.

> von
> LINKS+RECHTS, dann nimmt der uC natürlich den normalen Befehl für RECHTS
> oder LINKS...oh man, 3 Tasten sind echt scheisse, aber ich kann das
> nicht ändern.

Dann musst du das Menüsystem so umbauen, dass du nicht darauf angewiesen 
bist, dass 2 Tasten gleichzeitig gedrückt werden müssen!

> Was kann ich hier tun? Ich bin echt ratlos!

Im einfachsten Fall verzichtest du darauf, dass der Benutzer mit 
irgendeiner Sonderkombination wieder in den normalen Programmlauf kommt 
sondern zwingst ihn, dass er sauber über das Hauptmenü aussteigt.

Eine Variante davon zwingt den Benutzer gar nicht, dass er das selber 
macht, sondern das Programm bricht nach x Sekunden ohne Benutzereingabe 
das Menüsystem ab und geht selbsttätig zurück.

Du kannst ihm auch im Menü einen Menüpunkt 'Exit' anbieten, den er 
anwählen muss um direkt aus einem Submenü wieder in den normalen 
Programmlauf auszusteigen.

Du kannst die Taste für 'Auswahl' mit einer Sonderfunktion für 'langen 
Tastendruck' versehen und wenn das passiert erfolgt der Ausstieg und 
lebst damit, dass zunächst eine Funktion mehr oder weniger ausgewählt 
wird, die dann durch den langen Tastendruck abgebrochen wird.


Aber eines solltest du auf keinen Fall tun: Ohne Planung und Überlegung 
wie das Konzept deiner Benutzersteuerung funktionieren soll dich 
hinsetzen und drauflos programmieren. Denn das geht mit Sicherheit 
schief.


> oh man, 3 Tasten sind echt scheisse

3 Tasten reichen völlig aus, siehe die ganzen Menüsysteme die auf einem 
einzigen Drehencoder mit Tastfunktion basieren. Nur muss man sich im 
Vorfeld überlegen, wie die Menüsteuerung funktionieren soll.
Moderator Persönliche Seite #1752185
Lesenswert?

Karl heinz Buchegger schrieb:
> gleichzeitiges Drücken vom Benutzer zu verlangen ist praktisch IMMER
> Mist!

Naja.  Ist eine Frage der Definition von "gleichzeitig".  Ich habe
lange Zeit die Emulation der mittleren Maustaste (die bei X11-
Programmen ja seit Jahr und Tag üblich war) durch gleichzeitiges
Drücken beider Tasten einer 2-Tasten-Maus benutzt, das geht schon.
Man muss halt eine Karenzzeit einplanen, innerhalb derer beim Drücken
der ersten Taste der Zustand von "nicht gedrückt" nach "unentschlossen"
wandert, und erst nach dem Timeout wechselt er in "eine Taste gedrückt"
oder "zwei Tasten gedrückt".  Für die besagte Maustastenemulation
waren glaub' ich 50 ms Karenzzeit ein sinnvoller Wert, wenn die
mechanische Konstruktion der Tasten schlechter ist als bei einer Maus,
würde ich auf 100 ms gehen.  In dieser Zeit schafft es ein Normal-
sterblicher durchaus, beide Knöpfe gedrückt zu halten.
Gast #1752194
Lesenswert?

Volker Zabe schrieb:
> Ich glaube , ich würde die Variante "3 Tasten kurz/lang" wählen.

Ich habe jetzt auch erstmal die Kombination kurz/lang.

Jetzt ist es so: LINKS+RECHTS lang gedrückt, Menü zurück, geht auch, 
solange ich nicht NACH LINKS und NACH RECHTS mit get_key_PRESS sondern 
mit SHORT mache, was natürlich zur Folge hat, dass der nächste Punkt 
erst kommt, wenn man die entsprechende Taste wieder los lässt, 
währenddessen die lang gedrückten aufs Drücken reagieren und nicht aufs 
loslassen.

GRRR...
#1752205
Lesenswert?

Vladislav schrieb:
> Volker Zabe schrieb:
>> Ich glaube , ich würde die Variante "3 Tasten kurz/lang" wählen.
>
> Ich habe jetzt auch erstmal die Kombination kurz/lang.
>
> Jetzt ist es so: LINKS+RECHTS lang gedrückt, Menü zurück, geht auch,
> solange ich nicht NACH LINKS und NACH RECHTS mit get_key_PRESS sondern
> mit SHORT mache, was natürlich zur Folge hat, dass der nächste Punkt
> erst kommt, wenn man die entsprechende Taste wieder los lässt,
> währenddessen die lang gedrückten aufs Drücken reagieren und nicht aufs
> loslassen.
>
> GRRR...


Du versuchst krampfhaft eine 'Do what I mean' Steuerung zu bauen.
Das funktioniert nicht.

Entweder du löst deine Aktionen aus, wenn die Taste niedergedrückt wird.
 In dem Fall musst du damit rechnen, dass der Benutzer genau das
 eigentlich gar nicht wollte. Da dein Programm aber nicht hellsehen
 kann wie lange der Benutzer die Taste noch gedrückt halten wird,
 läufst du in das Problem, dass du eine Aktion die eigentlich schon
 stattgefunden hat, bei anhaltend langem Tastendruck wieder rück-
 gängig machen musst, bzw. das ganze Menüsystem so aufzubauen, dass
 dieser vom Benutzer eigentlich nicht gewollte Tastendruck keinen
 'Schaden' anrichtet.

Oder du löst die Aktion erst beim Loslassen (oder überschreiten einer 
Zeitbegrenzung) aus.
  Dann hast du natürlich das Problem, das es für den Benutzer so
  aussieht: Er drückt eine Taste und zunächst mal passiert nichts,
  weil die Aktion ja erst beim Loslassen angestossen werden kann, weil
  ja beim Niederdrücken noch nicht feststeht, ob das ein kurzer oder
  ein langer Tastendruck werden wird.


Die eierlegende Wollmilchsau, die auch noch zukünftige Aktionen des 
Benutzers erraten kann, existiert nun mal nicht.
#1752219
Lesenswert?

Jörg Wunsch schrieb:

> Man muss halt eine Karenzzeit einplanen, innerhalb derer beim Drücken
> der ersten Taste der Zustand von "nicht gedrückt" nach "unentschlossen"
> wandert, und erst nach dem Timeout wechselt er in "eine Taste gedrückt"
> oder "zwei Tasten gedrückt".  Für die besagte Maustastenemulation
> waren glaub' ich 50 ms Karenzzeit ein sinnvoller Wert, wenn die
> mechanische Konstruktion der Tasten schlechter ist als bei einer Maus,
> würde ich auf 100 ms gehen.  In dieser Zeit schafft es ein Normal-
> sterblicher durchaus, beide Knöpfe gedrückt zu halten.

Schon klar. So oder so ähnlich haben wir das wohl damals alle gemacht, 
als die ersten 3-Tasten Mäuse aufgekommen sind.

Aber mit dem, was in der PeDa Entprellung vorhanden ist, ist das ohne 
zuätzlichen Programmieraufwand nicht möglich. Die ist nicht darauf 
ausgelegt, dass mehrer Tastendrücke 'gleichzeitig' einen weiteren 
virtuellen Tastendruck ergeben.
#1752715
Lesenswert?

Karl heinz Buchegger schrieb:
> Aber mit dem, was in der PeDa Entprellung vorhanden ist, ist das ohne
> zuätzlichen Programmieraufwand nicht möglich.

Naja, es geht schon. Ist aber wirklich keine schöne Bedienung.
1
  for(;;){                                              // main loop
2
    switch( get_key_long(  1<<KEY0 | 1<<KEY1 ) |
3
            get_key_short( 1<<KEY0 | 1<<KEY1 )){
4

5
      case 1<<KEY0:             LED_PORT ^= 1<<LED0; break;
6

7
      case 1<<KEY1:             LED_PORT ^= 1<<LED1; break;
8

9
      default:
10
                if((key_press & (1<<KEY0 | 1<<KEY1)) != (1<<KEY0 | 1<<KEY1))
11
                  break;
12
                get_key_press( 1<<KEY0 | 1<<KEY1 );
13

14
      case 1<<KEY0 | 1<<KEY1:   LED_PORT ^= 1<<LED2; break;
15
    }
16
  }

Die Einzeltasten können natürlich erst nach Loslassen oder nach der 
Langdruckzeit erkannt werden.
Oder man muß eben die
1
#include <mentalist.h>
einbinden.


Peter
Gast #1754970
Lesenswert?

Peter Dannegger schrieb:
> Man kann auch auswählen, ob der Druck beider Tasten innerhalb einer
> bestimmte Zeit erfolgen soll (#define TIMEOUT)

Wo wird denn im Quelltext der Wert von TIMEOUT ausgewertet? Also wo wird
berücksichtigt, ob ich 10 oder 100 oder 1000 eingebe?

Ansonsten prima! Die Funktion fehlte noch - deine Tastenentprellung ist
wirklich der Hammer, PeDa! Danke sehr!
Gast #1755154
Lesenswert?

Hallo zusammen!

Ich habe die Entprellung grad bei mir ebenfalls mal mit eingebunden! 
Peter, großes LOB!!! Sehr gut!!!

Ne Frage habe ich noch. Ich werde die Entprellung hauptsächlich zur 
Menüsteuerung nutzen. Jetzt mache ich zum Beispiel während des Betriebs 
mit langem Tastendruck der einen Taste das Menü auf. Vorher wird auf 
keine Tasten reagiert.

Mir fällt dabei auf, dass wenn ich jetzt beispielsweise vorher bereits 
eine andere Taste mal gedrückt habe, sich der uC das ja merkt.

Es passiert während des Betriebes nichts, da die Taste nicht abgefragt 
wird.

Wenn ich aber jetzt ins Menü gehe und die Taste ab da eine Funktion hat, 
dann fragt er ja den Status ab und hat im Speicher noch, dass die Taset 
gedrückt worden war und führt das dann auch direkt aus.

Kann man das umgehen?

Danke schonmal,

Gerd

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren