Forum: Mikrocontroller und Digitale Elektronik "State Machines": Anzahl States minimieren oder maximieren?


von Roman K. (rk_aus_s)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Ich "baue" zur Zeit meine allererste State Machine (mit Code) und stehe 
vor vielen grundsätzlichen Fragen. Eine Frage beschäftigt mich ziemlich 
stark:

Sollte die Anzahl der States (also Zustände) so klein wie möglich 
gehalten werden, oder sollten die eizelnen States besser so einfach wie 
möglich gehalten werden, dafür werden es aber einige States mehr?

Um meine Frage zu veranschaulichen habe ich ein rein fiktives Beispiel 
im Bild (Dateianhang) skizziert:

- Im ersten Fall schalte ich in State 7 ein Relais, warte bis drei 
Minuten vergangen sind, dann folgt eine Abfrage (Helligkeit) und 
aufgrund dessen wird der nächste State (entweder 8 oder 9) entschieden.

- Im zweiten Fall schalte ich in State 7 NUR ein Relais. Dann gehe ich 
zu State 8 wo ich NUR warte bis 3 Minuten vorbei sind. Dann gehe ich zu 
State 9 wo die Abfrage (Helligkeit) durchgeführt wird, aufgrund dessen 
wird der nächste State (entweder 10 oder 11) entschieden.

Was ist "sauberer", "klüger" oder entspricht eher dem Wesen einer State 
Machine?

Ich hoffe, hier keine allzu doofe Frage gestellt zu haben...

Grüsse
Roman

: Verschoben durch User
von Bernd K. (prof7bit)


Lesenswert?

Du implementierst so viele Zustände wie Du brauchst. 3 Minuten Warten 
ist eindeutig ein separater Zustand. Irgendwas einschalten sind Dinge 
die bei Zustandsübergängen passieren, es verweilt nicht im Zustand 
"Einschalten", das ist überhaupt kein Zustand, das ist eine Aktion. Es 
verweilt im Zustand "Mit eingeschaltetem Relais 3 Minuten warten". Das 
ist ein Zustand.

: Bearbeitet durch User
von NichtWichtig (Gast)


Lesenswert?

naja, der Zustand Einschalten hat durchaus Sinn.

Zustand AUS
.. einschalttrigger
Zustand EINSCHALTEN
.. überwachung, timer aktivieren (z.B. 1s)
Zustand EINGESCHALTET (z.B. Rückmeldung durch messen von Spannung/Strom)
..  wird die Rückmeldung EIN eher geliefert als der Alarmtimer aus 
Zustand Einschalten abläuft ist alles gut, Timer stoppen.
..  sollte das Timeout im, Zustand EINSCHALTEN eintreffen ist das 
Einschalten gescheitert => Fehlerbehandlung

Zum Beispiel Bremslichtüberwachung am PKW

UML bietet eine übersichtliche statemachine an.
je weniger Gimmicks intern verbaut sind desto logischer ist die UML SM 
lesbar.

Zaubern man in einem state X trigger und Abfragen rein wird das zwar auf 
den ersten Blick kompakt, aber je mehr Zeug darin steckt desto schwerer 
wartbar.


https://de.wikipedia.org/wiki/Zustandsdiagramm_%28UML%29

von Falk B. (falk)


Lesenswert?

@Roman K. (rk_aus_s)

>Sollte die Anzahl der States (also Zustände) so klein wie möglich
>gehalten werden,

Nein.

> oder sollten die eizelnen States besser so einfach wie
>möglich gehalten werden, dafür werden es aber einige States mehr?

Jain.

Es muss eher möglichst gut lesbar sein und in den States darf man nicht 
warten, bestenfalls wenige us, in bestimmten Fällen (sehr langsame FSM) 
vielleicht auch Millisekunden.

>- Im ersten Fall schalte ich in State 7 ein Relais, warte bis drei
>Minuten vergangen sind, dann folgt eine Abfrage (Helligkeit) und
>aufgrund dessen wird der nächste State (entweder 8 oder 9) entschieden.

FAIL! Siehe Multitasking!

>- Im zweiten Fall schalte ich in State 7 NUR ein Relais. Dann gehe ich
>zu State 8 wo ich NUR warte bis 3 Minuten vorbei sind.

Ist so wie es gezeichnet ist immer noch falsch bzw. mehrdeutig. Der 
Zustand Warten ist an sich OK, WENN er immer wieder verlassen wird und 
dort nur ein Zähler läuft. Aber es darf mal sicher kein delay(3min) dort 
drinstehen!

>State 9 wo die Abfrage (Helligkeit) durchgeführt wird, aufgrund dessen
>wird der nächste State (entweder 10 oder 11) entschieden.

Im Prinzip bist du mit der unteren Version in der richtigen Richtung 
unterwegs. Siehe auch Statemachine.

von georg (Gast)


Lesenswert?

Roman K. schrieb:
> Im ersten Fall schalte ich in State 7 ein Relais, warte bis drei
> Minuten vergangen sind,

Grundsätzlich werden Änderungen bei einer Statemachine nicht in einem 
Zustand  durchgeführt, sondern beim Übergang von einem Zustand zum 
anderen. Das sollte schon deshalb logisch sein, weil ja das Einschalten 
des Relais den realen Zustand verändert, danach ist eben das Relais on.

Wechsel zu einem anderen Zustand werden durch Ereignisse ausgelöst, z.B. 
Änderungen an einem Eingang, auch das Ablaufen eines Timers kann einen 
neuen Zustand erfordern.

Der grosse Vorteil dabei: man macht eine Tabelle mit den Zuständen und 
den möglichen Ereignissen, für jede Kombination gibt es eine Funktion, 
die eine Aktion durchführt wie Relais on und danach den neuen Zustand 
bestimmt. Dadurch ist für jede mögliche Kombination von Zustand und 
Ereignis die Reaktion des Systems definiert, das ist mit anderer 
Softwarestruktur nur schwer erreichbar. Zumindest muss man sich über 
jede mögliche Kombination Gedanken machen, damit man in die Tabelle was 
eintragen kann. So entsteht sehr sichere Software.

Georg

von Eric B. (beric)


Lesenswert?

Falk B. schrieb:
> Zustand Warten ist an sich OK, WENN er immer wieder verlassen wird und
> dort nur ein Zähler läuft. Aber es darf mal sicher kein delay(3min) dort
> drinstehen!

Unsinn! Das hängt ganz von der Implementierung der delay() Funktion ab. 
Falls diese den zugehörigen Task zum Schlafen bringt, einen Timer 
startet, und den Task dann wenn der Timer abgelaufen ist, wieder zum 
Leben erweckt, ist da alles i.O.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Je mehr mögliche Zustände es gibt desto mehr unzulässige Zustände gibt 
es, die alle abgefangen werden sollten. Insofern ist eine minimale 
Anzahl besser.

von Gerd E. (robberknight)


Lesenswert?

Eric B. schrieb:
> Falk B. schrieb:
>> Zustand Warten ist an sich OK, WENN er immer wieder verlassen wird und
>> dort nur ein Zähler läuft. Aber es darf mal sicher kein delay(3min) dort
>> drinstehen!
>
> Unsinn! Das hängt ganz von der Implementierung der delay() Funktion ab.
> Falls diese den zugehörigen Task zum Schlafen bringt, einen Timer
> startet, und den Task dann wenn der Timer abgelaufen ist, wieder zum
> Leben erweckt, ist da alles i.O.

ganz richtig.

Das Konzept der Abarbeitung der Statemachine und die Möglichkeiten des 
verwendeten Multitask- oder Multithread-Systems (z.B. eines RTOS) 
fließen auch mit in das Design der Statemachine mit ein.

Wenn die Statemachine durch regelmäßige Aufrufe z.B. einer 
handle_statemachine()-Funktion aus einem Main-Loop heraus bearbeitet 
wird, brauche ich relativ kleinteilige States, bei denen ich jeweils 
prüfe, ob die Bedingung zum Übergang in einen der nächsten States 
erfüllt ist (3 Minuten Timer abgelaufen, dann xyz). Denn jedesmal wenn 
mein Handler aufgerufen wird, muss ich den ganzen Code für diesen State 
durchlaufen.

Läuft die Statemachine dagegen als eigener Thread, der jederzeit ein 
delay(3min) aufrufen darf und das RTOS lässt dann in der Zeit andere 
Threads laufen, dann können die States auch "dicker" werden und ich muss 
nicht jede Kleinigkeit als eigenen State modellieren. Es müssen nur die 
Übergänge in andere States (inkl. Fehler-States) stimmen. Macht das 
ganze etwas übersichtlicher. Aber Multithreading hat dafür andere Tücken 
wie z.B. Deadlocks etc. die ich ausschließen muss.

von Max D. (max_d)


Lesenswert?

In der Praxis erfordern die meisten state-machines eine zeitnahe 
Reaktion auf umweltbedingungen (bestes Beispiel: User Eingaben), dann 
ist ein delay egal welcher Form jenseits einiger Millisekunden keine 
Option mehr.
Wenn meine Applikation so linear ist, dass ich viele states hab in denen 
einfach nur gewartet wird, dann braucht ich normal auch keine 
state-machine um das zu modellieren.

von Cyblord -. (cyblord)


Lesenswert?

Max D. schrieb:
> In der Praxis erfordern die meisten state-machines eine zeitnahe
> Reaktion auf umweltbedingungen (bestes Beispiel: User Eingaben), dann
> ist ein delay egal welcher Form jenseits einiger Millisekunden keine
> Option mehr.
> Wenn meine Applikation so linear ist, dass ich viele states hab in denen
> einfach nur gewartet wird, dann braucht ich normal auch keine
> state-machine um das zu modellieren.

Was hat denn das Konzept State-Machine mit der Reaktionsgeschwindigkeit 
zu tun?

> In der Praxis erfordern die meisten state-machines eine zeitnahe
> Reaktion auf umweltbedingungen

Halte ich für eine haltlose Behauptung.

von LostInMusic (Gast)


Lesenswert?

Mit welcher Frequenz wird die FSM denn getaktet? Also wenn die z. B. 100 
mal pro Sekunde aufgerufen wird und man will sie minimalistisch mit 
einer Zustandsvariablen realisieren, dann komme ich bei 3 min 
Wartezeit auf 18000 Zustände. Auf zwei Werte, z. B. 18000 und 0, muss 
man testen und die entsprechenden Aktionen ausführen, also das Relais 
einschalten bzw. auf Helligkeit prüfen und das Licht passend dimmen.

Außer dem Drei-Minuten-Software-Timer muss die FSM für dieses einfache 
Problem keine weiteren Komponenten haben. Aktionen wie "Relais schalten" 
und "Helligkeit testen" Zustände zuzuordnen, ist natürlich sinnfrei. Das 
Konzept der Zustandsmaschine beruht ja gerade darauf, genau zwischen 
Zuständen, Zustandsübergängen und Aktionen zu unterscheiden.

von Eric B. (beric)


Lesenswert?

LostInMusic schrieb:
> Mit welcher Frequenz wird die FSM denn getaktet?

Nicht. Eine SM taktet man nicht, die reagiert auf Events/Ereignisse.

> Also wenn die z. B. 100
> mal pro Sekunde aufgerufen wird und man will sie minimalistisch mit
> einer Zustandsvariablen realisieren, dann komme ich bei 3 min
> Wartezeit auf 18000 Zustände.

Nein, dann komm ich auf 1 Zustand, nämlich "Warte bis 3min abgelaufen 
sind", und ich implementiere mir einen Timer, der nach 3 Minuten genau 
dieses Event an die SM schickt. (z.B. mit einem Zähler der jede 10ms 
hochgezählt wird und bei 18000 das Event auslöst).

von LostInMusic (Gast)


Lesenswert?

@Eric B:
Ich fasse den von Dir erwähnten Timer halt auch als Zustandsmaschine 
auf. Sie reagiert auf den Clock-"Tick", den sie irgendwoher (evtl. 
Hardware) bekommen muss, und ihre Reaktion darauf ist das Herunterzählen 
der Timer-Variable - die, die innerhalb der 3 min dann 18000 Zustände 
annimmt. So what?

Deine alternative Sichtweise, bei der Du den Timer als separates System 
ausklammerst, ist natürlich legitim und dann lautet die korrekte Antwort 
"Es ist eine Zustandsmaschine mit zwei Zuständen" (der Wechsel vom einen 
zum anderen erfolgt zum Zeitpunkt 3 min). Diese Darstellung finde ich 
aber für jemanden, der das Konzept Zustandsmaschine offensichtlich noch 
gar nicht verstanden hat, didaktisch wenig wertvoll.

von F. F. (foldi)


Lesenswert?

NichtWichtig schrieb:
> Zustand EINSCHALTEN

Irgendwie hast du das Thema nicht verstanden.

von Falk B. (falk)


Lesenswert?

@ Eric B. (beric)

>> Zustand Warten ist an sich OK, WENN er immer wieder verlassen wird und
>> dort nur ein Zähler läuft. Aber es darf mal sicher kein delay(3min) dort
>> drinstehen!

>Unsinn! Das hängt ganz von der Implementierung der delay() Funktion ab.
>Falls diese den zugehörigen Task zum Schlafen bringt, einen Timer
>startet, und den Task dann wenn der Timer abgelaufen ist, wieder zum
>Leben erweckt, ist da alles i.O.

Ja, wenn. Wollen wir mal wetten, daß der OP ebenso wie 99% der hier 
heute und auch in Zukunft Mitlesenden mal ganz sicher KEIN RTOS mit 
einem derartigen delay() haben? Sonder eher das klassisch blockierende?

von Falk B. (falk)


Lesenswert?

@Eric B. (beric)

>> Mit welcher Frequenz wird die FSM denn getaktet?

>Nicht. Eine SM taktet man nicht, die reagiert auf Events/Ereignisse.

Stimmt so allgmein auch nicht. Nicht alles läuft unter QT und ähnlichen 
Frameworks. Wir wollen doch mal eher bei den EINFACHEN, Grundlegenden 
Konzepten anfangen und die Neulinge nicht mit den allerneusten 
RTOS-Geschichten überfordern.

Und da wird eine FSM getaktet, indem sie periodisch aufgerufen wird.

von Cyblord -. (cyblord)


Lesenswert?

Falk B. schrieb:
> Und da wird eine FSM getaktet, indem sie periodisch aufgerufen wird.

Was soll man denn da aufrufen?
Man kann als Event in eine FSM z.B. ein "Event_Timer_Tick" reingeben. 
Alle 10 ms z.B.
Ein Zustand kann dann damit arbeiten, z.B. warten.

von Arne (Gast)


Lesenswert?

Hallo TO,

schau dir doch mal die SDL an 
(https://en.wikipedia.org/wiki/Specification_and_Description_Language)

Dort speziell das Kapitel "Behaviour" und versuche, deine Statemachine 
in SDL zu formulieren, das hilft dir vllt. beim systematischen 
Erarbeiten des Sachverhaltes. Für dein Vorhaben brauchst du die Symbole 
State, Input, Output, Decision, Start/Stop Timer, Plain Code

Für mich persönlich war das Erlernen und Verstehen dieser Syntax extrem 
hilfreich zum Erstellen von sauberen Statemachines und zum Diskutieren 
bzw. Darstellen von Funktionalitäten eines Systems für andere.

PS: Zu der Frage, ob Messen ein eigener Zustand ist:
Wenn die Messung viel Zeit benötigt, dann ggf eigener Zustand.
Bei Eintritt in den "Mess-Zustand" Messung starten
Bei Ereignis "Messung abgeschlossen" Ergebnis abholen, Auswerten, 
Aktion, Folgezustand

Eine andere Möglichkeit wäre es, die Messung immer im Hintergrund laufen
zu lassen, sodass immer ein aktuelles Ergebnis im Zugriff ist, dann muss
nicht gewartet werden. Aber es gibt auch noch viele andere 
Möglichkeiten, hängt letztlich von der Erfahrung ab, die geeignete 
Methode zu wählen.

von Arne (Gast)


Lesenswert?

PS:

Das Starten eines Timers ist in SDL eine Aktion
Das Ablaufen eines Timers ist in SDL ein Input (also Event)
Deine Abfrage Hell/dunkel ist eine Decision. Abhängig von der Decision
können unterschiedliche Funktionen, Outputs und Folgezustände kommen.

Oben steht immer der aktuelle Zustand, unten die Folgezustände.
Wenn jeder Strang 
Zustand->Input->Decision/Funktion...->Output->Folgezustand
aufgeschrieben wurde, ist die Statemachine vollständig beschrieben.

Zur Übersicht nimmt man meistens noch ein Statechart, in dem nur
Zustände und Übergänge zu sehen sind.

von Horst S. (Gast)


Lesenswert?

Vielleicht mal nen Blick auf die Implementierung werfen.
1.Fall
1
{
2
   SetRelaisOn();
3
   Wait3m();
4
   int x= GetBrightness();
5
   if (x >= Limit)
6
     DoSomething();
7
   else
8
      DoSomethingElse();
9
}
Irgendwie lässt sich das so ganz ohne Statemachine runterproggen

2.Fall
1
//Called from 1ms interrupt
2
TheStateCallback()
3
{
4
   static int state = 0;
5
   static uint32_t timerVal = 0;
6
7
   switch (state)
8
   {
9
      case 0: 
10
         SetRelaisOn();
11
         state++;
12
         break;
13
14
      case 1: 
15
         timerVal++;
16
         if(timerVal >= THREE_MIN)
17
         {
18
            timerVal = 0;
19
            state++;
20
         }
21
         break;
22
23
      case 2: 
24
         int x= GetBrightness();
25
         if (x >= BRIGHTNESSLIMIT)
26
           state = 3;
27
         else
28
           state = 4;
29
         break;
30
31
      case 3: // Do something
32
         ...
33
         state= 0;
34
         break;
35
36
      case 4: // Do something else
37
         ...
38
         state= 0;
39
         break;
40
   }
41
42
}
Das ist so der asynchrone Klassiker (für'n AVR).
Man kann sich jetzt noch streiten, ob man die Wartefunktionen um nen 
Callback, einen AfterwaitState, oder sonstewas erweitert (dann kann man 
auch parametriert an unterschiedlichen Stellen warten, ggf. ne 
Cancelfunktion einbauen, etc).
Auch kann man für den Statewert nen Enum bauen, ecetera, ecetera.

Man kann sich auch darüber streiten, ob State 3 und 4 so überhaupt 
gebraucht werden (die Anweisungen können auch direkt in die Entscheidung 
von State 2). Im Grunde genommen geht's doch nur darum, die 
Funktionsteile so zu gestalten, wie sie optimal wiederverwendet werden 
können.

(und man sollte daran denken, das Relais auch wieder auszuschalten)

von Stefan F. (Gast)


Lesenswert?

Kleiner Tipp, um den Code besser lesbar zu machen: Benutze enum statt 
Zahlen.

Dann steht dort anstelle der 2 CHECKBRIGHTNESS und wenn man mal 
mittendrin etwas einfügt, muss man nicht alle alle folgenden Zahlen 
ändern (bzw. eine chaotische Nummerierung hinnehmen)..

von Possetitjel (Gast)


Lesenswert?

Stefanus F. schrieb:

> Kleiner Tipp, um den Code besser lesbar zu machen:
> Benutze enum statt Zahlen.

Vor allem würde ich auf "state++" verzichten. Zustände
eines endlichen Automaten sind im allgemeinen Fall nicht
geordnet; auch ist der Folgezustand nur in sehr einfachen
Fällen gerade der Zustand mit der nächsthöheren Nummer.

von c-hater (Gast)


Lesenswert?

Max D. schrieb:

> In der Praxis erfordern die meisten state-machines eine zeitnahe
> Reaktion auf umweltbedingungen

Es ist noch viel schlimmer: state machines sind schon vom Grundkonzept 
her  völlig "zeitlos". Sie reagieren ausschließlich auf Ereignisse. 
Allerdings kann so ein Ereignis auch der Ablauf einer Zeitspanne sein. 
Natürlich müßte dazu die state machine bei einer Transition eben diesen 
Ablauf starten.

Sie kann aber nicht selber den Ablauf dieser Zeitspanne sicherstellen. 
Denn dann ist sie keine state machine mehr, weil sie vor Ablauf der 
Zeitspanne auf andere Ereignisse nicht reagieren kann. D.h.: delay()'n 
stuff ist in formal korrekten statemachines schlicht nicht erlaubt.

Wer was anderes behaupted, hat das Konzept einer state machine schlicht 
nicht wirklich begriffen. Und nein: selbst die eventuell vorhandene 
Tatsache, dass in so einer illegalen Wartezeit sowieso keine andere 
state transition erlaubt wäre, ändert am Sachverhalt rein garnichts. So 
ein Konstrukt ist und bleibt PFUSCH und ist eben keine state machine.

von Egon N. (egon2321)


Lesenswert?

https://martin-thoma.com/how-to-draw-a-finite-state-machine/

https://spin.atomicobject.com/2013/01/30/making-diagrams-with-graphviz/

Mach das mit graphviz, dann kannst du schnell etwas ändern und es sieht 
alles schön sauber aus.

von Bernd K. (prof7bit)


Lesenswert?

Egon N. schrieb:
> Mach das mit graphviz, dann kannst du schnell etwas ändern und es sieht
> alles schön sauber aus.

Hab ich auch schon probiert, sehr schnell kommt man aber an den Punkt an 
dem es die States und die Übergänge anders anordnet als es der Übersicht 
halber besser wäre, besonders schlimm wird es wenn man die Übergänge 
auch noch mit Text dekorieren will um Auslöser und Aktionen zu notieren, 
dann kämpft man einen halben Tag verzweifelt mit den Layoutoptionen und 
dann gibt man schließlich auf und zeichnet es sauber von Hand unter der 
Verwendung von Dia (sehr empfehlenswert) oder vergleichbaren 
Hilfsmitteln.

Es gibt bestimmt viele Anwendungen bei denen Graphwiz gute Dienste 
leistet, das saubere Dokumentieren einer halbwegs komplexen Statemachine 
gehört aber definitiv nicht dazum da stößt es schnell an seine Grenzen.

: Bearbeitet durch User
von Gerd E. (robberknight)


Lesenswert?

Auch wenn die Frage "womit zeichnen?" eher ein Nebenaspekt der Frage des 
TO ist:

Ich verwende gerne yed für sowas:
https://www.yworks.com/products/yed

Das macht es sehr leicht Blöcke zu verschieben und dennoch die 
Verbindungslinien zwischen ihnen in ansehnlicher Weise beizubehalten.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Ja yed finde ich auch super.

von S. R. (svenska)


Lesenswert?

Roman K. schrieb:
> Sollte die Anzahl der States (also Zustände) so klein wie möglich
> gehalten werden, oder sollten die eizelnen States besser so einfach wie
> möglich gehalten werden, dafür werden es aber einige States mehr?

Ein Automat (State Machine) kennt keine Zeit. Das heißt, dass du für 
alles, was messbar Zeit dauert, einen Zustand definieren musst. 
Messbar ist in dem Fall davon abhängig, mit welchem Takt du den 
Automaten laufen lässt (also z.B. wie oft du handle_states() aufrufst, 
z.B. alle 10 ms).

In deinem Beispiel hast du also einen Startzustand, der auf eine Eingabe 
wartet, um loszulegen. Während des Umschaltens schaltest du das Relais 
ein (das dauert keine Zeit) und gehst in den Wartezustand. Der wartet 
nur die 3 Minuten. Wenn die abgelaufen sind, misst du die Helligkeit 
(das dauert ebenfalls keine Zeit) und gehst direkt in den Folgezustand, 
der wieder auf irgendwas wartet.

Wenn die Messung messbar Zeit dauert, dann ist das ein eigener Zustand.

Roman K. schrieb:
> Ich hoffe, hier keine allzu doofe Frage gestellt zu haben...

Nö, die ist mal wirklich interessant. :-)

von stateit (Gast)


Lesenswert?

Zum spielen uns testen: http://qfsm.sourceforge.net/about.html

von LostInMusic (Gast)


Lesenswert?

>Man kann sich auch darüber streiten, ob State 3 und 4 so überhaupt
>gebraucht werden (die Anweisungen können auch direkt in die Entscheidung
>von State 2).

Ja. Beide Varianten sind übrigens nicht äquivalent, denn bei derjenigen 
mit State 3 und 4 wird die Folgeaktion ("DoSomething"/"DoSomethingElse") 
erst einen Zyklus später ausgelöst, d. h. in Deinem Beispiel 1 ms 
später. Das mag oft egal sein, aber in anderen Fällen kann eine solche 
Verzögerung durchaus problematisch sein. Die States 3 und 4 sind 
letztlich redundant und man sollte besser darauf verzichten.

Man kann sogar ohne Schwierigkeiten auf die "state"-Variable selbst 
verzichten (aber nicht auf "timerVal"):
1
static uint32_t timerVal = 0;
2
3
// Called once at power up
4
Init()
5
{
6
  timerVal = 3*60*1000;    // start timer (3 min)
7
  SetRelaisOn();
8
}
9
10
// Called periodically from 1ms interrupt
11
Run()
12
{
13
   if (timerVal>=0)   // if timer active...
14
   {
15
     timerVal--;
16
   }
17
18
   if (timerVal==0)   // if timer expired...
19
   {
20
     int x= GetBrightness();
21
     if (x >= BRIGHTNESSLIMIT)
22
       DoSomething;
23
     else
24
       DoSomethingElse;
25
   }
26
}

Das fundamentale Problem, das hier eigentlich vorliegt, ist die vom TO 
gewählte Aufgabenstellung: Die ist schlicht zu einfach, um daran das 
Zustandsmaschinen-Know-How gut lernen zu können. Ein etwas 
komplizierteres System mit z. B. zwei Tasten und zwei oder drei Timern 
wäre da meiner Meinung nach viel besser geeignet.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

LostInMusic schrieb:
> if (timerVal>=0)   // if timer active...
>    {
>      timerVal--;
>    }

 Das geht in die Hose sobald timerVal gleich Null ist.

 P.S.
 Und selbst wenn nicht - so macht man das ganz einfach nicht.

: Bearbeitet durch User
von guest...Rainer (Gast)


Lesenswert?

Liebe Leute,

zu Anfangs sah das doch recht einfach aus! Aber wenn man State-Machines 
(so nenne ich die) in realistischen Umgebungen implementieren will, dann 
geht es doch um ganz andere Dinge. Schnittstelle...wer sagt was...wer 
darf überhaupt was sagen...was mach ich mit mir selbst...wer macht wann, 
was , mit wem...was ist, wenn sonst noch was passiert...
Und ich persönlich mache das nicht! mit State-M.
Auf Controllerebe...eine gehörige Herausforderung. Und wenn auch alle 
heulen, dass mache ich entweder mit einem durchdachten Code oder ich 
lass' es sein (bin übrigens forthler"
Gruß Rainer

von Einer K. (Gast)


Lesenswert?

guest...Rainer schrieb:
> Und ich persönlich mache das nicht! mit State-M.

Provokation:
Ich behaupte, dass nahezu jedes funktionierende µC Programm eine 
StateMachine ist. Und das hat nichts damit zu tun, ob der Programmierer 
das Wort je gehört hat, oder beabsichtigt hat einen solchen Automaten zu 
bauen.

von Possetitjel (Gast)


Lesenswert?

guest...Rainer schrieb:

> Und ich persönlich mache das nicht! mit State-M.

Klar -- warum einfach, wenn's auch umständlich geht :)


> Auf Controllerebe...eine gehörige Herausforderung.
> Und wenn auch alle heulen, dass mache ich entweder
> mit einem durchdachten Code oder ich lass' es sein

Diese Option (seinlassen) hat man nicht immer.

Endliche Automaten ("state machines") sind nicht
kompliziert -- sie werden nur von den "richtigen"
Informatikern systematisch geringgeachtet. Übliche
Programmiersprachen haben keine Ausdrucksmittel
dafür, und Steuerungsprogrammierung gilt als Job
für debile Elektriker.

Das sollte einen aber dennoch nicht davon abhalten,
sich damit zu befassen.

von guest...Rainer (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Ich behaupte, dass nahezu jedes funktionierende µC Programm eine
> StateMachine ist

Ich mach einen "full-agree!" Es wird mal wieder mit einem "Mode"-Wort 
herumgeschmissen. Und ich möchte gern von allen denen Ardunio-Nutzern- 
oder wie sie heißen - hören, wo sie in ihren Libs eine StateMachine 
sehen können.
Natürlich müssen sie das auch nicht, aber dennoch(F.-K.-Wächter)
Gruß Rainer

von Possetitjel (Gast)


Lesenswert?

guest...Rainer schrieb:

> Es wird mal wieder mit einem "Mode"-Wort
> herumgeschmissen.

Quark.
Du musst schon zwischen dem schwachsinnigen Ausdruck
und dem dahinterstehenden Konzept unterscheiden.

Und das Konzept der endlichen Automaten ist super, denn
es ist viel einfacher als das ganze Chomsky-Grammatik-
Gewürge, das die Informatiker immer zelebrieren, und
überdies vor allem in den Fällen nützlich, in denen die
normale "sequenzielle" Denkweise versagt.


> Und ich möchte gern von allen denen Ardunio-Nutzern-
> oder wie sie heißen - hören, wo sie in ihren Libs eine
> StateMachine sehen können.

Das ist nicht fair, denn es gibt auch genügend studierte
Programmierer, die die Tragweite des Konzeptes nicht
erfassen.

von Proletus protectus Troll (Gast)


Lesenswert?

Die passenden Schluesselwoerter heissen :
State - Event - Action
In jedem "State" wartet man auf einen oder mehrere "Events", und wenn so 
ein "Event" ausgeloest wird, wird die passenden "Action" ausgefuehrt, 
und ein neuer "State" wird erlangt.

Sinnvollerweise ruft man die Zustandsmaschine waehrend der Zeit, wo 
nichts anderes laeuft auf, und faellt im Wesentlichen ohne einen Delay 
durch.

Der "State" sollte eine Zahl sein, denn die kann man dann per UART 
debuggen, dh sehen, in welchem Zustand die Zustandsmaschine steckt.
Dann benoetigt man nur noch einen Pin-puls zu Beginn der 
Zustandsmaschine, um mit dem Oszilloskop zu sehen, ob der Controller in 
der Zustandsmaschine steht, und wie oft sie dran kommt.
Und falls noetig, kann man den Controller am Ende der Zustandmaschine 
noch in einen  Sleep werfen, nachdem die "Hardware-Events" als 
Aufwachkriterium definiert wurden.

von Einer K. (Gast)


Lesenswert?

guest...Rainer schrieb:
> Und ich möchte gern von allen denen Ardunio-Nutzern-
> oder wie sie heißen - hören, wo sie in ihren Libs eine StateMachine
> sehen können.

Ich kann dir lebhaft bestätigen, dass viele Arduinouser dauernd und 
bewusst mit endlichen Automaten hantieren. Und von daher auch einen 
solchen Automaten erkennen, wenn sie ihnen über den Weg läuft.

Es ist DAS maßgebliche "Design Pattern" für Ablaufsteuerungen.

von guest...Rainer (Gast)


Lesenswert?

Possetitjel schrieb:
> Quark.
> Du musst schon zwischen dem schwachsinnigen Ausdruck
> und dem dahinterstehenden Konzept unterscheiden.

Quark ist "das" Schlüsselwort, für mich...anstatt sich mit Schwachköpfen 
auseinander zu setzen, muß man die Kompetenz des Progs gnadenlos inFrage 
stellen. "Das Leben ist nicht wirklich schwer" #Schopenhauer#
Gruß Rainer

von Possetitjel (Gast)


Lesenswert?

guest...Rainer schrieb:

> Possetitjel schrieb:
>> Quark.
>> Du musst schon zwischen dem schwachsinnigen Ausdruck
>> und dem dahinterstehenden Konzept unterscheiden.
>
> Quark ist "das" Schlüsselwort, für mich...anstatt sich
> mit Schwachköpfen auseinander zu setzen, [...]

Wer nicht will, der hat schon.

Ich habe nur versucht, Dir zu verdeutlichen, dass es
einen Unterschied gibt zwischen dem idiotischen Wort
"state machine" und dem ganz und gar nicht idiotischen
Konzept.
Wenn Dich das nicht interessiert -- auch gut.

Schlaf gut.

von Possetitjel (Gast)


Lesenswert?

Proletus protectus Troll schrieb:

> Die passenden Schluesselwoerter heissen :
> State - Event - Action

Interessant. Welche Programmiersprache ist das?

SCNR

von guest...Rainer (Gast)


Lesenswert?

Possetitjel schrieb:
> Das ist nicht fair, denn es gibt auch genügend studierte
> Programmierer, die die Tragweite des Konzeptes nicht
> erfassen.

...so weit wollte ich eigentlich nicht gehen....
Rainer

von Egon N. (egon2321)


Lesenswert?

Proletus protectus Troll schrieb:
> Der "State" sollte eine Zahl sein, denn die kann man dann per UART
> debuggen, dh sehen, in welchem Zustand die Zustandsmaschine steckt.

Das gute alte enum...

Wieso sollter man per UART debuggen? GDB gibt es doch genauso.

von A. S. (Gast)


Lesenswert?

An den TO:

erstmal auch von mir das Kompliment, die Frage ist sinnvoll, gut 
gestellt, Deine gezeichntete Statemachine sehr gut.

A) Die Nutzung von Zahlen (statt enums) ist in diesem Stadium richtig! 
Eine Sinnvolle Benennung der States ist erst möglich, wenn man ungefähr 
weiss, was man will. Solange eine aussagekräftige Definition eines 
States fehlt, ist eine Zahl besser als ein fast passender enum.

B) beide vorgehen haben Vor- und Nachteile.

Wenn Du irgendwo anders entscheidungen anhand des Zustand triffst, sind 
viele States unübersichtlicher.

Wenn Du mit zyklischen Aufrufen (SPS-Loop) arbeitest, brauchst Du bei 
weniger States entweder Zusatzsstates (bool state_changed;) oder musst 
die Eingangsaktion als Ausgangsaktion des vorherigen States 
implementieren. Letzteres wird dann Problematisch, wenn von mehreren 
oder einem "weit entfernten" State hierhin gesprungen wird.

Fazit: Programmiere erstmal so, wie es Dir sinnvoll erscheint und sammle 
damit Erfahrungen. Du machst das schon sehr gut. Die Unterschiede 
ergeben sich (wie schon vor mir erwähnt) aus dem Umfeld 
(Programmiersprache, SPS-Loop oder Task, Übergeordnete Prozesse wie 
Not-Aus oder Abbruch, die vorher oder woanders zentral behandelt werden, 
....)

Auf meiner Arbeit verwenden wir übrigens zwar getrennte States für 
Einsprung und Dauer, springen dafür aber (falls zeitlich sinnvoll) per 
"fallthrough" in den nächsten State. Und ja, am Ende haben wir auch 
sinnvoll benamte enums.

von F. F. (foldi)


Lesenswert?

Arduino Fanboy D. schrieb:
> Provokation:
> Ich behaupte, dass nahezu jedes funktionierende µC Programm eine
> StateMachine ist. Und das hat nichts damit zu tun, ob der Programmierer
> das Wort je gehört hat, oder beabsichtigt hat einen solchen Automaten zu
> bauen.

Jau.
Zumindest Teile vom Programm.

Die state machine hat in erster Linie Zustände zu erfassen und darauf zu 
reagieren. Streng genommen gehört nicht mal die Fehlerbehandlung 
vorrangig dazu. Natürlich macht man das, weil man weiß, dass ein Taster 
klemmen kann oder ein Sensor defekt sein kann.
Und um die ursprünglich Frage zu beantworten.
So viele states wie nötig, so wenig wie möglich. Das macht die 
Fehlerbehandlung einfacher.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Spätestens wenn man Multi-Tasking benötigt, werden Zustandsautomaten 
plötzlich sehr hilfreich.

> Der "State" sollte eine Zahl sein, denn die kann man dann per UART
> debuggen, dh sehen, in welchem Zustand die Zustandsmaschine steckt.

Enums SIND Zahlen (im  Maschinencode) und lassen sich daher problemlos 
auf einem Debugging Terminal ausgeben. Wenn du möchtest, kannst du jedem 
enum Wert eine konkrete Zahl zuweisen, ansonsten nummeriert der Compiler 
sie selbst durch.

Egal ob enums oder integer: Irgendwo musst du Dir eine Tabelle hinlegen, 
die das ganze in menschen-lesbare Form übersetzt. Wenn der µC genug 
Speicher hat, kann er das gleich selbst erledigen.

> Wieso sollter man per UART debuggen?

"Früher" ging es nicht anders, in dieser Zeit hatte ich das 
Programmieren gelernt. Heute scheitert das Debuggen in der IDE oft 
daran, dass man das Programm nicht anhalten kann/darf oder dass man aus 
Sicherheitsgründen keinen Debugger an die produktive Maschine 
anschließen darf.  Das gilt insbesondere für meinen Job (Java Backend 
Entwicklung im E-Commerce Umfeld). Für mich sind Logfiles daher immer 
der erste Ansatz, Debugger kommen nur auf dem Schreibtisch während der 
Entwicklung zum Einsatz.

Ich habe zu 99% sogar überhaupt keinen Zugang zu den produktiven 
Maschinen. Ich muss fast jedes Problem ausschließlich anhand von 
Logfiles erkennen und dann eine Simulationsmethode erarbeiten, die das 
Problem reproduzierbar macht. Erst dann kommt die Entwicklungsumgebung 
(eventuell mit Debugger) zum Einsatz.

Wenn ich beruflich µC programmieren würde, wäre die Situation häufig 
nicht anders - denke ich jedenfalls.

von Bernd K. (prof7bit)


Lesenswert?

Proletus protectus Troll schrieb:
> Der "State" sollte eine Zahl sein

Der State kann auch ein Funktionszeiger sein, auch auf diese Weise kann 
man das was das äußere switch() macht implementieren, jeder State wäre 
dann eine separate Funktion.

von Proletus protectus Troll (Gast)


Lesenswert?

Weshalb man mit UART Debuggen soll ? Weil bei den ueblichen Prozessen 
der Kontext kaputt ist wenn man per Breakpoint anhaelt. Bedeutet der 
Prozess laeuft, das Programm laeuft, man hat aber keine Ahnung weshalb 
es nicht geht. Dann benoetigt man das Wissen ueber den Zustand des 
Programmes, den Zustand der Zustandsmaschine.

Logfile .. ein UART ist von der Komplexitaet viel einfacher wie ein 
Logfile.

von S. R. (svenska)


Lesenswert?

Proletus protectus Troll schrieb:
> Logfile .. ein UART ist von der Komplexitaet
> viel einfacher wie ein Logfile.

Ein UART ist ein Logfile. Nur, dass die Daten nicht in eine Datei 
geschrieben werden, sondern auf ein Kabel.

von Stefan F. (Gast)


Lesenswert?

> Der State kann auch ein Funktionszeiger sein, auch auf diese Weise kann
> man das was das äußere switch() macht implementieren, jeder State
> wäre dann eine separate Funktion.

Interessanter Ansatz, darüber muss ich mal nachdenken, bzw. es 
ausprobieren.

von Stefan F. (Gast)


Lesenswert?

> Logfile .. ein UART ist von der Komplexitaet viel
> einfacher wie ein Logfile.

Das ist für mich prinzipiell das Selbe. Ob der Computer sein Protokoll 
auf einem Speichermedium, Netzlaufwerk oder in serieller Form bereit 
Stellt, spielt nur eine untergeordnete Rolle. Hauptsache man kann es 
irgendwie irgendwo abspeichern und untersuchen.

von Einer K. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Interessanter Ansatz, darüber muss ich mal nachdenken, bzw. es
> ausprobieren.

Aus meiner bescheidenen Sicht gibt es mehrere gesunde Möglichkeiten.

---

Switch/case - Enum
Einfach und übersichtlich.
Kann aber recht unangenehm werden, wenn der Compiler keine Sprungleisten 
erstellen kann. z.B. bei lückenhafter Abfolge, oder sehr vielen Fällen. 
Dann wird intern sowas wie eine if Kaskade erstellt.

If Kaskade
Naja, nicht sehr Wartungsfreundlich. Die vorderen Fälle werden schnell 
erreicht, für die hinteren sind N Vergleiche nötig.

Funktionspointer
Recht fix, aber Speicher hungrig, wenn Pointer Arrays aufgebaut werden.
Gut wartbar, auch bei bei großen Statemachines

Computed Goto (in der eingeschränkten Version, ohne Distanzberechnungen)
In etwa wie Funktionspointer, nur dass man auf den Funktionsoverhead 
verzichten kann

OOP, Pointer auf State Objekte (C++)
Wohl etwas hungriger..
Hat aber den Vorteil, den globalen Namensraum nicht so zudonnern zu 
müssen. Es lassen sich für jeden State Einstiegs und Ausstiegs Methoden 
schreiben und natürlich automatisch aufrufen.
Schön bei sehr großen und komplexen Statemachines

---

Welche Methode jetzt gerade die beste, oder schönste, ist sollte man aus 
meiner bescheidenen Sicht dem konkreten Problem überlassen.

Eine Geschmacksfrage....
Und damit reichlich Potential für Grabenkriege.

von Bernd K. (prof7bit)


Lesenswert?

Arduino Fanboy D. schrieb:
> Funktionspointer
> Recht fix, aber Speicher hungrig.

Warum soll das speicherhungrig sein? Die Variable die sich den State 
merkt hat dann halt die Breite eines ganzen Maschinenwortes statt nur 
ein Byte und der Stack wird eine Ebene tiefer. Wir sprechen also über 
Speichermehrverbrauch den man an ein oder zwei Händen abzählen kann, ist 
es das was Du meinst?

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Bernd K. schrieb:
> ist es das was Du meinst?
Hatte ich noch editiert....
Weil nicht exakt genug formuliert.

Ich meinte eigentlich die Schrittkette, als Sonderform des endlichen 
Automaten. Sie bedarf eines Arrays, oder einer Liste von Pointern.

Außerdem sind die Beurteilungen, die ich da verwendet habe "weich". Eher 
von der konkreten Anwendung abhängig, als dass sie Muss Bedingungen 
sind.

von Horst S. (Gast)


Lesenswert?

Stefanus F. schrieb:
> Egal ob enums oder integer: Irgendwo musst du Dir eine Tabelle hinlegen,
> die das ganze in menschen-lesbare Form übersetzt. Wenn der µC genug
> Speicher hat, kann er das gleich selbst erledigen.

Wenn's in der Anwendung komplizierter wird:

- Stati, die den Anfang eines Zweiges oder einen wiederverwertbaren 
Einstiegspunkt bilden, benenne ich über nen Enum.
- Stati, die nur durch den Anspruch der Asynchronität entstehen, benenne 
ich üblicherweise nicht. Ein Enum mit 50 Elementen macht weder beim 
Lesen, noch beim Schreiben besonders Spaß, insbesondere, wenn die 
Bezeichner immer diffiziler, sperriger und dadurch länger werden.

Beispiel: Beim asynchronen Lesen eines AD-Wertes aus der StateMachine 
könnte man sich im Enum ein StartGetADVal und ein PollGetADVal 
vorstellen? Ich würde ein GetADVal präferieren und im switch tatsächlich 
auch ein "case GetADVal+1:" benutzen. Man kann nichts pollen, wo nichts 
gestartet ist. Insofern sollte man sich auch die Benennung sparen. 
(Ansonsten pollt der Kollege und wundert sich.)

Das setzt halt den Gebrauch von Nummernzirkeln im Enum voraus. In der 
state-Variable ist das sowieso üblich.

Interessant dabei:
1
typedef enum
2
{
3
   Start = 0,
4
   Something = 10,
5
   SomethingElse = 20
6
} State_t
Nach dem Beispiel des TO entspricht dies eher der 1. Zeichnung (man muss 
es nur asynchron ausführen). Die zeigt zwar nicht den typischen Anspruch 
der Asynchronität, komprimiert aber den Ablauf auf's Wesentliche. Man 
sieht, was untrennbar zusammengehört und was für ein Reusing vorbereitet 
werden muss. Da kann man keinen Pfeil zu "Warte3Min" ziehen.

von Einer K. (Gast)


Lesenswert?

Horst S. schrieb:
> Interessant dabei:typedef enum
> {
>    Start = 0,
>    Something = 10,
>    SomethingElse = 20
> } State_t
Mit solchen Lücken, macht man sich fix die Switch/Case Optimierungen 
kaputt. Es degeneriert zu einer if Kaskade.

von S. R. (svenska)


Lesenswert?

Horst S. schrieb:
> Beispiel: Beim asynchronen Lesen eines AD-Wertes aus der StateMachine
> könnte man sich im Enum ein StartGetADVal und ein PollGetADVal
> vorstellen?

"StartGetADVal" dauert keine messbare Zeit, sollte also kein eigener 
Zustand sein. Nur "PollGetADVal" (bzw. "WaitForADVal") dauert Zeit.

> Ich würde ein GetADVal präferieren und im switch tatsächlich
> auch ein "case GetADVal+1:" benutzen.

Das ist extrem schlecht. Du bist damit nicht nur inkonsistent, sondern 
stellst späteren Entwicklungen zusätzlich auch noch eine Falle.

von Falk B. (falk)


Lesenswert?

@ Arduino Fanboy D. (ufuf)

>Mit solchen Lücken, macht man sich fix die Switch/Case Optimierungen
>kaputt. Es degeneriert zu einer if Kaskade.

Mach dir mal nicht zuviele Gedanken über derartige Details. Ersten haben 
die allerwenigsten State machines ultimative 
Geschwindigkeitsanforderungen, da spielen ein paar Takte mehr oder 
weniger keine Rolle. Und zweitens sind altuelle Compiler, auch der avr 
gcc unter der Arduino-Haube schlau genug, um das gescheit zu optimieren. 
Manuelle Codierung von States hat selten Sinn, nimm ein Enum und gut, 
der Compiler macht da schon was gescheites draus.

von Rolf M. (rmagnus)


Lesenswert?

Das Bild im Startposting zeigt für mich keinen Zustandasautomaten, 
sondern ein Flussdiagramm. Wozu brauche ich da Zustände? Das ist einfach 
nur ein Ablauf, der da beschrieben wird.

Falk B. schrieb:
> @Eric B. (beric)
>
>>> Mit welcher Frequenz wird die FSM denn getaktet?
>
>>Nicht. Eine SM taktet man nicht, die reagiert auf Events/Ereignisse.
>
> Stimmt so allgmein auch nicht. Nicht alles läuft unter QT und ähnlichen
> Frameworks.

Was hat denn das mit Qt zu tun?

> Wir wollen doch mal eher bei den EINFACHEN, Grundlegenden
> Konzepten anfangen und die Neulinge nicht mit den allerneusten
> RTOS-Geschichten überfordern.

Das ist das EINFACHE Konzept: Es gibt Zustände, es gibt Ereignisse, die 
Zustandsübergänge auslösen, und es gibt Aktionen, die bei diesen 
Zustandsübergängen ausgeführt werden. Irgendeine Taktung ist zunächst 
mal nicht Teil einer Statemachine.

> Und da wird eine FSM getaktet, indem sie periodisch aufgerufen wird.

Man macht vielleicht ein Polling, um zu schauen, ob eines der Ereignisse 
eingetreten ist, aber das ist nicht Teil der Statemachine. Die kommt 
erst dran, wenn tatsächlich irgendwas passiert ist.

Arne schrieb:
> PS: Zu der Frage, ob Messen ein eigener Zustand ist:
> Wenn die Messung viel Zeit benötigt, dann ggf eigener Zustand.

Ob nun viel Zeit oder nicht, ist eigentlich egal. Es gibt, wie schon 
festgestellt, drei Dinge: Ereignisse, Zustände und Aktionen. Ein Zustand 
ist dabei etwas, wohin die Statemachine wechseln kann, worin sie 
verweilen kann und aus dem sie wieder austreten kann. Wenn das "etwas", 
von dem wir sprechen, das kann, ist es ein Zustand. Ob die nun 3 
Taktzyklen oder 3 Minuten darin verweilt, spielt keine Rolle.
Wie schon mehrfach erwähnt wurde: Eine Statemachine kennt keine Zeit und 
damit natürlich auch keine Taktung.

von Horst S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Mit solchen Lücken, macht man sich fix die Switch/Case Optimierungen
> kaputt. Es degeneriert zu einer if Kaskade.

Zeig mir doch mal bitte 'nen Beispiel dafür.

von S. R. (svenska)


Lesenswert?

Rolf M. schrieb:
> Wozu brauche ich da Zustände? Das ist einfach
> nur ein Ablauf, der da beschrieben wird.

Man benutzt Automaten, um Abläufe zu beschreiben...

Rolf M. schrieb:
>> Wenn die Messung viel Zeit benötigt, dann ggf eigener Zustand.
> Ob nun viel Zeit oder nicht, ist eigentlich egal. [...] Ob die nun 3
> Taktzyklen oder 3 Minuten darin verweilt, spielt keine Rolle.

Ein eigener Zustand gehört da sinnvollerweise nur hin, wenn die Messung 
messbar viel Zeit benötigt. Wie lange das ist, hängt von der Taktung 
des Automaten ab (so er denn getaktet ist).

Beispiel: Wenn ich zwischen "Command-Byte in Register schreiben" und 
"Statusregister meldet Busy" noch messbar Zeit vergeht, weil die 
Hardware zu langsam reagiert, dann muss ich da einen zusätzlichen 
Zustand einfügen, um Race Conditions zu vermeiden.

von Einer K. (Gast)


Lesenswert?

Horst S. schrieb:
> Zeig mir doch mal bitte 'nen Beispiel dafür.
Schwierig...
Da doch sehr Prozessor/Compiler und Optimierungsstufen abhängig.

Der AVR-GCC kennt da den Schalter -case-values-threshold
> The smallest number of different values for which
> it is best to use a jump-table instead of a tree of
> conditional branches.


http://ww1.microchip.com/downloads/en/AppNotes/doc8453.pdf
Sagt:
> for a “switchcase”, the compiler usually
> generates lookup tables with index and
> jump to the correct place directly.
Gewöhnlich macht er das, wenn man ihm die Chance gibt.

Aber wenn man ihm genügend Stöcke zwischen die Beine wirft, kollidiert 
das mit z.B. -Os.
Diese Lücken sind halt solche Stöcke.
Und dann wundert man sich, wenn sich bei einer eher marginalen Code 
Änderung, das Laufzeitverhalten doch recht massiv ändert. Gerade in 
einer ISR, will man das nicht unbedingt.

von Rolf M. (rmagnus)


Lesenswert?

S. R. schrieb:
> Rolf M. schrieb:
>> Wozu brauche ich da Zustände? Das ist einfach
>> nur ein Ablauf, der da beschrieben wird.
>
> Man benutzt Automaten, um Abläufe zu beschreiben...

Ein Zustandsautomat ist etwas mehr als nur ein Ablauf. Was ich meine 
ist, dass man hier keinen Automat braucht. Man kann diese Aktionen auch 
einfach eine nach der anderen so als Code hinschreiben wie in dem 
Bildchen. Ich muss mir gar keinen Zustand merken. Das ergibt sich von 
selbst aus dem sequentiellen Ablauf des Programms.

> Rolf M. schrieb:
>>> Wenn die Messung viel Zeit benötigt, dann ggf eigener Zustand.
>> Ob nun viel Zeit oder nicht, ist eigentlich egal. [...] Ob die nun 3
>> Taktzyklen oder 3 Minuten darin verweilt, spielt keine Rolle.
>
> Ein eigener Zustand gehört da sinnvollerweise nur hin, wenn die Messung
> messbar viel Zeit benötigt. Wie lange das ist, hängt von der Taktung
> des Automaten ab (so er denn getaktet ist).

Wie ich schrieb: Wenn es etwas ist, in das er erst eintreten, dann darin 
verweilen, dann wieder austreten muss, dann ist es ein Zustand. 
Vielleicht ist es das, was du mit "messbar viel Zeit" meinst.

> Beispiel: Wenn ich zwischen "Command-Byte in Register schreiben" und
> "Statusregister meldet Busy" noch messbar Zeit vergeht, weil die
> Hardware zu langsam reagiert, dann muss ich da einen zusätzlichen
> Zustand einfügen, um Race Conditions zu vermeiden.

"Command-Byte in Register schreiben" ist eine Aktion, "Statusregister 
meldet Busy" ist ein Ereignis. Dazwischen ist natürlich ein Zustand. Ich 
denke aber, ich weiß, was du meinst. Dabei geht es aber nicht darum, zu 
entscheiden, um was für ein Element eines Zustandsautomaten es sich 
handelt, sondern ob es überhaupt Teil des Zustandsautomaten ist.

von Falk B. (falk)


Lesenswert?

@ Rolf M. (rmagnus)

>Ein Zustandsautomat ist etwas mehr als nur ein Ablauf. Was ich meine
>ist, dass man hier keinen Automat braucht. Man kann diese Aktionen auch
>einfach eine nach der anderen so als Code hinschreiben

Wer lesen kann ist klar im Vorteil.

"Um meine Frage zu veranschaulichen habe ich ein rein fiktives Beispiel
im Bild (Dateianhang) skizziert:"

von Einer K. (Gast)


Lesenswert?

Rolf M. schrieb:
> Ich muss mir gar keinen Zustand merken. Das ergibt sich von
> selbst aus dem sequentiellen Ablauf des Programms.

Ich unterscheide zwischen einem explizitem Zustand und einem impliziten.
Explizite sind klar benannt.
Egal, ob das jetzt Funktionsbezeicher, Enums oder Goto Lables sind.

z.B. ein Ringbuffer
Da ergibt sich der Zustand durch die beiden Zeiger (Leer, hat Inhalt, 
Voll)

von Rolf M. (rmagnus)


Lesenswert?

Falk B. schrieb:
> Wer lesen kann ist klar im Vorteil.

Lesen alleine reicht nicht immer…

> "Um meine Frage zu veranschaulichen habe ich ein rein fiktives Beispiel
> im Bild (Dateianhang) skizziert:"

Etwas, wofür man gar keine Statemachine braucht, ist aber ein eher 
weniger gutes Beispiel, um anhand diesem zu verstehen, wie man eine 
Statemachine am besten aufbaut.

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> Man kann diese Aktionen auch
> einfach eine nach der anderen so als Code hinschreiben wie in dem
> Bildchen.

Über welches Bildchen sprechen wir jetzt? In dem Bild in Post 1 kommt 
unverkennbar eine Wartezeit von 3 Minuten vor. Wenn man Threads haben 
kann, ja dann implementiert man das locker flockig als separaten Thread 
der in den 3 Minuten schläft mit sleep(), das mach ich auch so weils 
einfacher hinzuschreiben und zu lesen ist, weil ein Thread letztendlich 
auch nur eine schöne Abstraktion für eine Statemachine ist. Zum Beispiel 
ein Thread der 99.999% der Zeit blockierend an einem Netzwerksocket 
wartet und nichts tut, da kollabiert die Statemachine zur einfachen 
while-Schleife und die ganze Magie und der State ist im Scheduler 
versteckt und schön wegabstrahiert.

Aber wenn man keine Threads haben kann weil man keinen Scheduler hat 
oder weil man 100000 offene Netzwerkverbindungen haben könnte und 100000 
schlafende Threads selbst auf großen Maschinen der helle Wahnsinn wären 
dann muss man sich was anderes überlegen, dann macht man es 
event-gesteuert mit einem einzigen Thread (oder so vielen wie man Kerne 
hat) und dann braucht man selbst für die simpelsten Abläufe eine 
Statemachine sobald der Ablauf auf irgendwas warten muss (zum Beispiel 
auf das nächste Byte einer Nachricht oder auf ein ACK oder auf das 
Ausbleiben desselben).

In manchen Sprachen hat man Sprachkonstrukte oder Frameworks für solche 
Probleme wie Coroutinen oder Greenlets oder Futures oder Callbacks, etc. 
und unter der Haube eine Runtime mit Eventloop und Scheduler aber hier 
haben wir es mit nacktem C zu tun!

Im Falle eines kleinen AVRs kann man keine Threads haben, sobald einem 
da die Interrupts ausgehen oder man noch einen zweiten Ablauf braucht 
weil irgendwo noch manchmal eine LED mit 2Hz blinken soll während der 
main Thread mit Warten blockiert ist oder ein paar Tasten abgefragt 
werden sollen kommt man um Statemachines nicht mehr herum.

Wenn Du jetzt sagst "dann mach das Blinken und das Tastenabfragen halt 
in einem Timer-Interrupt" dann sag ich: Gratuliere! Jetzt hast Du doch 
zwei Statemachines gebaut, eine fürs Blinken und eine fürs 
Tastenabfragen weil Du nur 2 Threads hast (main und timer-IRQ) aber Du 
hast 3 Abläufe (der Ablauf aus dem Bild, das Blinken und das Tasten 
abfragen)". Um das explizite Hinschreiben der Statemachine zu vermeiden 
bräuchtest mindestens 2 Timer und main und irgendwann gehen Dir die 
Interrupts aus oder Du fängst an einen Scheduler für Threads zu 
implementieren (halte ich für unwahrscheinlich) oder Du baust 
Statemachines für die ganze asynchrone nebenläufige Warterei überall 
(der übliche Ansatz der in allen Tutorials ab dem zweiten Kapitel 
gelehrt wird).

: Bearbeitet durch User
von Karl (Gast)


Lesenswert?

georg schrieb:
> Grundsätzlich werden Änderungen bei einer Statemachine nicht in einem
> Zustand  durchgeführt, sondern beim Übergang von einem Zustand zum
> anderen.

Mit Verlaub. So ein Quatsch. Das kann man so machen, muss es aber nicht.
In der Digitaltechnik werden die Ausgänge einer FSM einzig aus dem 
aktuellen Zustand gebildet. Es gibt das Konzept der Aktion am Übergang 
nicht so Recht. Dementsprechend ist auch deine Verallgemeinerung nicht 
sinnvoll.

Weiter gibt es oft kein schwarz und weiß bei der Anzahl der states. 
Blödes Beispiel: man kann einen Zähler wunderbar als FSM darstellen, 
aber bei mehr als einigen wenigen Bits ist es sinnbefreit, weil 
unglaublich aufwändig. Meiner Erfahrung nach bleibt es besser 
nachvollziehbar, wenn man die FSM auf die Beschreibung der Zustände und 
deren Übergangsbedingungen beschränkt. Mögliche Darstellungen von 
timern, countern, komplexer kombinatorischer Übergangsbedingungen macht 
man mmn besser außerhalb.

von Bernd K. (prof7bit)


Lesenswert?

Karl schrieb:
> In der Digitaltechnik werden die Ausgänge einer FSM einzig aus dem
> aktuellen Zustand gebildet Es gibt das Konzept der Aktion am Übergang
> nicht so Recht.

Dann hast Du an der Stelle zwei Zustände: "Eingeschaltet" und 
"Ausgeschaltet". Aber immer noch keinen Zustand "Einschalten". Und genau 
darum ging es eigentlich, nicht um das Implementierungsdetail wie diese 
Änderung des Zustands ihren Weg zur Änderung des Ausgangspins findet.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Karl schrieb:
> Mit Verlaub. So ein Quatsch. Das kann man so machen, muss es aber nicht.
> In der Digitaltechnik werden die Ausgänge einer FSM einzig aus dem
> aktuellen Zustand gebildet. Es gibt das Konzept der Aktion am Übergang
> nicht so Recht. Dementsprechend ist auch deine Verallgemeinerung nicht
> sinnvoll.

 Wieso Quatsch ?

 Du sagst doch selber: > aus dem aktuellen Zustand gebildet.
 Beispiel:
 Ein Transistor als Schalter ist entweder ON oder OFF, Übergang
 selbst wird von der SM nicht registriert, deswegen aktueller Zustand.

 Und selbst wenn man auf einen Sinus reagiert, irgendwo muss es eine
 Triggerschwelle geben, ab da ist es auch entweder ON oder OFF.

von Bernd K. (prof7bit)


Lesenswert?

Karl schrieb:
> In der Digitaltechnik werden die Ausgänge einer FSM einzig aus dem
> aktuellen Zustand gebildet Es gibt das Konzept der Aktion am Übergang
> nicht so Recht.

Ob da bei jedem Übergang ein Fetzen Code ausgeführt werden muss weil man 
die Information des neuen Zustands nicht anders zu dem Ausgangspins hin 
transportiert bekommt oder ob alles direkt verdrahtet ist ist ein 
Implementierungsdetail. Wir gehen davon aus daß der TE es in Software 
implementieren will.

Deshalb sieht das Standardmodell einer Statemachine die Übergänge vor wo 
man bei Bedarf solche Codefetzen einhängen kann (aber nicht muß) die den 
neuen Zustand bei Bedarf irgendwie an die Außenwelt tragen und/oder dort 
was auslösen.

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

Bernd K. schrieb:

> Deshalb sieht das Standardmodell einer Statemachine
> die Übergänge vor wo man bei Bedarf solche Codefetzen
> einhängen kann (aber nicht muß) die den neuen Zustand
> bei Bedarf irgendwie an die Außenwelt tragen und/oder
> dort was auslösen.

Auch wenn das jetzt "voll Achziger" ist:

- "Statemachines" sind einfach "endliche Automaten".

- Die Automatentheorie kennt zwei Grundformen endlicher
Automaten, nämlich den Moore-Automaten, bei dem die
Ausgangssignale NUR aus den Zuständen gebildet werden,
und den Mealy-Automaten, der die Ausgangssignale aus
(altem) Zustand und Eingangssignal bildet. Alter Zustand
und (aktuelles) Eingangssignal bilden gerade eine Kante
("Transition").

Es gibt also beide Varianten.

von S. R. (svenska)


Lesenswert?

Karl schrieb:
> In der Digitaltechnik werden die Ausgänge einer FSM einzig aus dem
> aktuellen Zustand gebildet. Es gibt das Konzept der Aktion am Übergang
> nicht so Recht.

Es gibt den Unterschied zwischen Moore-Automaten (die Ausgänge werden 
aus dem aktuellen Zustand gebildet) und Mealy-Automaten (die Ausgänge 
werden aus dem aktuellen Zustand und den Eingängen gebildet).

Ein Moore-Automat benötigt immer zusätzliche Zustände, weil du immer 
eine Zustandskette "ausgeschaltet - einschaltend - eingeschaltet" bauen 
musst:
1
switch(moore_state) {
2
case AUSGESCHALTET:
3
  if(PINB & TASTER /* Einschaltbedingung */) {
4
    state = EINSCHALTEND;
5
  }
6
  break;
7
8
case EINSCHALTEND:
9
  PORTD |= SIGNAL; /* Einschaltaktion */
10
  state = EINGESCHALTET;
11
  break;
12
13
case EINGESCHALTET:
14
  /* fertig */
15
  break;
16
}

Mit einem Mealy-Automaten ziehst du die Zustandsänderung (sofern sie 
nicht messbar Zeit benötigt) in den Zustand mit rein und sparst dir so 
Zustände:
1
switch(mealy_state) {
2
case AUSGESCHALTET:
3
  if(PINB & TASTER /* Einschaltbedingung */) {
4
    state = EINGESCHALTET;
5
    PORTD |= SIGNAL;
6
  }
7
  break;
8
9
case EINGESCHALTET:
10
  /* fertig */
11
  break;
12
}

Man kann beide Ansätze fahren, aber ich finde Mealy meistens 
übersichtlicher, weil er unnötige kurze Zwischenzustände einspart. 
Außerdem ist er einen FSM-Takt schneller. In einem FPGA lässt sich ein 
Moore-Automat manchmal effizienter implementieren, weil man die gesamte 
Logik in Tabellenform codieren kann, aber in einem Controller spielt das 
keine Rolle (man schreibt nicht alle Register in jedem Zustand).

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Ich meinte eigentlich die Schrittkette, als Sonderform des endlichen
> Automaten. Sie bedarf eines Arrays, oder einer Liste von Pointern.

Nein. Kein Array, keine Liste. Der State IST ein Funktionspointer, und 
jede Funktion manipuliert ihn ggf. mit der Adresse des nachsten States. 
So wie das enun auch nirgendwo explizit im Speicher liegt, aber jeder 
Wert mal irgendwo zugewiesen wird.

Bei Steuerungen meist nicht sinnvoll, aber häufig bei Menüs, Protokollen 
oder Interrupts.

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> Nein.

Mir scheint, hast du das Prinzip eines endlichen Automaten verstanden.
Aber der Funktionsbaustein Schrittkette ist dir offensichtlich noch 
nicht unter gekommen.

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Aber der Funktionsbaustein Schrittkette ist dir offensichtlich noch
> nicht unter gekommen.

Doch, aber das ist mit enums genauso, während dann die statemachine mit 
FP bei deiner Aufzählung fehlt.

von Vincent H. (vinci)


Lesenswert?

Arduino Fanboy D. schrieb:
> OOP, Pointer auf State Objekte (C++)
> Wohl etwas hungriger..
> Hat aber den Vorteil, den globalen Namensraum nicht so zudonnern zu
> müssen. Es lassen sich für jeden State Einstiegs und Ausstiegs Methoden
> schreiben und natürlich automatisch aufrufen.
> Schön bei sehr großen und komplexen Statemachines


Die moderne Variante davon ist ein Summentype der alle States abbildet.
1
using sm = variant<State0, State1, State2, ...>;

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> Doch, aber das ist mit enums genauso,
Nöö..
schritt++
>  error: no match for 'operator++'


Achim S. schrieb:
> während dann die statemachine mit
> FP bei deiner Aufzählung fehlt.
Funktionspointer habe ich doch extra mit aufgeführt...
Warum siehst du das nicht?

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
>> Doch, aber das ist mit enums genauso,
> Nöö..
> schritt++
>>  error: no match for 'operator++'

Hä? verstehe ich nicht.

Arduino Fanboy D. schrieb:
> Funktionspointer habe ich doch extra mit aufgeführt...

OK, dann meintest Du hier also beides, wobei sich Deine Ausführungen zum 
Speicher nur auf die Schrittkette bezogen.

Arduino Fanboy D. schrieb:
> Funktionspointer
> Recht fix, aber Speicher hungrig, wenn Pointer Arrays aufgebaut werden.
> Gut wartbar, auch bei bei großen Statemachines

Dann ist ja gut, dass wir das herausgearbeitet haben, zumal die echte 
Statemachine mit FP anscheinend selbst alte Hasen hier nicht kennen.

Also nichts für ungut.

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> Hä? verstehe ich nicht.

Eine Schrittkette, mit in enums definierten Schritten, macht meines 
Erachtens nach keinen Sinn. Denn dann verliert man einen der größten 
Vorteile einer solchen Schrittkette. Und man muss die Schrittbezeichner 
doppelt mit führen.

Eigentlich muss kein Schritt, was über seine Nachfolger wissen.
Man sagt dem KettenModul einfach next(), oder was ähnliches, und es geht 
einen Schritt weiter.
Das geht nicht, wenn die Schritte in enums definiert werden.

Der Vorteil, wenn ein Schritt nichts über seinen Nachfolger weiß, ist, 
dass man Schritte in einer Kette mehrfach verwenden kann. Und bei 
Umsortierungen/Anpassungen nicht unbedingt in den Schritten selber rum 
fummeln muss.

Heizen
Pause
Heizen
Pause
Kühlen
Pause
Abfüllen

Achim S. schrieb:
> OK, dann meintest Du hier also beides, wobei sich Deine Ausführungen zum
> Speicher nur auf die Schrittkette bezogen.
Ja, so ist es.

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Man sagt dem KettenModul einfach next(), oder was ähnliches, und es geht
> einen Schritt weiter.
> Das geht nicht, wenn die Schritte in enums definiert werden.

Nein, es ist identisch, ob eine Schrittkette enums oder FP enthält. 
Vielleicht meinst du verkettete Listen, die gehen bei beiden nicht bzw 
wären Unsinn.

von Horst S. (Gast)


Lesenswert?

Achim S. schrieb:
> ann ist ja gut, dass wir das herausgearbeitet haben, zumal die echte
> Statemachine mit FP anscheinend selbst alte Hasen hier nicht kennen.

Die sind etwas verpönt, weil aus ner ISR heraus pro forma alle Register 
auf'm Stack gesichert werden.
Und letztendlich wirst Du auch mit Funktionspointern zur Diagnose nach 
außen wieder eine (numerische) Abstraktion einfügen, weil die Adressen 
selbst recht dynamisch und auch mies zu lesen sind.

Das hat seinen Reiz, aber nicht nur Vorteile.

von A. S. (Gast)


Lesenswert?

Horst S. schrieb:
> Die sind etwas verpönt, weil aus ner ISR heraus pro forma alle Register
> auf'm Stack gesichert werden.
> Und letztendlich wirst Du auch mit Funktionspointern zur Diagnose nach
> außen wieder eine (numerische) Abstraktion einfügen, weil die Adressen
> selbst recht dynamisch und auch mies zu lesen sind.
>
> Das hat seinen Reiz, aber nicht nur Vorteile.

Völlig d'accor. In ISRs nur, wenn "sowieso" Funktionsaufrufe erfolgen 
würden und mies zu lesen sehe ich auch so, daher

Achim S. schrieb:
> Bei Steuerungen meist nicht sinnvoll

Bei Menüs entfällt dieser Nachteil offensichtlich, im Gegenteil ;-)

Bei Steuerungsaufgaben kommt  hinzu, dass in den meisten Fällen ein 
funktionslokaler Kontext vorhanden ist (Zustand von 
Sensoren/Notaus/Timer, Plausibiltäten, Redundanzprüfungen, ...) der 
entweder künstlich in den State-Kontext mit eingearbeitet oder in jeder 
Funktion parallel ausgewertet werden muss. Beispiel: bool 
Cancel=Cancel_A() || Cancel_B();

von NichtWichtig (Gast)


Lesenswert?

F. F. schrieb:
> NichtWichtig schrieb:
>> Zustand EINSCHALTEN
>
> Irgendwie hast du das Thema nicht verstanden.

Du hast es nicht kapiert.

Denk nochmal drüber nach, vielleicht verstehst Du es dann ja auch.

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> Nein, es ist identisch, ob eine Schrittkette enums oder FP enthält.

Erstens:
Mit Enum Values in einem Array benötigt man eine weitere Auflösungsstufe 
um das, um es ausführen zu können.

Zweitens:
Hat man für jeden Schritt 2 Bezeichner.
Einmal im Enum, und einmal den Funktions/Klassen Bezeichner.
Doppelt ist immer böse.

Drittens:
Bei Verwendung eines Enum muss jeder Schritt um seinen Nachfolger 
wissen.

Viertens:
Codeduplikate sind böse/fehlerträchtig, wartungsunfreundlich.


Einen dieser Punkte kannst du evtl. eliminieren.
Man kann sich, in Grenzen, sogar aussuchen welchen....
Aber nicht alle.


--------

Achim S. schrieb:
> Nein, es ist identisch, ob eine Schrittkette enums oder FP enthält.
So langsam hätte ich gerne mal gesehen, was du meinst...
Ein einfaches "Nein" reicht mir nicht, um zu verstehen, was du meinst.

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> So langsam hätte ich gerne mal gesehen, was du meinst...
1
enum States={ S1, S2, .... Sn, Sende};
2
3
enum States Schritte[]={S1, S3, S1, S2, S1, ....};
Ist gleichwertig zur Implementierung mit FP.

Und eine declaration braucht die FP-Version meist auch.

Wo siehst Du denn Unterschiede und wieso?

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> Ist gleichwertig zur Implementierung mit FP.

Bei Funktionspointern ist klar, wie man sie aufrufen muss, wenn sie in 
einem Array stecken und man darüber weg iteriert.

Bei deinem Beispiel sehe ich das nicht.
Das (für mich) interessanteste hast du also weg gelassen...

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Bei Funktionspointern ist klar, wie man sie aufrufen muss, wenn sie in
> einem Array stecken und man darüber weg iteriert.

Es gibt verschiedene Arten des Aufrufs. Und zu jeder gibt es ein 
enum-analogon.

Z.b: mit i als Laufindex übers Array:

FPliste[i](...);

Statemachine(EnumListe[i]);

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> FPliste[i](...);
Das ist klar!
(glaube ich)

Achim S. schrieb:
> Statemachine(EnumListe[i]);
Aber hier fehlt der letzte Schliff...
Da sehe ich nicht wie es zur Ausführung des konkreten Codes kommt.
Die Enums sind ja nur benannte Zahlen. Keine Pointer, oder so..
Da fehlt mir noch eine Stufe der "Umschlüsselung".

Oder:
Willst du das dann in ein Switch/Case Konstrukt einbetten?

Dann hast du trotz des Arrays evtl. alle Geschwindigkeitsvorteile 
verschenkt.
Und dazu noch den ganzen Code (für alle Stati) in einer großen Wurst.

Wie du siehst, ich sehe es (noch) nicht, was du meinst!

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Willst du das dann in ein Switch/Case Konstrukt einbetten?
>
> Dann hast du trotz des Arrays evtl. alle Geschwindigkeitsvorteile
> verschenkt.
> Und dazu noch den ganzen Code (für alle Stati) in einer großen Wurst.

Natürlich mit enum im Switch Case. Und natürlich hat beides seine Vor 
und Nachteile, das wurde doch schon alles aufgeführt. Ein Switch hat 
z.b.den Vorteil, einzelne individuelle Dinge rauszuziehen und dass es 
nicht in dutzende Minifunktionen zerfällt.

von Einer K. (Gast)


Lesenswert?

Achim S. schrieb:
> Natürlich mit enum im Switch Case.
Ah, ja...
Und ich dachte schon, ich hätte da einen wesentlichen Trick übersehen.

Danke, dafür, dass wir darüber geredet haben.

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.