Forum: Mikrocontroller und Digitale Elektronik Taster debouncen


von Franz M. (shadow010)


Lesenswert?

Hallo zusammen

Ich habe einen Mega8 im Betrieb an dem ich auf PD5 Led hängen habe. An 
PB0 ist ein Taster nach GND geschaltet. Nun habe ich folgendes 
programmiert:
1
#include <avr/io.h>
2
#include <inttypes.h>
3
#ifndef F_CPU
4
#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
5
#define F_CPU 8000000UL     /* Quarz mit 16000000 Mhz  */
6
#endif
7
#include <util/delay.h>     /* bei alter avr-libc: #include <avr/delay.h> */      
8
 
9
/* Einfache Funktion zum Entprellen eines Tasters */
10
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
11
{
12
    if ( !(*port & (1 << pin)) )
13
    {
14
        /* Pin wurde auf Masse gezogen, 100ms warten   */
15
        _delay_ms(50);   // Maximalwert des Parameters an _delay_ms 
16
        _delay_ms(50);   // beachten, vgl. Dokumentation der avr-libc
17
        if ( *port & (1 << pin) )
18
        {
19
            /* Anwender Zeit zum Loslassen des Tasters geben */
20
            _delay_ms(50);
21
            _delay_ms(50); 
22
            return 1;
23
        }
24
    }
25
    return 0;
26
}
27
 
28
int main(void)
29
{
30
    DDRB &= ~( 1 << PB0 );        /* PIN PB0 auf Eingang Taster)  */
31
    PORTB |= ( 1 << PB0 );        /* Pullup-Widerstand aktivieren */
32
    
33
    if (debounce(&PINB, PB0))
34
    {
35
        /* Falls Taster an PIN PB0 gedrueckt     */
36
        /* LED an Port PD5 an- bzw. ausschalten: */
37
        PORTD = PORTD ^ ( 1 << PD5 );
38
    }
39
    
40
}

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Suche mal nach "Taster entprellen".

von Karl H. (kbuchegg)


Lesenswert?

Franz Maier schrieb:

Abgesehen davon, dass das Thema 'entprellen' alle gefühlte 6 Stunden 
erneut aufs Tapet kommt, und du dir aus dem Artikel 'Entprellung' die 
schlechteste Möglichkeit rausgesucht hast:

* wie lautet deine Frage?
* Dir ist klar, dass du den LED-Ausgang nicht auf Ausgang geschaltet 
hast?

von Franz M. (shadow010)


Lesenswert?

Danke für die Antwort

Das hab ich von diesem Forum unter 
:http://www.mikrocontroller.net/articles/Entprellung
im Abschnitt Warteschleifen-Verfahren gefunden. Was ist falsch daran?

von Karl H. (kbuchegg)


Lesenswert?

Franz Maier schrieb:
> Danke für die Antwort
>
> Das hab ich von diesem Forum unter
> :http://www.mikrocontroller.net/articles/Entprellung
> im Abschnitt Warteschleifen-Verfahren gefunden. Was ist falsch daran?

Steht doch im Artikel
1
Die obige Routine hat leider mehrere Nachteile:
2
3
* sie detektiert nur das Loslassen (unergonomisch)
4
* sie verzögert die Mainloop immer um 100ms bei gedrückter Taste
5
* sie verliert Tastendrücke, je mehr die Mainloop zu tun hat.

Und ich möchte noch einen Punkt anfügen:
Bei mehr als 1 Taster veschlimmern sich alle Punkte. Aber nicht additiv 
sondern exponentiell.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Franz Maier schrieb:
> Was ist falsch daran?

Nicht falsch. Eher Verschwendung von Rechenzeit ;)

von Karl H. (kbuchegg)


Lesenswert?

Joachim Drechsel schrieb:
> Franz Maier schrieb:
>> Was ist falsch daran?
>
> Nicht falsch. Eher Verschwendung von Rechenzeit ;)

:-)
Ich würd ruhig das Attribut falsch vergeben.
Das Problem ist, dass das Loslassen des Tastendrucks in den ersten 100ms 
nach prüfen auf 'Taste low' erfolgen muss.
Bei dem simplen Testprogramm ist das kein Thema. Da steckt der µC die 
meiste Zeit in den delays drinnen. Die Wahrscheinlichkeit, dass der 
Taster genau in diesem Zeitfenster seinen Zustand wechselt ist daher 
hoch.
Sobald aber die Hauptschleife umfangreicher wird, wird die 
Wahrscheinlichkeit höher, dass das Loslassen eben nicht genau in diesem 
Zeitraum erfolgt. Und dann detektiert dieses Verfahren das Loslassen in 
diesem Fall nicht mehr.

Man kann es ganz leicht testen
1
int main(void)
2
{
3
    DDRB &= ~( 1 << PB0 );        /* PIN PB0 auf Eingang Taster)  */
4
    PORTB |= ( 1 << PB0 );        /* Pullup-Widerstand aktivieren */
5
    
6
   while( 1 ) { 
7
 
8
     if (debounce(&PINB, PB0))
9
     {
10
        /* Falls Taster an PIN PB0 gedrueckt     */
11
        /* LED an Port PD5 an- bzw. ausschalten: */
12
        PORTD = PORTD ^ ( 1 << PD5 );
13
     }
14
15
     _delay_ms( 1000 );
16
   }
17
}

wenn du da nach 10 Minuten nicht auszuckst, weil sich die LED bei 
Dauertests nicht zuverlässig umschalten lässt, dann musst du eine 
Engelsgeduld haben.
Da existiert also ein subtiler Zusammenhang zwischen dem _delay_ms( 1000 
); in der Hauptschleife und der Zuverlässigkeit der Tastenerkennung.

von Karl H. (kbuchegg)


Lesenswert?

@Franz

Mir fällt gerade auf:

Wo ist eigentlich deine Hauptschleife?

von Franz M. (shadow010)


Lesenswert?

Ja stimmt der teil hats mir nicht mit kopiert. Sorry
Ich habe das Programm nochmals neu aufgebaut aber die LED an D0 schaltet 
nur aus während dem Tastendruck. Wieso das? Was fehlt den noch?
1
#include  <avr\io.h>  
2
#include  <avr\interrupt.h>
3
#include  <stdlib.h>
4
#include  <inttypes.h>
5
6
//                       Initialisierung          
7
8
void initial(void)
9
{    
10
11
// **** Einrichten von Ein- und Ausgängen *************** 
12
DDRD = 0x0f;        // PortD0-3  Ausgänge PORTD4-7 Eingänge
13
PORTD |= _BV(7);  // Pull Up an PortD7 aktivieren
14
15
}
16
 
17
// Hauptprogramm
18
19
int main(void)
20
{
21
initial();  // Initialisierung Ports
22
  
23
while(1){
24
25
if ( PIND & (1<<7) )  PORTD |= _BV(0)  ; else PORTD &=~_BV(0); 
26
27
  }  // end of while(1){
28
}    // end of main

von Peter D. (peda)


Lesenswert?

Franz Maier schrieb:
> Nun habe ich folgendes
> programmiert:

Schade.
Das ist leider genau der Weg, wie man es auf keinen Fall machen sollte.
Nicht alles, was im I-Net steht, darf man ungeprüft glauben.


Peter

von Walter S. (avatar)


Lesenswert?

Franz Maier schrieb:
> An
> PB0 ist ein Taster nach GND geschaltet.

und wieso fragst du dann PIND7 ab?

von Franz M. (shadow010)


Lesenswert?

Peter Dannegger schrieb:
> Franz Maier schrieb:
>> Nun habe ich folgendes
>> programmiert:
>
> Schade.
> Das ist leider genau der Weg, wie man es auf keinen Fall machen sollte.
> Nicht alles, was im I-Net steht, darf man ungeprüft glauben.
>
>
> Peter

Hmhhh... ja schon aber irgend wie muss mans ja lehrnen leider sehe ich 
den Fehler nicht. Hilf mir doch und sage mir was daran falsch ist?

PB0 war die alte Version nun habe ich es neu gemacht.

von Peter D. (peda)


Lesenswert?

Franz Maier schrieb:
> Hilf mir doch und sage mir was daran falsch ist?

Wenn Du ein paar der eine Million Threads zum Entprellen liest, sollte 
sich eigentlich die perfekte Lösung heraus kristallisieren.


Peter

von Franz M. (shadow010)


Lesenswert?

Ich bin seit zwei Tagen am suchen hab X Mal diverses gelesen auch  das 
hier.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Taster_und_Schalter

Funktionieren tut es eben immer noch nicht.

so ich erkläre dir nochmals mein Problem dann kannst du mir ja helfen 
denn die Hot Tos sagen mir nicht wo mein fehler liegt!

Ich habe eine LED an PORTD.O mit einem 10kOhm Widerstand gegen GND und
einen Taster an PORTD.7 gegen GND
1
#include  <avr\io.h>  //AVR Register und Konstantendefinitionen
2
#include  <avr\interrupt.h> //AVR Interrupt Vektoren
3
#include  <stdlib.h>
4
#include  <inttypes.h>
5
6
void initial(void)
7
{    
8
9
DDRD = 0x0f;        // PortD0-3  Ausgänge PORTD4-7 Eingänge
10
PORTD |= _BV(7);           // Pull Up an PortD7 aktivieren
11
12
}
13
14
15
int main(void)
16
{
17
18
initial();  // Initialisierung Ports
19
   
20
while(1){
21
22
if ( PIND & (1<<7) )  PORTD |= _BV(0)  ; else PORTD &=~_BV(0);
23
24
  }
25
}

Kannst du mir jetzt sagen was ich um ändern muss damit die LED nich 
wieder angeht wenn man den Taster losläst? denn nach dem How To ist der 
Pull-UP an und das müsst so funktionieren.

von pom p. (pompete)


Lesenswert?

Taster "debouncen"....so große Worte und nichts dahinter?
was ist eigentlich "Taster debouncen"..Weder deutsch noch englisch, ich 
behaupte mal, es ist genauso oberflächlich wie Deine Recherchen und 
Wille etwas zu begreifen!
Einen Taster auszuwerten bzw. zu entprellen ist mit etwas Überlegung und 
Probierfreudigkeit aus eigener Kraft zu realisieren.
Für weniger ambitionierte gibt es fertigen Code mit ausreichender 
Dokumentation zu Hauf in jeder Programmiersprache!

Es ist nicht böse gemeint,aber ich denke Du bist kritikfähig genug um 
jetzt nich gleich loszuheulen, denn wenn Du in zwei Tagen nicht fündig 
geworden bist, dann such Dir besser ein anderes Hobby, wo vielleicht 
Dein cooler Slang besser passt ;-)

von asaa (Gast)


Lesenswert?

Das Wort "Debounce" fällt mehrfach im Wiki-Artikel: 
http://www.mikrocontroller.net/articles/Entprellung

Viele Vorwürfe kann man ihm diesbezüglich nicht machen ;)

von Karl H. (kbuchegg)


Lesenswert?

Franz Maier schrieb:
> Ja stimmt der teil hats mir nicht mit kopiert. Sorry
> Ich habe das Programm nochmals neu aufgebaut aber die LED an D0 schaltet
> nur aus während dem Tastendruck. Wieso das?

Weil du genau das in deinem 'Neuaufbau' programmiert hast.

Überprüfe ca. 100000 mal pro Sekunde den Eingang an dem der Taster 
hängt. Ist der Taster gedrückt, schalte die LED aus. Ist der Taster 
nicht gedrückt schalte sie ein.

von max (Gast)


Lesenswert?

Franz Maier schrieb:

> Kannst du mir jetzt sagen was ich um ändern muss damit die LED nich
> wieder angeht wenn man den Taster losläst? denn nach dem How To ist der
> Pull-UP an und das müsst so funktionieren.

In etwa so:
1
int main(void) {
2
3
// ...
4
5
int led = 0;   
6
   
7
while(1) {
8
9
  if ( PIND & (1<<7) ) {
10
    if (led = 1 - led)
11
      PORTD |= _BV(0);
12
    else
13
      PORTD &=~_BV(0);
14
  }
15
}

von Karl H. (kbuchegg)


Lesenswert?

max schrieb:
> Franz Maier schrieb:
>
>> Kannst du mir jetzt sagen was ich um ändern muss damit die LED nich
>> wieder angeht wenn man den Taster losläst? denn nach dem How To ist der
>> Pull-UP an und das müsst so funktionieren.
>
> In etwa so:


Nö.

Der wesentliche Unterschied ist die Unterscheidung von
* IST der Taster momentan gedrückt
* WIRD der Taster gerade niedergedrückt.

Im ersten Fall wird nur der Zustand des Tasters ausgewertet
Im zweiten Fall muss man den Wechsel des Zustands feststellen

Dein Code leistet leider 2.teres nicht. Dazu muss immer in irgendeiner 
Form der Zustand des Tasters mit dem Zustand im letzten 
Schleifendurchlauf verglichen werden.

Dein Code macht ganz was anderes: Wenn der Taster nicht gedrückt ist, 
dann blinke die LED ganz schnell.

von pom p. (pompete)


Lesenswert?

asaa schrieb:
> Das Wort "Debounce" fällt mehrfach im Wiki-Artikel:
> http://www.mikrocontroller.net/articles/Entprellung
...so ist es,aber dort gibt es eben kein "Denglisch" sondern eine 
saubere englische Dokumentation ;-)


> Viele Vorwürfe kann man ihm diesbezüglich nicht machen ;)
....doch kann man, grundsätzlich sind Fleiß und korrekte Schreibweisen 
die Grundbausteine für guten Erfolg beim programmieren (beispielhaft in 
der o.g. Routine von Peter Dannegger) ;-)
Von beiden Eigenschaften hält der Franz momentan (noch) nicht viel, er 
erwartet viel mehr (wie viele tausende auch) das die User des Forums 
Privatlehrer spielen und ihm das Denken abnehmen indem er einen reutigen 
Knochen hinwirft und wartet bis die Leute anbeissen....

Ich bewundere da Leute wie Karl Heinz Buchegger, die dann immer und 
immer wieder so gelassen reagieren und zum x-tausendsten mal nett 
schritt für schritt Leuten wie Franz jeden Popel aus der Nase ziehen um 
dann letztendlich auch diesen User das selbe beizubringen, was schon 
tausend male hier diskutiert wurde und dieser User in der halben Zeit 
auch durch eigene Recherchen hätte lernen können.
Aber diese Threads sind genauso sinnbefreit wie dieser,wenn sie 
zukünftig nicht gelesen werden weil es aus Faulheit einfacher ist einen 
neuen zu eröffnen!

Wie Du siehst, mein lieber Franz, es ist nicht böse gemeint und Du bist 
auch nicht der einzige mit diesen Eigenschaften, aber vielleicht 
verschafft Dir dieser "kleine OT-Beitrag" eine andere Sichtweise....

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.