Taster debouncen

OP #2673298
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
}
#2673317
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.
#2673324
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.
OP #2673603
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
OP #2673652
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.
OP #2673746
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.
#2673780
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 ;-)
#2673907
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.
Gast #2674096
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
}
#2674252
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.
#2674286
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....

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