mikrocontroller.net

Forum: Compiler & IDEs Tastenentprellen ADC


Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich versuche grade drei Tasten die ich an einem ADC pin eines Tiny 85 
angehägt habe zu entprellen.
(Tastenwert) wird duch eine ADKanallesenfunktion bestimmt und liegt
zwischen 0 und 5
zuerst habe ich die 3 Zustände in einer funktion definiert

uint8_t Tastenabfrage(void){
  uint8_t Taste;

   Taste  = 0;
   if      (Tastenwert > 4) Taste=1; //Werte grösser als 4, schalter mit 
einem KOhm wurde gedrückt
   else if (Tastenwert > 2) Taste=10;//Werte grösser als 2, schalter mit 
10 KOhm wurde gedrückt
   else if (Tastenwert > 1) Taste=33;//Werte grösser als 1, schalter mit 
33 KOhm wurde gedrückt
   else Taste = 0;
   return Taste;
}

danach habe ich versucht die Tasten so zu entprellen sodass ein 
Tastendruck was ein Wert zwischen 0 und 5 erbit nicht erkannt wird,
er wird erst dann erkannt wenn  der Wert zweimal rauskommt, und dann 
wird 10 ms gewartet und letzendlich werden Taste als definiert.
Das Prozessflag definiert mehrere Zustände. Für Jeden Zustand wird ein 
Bit reserviert in einem 8 Bit.
Ich habe das folgende Code geschrieben.

void TastenEntprellung(){

  if((Tastenabfrage()==1)||(Tastenabfrage()==10)||(Tastenabfrage()==33)){
// wenn nur einmal gedrückt (KeineTaste)
   Anreiz=KeineTaste;

     if(Tastenabfrage()==1){// zweimal erkannt TasteEins
   _delay_ms(10);
   Anreiz=TasteEins;
     Prozessflag|= Benutzeroberflaeche;
    }

   if(Tastenabfrage()==10){// zweimal erkannt TasteZwei
   _delay_ms(10);
   Anreiz=TasteZwei;
   Prozessflag|=Benutzeroberflaeche;
    }

   if(Tastenabfrage()==33){// zweimal erkannt TasteDrei
   _delay_ms(10);
   Anreiz=TasteDrei;
   Prozessflag|=Benutzeroberflaeche;
    }
      }
        }

Kann mir jemand sagen ob es richtig ist und ob es 
Verbesserungsvorschläge gibt.
Mein bessten Dank

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
henry wrote:

> danach habe ich versucht die Tasten so zu entprellen sodass ein
> Tastendruck was ein Wert zwischen 0 und 5 erbit nicht erkannt wird,
> er wird erst dann erkannt wenn  der Wert zweimal rauskommt,

Bis zur 2. Abfrage schätze ich mal 10µs Programmlaufzeit, das ist keine 
Entprellung.

> und dann
> wird 10 ms gewartet

Wozu?


Hier mal ein funktionierendes Beispiel:

Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"


Peter

Autor: Ulli Vex (vex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm na ein bissl mehr ist es schon, allein weil der Adc länger braucht

Beispiel ADC Takt = 250 kHz 13 Takte Wandlungzeit = ~19.230 khZ 
Abtastung.
(~50µS) Das dann noch durch Anzahl der Kanäle teilen. Bei 8 wären es 
dann schon 400µS. Wohlgemerkt ohne Software

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ulli Vex wrote:
> hmmm na ein bissl mehr ist es schon, allein weil der Adc länger braucht

Nur fragt die Funktion nicht den ADC ab, sondern die globale Variable 
"Tastenwert".
Es wird also nirgendwo auf ein neues ADC-Ergebnis gewartet und daher 
auch nicht entprellt.


Peter

Autor: Ulli Vex (vex)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt Danke

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal,

//Bis zur 2. Abfrage schätze ich mal 10µs Programmlaufzeit, das ist 
keine
Entprellung.

die Abfragen wollte ich nur zur Bestätigung haben, die eigentliche 
Entprellung wollte ich dann haben in dem ms wartet deswegen // 
_delay_ms(10);

Das Beispiel von peda habe ich mir angeschaut, nun gibts es paar 
unterschiede.
Ich habe drei Widerstände genommen mit unterschiedlichen Werten (1k, 
10k, 33k)
die an einem anderen Widerstand angehängt sind (10k), und die 
funktionieren über die Spannungsteilerregel. Ich will die Tasten 
abfragen nur wenn ein Taste gedrückt ist, das heisst ich habe 3 Fälle, 
und ich glaube da bracuhe ich nicht eine Tabelle und ein Schwellwert wie 
im Beispiel von peda.
deswegen wollte ich es so einfach wie möglich entprellen.

wäre dankbar für weitere Hilfe und Verbesserungsvorschläge.
henry

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
frage an peda, könntest du vielleicht dein code kommentieren, viele 
Sachen habe ich  nicht  so wirklich verstanden, und glaube  andere gehts 
genauso.
Ich bedanke  mich

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
henry wrote:
> frage an peda, könntest du vielleicht dein code kommentieren, viele
> Sachen habe ich  nicht  so wirklich verstanden

Es ist schwer, zu wissen, was der andere nicht wissen könnte.

Durch die Tastenmatrix werden unterschiedlich viele Widerstände 
eingeschaltet, 0k-1k-2k-3k, nächste Reihe 3,9k-4,9k-5,9k usw.
Diese bilden dann mit dem Widerstand gegen VCC einen Spannungsteiler.
Per Macro werden dann die Spannungen je Taste ausgerechnet und in der 
Tabelle die Werte zwischen 2 Tasten eingetragen.
Die ADC-Werte werden im Timerinterrupt alle 10ms ausgelesen und damit 
verglichen.
Danach gehts weiter mit meiner Standardentprellroutine, d.h. wird 4* 
hintereinander die gleiche Taste erkannt, wird sie gespeichert.
Da es 12 Tasten sind, arbeitet die Entprellroutine mit 16Bit.


Peter

Autor: henry (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Peter,
danke für die Erklärung, soweit habe ich verstanden wie du es berechnen 
willst, durch schwellenwert, der eine 0 bei Unterschreiten ausgibt und 
ein 1 beim Überschreiten.
Nun versuche ich dann mittels dein Code, ein ähnliches für meinen Fall 
zu schreiben.
Habe nur paar fragen die ich nicht verstanden habe.

#define THRESHOLD(n)  (u16)((ADCVAL(n)+ADCVAL(n+1))/2)

wieso steht (u16) davor

und hier

static inline
u16 key_no( u8 adcval )
{
  u16 num = 0x1000;
  prog_uint8_t * thr = THRESHOLDS;//nimmt hier * thr die Werte vom 
THRESHOLDS ???

  while( adcval < pgm_read_byte( thr )){
    thr++;
    num >>= 1;
  }
  return num & ~0x1000;
}

dabei hänge ich mein Code nur leider bekomme ich eine Fehlermeldung 
bezuglich des Arrays
die lautet: expected ')' bevor token '}'

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
henry wrote:

> wieso steht (u16) davor

Die Macros enthalten float-Werte.
Um nicht versehentlich die float-Library einzubinden, wird das Ergebnis 
nach 16Bit int gecastet.


> dabei hänge ich mein Code nur leider bekomme ich eine Fehlermeldung
> bezuglich des Arrays
> die lautet: expected ')' bevor token '}'

Dann poste bitte einen compilierbaren Code (mit allen verwendeten 
Macros), sonst kann man den Fehler ja nicht sehen.

Und nenne den Code nicht *.txt sondern *.c!


Peter

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,

das Problem ist behoben, ich hatte nur ein Klammer vergessen :-)
passiert mir ständig.

  //prog_uint8_t * thr = THRESHOLDS;//nimmt hier * thr (Zeiger)die Werte 
vom
THRESHOLDS ???

das war meine zweite Frage

Danke nochmal

Autor: henry (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich versuche es immer noch mit der Erkennung der Tasten über ADC, leider 
komme ich zu keinem Erfolg.
das folgende Code habe ich nach dem Prinzip von peda geschrieben, aber 
wenn ich es auf meinem MC lade führt es zu keinem Erfolg.
Bitte um Fehleranalyse, danke im voraus

Autor: henry (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
das code für ADkanalLesen:

Autor: henry (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Die Schaltung der Tasten am MC

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm Dir mal ne SW-UART und gib die ADC-Werte aus.


Peter

Autor: henry (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe nochmal versucht einbischen umzuändern und kamm zu paar Efolge, 
aber paar Fehler sind aufgetreten und verstehe bis jetzt nicht warum.
Ich habe die Werte, die die Funktion ADkanallesen ausgibt bzw die 
adcwerte berechnet.
(erste Taste --> 1,22V --> 235)
(zweite Taste --> 2,62V --> 506)
(dritte Taste --> 4,75V --> 918)

und die berechnete Schwellwerte sind (712,370,118)

Wenn ich jetzt auf die erste Taste drücke bekomme ich das gewunschte 
Zeichen
"A" siehe Anhang.
Wenn ich auf die zweite drucke (wollte ich das Zeichen "B" bekommen)aber 
ich bekomme wieder "A".
auf die Dritte bekomme ich "C" (will das es dann auf LCD bleibt) aber 
nach kurzer Zeit zeigt sich "A" wieder zurück

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast die Tasten ja umgekehrt angeschlossen (gegen VCC).
Dann mußt Du auch den Vergleich und die Tabelle umgekehrt machen.


Peter

Autor: henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi peda,
ich habe s versucht wie du es beschriben hast.
---------------------------------
typedef unsigned char  u8;
typedef unsigned short u16;
volatile uint16_t adcwert; //ADCWERT WIRD AUS DER FUNKTION LeseADkanal 
berechnet

prog_uint16_t SCHWELLWERTE[] = {370,712,970};// berechnete Schwellwerte
static inline
u8 taste_no( u8 adcwert )
{
  adcwert = LeseADkanal(3);
  u16 num = 0x08; // DA NUR DREI FÄLLE SIND 0b00001000
  prog_uint16_t * thr = SCHWELLWERTE;

  while(adcwert > pgm_read_byte(thr)){

    thr++;
    num >>= 1;
  }
  return num & ~0x08;
}
--------------------------------
Bekomme ich aber nur ein "C" Zeichen wenn ich auf die Taste
(dritte Taste --> 4,75V --> 918) Drücke
Ich habe auch die Werte des Arrays mehrmals geändert, und
u16 num = 0x08  --->   u16 num = 0x01
 num >>= 1;     --->   num <<= 1;
hat auch nix gebracht? Weiss nicht woran es liegen kann :(
henry

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
henry wrote:
> Ich habe die Werte, die die Funktion ADkanallesen ausgibt bzw die
> adcwerte berechnet.
> (erste Taste --> 1,22V --> 235)
> (zweite Taste --> 2,62V --> 506)
> (dritte Taste --> 4,75V --> 918)
>
> und die berechnete Schwellwerte sind (712,370,118)

Wenns nicht funktioniert, dann zeige doch erstmal die gemessenen Werte 
auf dem LCD an.
Vielleicht hast Du ja einen Rechenfehler oder einen Schaltungsfehler.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P.S.:
Du solltest mal versuchen, nicht nur planlos rumzuprobieren, sondern 
überlegt zu debuggen.

Also wenn was nicht geht, das Problem in einzelne Abschnitte zerlegen 
und diese für sich kontrollieren.

Z.B. ob der ADC überhaupt das richtige macht.

Oder statt des ADC über die UART oder über nen Timer im Sekundentakt 
verschiedene ADC-Werte zu simulieren (der Auswertefunktion übergeben).
Usw.


Peter

P.S.:
Du hast da noch einige Variablen und Funktionen 16Bittig, was bei 3 
Tasten nicht nötig ist. Das ist aber nicht der Fehler, würde nur SRAM 
und Flash einsparen.

Autor: S-E, O (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
ich habe eine Frage bezüglich dem Code "Tastenmatrix auslesen über nur 2 
Leitungen"
 von Peter Dannegger.
Und zwar im Teil an der Interrupt Routine

ISR(TIMER0_OVF0_vect )
{
  static u16 ct0, ct1;
  u16 i;

  TCNT0 = (u16)(256 - XTAL  1024  100);  // 100Hz (10ms)

  i = key_state ^ key_no( ADCH );  // key changed ?
  ct0 = ~( ct0 & i );      // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);    // reset or count ct1
  i &= ct0 & ct1;      // count until roll over ?
  key_state ^= i;      // then toggle debounced state
  key_press |= key_state & i;    // 0->1: key press detect
}

Hier wird ein Interrupt jede 10 ms ausgelöst???
und wie lange dann dauert diese 4*mal abfrage? findet sie in diesen 10 
ms statt??

Danke im Voraus

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S-E, O wrote:
> Hier wird ein Interrupt jede 10 ms ausgelöst???
> und wie lange dann dauert diese 4*mal abfrage? findet sie in diesen 10
> ms statt??

Natürlich 40ms.
Eine Entprellung durch Mehrfachabtastung funktioniert nur dann, wenn sie 
in gleichen Zeitabständen erfolgt.
Hier wird allerdings weniger das Prellen unterdrückt, sondern 
Störeinstreuungen auf die AD-Wandlung.


Peter

Autor: S-E, O (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun was ich nicht verstehe, das es jede 10ms ein Interrupt ausgelöst 
wird was eine abfrage von 40ms beinhaltet. Nehmen wir an ich wurde ein 
Event bei 40ms beschreiben, in dem ich ein Counter reinschreibe was mir 
bei Counter==4 --> 40ms ein Interrupt auslöst.
würde das dann funktionieren?
ich frage weil ich deine Funktion zur Nutze nehmen will aber will auch 
in der Interrupt Routine noch eine Funktion beschreiben.
Danke

S-E, O

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
S-E, O wrote:
> Nun was ich nicht verstehe, das es jede 10ms ein Interrupt ausgelöst
> wird was eine abfrage von 40ms beinhaltet. Nehmen wir an ich wurde ein
> Event bei 40ms beschreiben, in dem ich ein Counter reinschreibe was mir
> bei Counter==4 --> 40ms ein Interrupt auslöst.

Du kannst in einem Timerinterrupt generell viele verschiedene Sachen 
machen, er ist durch das Entprellen nicht "verbraucht".


Peter

Autor: henry (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi, ich habe solange versucht bis ich endlich es geschafft habe durch 
die Entprellfunktion ein laufendes Code zu realisieren.
wenn ich Taste 1,2 oder 3  drücke bekomme ich was.

jetzt habe ich diese Funktion zur nutze genommen, nur leider geht sie 
jetzt nicht mehr.

wenn ich auf die erste oder dritte Taste drücke bekomme ich den selben 
Ergebnis, und auf die zweite reagiert es überhaupt nicht.
bin jetzt die ganze Zeit am debuggen, weiss nicht wieso es jetzt nicht 
funktioniert.
die berechneten Schwellenwerte haben einwandfrei funktioniert.
s.a

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was macht LeseADkanal (Code)?


Nimm dochmal 3 LEDs und laß Dir die 3 TastenStatus-Bits anzeigen.

Dann nimm die 3 LEDs und laß sie mit TastenErkennung togglen.

LCDs sind zum Debuggen schlecht, da sie viel zu träge sind.
Außerdem könnte die Ausgabezeit den Ablauf stören, insbesondere wenn man 
Display-Clear benutzt.


Peter

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.