Forum: Mikrocontroller und Digitale Elektronik Tasten entprellen


von Björn (Gast)


Angehängte Dateien:

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

von inoffizieller WM-Rahul (Gast)


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.

von Björn (Gast)


Lesenswert?

Also der AD-Wandler ist eingelesen. Entprechender Wert steht in ADCH.

Was meinst du mit Tasten decodieren?

von inoffizieller WM-Rahul (Gast)


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...).

von Björn (Gast)


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.

von Karl heinz B. (kbucheg)


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.

von Björn (Gast)


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?

von Karl heinz B. (kbucheg)


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.

von Björn (Gast)


Lesenswert?

Hab ich, klappt super!

DANKE!

von Björn (Gast)


Angehängte Dateien:

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

von Björn (Gast)


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.

von Björn (Gast)


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?

von Markus (Gast)


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

von inoffizieller WM-Rahul (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


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.

von Björn (Gast)


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

von Björn (Gast)


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ß

von Björn (Gast)


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?

von inoffizieller WM-Rahul (Gast)


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();
    }
  }

von Björn (Gast)


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?

von Karl heinz B. (kbucheg)


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.

von Björn (Gast)


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.

von Björn (Gast)


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?

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.