Forum: Mikrocontroller und Digitale Elektronik Taster richtig entprellt?


von Sven (Gast)


Lesenswert?

Hallo,

ich habe ein Mini Programm zum Üben (Newbie) geschrieben, welches 
einfach eine LED Mittels Taster ein- und ausschalten soll. Aber 
irgendwie reagiert der Taster nicht bei jedem Tastendruck, nur manchmal 
nur jeder 2. oder 3., manchmal auch wirklich direkt wie es sollte. Nun 
ist meine Frage, ob der Taster so richtig entprellt ist.
Atmega 8, an PB0 Taster gegen Masse (active-low), an PB1 LED, leuchtet, 
wenn PB1 low ist.
Die Funktion zum Entprellen habe ich hier aus dem Tutorial so kopiert 
(und hoffentlich richtig angewendet)

Das Programm:
1
#define F_CPU           8000000UL                   // processor clock frequency 8Mhz
2
3
#include <stdint.h>
4
#include <avr/io.h>
5
#include <util/delay.h>
6
7
8
#define Taster  PB0    //Pin des Tasters
9
#define LED    PB1    //Pin der LED
10
11
12
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin);
13
14
15
//Das Hauptprogramm
16
int main()
17
{
18
//variablen für das Programm
19
char Status=0;
20
  
21
  DDRB = 0x00;      //Datenrichtungsregister zunächst alle Eingang 
22
  DDRB |= (1 << DDB1);     //PB1 als Ausgang schalten für LED
23
  PORTB = (1 << PB0) | (1 << PB1);//an PB0 interne Pullup aktiviert (Eingang), LED anfangs ausschalten
24
  
25
  while(1)
26
  
27
  //Zustand des Tasters abfragen mit Entprellfunktion
28
  if ((debounce(&PINB, Taster)&&Status==0)){
29
    PORTB &=~ (1 << LED);    //LED anschalten
30
    Status=1;
31
  }
32
    
33
  else if ((debounce(&PINB, Taster)&&Status==1)){
34
    PORTB |= (1 << LED);    //LED ausschalten
35
    Status=0;
36
  }
37
38
}
39
40
41
// ----------------------------------------------------------------------------
42
// Funktionen
43
// ----------------------------------------------------------------------------
44
45
46
47
/*Funktion zum einfachen entprellen der Tastern*/
48
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) {
49
50
  if ( ! (*port & (1 << pin)) )
51
  {
52
  /* Pin wurde auf Masse gezogen, 100ms warten */
53
  _delay_ms(50); // max. 262.1 ms / F_CPU in MHz
54
  _delay_ms(50);
55
    if ( *port & (1 << pin) ){
56
    /* Anwender Zeit zum Loslassen des Tasters geben */
57
    _delay_ms(50);
58
    _delay_ms(50);
59
    return 1;
60
    }
61
  }
62
  return 0;
63
}

von Sven (Gast)


Lesenswert?

Kann mir denn keiner helfen?
Sollte doch für jemand der ein kleinwenig mehr Erfahrung hat eine 
lösbare Aufgabe sein oder?

Vielen Dank.

von Karl H. (kbuchegg)


Lesenswert?

Die Entprellung ist zwar grundsätzlich eine von der miesen Sorte, sollte 
aber funktionieren.

Wackelkontakt?
Läuft der Prozessor auch wirklich mit 8Mhz?

von Sven (Gast)


Lesenswert?

Danke für die Antwort.
Ja, die Fuses habe ich auf 8Mhz umgestellt.
Ich werde mal versuchen, einen anderen Taster zu verwenden, vielleicht 
ist dieser schon ausgelutscht...Ansonsten steckt alles auf dem 
Breadboard, ich denke doch wackelfrei.

Mir ging es nur darum, auf der sicheren Seite mit der Software zu sein, 
um Fehlerquellen auszuschließen.
Wenn alles Neuland ist, weiß man nicht, bei welcher Baustelle der Fehler 
ist.
Die Entprellung nach Peter Danegger scheint wohl das "Top Modell" zu 
sein. Aber für die ersten Schritte wollte ich zunächst etwas einfacheres 
nehmen.

Aber die Antwort, dass der Code so zumindest mal funktionieren sollte, 
hilft mir weiter. Danke nochmal.

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:

> ist dieser schon ausgelutscht...Ansonsten steckt alles auf dem
> Breadboard, ich denke doch wackelfrei.

Autsch.
Gerade wenn du mit Breadbord arbeitest, sind Wackelkontakte 
vorprogrammiert. Speziell wenn du solche Digitaster benutzt, deren 
Anschlüsse nicht richtig in die Aufnahmen auf dem Board passen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

In deinem Code ist ein Loch, in dem du blind bist:
Was passiert, wenn du in die debounce mit gedrücktem Taster hineingehst, 
den während der Funktionsausführung betätigst, mit 0 aus der Funktion 
herauskommst, dann logischerweise nichts an den LEDs änderst, jetzt aber 
den Taster loslässt, bevor du wieder in die debounce reinkommst?
Richtig: gar nichts, der Tastendruck wird nicht erkannt  :-o

Allerdings wundert mich schon, dass dir das so oft passieren sollte...

Du müsstest dir für so eine zyklische Flankenabfrage den vorherigen Wert 
des Tasters merken. Nur so geht das zuverlässig.

BTW:
Die LED-Geschichte würde ich auch etwas anders angehen:
Die Ursache ist die Tasterbetätigung. Deshalb gehört die ganz oben hin.
1
  if (debounce(&PINB, Taster)) { // Taster losgelassen?
2
    if (Status==0) {  //LED anschalten
3
       Status=1;  
4
       PORTB &=~ (1 << LED); 
5
    }
6
    else {            //LED ausschalten
7
       Status=0;   
8
       PORTB |= (1 << LED);
9
    }
10
  }

von Sven (Gast)


Lesenswert?

Vielen Dank.
Ich werde die Vorschläge beherzigen und weiter Spaß beim Üben und 
Basteln haben :-)

von Hannes L. (hannes)


Lesenswert?

> Die Entprellung nach Peter Danegger scheint wohl das "Top Modell" zu
> sein.

Das ist es unbestritten. Ich nutze diesen Algorithmus in verschiedenen 
Varianten (mit/ohne Repeat bzw. Unterscheidung kurz/lang, mit/ohne 
Loslasserkennung).

> Aber für die ersten Schritte wollte ich zunächst etwas einfacheres
> nehmen.

Es gibt nichts "Einfacheres" was auch noch funktioniert. Die 
Grundroutine in einfachster Form braucht in der Timer-ISR ganze 12 
ASM-Befehle, die Abarbeitung kostet alle 20 ms ganze 12 Takte für bis zu 
8 gleichzeitig zu behandelnde Tasten. Die Abarbeitung läuft "nebenher", 
es wird an keiner Stelle auf irgendwas gewartet oder per Zeitschleife 
Takte gezählt. Die Auswertung vom Hauptprogramm ist sehr komfortabel, es 
gehen auch bei schlechtem Timing des Hauptprogramms keine Tastendrücke 
verloren.

Zugegeben, ich sehe das aus ASM-Sicht, da ist alles schön übersichtlich 
und verständlich, mit der Formulierung des Algorithmus in C komme ich 
auch nicht zurecht. Das muss ich aber auch nicht, der AVR kann auch kein 
C.
;-)

...

von Karl H. (kbuchegg)


Lesenswert?

Hannes Lux schrieb:

> Es gibt nichts "Einfacheres" was auch noch funktioniert.

Leider.
Sonst hätte man das schon ins Tutorial eingebaut.
Die dortige Entprellung mit delay ist vielen sowieso ein Dorn im Auge. 
Auf der anderen Seite kann man die PeDa Entprellung nicht einfach so ins 
Tutorial übernehmen, eben weil sie "nicht ohne" ist.

> Zugegeben, ich sehe das aus ASM-Sicht, da ist alles schön übersichtlich
> und verständlich, mit der Formulierung des Algorithmus in C komme ich
> auch nicht zurecht.

Die ist genauso simpel wie die Assemblerversion, wenn man ds Prinzip 
erst mal verstanden hat. Das Trickreiche sind die 8 Stück 4-Bit Zähler, 
die sich auf 2 Variablen verteilen :-)

von Sven (Gast)


Lesenswert?

Hallo,

ok. Jetzt bleibt für mich noch eine Frage.
Angenommen ich habe ein kleineren Prozessor, z.B. Attiny13. Möchte dort 
mit dem Timer0 etwas messen, muss diesen also stoppen und starten.
Wie kann ich dann die Entprellung mit einbauen? In dem Moment wo der 
Timer gestoppt ist, würde ja die Entprellroutine nicht mehr 
funktionieren oder?

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:
> Hallo,
>
> ok. Jetzt bleibt für mich noch eine Frage.
> Angenommen ich habe ein kleineren Prozessor, z.B. Attiny13. Möchte dort
> mit dem Timer0 etwas messen, muss diesen also stoppen und starten.

1) Warum musst du den Stoppen und Starten?
   Kann der nicht einfach durchlaufen und du merkst dir zb den
   Zählerstand bei Beginn der Messung und beim Ende der Messung und
   rechnest die Differenz aus (Das ist dann genausogut, als ob der
   Timer beim Starten der Messung bei 0 angefangen hätte)

2) Hast du nur den Timer 0?


In praktisch jedem Programm hat man einen Timer, der dafür abgestellt 
ist einfach nur ein regelmässiges Signal in Form eines ISR Aufrufs zu 
erzeugen. Sowas wie der 'Pulsschlag' des Programms. Für die 
Tastenentprellung ist es ziemlich unerheblich, ob dieser Herzschlag nun 
5ms oder 15ms oder 20ms oder eben 10ms dauert. Irgendwo in dem Bereich 
sollte er für die Tastenentprellung sein aber wo genau ist wieder 
weniger wichtig.

von Sven (Gast)


Lesenswert?

1. Ok, das ist in der Tat eine Lösung.
2. Beim Atmega8 nicht, aber wie im Beispiel genannt hat ein Attiny13 
doch nur einen 8-bit Timer (so stehts im Datenblatt) oder täusche ich 
mich da?

von Karl H. (kbuchegg)


Lesenswert?

Sven schrieb:

> 2. Beim Atmega8 nicht, aber wie im Beispiel genannt hat ein Attiny13
> doch nur einen 8-bit Timer (so stehts im Datenblatt) oder täusche ich
> mich da?

Keine Ahnung.
Habe das Datenblatt nicht da.

von Hannes L. (hannes)


Lesenswert?

Der Tiny13 hat nur einen Timer. Dieser hat aber neben dem Überlauf auch 
zwei Compare-Einheiten, die sich separat verwenden lassen. Die 
Entprellung braucht keinen eigenen Timer, sie lässt sich nebenher von 
einem anderen Timerjob erledigen. Dazu kann man Zähler (Zählvariable) 
nutzen, der die Entprellung nur jedes x-te mal aufruft.

Übrigens:
Wenn man den Timer konsequent frei durchlaufen lässt, dann kann man 
jeden der Interrupts verwenden und nebenher noch Impulsmessungen (ICP 
bei großen oder ext.Int bei kleinen AVRs) machen. Selbst Hardware-PWM 
ist quasi gleichzeitig möglich.

...

von Peter D. (peda)


Lesenswert?

Der ATtiny13 rechnet sich nur bei extrem hoher Stückzahl.
Für Basteleien nimm besser den pinkompatiblen ATtiny25/45/85.


Peter

von Hannes L. (hannes)


Lesenswert?

Er rechnet sich eigentlich nicht mehr, da der (Bastler-)Preis von 85 
Cent (DIL) Geschichte ist. Bei derzeit 1,15 Eu ist er nicht mehr 
lukrativ. Trotzdem nutze ich ihn noch aus Gewohnheit, für kleine Dinge 
wie DCC-Einzelweichendecoder tut er seine Arbeit ganz gut.

Tiny85 ist natürlich Klasse, da passt sogar ein komplettes 
Diesellok-Geräusch mit Anlasser Signalhorn und Glocke rein, wobei die 
Highspeed-PWM einen halbwegs akzeptablen DAC darstellt. Schade dass es 
den nicht als Tiny645 oder Tiny2565 gibt... ;-)

...

von Georg (Gast)


Lesenswert?

>Tiny85 ist natürlich Klasse, da passt sogar ein komplettes
>Diesellok-Geräusch mit Anlasser Signalhorn und Glocke rein, wobei die
>Highspeed-PWM einen halbwegs akzeptablen DAC darstellt.

Wie schafft man es eigentlich, bei 250kHz auch noch 16bit Auflösung
PWM zu bekommen? ChaN macht so etwas mit 16bit .wav Dateien. Ich dachte 
immer, OCR1A/B haben nur 8 bit.

von Hannes L. (hannes)


Lesenswert?

> Wie schafft man es eigentlich, bei 250kHz auch noch 16bit Auflösung
> PWM zu bekommen?

8 Bit reicht für meine Zwecke. Und die 250 kHz PWM-Frequenz bedeutet ja 
nicht, dass man dies auch als Samplerate braucht. Anlasser und 
Dieselsound wird mit einer variablen Samplerate von 4 bis 12 kHz 
ausgegeben, Glocke und Horn mit etwa 7 kHz, wobei das Horn als Schleife 
läuft und nur wenige hundert Bytes hat.

Was ChaN macht, weiß ich nicht, ich gucke nicht bei ihm ab.

...

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.