mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Taster richtig entprellt?


Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define F_CPU           8000000UL                   // processor clock frequency 8Mhz

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>


#define Taster  PB0    //Pin des Tasters
#define LED    PB1    //Pin der LED


inline uint8_t debounce(volatile uint8_t *port, uint8_t pin);


//Das Hauptprogramm
int main()
{
//variablen für das Programm
char Status=0;
  
  DDRB = 0x00;      //Datenrichtungsregister zunächst alle Eingang 
  DDRB |= (1 << DDB1);     //PB1 als Ausgang schalten für LED
  PORTB = (1 << PB0) | (1 << PB1);//an PB0 interne Pullup aktiviert (Eingang), LED anfangs ausschalten
  
  while(1)
  
  //Zustand des Tasters abfragen mit Entprellfunktion
  if ((debounce(&PINB, Taster)&&Status==0)){
    PORTB &=~ (1 << LED);    //LED anschalten
    Status=1;
  }
    
  else if ((debounce(&PINB, Taster)&&Status==1)){
    PORTB |= (1 << LED);    //LED ausschalten
    Status=0;
  }

}


// ----------------------------------------------------------------------------
// Funktionen
// ----------------------------------------------------------------------------



/*Funktion zum einfachen entprellen der Tastern*/
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) {

  if ( ! (*port & (1 << pin)) )
  {
  /* Pin wurde auf Masse gezogen, 100ms warten */
  _delay_ms(50); // max. 262.1 ms / F_CPU in MHz
  _delay_ms(50);
    if ( *port & (1 << pin) ){
    /* Anwender Zeit zum Loslassen des Tasters geben */
    _delay_ms(50);
    _delay_ms(50);
    return 1;
    }
  }
  return 0;
}

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

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

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
  if (debounce(&PINB, Taster)) { // Taster losgelassen?
    if (Status==0) {  //LED anschalten
       Status=1;  
       PORTB &=~ (1 << LED); 
    }
    else {            //LED ausschalten
       Status=0;   
       PORTB |= (1 << LED);
    }
  }

Autor: Sven (Gast)
Datum:

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

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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.
;-)

...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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.

...

Autor: Peter Dannegger (peda)
Datum:

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


Peter

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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... ;-)

...

Autor: Georg (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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.

...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.