Forum: Compiler & IDEs Debounce - LED leuchten lassen


von Andreas (Gast)


Lesenswert?

Hallo Leute!

Ich habe aus dem AVR-GCC-Tutorial die Entprell-Routine genommen und mir 
ein Programm geschrieben, welches folgendes bezwecken soll:

Ich habe einen ATTiny25 in Verwendung, an dem 3 Taster angeschlossen 
werden sollen.

Wenn Taster 0 gedrückt wird, soll die LED 500 ms leuchten,
Wenn Taster 1 gedrückt wird, 2000 ms leuchten
Wenn Taster 2 gedrückt wird, 3000 ms leuchten.


Die LED ist an PINB3 angeschlossen (siehe Quellcode).

Könntet ihr mir sagen, ob das Programm so funktionieren würde?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
6
void entprellung (volatile uint8_t *port, uint8_t maske ) 
7
{
8
  uint8_t   port_puffer;
9
  uint8_t   entprellungs_puffer;
10
 
11
  for(entprellungs_puffer=0;entprellungs_puffer!=0xff;) 
12
  {
13
    entprellungs_puffer<<=1;
14
    port_puffer = *port;
15
    _delay_us(150);
16
    
17
  if((*port & maske) == (port_puffer & maske) )
18
  {
19
      entprellungs_puffer |= 0x01;
20
  }
21
  }
22
} 
23
24
25
void main (void)
26
{
27
  DDRB = 0;          // alle Pins als Eingang schalten
28
  DDRB |= (1<<PINB3);      // nur Pin3 (Port B) auf Ausgang schalten
29
30
  while(1)
31
  {
32
  
33
      entprellung( &PINB, (1<<PINB0) ); // ggf. Prellen abwarten 
34
      if( PINB & (1<<PINB0) )           // dann stabilen Wert einlesen
35
      {
36
        PORTB |= (1<<PINB3);       // wenn Taster0 gedrückt wurde....
37
      delay_ms(500);           // Licht einschalten, 500 ms warten, dann ausschalten
38
      PORTB &= ~(1<<PINB3);
39
      
40
      }
41
42
      entprellung( &PINB, (1<<PINB1) );
43
    if( PINB & (1<<PINB1)) 
44
    {
45
46
      PORTB |= (1<<PINB3);
47
      delay_ms(2000);
48
      PORTB &= ~(1<<PINB3);
49
    }
50
51
      entprellung( &PINB, (1<<PINB2) );
52
    if( PINB & (1<<PINB2)) 
53
    {
54
      PORTB |= (1<<PINB3);
55
      delay_ms(3000);
56
      PORTB &= ~(1<<PINB3);      
57
58
    }
59
60
}
61
62
}

Vielen Dank und Gruß
Andreas

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Könntet ihr mir sagen, ob das Programm so funktionieren würde?

Was hält Dich davon ab, es einfach auszuprobieren?

von Andreas (Gast)


Lesenswert?

Hey,

das Problem ist, dass ich hier im Moment keine Möglichkeit habe, 
Hardware aufzubauen.
Da die Steuerung einem Bekannten von mir gehört, die er bereits gelötet 
hat und er mich "beauftragte", die Software zu schreiben, wollte ich 
zunächst erfragen, ob das Programm soweit gut aussieht?!

Bevor ich etwas übergebe, was nicht funkioniert :)

Außerdem seit ihr ja quasi die besten Hardware-Emulanten und wisst wo 
der Fehler liegt ;-)


Gruß
Andreas

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> entprellung( &PINB, (1<<PINB0) ); // ggf. Prellen abwarten
>       if( PINB & (1<<PINB0) )           // dann stabilen Wert einlesen

Da dreht sich mir der Magen um.

Du liest den Pin nur einmal ein, warum soll er ausgerechnet dabei stabil 
sein?
Bist Du etwa Hellseher?
Die Entprellung machen indirekt nur Deine Monsterdelays >=500ms danach.

Eine zuverlässige Entprellung erreicht man nur durch Mehrfachabtastung 
in beide Richtungen (drücken + loslassen). Und vorzugsweise im 
Timerinterrupt, damit keine wertvolle CPU-Zeit unnütz verwartet wird.


Peter

von Andreas (Gast)


Lesenswert?

Ähm wofür dient dann das Beispiel im Tutorial?


Außerdem ist es dort genauso beschrieben, wie ich es in meinem Programm 
auch gemacht habe.

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> Ähm wofür dient dann das Beispiel im Tutorial?

Welches denn?
Zeig mal den Link darauf.
Ich sehe da keines, welches den Typ void liefert.

Auch heißt es nicht, wenn etwas im Tutorial steht, daß es unbedingt 
richtig ist oder wirklich gut funktioniert. Das Tutorial schreiben ja 
auch nur Menschen.


Gerade beim Entprellen wird sehr viel Murks gemacht, weil der 
Programmierer es nicht verstanden hat und es auch nicht merkt, solange 
die Tasten neu sind.
Erst der Kunde merkt es mit der Zeit, wenn die Tasten ermüden und 
oxydieren.
Auch Du kennst bestimmt Geräte mit schlecht entprellender 
Tastensoftware.


Peter

von Andreas (Gast)


Lesenswert?

Hallo,

hier der Link mit dem Quellcode aus dem Tutorial:

http://www.mikrocontroller.net/articles/Entprellung#Warteschleifen-Verfahren



Aber gibt es denn keine Routine, die einfach und trotzdem hilfreich ist?

Das ist ja eigentlich das Grundlegendste, einen Taster an einem 
Controller abzufragen....


Gruß

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> http://www.mikrocontroller.net/articles/Entprellun...

Ja, die ist schlecht.
Ihre Hauptaufgabe ist, bei jedem Aufruf >= 1.2ms zu verschwenden.
Das Einlesen eines Ports kann jedesmal einen anderen Wert liefern. Das 
mag vielleicht selten passieren, aber es kann. Insbesondere wenn Du 
Interrupts verwendest, steigt die Gefahr. Da kann ja zwischen den 
Einlesungen schon viel Zeit (Interrupthandler: mehrere ms) vergangen 
sein.
Daher sollte die Entprellroutine immer auch den Erfolg direkt als 
Rückgabewert liefern.
Unnötige Mehrfacheinlesungen eines Ports sind unbedingt zu vermeiden!


Andreas schrieb:
> Aber gibt es denn keine Routine, die einfach und trotzdem hilfreich ist?

Gibt es:
http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_type=project&item_id=1801

http://www.mikrocontroller.net/articles/Entprellung#Debounce-Makro_von_Peter_Dannegger


Andreas schrieb:
> Das ist ja eigentlich das Grundlegendste, einen Taster an einem
> Controller abzufragen....

Das schon. Allerdings denken wohl viele Programmer, das ist nicht so 
wichtig, als das man es richtig machen müßte.
Oder die Programmierer lernen zwar viel über Software, aber haben wenig 
Wissen über Hardware.


Peter

von Andreas (Gast)


Lesenswert?

Nun mach' ich es mit Hardware.

Diese unkommentierten kryptischen Codes mag ich nicht, da ist mir ein 
Kondensator und ein Widerstand deutlich sympathischer und ich 
verschwende dabei keine Ressourcen vom Mikrocontroller.

von Andreas (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,


habe hier mal einen Schaltplan gezeichnet (Eagle).

Im Anhang findet ihr das PDF.


Könnte mal bitte jemand drüber schauen ob das so in Ordnung ist?
(Auch die Debounce-Schaltungen)






Vielen Dank!

Gruß
Joh

von A. F. (frankalicious)


Lesenswert?

Andreas schrieb:
> Diese unkommentierten kryptischen Codes mag ich nicht,

Unkommentiert?
Hier sind doch Kommentare im Code und die Funktionsweise ist auch noch 
erläutert...
http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

von Andreas (Gast)


Lesenswert?

Stimmt die Schaltung so?

von Andreas (Gast)


Lesenswert?

Hallo nochmal,

ich habe nun diesen Quellcode von Peter Dannegger verwendet und 
"umgeschrieben", für meine Bedürfnisse.
1
/************************************************************************/
2
/*                                                                      */
3
/*                      Not so powerful Debouncing Example              */
4
/*                      No Interrupt needed                             */
5
/*                                                                      */
6
/*              Author: Peter Dannegger                                 */
7
/*                                                                      */
8
/************************************************************************/
9
// Target: ATtiny13
10
 
11
#include <avr/io.h>
12
#define F_CPU 9.6e6
13
#include <util/delay.h>
14
 
15
 
16
#define debounce( port, pin )                                         \
17
({                                                                    \
18
  static uint8_t flag = 0;     /* new variable on every macro usage */  \
19
  uint8_t i = 0;                                                      \
20
                                                                      \
21
  if( flag ){                  /* check for key release: */           \
22
    for(;;){                   /* loop ... */                         \
23
      if( !(port & 1<<pin) ){  /* ... until key pressed or ... */     \
24
        i = 0;                 /* 0 = bounce */                       \
25
        break;                                                        \
26
      }                                                               \
27
      _delay_us( 98 );         /* * 256 = 25ms */                     \
28
      if( --i == 0 ){          /* ... until key >25ms released */     \
29
        flag = 0;              /* clear press flag */                 \
30
        i = 0;                 /* 0 = key release debounced */        \
31
        break;                                                        \
32
      }                                                               \
33
    }                                                                 \
34
  }else{                       /* else check for key press: */        \
35
    for(;;){                   /* loop ... */                         \
36
      if( (port & 1<<pin) ){   /* ... until key released or ... */    \
37
        i = 0;                 /* 0 = bounce */                       \
38
        break;                                                        \
39
      }                                                               \
40
      _delay_us( 98 );         /* * 256 = 25ms */                     \
41
      if( --i == 0 ){          /* ... until key >25ms pressed */      \
42
        flag = 1;              /* set press flag */                   \
43
        i = 1;                 /* 1 = key press debounced */          \
44
        break;                                                        \
45
      }                                                               \
46
    }                                                                 \
47
  }                                                                   \
48
  i;                           /* return value of Macro */            \
49
})
50
 
51
/*
52
   Testapplication
53
 */
54
int main(void)
55
{
56
  
57
  DDRB  &= ~(1<<PB0);    // Eingang 1 (Taster)
58
  DDRB  &= ~(1<<PB1);    // Eingang 2 (Taster) 
59
  DDRB  &= ~(1<<PB2);    // Eingang 3 (Taster)   
60
  DDRB  |=   1<<PB3;     // Ausgang (LED)
61
  
62
63
  whie(1)
64
  {
65
    if( debounce( PINB, PB0 ) )     // wenn Taster 1 gedrückt...
66
    {
67
      PORTB |= 1<<PB3;              // Am Ausgang HIGH ausgeben
68
      _delay_ms(500);               // warten...
69
      PORTB &= ~(1<<PB3);           // Ausgang auf LOW schalten
70
    } 
71
    
72
    if( debounce( PINB, PB1 ) )     // wenn Taster 2 gedrückt...
73
    {
74
      PORTB |= 1<<PB3;
75
      _delay_ms(1000);
76
      PORTB &= ~(1<<PB3);
77
    }     
78
79
    if( debounce( PINB, PB2 ) )      // wenn Taster 3 gedrückt...
80
    {
81
      PORTB |= 1<<PB3;
82
      _delay_ms(2000);
83
      PORTB &= ~(1<<PB3);
84
    }     
85
86
87
}



Ich habe nun die Taster direkt an 5 V gehängt und schalte somit beim 
Drücken des Tasters 5 V auf den Eingang des Controllers.

Stimmt nun der Quellcode zum Entprellen (laut Tutorial)?



Danke!

Gruß
Andreas

von Peter D. (peda)


Lesenswert?

Andreas schrieb:
> Ich habe nun die Taster direkt an 5 V gehängt und schalte somit beim
> Drücken des Tasters 5 V auf den Eingang des Controllers.

Dann ist die Preisfrage aber, was liegt an bei Losgelassen ???

Die Leute sind ja nicht blöd, die den Taster gegen GND legen und im AVR 
den Pullup einschalten.


Peter

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.