Forum: Mikrocontroller und Digitale Elektronik Taster Automat


von AVR (Gast)


Lesenswert?

Hallo, folgende Situation, ich habe z.B drei Taster am Mikrocontroller , 
und möchte 7 Zustände darstellen:

0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

folgender Pseudocode:

WENN TASTER 1 DANN ZUSTAND 1
WENN TASTER 2 DANN ZUSTAND 2
WENN TASTER 1 UND TASTER 2 DANN ZUSTAND 3
WENN TASTER 3 DANN ZUSTAND 4
WENN TASTER 1 UND TASTER 3 DANN ZUSTAND 5
WENN TASTER 2 UND TASTER 3 DANN ZUSTAND 6
WENN ALLE TASTER DANN ZUSTAND 7
WENN KEIN TASTER und VORHER IRGENDEIN TASTER GEDRÜCKT DANN ZUSTAND 0

zB wenn drei Taster gleichzeitig gedrückt sind und ich die ersten beiden 
Taster loslasse, soll das Programm in Zustand 4 gehen.

wie kann man das geschickt im C Code zB für einen AVR verarbeiten.

von astroscout (Gast)


Lesenswert?

Ich würde das folgendermaßen realisieren:

zustand = taster1 + 2*taster2 + 4*taster3

Hierbei hat tasterx den Wert 0, wenn Taster nicht gedrpckt ist und denr 
Wert 1 wenn der Taster gedrückt ist.

Beachte jedoch, dass die Taster ggf. noch entprellt werden müssen.

von AVR (Gast)


Lesenswert?

Ich habe bereits ne Funktion taster1(), taster2(),taster3() mit return 1 
bei gedrückt und return 0 bei losgelassen.


Wie kann ich das noch machen, dass die if Routinen nur einmal ausgeführt 
werden und der Zustand 0 nur einmal ausgeführt wird wenn vorher Zustand 
1-7 ausgeführt war.



if (Zustand==0)
{
  fuhereFunktionAus(0);

}

if (Zustand==1)
{
    fuhereFunktionAus(0);

}

von Mike M. (mikeii)


Lesenswert?

> if (Zustand==0)
> {
>   fuhereFunktionAus(0);
>
> }
>
> else if (Zustand==1)
> {
>     fuhereFunktionAus(0);
>
> }

von astroscout (Gast)


Lesenswert?

AVR schrieb im Beitrag #3376346:
> Wie kann ich das noch machen, dass die if Routinen nur einmal ausgeführt
> werden

Mach das am besten mit switch case:
http://www.c-howto.de/tutorial-verzweigungen-switch-case.html

AVR schrieb im Beitrag #3376346:
> und der Zustand 0 nur einmal ausgeführt wird wenn vorher Zustand
> 1-7 ausgeführt war.

Es gibt nur 8 Zustände, oder? Dann ist zwingend vor Zustand 0 immer 
Zustand 1-7 aktiv gewesen. Oder habe ich das falsch verstanden?

von Avr A. (colombo010)


Lesenswert?

Ja das hast du richtig verstanden, aber wenn ich das mit switch case 
mache kann  kann ich nur auf Zustand abfragen. und falls ich gedrückt 
halte, wird das Programm ständig die Anweisung ausführen, das soll ja 
eben verhindert werden oder sehe ich das falsch

switch(Zustand)
{
  case 0: fuehreFunktionAus(0); break;
  case 1: fuehreFunktionAus(0); break;
  ...
  ...
}

von cppler (Gast)


Lesenswert?

Stichwort hast Du ja selber vorgegeben das nennt sich Statemachine.
Üblicherweise definiert man die Zustände via defines und wertet das in 
einem switch/case aus.
Wenn zu den Übergängen noch Sonderbehandlungen kommen bzw. das flexibel 
werden soll schreibst Du in die cases die Funktionen für den Übergang.

von c-hater (Gast)


Lesenswert?

AVR schrieb im Beitrag #3376303:

> Hallo, folgende Situation, ich habe z.B drei Taster am Mikrocontroller ,
> und möchte 7 Zustände darstellen
> [...]

Schon falsch. Du hast nicht erkannt, daß du eigentlich acht Zustände 
darstellen willst.

> WENN KEIN TASTER

Aha, da isser ja.

> und VORHER IRGENDEIN TASTER GEDRÜCKT DANN ZUSTAND 0

Hier verläßt du das Gebiet der boolschen Logik, denn du führst hier eine 
temporale Komponente ein. Nämlich ein Bit, in dem steht, ob "zuvor" eine 
Taste gedrückt wurde. Da wird es das erste Mal spannend bei der 
Definition von "zuvor". Das kann nämlich bedeuten "irgendwann zuvor" 
oder "irgendwann seit dem letzten ZUSTANDx" (wahrscheinlich ist wohl 
ZUSTAND0 gewünscht).

Und natürlich muß du dir unabhängig von der Definition dieses "zuvor" 
erstens das "zuvor" merken und zweitens als zusätzliches Eingangsbit 
deiner Statemachine verwenden. Die bekommt dadurch zwingend 16 statt 8 
Zustände. Das hast du wohl nicht erkannt...

von Avr A. (colombo010)


Lesenswert?

Was hat denn die ZusätzlichE Übergangsbedingung damit zu tun, dass man 
aufeinmal 16 Zustände bekommt. Es gibt nach wie vor 8 Zustände.

Hier kurz mal was geschrieben was mir auf die schnelle eingefallen ist.

char StatusVariable=0;

switch(Zustand)
{
  case 0:
   if(StatusVariable !=0){
  fuehreFunktionAus(0);
        }
  StatusVariable=0

  break;

 case 1:
       if (StatusVariable !=1){
  fuehreFunktionAus(1);
  }
  StatusVariable=1;
  break;
  ...
.....

  case 7:
       if (StatusVariable !=7){
  fuehreFunktionAus(6);
        }
  StatusVariable=7;
  break;

}

von astroscout (Gast)


Lesenswert?

avr avr schrieb:
> Was hat denn die ZusätzlichE Übergangsbedingung damit zu tun, dass man
> aufeinmal 16 Zustände bekommt. Es gibt nach wie vor 8 Zustände.

betrachtet man das ganze streng als Zustandsautomat, so hätte man 
tatsächlich 16 Zustände, die von dem Zustand er Taster (8 Zustände) 
sowie der Statusvariable (2 Zustände) abhängen, also 2*8=16 Zustände

Praktisch gesehen würde ich es jedoch auch so realisieren wie "avr avr"

von Peter D. (peda)


Lesenswert?

AVR schrieb im Beitrag #3376303:
> zB wenn drei Taster gleichzeitig gedrückt sind

Dazu ist kein Mensch aus der Sicht eines MC in der Lage.
Selbst innerhalb 50ns ist nicht garantiert gleichzeitig.

Aber es gibt Lösungen dafür. Die Einschränkung dabei ist, das 
gleichzeitig muß innerhalb eines festgelegten Zeitfensters oder bis zu 
Loslassen einer Taste erfolgen.

Beitrag "Re: Universelle Tastenabfrage"

: Bearbeitet durch User
von kaplic (Gast)


Lesenswert?

Hier wieder der Verweis auf die Routinen zum Taster entprellen:
http://www.mikrocontroller.net/articles/Entprellung

Bei den Komfortroutinen kann man die Tasten hervorragend mit einer Maske 
abfragen!

Mir stellt sich nur die Frage, ob man immer in den gewünschten Zustand 
kommt, da man ja nie die gewünschten Tasten synchron drücken kann, es 
sei den die Taktfrequenz des uC ist niedrig genug.

von Avr A. (colombo010)


Lesenswert?

Das Entprellen ist schon mit eingebaut es geht um den Zustandsautomat.

Das Ziel ist auch nicht das synchrone Drücken.
Du kannst die Tasten nacheinander drücken zb. hälst du einen Taster 
gedrückt und drückst dabei den zweiten,  dann soll er in den 
dazugehörigen Zustand übergehen.

von Peter D. (peda)


Lesenswert?

avr avr schrieb:
> Das Entprellen ist schon mit eingebaut es geht um den Zustandsautomat.

Dann läßte eben die 2 Zeilen weg.

von cppler (Gast)


Lesenswert?

Zeichne Dir erstmal auf einem Blatt Papier alle Deine Zustände und deren 
Transitionen auf.
Dann überlege Dir welche Zustände Sinn ergeben und wie deren 
Zusammenhänge sind.
So wie das bis jetzt verstehe hast Du nur bestimmte Tastendrücke die in 
einen bestimmten Zustand führen sollen alle anderen sind Zustand0 = 
default.

von Avr A. (colombo010)


Lesenswert?

alle anderen? Ich hab doch schon ne Lösung vorgeschlagen.

von cppler (Gast)


Lesenswert?

Lies Dir nochmal Deinen ersten Post durch, Du bist doch der TE ?
Was fällt Dir dabei auf ?

von c-hater (Gast)


Lesenswert?

avr avr schrieb:

> Was hat denn die ZusätzlichE Übergangsbedingung damit zu tun, dass man
> aufeinmal 16 Zustände bekommt. Es gibt nach wie vor 8 Zustände.

Ob man das als zusätzliche Übergangsbedingung auffaßt oder als 
Erweiterung des Zustandsraums spielt von der Funktion her keine Rolle, 
sehr wohl aber für die Implementierung.

Die Variante mit den 16 Zuständen läßt nämlich eine um Längen fixere 
Implementierung per Lookup-Tabelle zu, die sich obendrein noch durch 
eine konstante Laufzeit auszeichnet, was manchmal auch nicht ganz 
unwichtig ist. Und, last but not least, es schreibt sich auch noch viel 
schneller als endlose switch..case- oder if..elseif..else-Wüsten.

von Jobst M. (jobstens-de)


Lesenswert?

avr avr schrieb:
> Du kannst die Tasten nacheinander drücken zb. hälst du einen Taster
> gedrückt und drückst dabei den zweiten,  dann soll er in den
> dazugehörigen Zustand übergehen.

Und woher weiß der Controller, dass er nicht noch auf den dritten Taster 
warten soll? Auf den zweiten wartet er ja wohl auch ...

Oder werden bei dem drücken von zwei Tastern immer alle damit 
auszulösenden Funktionen für jede Kombination ausgeführt?

Beschreib doch mal genau, was Du überhaupt vor hast. Siehe Netiquette - 
vor allem Punkt 3


Gruß

Jobst

von Amateur (Gast)


Lesenswert?

Nimm 'ne ordentliche Tastenerkennung, z.B. die von P. Dannegger und 
Google dann mal nach boolescher Algebra.

von AVR (Gast)


Lesenswert?

Die von mir gepostete Lösung hab ich nun getestet, sie Funktioniert.

Es soll folgendermaßen Funktionieren. Es gibt 3 Taster die 8 Zustände 
darstellen. Jeder Zustand hat eine Funktion einmal auszuführen.

 zB: Es wird der 1.Taster gedrückt gehalten und dabei der zweite 
gedrückt, dann springt das Programm in Zustand 3. In diesem Zustand wird 
eine beliebige Funktion nur einmal ausgeführt. Wenn also die beiden 
Taster weiterhin gedrückt gehalten werden soll die Funktion nicht 
nochmal ausgeführt werden.

Nun wird sagen wir mal Taster 2 losgelassen, dann landet man im Zustand 
1. Es passiert das Gleiche wie in allen Zuständen, eine beliebige 
Funktion wird einmalig ausgeführt.

Der Zustand 0 soll nur erreicht werden, wenn vorher irgendein oder 
mehrere Taster gedrückt waren.

von AVR (Gast)


Lesenswert?

"Amateur (Gast)"

Toller Beitrag, Ich hab doch bereits geschrieben, dass ich eine 
Tastenerkennung mit Entprellung habe, mittlerweile funktionieren die 
Zustände auch.

von LostInMusic (Gast)


Lesenswert?

Alle 20 ms ausführen:

1
StateOld = State;
2
State    = (KeyC<<2) | (KeyB<<1) | (KeyA<<0);  
3
4
if (StateOld != State) {  
5
  Action(State)
6
  };

wobei die int-Variablen KeyA, KeyB, KeyC die (ggf. entprellten) 
Tastenzustände enthalten:

KeyX = 0(1) wenn Taster X up(down)

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.