www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Tasten entprellen


Autor: Björn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

hab den Code zum entprellen von Tasten von Peter Danegger auf meinen
Controller angepasst. Im Moment schaltet mir der Taster 0 die LED 0 ein
und wieder aus.

Nun möchte ich dies mit einer Taster-Matrix die über einen AD-Wandler
eingelesen wird erweitern. Dabei soll erst einmal nur diese eine LED
bei einem Wert zwischen 30 und 35 ein- und ausgeschaltet werden.

Wo muss ich in dem Code ansetzen? Hatte schon ein paar Ansätze, aber
die haben alle nicht funktioniert. Wäre super wenn mir da jemand helfen
könnte.

Gruß

Björn

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab deinen Code (noch) nicht angeguckt.
Es müsste aber so laufen:
AD-Wandler einlesen, Tasten decodieren, feststellen, ob sich seit dem
letzten Lesevorgang etwas verändert hat.
Wenn sich etwas verändert hat, den entsprechenden Entprellzähler
zurücksetzen (Prellen).
Hat sich nichts verändert, Entprellzähler weiterzählen.
Falls Schwellwert überschritten wurde, entsprechend handeln.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also der AD-Wandler ist eingelesen. Entprechender Wert steht in ADCH.

Was meinst du mit Tasten decodieren?

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Was meinst du mit Tasten decodieren?

Du hast eine Tatatur-Matrix am ADC hängen, die für jeden Tastendruck
einen bestimmten Wert zurückliefert. Der Zusammenhang zwischen ADC-Wert
und gedrückter Taste muß decodiert werden.
Du kannst natürlich auch feststellen, ob sich der ADC-Wert seit der
letzten Messung verändert hat, und dann reagieren (decodieren und
entprellen...).

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, verstanden!

Aber kann ich nicht den ADC-Wert einfach irgendwo in den Code von Peter
einbauen und dann ne Abfrage machen, ob dieser zwischen 30-35 liegt?

Im Moment will ich ja nur einen Taster benutzen, hab ja dann auch nur
einen ADC-Wert.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm.
Theoretisch könnte man das machen.

Peter's Code geht von zwei Prämisse aus:
* Alle Taster hängen an einem Port und werden von dort
  gemeinsam als 1 Byte eingelesen.
* Für jede Taste gibt es ein Bit, welches auf 0 geht, wenn die
  Taste gedrückt wird.

Theoretisch könnte man das so umbauen, dass der Tastenzustand nicht
von einem Port kommt sondern von einer globalen Variablen, bei
der jedes Bit wieder einer Taste in der Matrix entspricht.
Die Frage ist halt nur: hast du mehr als 8 Tasten, dann geht
das nicht mehr, weil du ja bekanntlich in einem Byte nur 8
Bits unterbringst.

Daher: Schrieb dir selber was.
Du kannst ja die Grundidee von PeDa-s Code übernehmen. WM-Rahul
war ja bereits so freundlich und hat dir die Grundidee nach der
der Code funktioniert geschildert.
Sooo schwer ist das auch wieder nicht. Und wenn ich mir das alles
so anschaue, dann kannst du nicht genug Übung im Umsetzen von
Ideen bekommen.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, 8 Taster würden mir reichen.

Also müsste ich das so umbauen, dass nicht der PINB( wie in Peters
Code) den Tastenzustand angibt sondern eine Varialble z.B. "Taster".

Betätige ich nun den ersten Taster meiner Matrix, schreibt der
AD-Wandler mir einen Wert von 33, also zwischen 30-35 ins ADCH.
Das ADCH vergleiche ich dann auf einen Wert zwischen 30-35, und wenn
dies zutrifft setze ich das erste Bit meiner Variablen "Taster" auf
null.

So ungefähr?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ungefähr. Klingt nicht so schlecht.
Wenn dir der ADC einen anderen Wert liefert musst du das Bit
natürlich wieder auf 1 setzen.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ich, klappt super!

DANKE!

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich noch mal. Also mit einer LED klappt das super. Nur sobald ich einen
zweiten Wert dazu nehme und eine zweite LED schalten will, klappt das
nicht.

Kann vielleicht mal einer den Code überfliegen, ist bestimmt nur ne
Kleinigkeit. Nur mitlerweile sehe ich schon gar nichts mehr, häng schon
zu lange da vor.

Danke

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Fehler!

Die Abfrage if((ADCH <=105) && (ADCH >= 110)) ist falsch.

Muss natürlich if((ADCH <=110) && (ADCH >= 105)) heißen, bei einem Wert
von 107.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und noch mal ich.

Kann man den folgenden Term nicht irgendwie vereinfachen:

//erste LED
   if((ADCH <=35) && (ADCH >= 30))
  taster &= ~(1 << 0);

  else
  taster |= (1 << 0);

    if( get_key_press( 1<<KEY0 ))
    LED_PORT ^= 1<<LED0;

    //zweite LED
  if((ADCH <=110) && (ADCH >= 105))
  taster &= ~(1 << 1);

  else
  taster |= (1 << 1);


    if( get_key_press( 1<<KEY1 ))
      LED_PORT ^= 1<<LED1;


    //dritte LED
   if((ADCH <=207) && (ADCH >= 202))
  taster &= ~(1 << 2);

  else
  taster |= (1 << 2);

    if( get_key_press( 1<<KEY2 ))
    LED_PORT ^= 1<<LED2;

    //vierte LED
  if((ADCH <=253) && (ADCH >= 248))
  taster &= ~(1 << 3);

  else
  taster |= (1 << 3);


    if( get_key_press( 1<<KEY3 ))
      LED_PORT ^= 1<<LED3;


Weil bei 8 LED's wird es dann ein bißchen viel. Hat einer ne Idee?

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Björn,
mach doch eine Schleife in der Du z.B. ein zweidimensionales Array
abfragst ;)
z.B.:

for(in i=0;i<8;i++)
{
 if((ADCH <=wert[i][0]) && (ADCH >= wert[0][i]))
  taster &= ~(1 << 0);

  else
  taster |= (1 << 0);
}

Nur zum Bleistift ;)
Bye,
Markus

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schreib mal bite auf, wie die Intervall-Werte aussehen.
Vielleicht kann man das durch eine simple Schleife und etwas Gerechne
erzeugen.

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

Bewertung
0 lesenswert
nicht lesenswert
Schleife ist gut. Aber 2-d Array ist schlecht.

Für sowas definiert man sich eine struct.

Also: Was sind den die Variablen die eine Schaltstufe
betreffen? Da sind
 MinimalWert, Maximalwert  die den Taster identifizieren
 Weiters gehört da das zu setzende bzw. löschende Bit in taster
 Ausserdem das Bit das zu setzen bzw. zu löschen ist für die LED

Wir haben also:

struct Stufe
{
  unsigned int  ADCMin;
  unsigned int  ADCMax;
  unsigned char TasterBit;
  unsigned char LedBit;
}

Damit definieren wir uns ein Array von solchen Stufen und
initialisiern sie mit dem was wir wissen:

struct Stufe[] Stufen = {
  {  30,  35, ( 1 << KEY0 ), ( 1 << LED0 ) },
  { 105, 110, ( 1 << KEY1 ), ( 1 << LED1 ) },
  { 202, 207, ( 1 << KEY2 ), ( 1 << LED2 ) },
  { 248, 253, ( 1 << KEY3 ), ( 1 << LED3 ) }
};

unsigned char NrStufen = sizeof( Stufen ) / sizeof( *Stufen );


Damit programmieren wir:


  for( i = 0; i < NrStufen; ++i ) {

    if( ADCH >= Stufen[i].ADCMin && ADCH <= Stufen[i].ADCMax )
      taster &= ~ Stufen[i].TasterBit;
    else
      taster |= Stufen[i].TasterBit;

    if( get_key_press( Stufen[i].TasterBit ) )
      LED_PORT ^= Stufen[i].LedBit;
  }

Ich haben fertig.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, erst einmal Danke für eure Tips!

Versuch mich gerade mal an dem Code-Stück von Karl-Heinz. Respekt! Muss
ich ja gestehen dass ich da selber nie drauf gekommen wäre. Da fehlt mir
wohl noch ziemlich viel Übung. Aber ich bin ja dabei.

Soweit ist der Code klar, nur der folgende Teil macht mir Probleme:

struct Stufe[] Stufen = {
  {  30,  35, ( 1 << KEY0 ), ( 1 << LED0 ) };
  { 105, 110, ( 1 << KEY1 ), ( 1 << LED1 ) };
  { 202, 207, ( 1 << KEY2 ), ( 1 << LED2 ) };
  { 248, 253, ( 1 << KEY3 ), ( 1 << LED3 ) };
};

Müsste doch eigenlich:

struct Stufe Stufen[] = {
  {  30,  35, ( 1 << KEY0 ), ( 1 << LED0 ) };
  { 105, 110, ( 1 << KEY1 ), ( 1 << LED1 ) };
  { 202, 207, ( 1 << KEY2 ), ( 1 << LED2 ) };
  { 248, 253, ( 1 << KEY3 ), ( 1 << LED3 ) };
};

heißen. Oder bin ich da auf dem Holzweg?

Leider erzeugt beides bei mir einen Fehler. Kommt immer ...c:57:
Fehler: Syntaxfehler vor »[«-Zeichen

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, dummer Fehler!

Jetzt gehts, muss natürlich so heißen:

struct Stufe Stufen[] = {
  {  30,  35, ( 1 << KEY0 ), ( 1 << LED0 ) },
  { 105, 110, ( 1 << KEY1 ), ( 1 << LED1 ) },
  { 202, 207, ( 1 << KEY2 ), ( 1 << LED2 ) },
  { 248, 253, ( 1 << KEY3 ), ( 1 << LED3 ) }
};


Danke und Gruß

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

der Code funktionier soweit einwandfrei!

Nun will ich ne Kleinigkeit ändern. Nehmen wir mal das Codestück oben
von Karl Heinz:

Wir haben also:

struct Stufe
{
  unsigned int  ADCMin;
  unsigned int  ADCMax;
  unsigned char TasterBit;
  unsigned char LedBit;
}

Damit definieren wir uns ein Array von solchen Stufen und
initialisiern sie mit dem was wir wissen:

struct Stufe[] Stufen = {
  {  30,  35, ( 1 << KEY0 ), ( 1 << LED0 ) },
  { 105, 110, ( 1 << KEY1 ), ( 1 << LED1 ) },
  { 202, 207, ( 1 << KEY2 ), ( 1 << LED2 ) },
  { 248, 253, ( 1 << KEY3 ), ( 1 << LED3 ) }
};

unsigned char NrStufen = sizeof( Stufen ) / sizeof( *Stufen );


Damit programmieren wir:


  for( i = 0; i < NrStufen; ++i ) {

    if( ADCH >= Stufen[i].ADCMin && ADCH <= Stufen[i].ADCMax )
      taster &= ~ Stufen[i].TasterBit;
    else
      taster |= Stufen[i].TasterBit;

    if( get_key_press( Stufen[i].TasterBit ) )
      LED_PORT ^= Stufen[i].LedBit;
  }

Hierbei wird ja bei drücken des entsprechenden Tasters eine LED
eingeschaltet. Nun will ich bei einem Taster keine LED schalten,
sondern was anderes machen. Ist doch aber bei der Form des Codes jetzt
gar nicht mehr möglich, oder?

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
for( i = 0; i < NrStufen; ++i ) {

    if( ADCH >= Stufen[i].ADCMin && ADCH <= Stufen[i].ADCMax )
      taster &= ~ Stufen[i].TasterBit;
    else
      taster |= Stufen[i].TasterBit;

    if( get_key_press( Stufen[i].TasterBit ) )
    {
      LED_PORT ^= Stufen[i].LedBit;
      machnochwas();
      machwasanderes();
    }
  }

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab es jetzt anders versucht. Klappt aber noch nicht wirklich...

if(!(PIND & (1 << PIND3)))
  taster &= ~(1 << 0);

else
  taster |= (1 << 0);

Mit diesem Codestück will ich, wenn ein Lowpegel a PORTD, PIN3 anliegt,
dass erste Bit der Variablen Taster löschen.

Ist das so richtig?

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Darf ich einen Vorschlag machen?
Besorg dir AVR-Studio, installiere es und lass deine
Programme unter Kontrolle des Simulators laufen. Der Simulator
lässt dich auch auf seinen virtuellen Ports Werte einstellen.
Damit kannst du wunderbar testen was denn in deinem Programm
wirklich vor sich geht; welche if genommen werden, welche nicht;
wie Ports ihre Werte verändern; welche Werte die Variablen haben etc.

> if(!(PIND & (1 << PIND3)))
>   taster &= ~(1 << 0);
>
> else
>   taster |= (1 << 0);
>
> Mit diesem Codestück will ich, wenn ein Lowpegel a PORTD, PIN3
> anliegt, dass erste Bit der Variablen Taster löschen.

Und was soll passieren, wenn kein Lowpegel anliegt?
Im Moment wird dann das Bit wieder gesetzt.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es soll so funktionieren wie hier:

if((ADCH <=110) && (ADCH >= 105))
  taster &= ~(1 << 1);

  else
  taster |= (1 << 1);


    if( get_key_press( 1<<KEY1 ))
      LED_PORT ^= 1<<LED1;

Dort wird ja bei gültiger if-Anweisung die LED1 ein- und ausgeschaltet.
Klappt einwandfrei.

Das soll hierbei:

if(!(PIND & (1 << PIND3)))
  taster &= ~(1 << 0);

  else
  taster |= (1 << 0);

    if( get_key_press( 1<<KEY0 ))
      LED_PORT ^= 1<<LED1;

auch passieren, nur mit ner anderen if-Anweisung. Nur dabei klappt es
nicht! Möchte das dort bei einem Tasterdruck, also einem kurzen
Low-Pegel die LED eingeschaltet wird.

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit nem anderen Pin z.B. PD2 klappt es.

Kann es daran liegen, dass ich zusätzlich noch den INT1-Interrupt
verwende, der an PD3 ausgelöst wird?

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.