Hallo,
Ich hab ein Projekt wo ein ATMega328 ein Sim-Modul steuert. Das
Grundprogramm ist mittlerweile fertig, jedoch habe ich versucht
Spaghetti-code zu vermeiden, was mir jedoch nicht ganz gelang.
Die Grundschleife läuft im 50ms Zyklus, indem Statemachines abgearbeitet
werden und der µC für den Rest der Zeit im Sleep Mode befindet.
Die Statemachine in main() hat 23 Zustände, wobei bspw. in einem State
sich wiederrum eine Statemachine befindet, die 8 Zustände beinhaltet,
diese wiederrum hat auch eine verschachtelte Statemachine mit 9
Zuständen, und die hat wieder eine mit 5 Zuständen.
Soweit so schlecht.
An sich funktioniert der Code jetzt, jedoch sollen jetzt Funktionen
hinzukommen, bei den mir das Implementieren schwer fällt.
Die Verschachtelung habe ich so umgesetzt, da diese Abschnitte
wiederholt aufgerufen werden, weshalb eine Auflösung als eine große
Statemachine den Programmspeicher unnötig füllt und unpraktisch ist,
wenn man was ändern will.
Jedoch hat die Verschachtelung ein Problem. Die Statemachine in main()
hat ein Timer, der nach Ablauf einer Zeit den State verlässt, und den
Vorgang nach bestimmter Zeit wieder versucht (z.B. Loginschwierigkeit
durch schlechten Empfang oder Timeout bei keiner Tastereingabe).
Das Problem:
Durch diesen Abbruch sind jedoch die verschachtelten Statemachines noch
in ihren alten Zuständen, was bei Wiedereintritt für Probleme sorgt.
Um das Problem zu lösen, muss vor dem Abbruch die unterliegende
Statemachine über den Abbruch informiert, die wiederum auch alle
unterliegenden informiert. Gibt es elegantere Lösungen? Dadurch wird das
ganze Konstrukt sehr undurchsichtig. Wenn ich eine Funktion hinzufüge,
muss ich gucken, ob abgebrochen wird, und an welcher Unterfunktion
dieser Abbruch bekannt gemacht werden muss.
Eine Möglichkeit die ich gerade sehe, ist die Umsetzung Yakindu, wo ich
den Code aus Statecharts generieren lasse. Ich denke ich gewinne daraus
etwas Übersicht, jedoch ist das für mich Neuland und ich denke die
Einarbeitung erfordert sehr viel Zeit.
Eine Umsetzung mit Funktionspointern und Transitionsstabelle statt
Switch-Case könnte auch für mehr Übersicht sorgen, jedoch löst es nicht
das Problem mit den Verschachtelungen.
Hat jemand ein Vorschlag für mich, wie ich so eine Statemachine umsetzen
kann, zum Beispiel, dass die verschachtelten Statemachines sich
automatisch zurücksetzen, oder was eine Verschachtelung überflüssig
macht?
Christian S. schrieb:> Durch diesen Abbruch sind jedoch die verschachtelten Statemachines noch> in ihren alten Zuständen, was bei Wiedereintritt für Probleme sorgt.
sollte man dann nicht dieses Problem lösen?
Sorge doch einfach dafür das bei eintritt alle untergeordneten dinge
zurückgesetzt werden.
Christian S. schrieb:> Die Statemachine in main() hat 23 Zustände, wobei bspw.> in einem State sich wiederrum eine Statemachine befindet,> die 8 Zustände beinhaltet, diese wiederrum hat auch eine> verschachtelte Statemachine mit 9 Zuständen, und die hat> wieder eine mit 5 Zuständen.
Das klingt schonmal etwas ungesund.
> Die Verschachtelung habe ich so umgesetzt, da diese> Abschnitte wiederholt aufgerufen werden, weshalb eine> Auflösung als eine große Statemachine den Programmspeicher> unnötig füllt und unpraktisch ist, wenn man was ändern will.
???
Ich verstehe kein Sterbenswörtchen.
> Um das Problem zu lösen, muss vor dem Abbruch die> unterliegende Statemachine über den Abbruch informiert,> die wiederum auch alle unterliegenden informiert.
Richtig.
> Gibt es elegantere Lösungen?
Nein.
Wenn ein Reset notwendig ist, musst Du Reset passend beschalten.
> Eine Möglichkeit die ich gerade sehe, ist die Umsetzung Yakindu,> wo ich den Code aus Statecharts generieren lasse. Ich denke ich> gewinne daraus etwas Übersicht,
Glaube ich nicht.
Grundlagen der Automatentheorie wären wohl nützlich: Eingangs-
signale, Ausgangssignale, Zustände, Überführungsfunktion,
Ausgabefunktion.
Fertig ist der Automat.
> Eine Umsetzung mit Funktionspointern und Transitionsstabelle> statt Switch-Case könnte auch für mehr Übersicht sorgen,
Die Überführungsfunktion würde ich immer als Tabelle (=Array)
formulieren; switch/case ist dafür ein Furunkel am Arsch.
Wozu man in dem Kontext Funktionspointer braucht, weiss ich
nicht. -- Ach so: Für die Ausgabe wahrscheinlich. -- Ja, das
sollte funktionieren.
> jedoch löst es nicht das Problem mit den Verschachtelungen.
Ich vermute Fehler im Automatenentwurf.
> Hat jemand ein Vorschlag für mich, wie ich so eine> Statemachine umsetzen kann, zum Beispiel, dass die> verschachtelten Statemachines sich automatisch> zurücksetzen,
Ich vermute, Du hast Dich im switch/case-Dschungel verlaufen:
Man kann natürlich mehrere gekoppelte Automaten (="Verschachtelung")
programmieren, aber Du musst in der Hauptschleife JEDEM Automaten
Rechenzeit geben!
> oder was eine Verschachtelung überflüssig macht?
Nicht "Verschachteln"! Die Automaten über Hilfssignale koppeln
(Freigaben bzw. Verriegelungen).
Danke schonmal für die Antworten
Possetitjel schrieb:> Christian S. schrieb:>>> Die Verschachtelung habe ich so umgesetzt, da diese>> Abschnitte wiederholt aufgerufen werden, weshalb eine>> Auflösung als eine große Statemachine den Programmspeicher>> unnötig füllt und unpraktisch ist, wenn man was ändern will.>> ???> Ich verstehe kein Sterbenswörtchen.>
Vielleicht mal ein konkretes Beispiel mit folgenden States:
Login -> Signalstärke anzeigen -> Logout -> Ereignis warten -> Login ->
SMS senden -> Logout
Wobei jedes State wiederum ein eine eigene Statemachine ist.
Ich könnte eine natürlich eine riesige Statemachine daraus machen, was
aber unsinnig ist, da ich dann zwei identische Abschnitte in der
Statemachine habe.
Deshalb habe ich aus dem kompletten Loginvorgang wiederum eine eigene
Statemachine gemacht, die als Funktion aus der "Haupt Statemachine"
aufgerufen wird.
Der Loginvorgang kann ein Fehler zurückgeben, z.B. keine SIM-Karte oder
kein Netzsignal, aber auch die "Haupt Statemachine" kann nach einer
gewissen Zeit den Loginvorgang abbrechen und den State auf Fehlerausgabe
wechseln (z.B. GSM Modul braucht zu lange für den Login zum
Netzbetreiber).
Wenn das eintrifft muss der State das Loginvorgangs zurückgesetzt
werden.
>> Eine Umsetzung mit Funktionspointern und Transitionsstabelle>> statt Switch-Case könnte auch für mehr Übersicht sorgen,>> Wozu man in dem Kontext Funktionspointer braucht, weiss ich> nicht. -- Ach so: Für die Ausgabe wahrscheinlich. -- Ja, das> sollte funktionieren.>
Ja, in der Transitionstabelle (Array) sind Pointer auf die Funktionen,
die bei Eintritt, jedem Tick und Austritt das States ausgeführt werden
sollen.
>> jedoch löst es nicht das Problem mit den Verschachtelungen.>> Ich vermute Fehler im Automatenentwurf.>
Mag wohl sein, bin auch nicht so fit im Automatenentwurf, ich kenn nur
einige Grundlagen. Aber deshalb auch meine Problemschilderung ;-)
>> Hat jemand ein Vorschlag für mich, wie ich so eine>> Statemachine umsetzen kann, zum Beispiel, dass die>> verschachtelten Statemachines sich automatisch>> zurücksetzen,>> Ich vermute, Du hast Dich im switch/case-Dschungel verlaufen:> Man kann natürlich mehrere gekoppelte Automaten (="Verschachtelung")> programmieren, aber Du musst in der Hauptschleife JEDEM Automaten> Rechenzeit geben!>
Ich glaube ich hab ein jetzt ein entscheidenden Fehler im Entwurf
gefunden.
Die "Haupt Statemachine" hat immer Rechenzeit, jedoch die aufgerufenden
Statemachines takten nur durch Aufruf aus der "Haupt Statemachine".
Deshalb auch ein Problem bei abbruch, die Statemachines bleiben stehen,
und müssen umständlich zurückgesetzt werden.
>> oder was eine Verschachtelung überflüssig macht?>> Nicht "Verschachteln"! Die Automaten über Hilfssignale koppeln> (Freigaben bzw. Verriegelungen).
Ja ok, jetzt ist der Groschen gefallen ;-)
Dann werd ich erstmal meine Freestyle State Machine etwas umschreiben
;-)
Christian S. schrieb:> Die "Haupt Statemachine" hat immer Rechenzeit, jedoch die aufgerufenden> Statemachines takten nur durch Aufruf aus der "Haupt Statemachine".
Nö, alle Statemaschienen takten parallel, d.h. werden von der Mainlopp
aufgerufen.
Wie eine Statemaschine auf eine andere reagieren soll, wird über
Ereignisse (Variablen) gesteuert.
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