Guten Tag,
ich versuche gerade die Statemachine (siehe Anhang) in C umzusetzen. Es
handelt sich dabei um eine Lichtsteuerung wobei das Licht nur angehen
soll wenn ich nachts heimkomme. Dazu habe ich 4 Status zwischen welchen
gewechselt wird (Tagsüber/Zuhause, Tagsüber/NichtZuhause, Nachts/Zuahuse
und Nachts/NichtZuhause).
Die Bedingungen sind wie folgt zu interpretieren:
Tag = 1
Nacht = 2
Da = 1
NichtDa = 2
An den Übergängen ist die jeweilige Aktion beschrieben die bei dem
Übergang in einen anderen Status ausgeführt werden soll.
Hierzu habe ich mir den unten stehenden C-Code überlegt. Allerdings
kommt mir das nicht sehr elegant vor, aber ich komme im Moment auf keine
bessere Idee. Daher die Frage wie man diese Statemachine eleganter in C
Code umsetzen kann.
Die Beispiele die ich gefunden habe basieren leider alle darauf das die
einzelnen Staus die Funktion beschreiben (in meinem Fall hätte ich dann
zwei Status, LichtAn und LichtAus). Hierbei verstehe ich allerdings
nicht wie ich das mit meinen Übergangsbedingungen umsetzen könnte.
PS: Ich weiß das der Code C# ist, ich wollte es nur schnell testen, das
eigentliche Programm wird in C realisiert.
Vielen Dank im Voraus.
Ja. ist nichts gegen einzuwenden. Ich würde allerdings noch folgendes
optimieren:
Das setzen des Textes muss nur einmal passieren, wenn du in den (neuen)
Schritt reinläufst. Ebenso würde ich das Schalten der Lampen auch einem
Schritt und nicht einer Transistion zuordnen und auch nur beim Einsprung
machen.
Beitrag "Re: Programm bzw. Ablaeufe steuern"
@Anfänger (Gast)
>soll wenn ich nachts heimkomme. Dazu habe ich 4 Status zwischen welchen
Zustände. Die Mehrzahl von Status ist die Status. Klingt komisch, ist
aber so ;-)
http://www.duden.de/rechtschreibung/Status>Tag = 1>Nacht = 2
Ist das nicht redundanz? Wenn Tag ist, kann nicht Nacht sein.
>Da = 1>NichtDa = 2
Das Gleiche!
>Hierzu habe ich mir den unten stehenden C-Code überlegt. Allerdings>kommt mir das nicht sehr elegant vor,
Ist er auch nicht.
> aber ich komme im Moment auf keine>bessere Idee. Daher die Frage wie man diese Statemachine eleganter in C>Code umsetzen kann.
Siehe Statemachine
Anfänger schrieb:> if (TagNacht == 1 && DaWeg == 1)
warum so "merkwürdige" Variablennamen?
wäre nicht besser:
if(Tag && Da)
oder
if(!Tag)
if(!Da)
ggfs. auch verschachtelt oder negiert oder verodert -> Wahrheitstabelle.
Tag als bool
Da als bool
wenn nicht Tag, dann muss doch Nacht sein.
wenn nicht Da, dann muss doch Weg sein.
Es steht dir frei überflüssige Variablen einzufügen wenn es dadurch
leichter lesbar wird, aber fehlerträchtiger.
Nacht=!Tag;
Weg=!Da
Falk B. schrieb:>> aber ich komme im Moment auf keine>>bessere Idee. Daher die Frage wie man diese Statemachine eleganter in C>>Code umsetzen kann.>> Siehe Statemachine
Diesen Artikel habe ich mir selbstverständlich schon angesehen:
Anfänger schrieb:> Die Beispiele die ich gefunden habe basieren leider alle darauf das die> einzelnen Staus die Funktion beschreiben (in meinem Fall hätte ich dann> zwei Status, LichtAn und LichtAus). Hierbei verstehe ich allerdings> nicht wie ich das mit meinen Übergangsbedingungen umsetzen könnte.
Zu den Variablen, die Namen sind wirklich schlecht gewählt, das werden
ich ändern.
MfG.
Eric B. schrieb:> typedef enum> {> NONE,> COMING_HOME,> LEAVING_HOME,> DAYTIME,> NIGHTTIME> } Event;
ich sag nur Klasse!
gut lesbar klar logisch, ich lerne auch gerne dazu, mit den enum muss
ich mich endlich mal anfreunden, fällt mir immer noch schwer.
Joe F. schrieb:> ehm, Vorschlag: das hier macht das Gleiche. [...]
Nee, leider nicht.
Bei Dir geht das Licht im Zustand "Nacht/Da" immer an - also
auch beim Übergang "Tag/Da --> Nacht/Da"; laut Graph soll es
in diesem Zustand aber aus bleiben.
Deine Idee ist trotzdem gut:
IF ((AlterZustand=Weg) AND (NeuerZustand=Nacht/Da))
THEN LichtAn
ELSE LichtAus
;
Ein typisches Verfahren so was zu machen ist eine Zustandstabelle. Das
verhindert, dass Du so viel praktisch unlesbaren Code mit case oder
if-Abfragen hast.
Du hättest dann an einer Stelle eine Tabelle in der der momentane
Zustand, die Übergangsbedinung und der neue Zustand drin steht. Die
kannst Du dann einfach durchsuchen.
Das macht Deinen Code plötzlich viel kürzer und lesbarer und somit
leichter zu warten.
Joachim B. schrieb:>> gut lesbar klar logisch, ich lerne auch gerne dazu, mit den enum muss> ich mich endlich mal anfreunden, fällt mir immer noch schwer.
Mir geht es ganz genau so - ich weiss auch nicht, warum. Ist einfach so.
Auf jeden Fall ist das eine sehr schöne Implementierung :-)
Weinga U. schrieb:> Passend zum Thema möchte ich euch auf mein XML Framework für> Statemachines aufmerksam machen:>> Seite 16 auf> http://journal.embedded-projects.net/downloads/EPJ_17_web.pdf
Vielen Dank für den Hinweis, Klaus. Irgendwie hatte ich das damals wohl
in der Printausgabe übersehen.
Danke für die Blumen :-)
Christian B. schrieb:> Ein typisches Verfahren so was zu machen ist eine Zustandstabelle. Das> verhindert, dass Du so viel praktisch unlesbaren Code mit case oder> if-Abfragen hast.>> Du hättest dann an einer Stelle eine Tabelle in der der momentane> Zustand, die Übergangsbedinung und der neue Zustand drin steht. Die> kannst Du dann einfach durchsuchen.>> Das macht Deinen Code plötzlich viel kürzer und lesbarer und somit> leichter zu warten.
Das kann aber, vor allem wenn die Tabelle mal länger wird, zu erheblich
langsamere Laufzeiten führen. Was die bessere Wahl ist hängt von der
Anzahl der Zuständen und Übergangen ab, und davon wie man die
Übergangsbedingungen formuliert.
Rene H. schrieb:> Ich würde auch eher auf eine Zustandstabelle greifen. Also erst> Enum und> in der Tabellenbeschreibung enum verwenden.>> Gut lesbar, kurzer Code.
Zeig her! :-)
Eric B. schrieb:>> Du hättest dann an einer Stelle eine Tabelle in der der momentane>> Zustand, die Übergangsbedinung und der neue Zustand drin steht. Die>> kannst Du dann einfach durchsuchen.>>>> Das macht Deinen Code plötzlich viel kürzer und lesbarer und somit>> leichter zu warten.>> Das kann aber, vor allem wenn die Tabelle mal länger wird, zu erheblich> langsamere Laufzeiten führen. Was die bessere Wahl ist hängt von der> Anzahl der Zuständen und Übergangen ab, und davon wie man die> Übergangsbedingungen formuliert.
Das Problem des langen Suchens könnte man durch Hashen lösen. Dadurch,
dass die Zustände ja bei Programmstart bekannt sind, kann man sogar "in
Ruhe" den optimalen Hash berechnen und hätte dann von der Anzahl der
Zustände unabhängig konstante Zugriffszeiten (O(1)).
Chris D. schrieb:> Das Problem des langen Suchens könnte man durch Hashen lösen.
Wozu willst du da denn hashen?
Du weisst doch zu jedem Zeitpunkt, welches der aktuelle Zustand ist. Das
ist nichts anderes als der Index in die Tabellenzeilen! Sinnvollerweise
wird man natürlich die Nummern der Zustände aufsteigend und ohne Lücken
vergeben. Womit wir dann wieder beim enum sind, deren numerische Werte
automatisch vom Compiler durchnummeriert werden.
Ein sich möglicherweise ergebender neuer Zustand ist dann nicht anderes
als der Index der ab dann gültigen Tabellenzeile. Da muss nichts gesucht
werden.
Das 'Problem' bei tabellengesteuerten Statemaschinen ist die
Beschreibung der Übergangsbedingung bzw. die zugehörigen Aktionen. Die
lässt sich in der Tabelle meistens eher schlecht darstellen. Bei
einfachen Beipielen hat man für jeden Eingang eine Tabellenspalte wobei
immer noch das Problem bleibt, wie die zu verknüpfen sind. Jeder Ausgang
ist auch eine Tabellenspalte.
Bei komplexeren Maschinen mit vielen Ein und Ausgängen versagt das aber,
weil man sonst riesig breite Tabellen kriegt, die dann erst recht wieder
nicht wartbar sind. Dann kommen in die Tabelle Funktionspointer, was
wiederrum das 'Problem' aufwirft, dass nicht mehr die komplette Logik
ausschliesslich innerhalb der Tabelle kodiert ist.
Eric B. schrieb:> Danke für die Blumen :-)
nicht abheben :-)
zum besseren Verständnis fehlt mir noch
wo und wie ist ev definiert und initialisiert?
Eric B. schrieb:> switch(ev)Eric B. schrieb:> static LightState lightState = LIGHT_UNDEFINED;
wo und wie ist LightState definiert und initialisiert?
Eric B. schrieb:> void runstate(Event ev)
wo und wie ist Event definiert und initialisiert?
dito LIGHT_UNDEFINED und andere?
Joachim B. schrieb:> Eric B. schrieb:>> Danke für die Blumen :-)>> nicht abheben :-)> zum besseren Verständnis fehlt mir noch
Nur zum Verständnis.
Das was Eric da weiter oben fabriziert hat ist keine Statemachine im
klassischen Sinn.
Sieht man schon daran, dass es keinen fortlaufenden Status gibt, dir
sich ändern könnte.
Das was er da oben gezeigt hat ist die Auswertung von Events, die auf
Zustandsvariablen wirken und die Auswertung der
Kombinationsmöglichkeiten dieser Zustandsvariablen.
Bei derart einfachen Beispielen ist das natürlich völlig legitim.
Eric B. schrieb:> /* walk through trnasitions table */> for(i = 0; i < sm->nofTransitions; i++)> {> /* event and current state match? */> if((ev == sm->transitions[i].ev) && (sm->current ==> sm->transitions[i].old))
Hmm
Ich frage mich gerade, ob es nicht einfacher wäre, für jeden Zustand
eine eigene Tabelle (Array) zu benutzen. Eines davon ist der aktuelle
Zustand (repräsentiert durch einen Pointer auf das gerade aktuell
gültige Array). Ein Zustandsübergang ist dann nicht anderes als den
Pointer auf ein anderes Array setzen.
Dann könnte man auch den Fall handhaben, dass es mehr als 1 Transistion
von einem Zustand in einen anderen Zustand gibt, ohne dass man hier
suchen muss.
Nachteil ist natürlich, dass nicht mehr die komplette Logik in einem
einzigen Array beisammen ist.
Hi,
Eine recht übersichtliche und von der Laufzeit her schöne Methode ist
auch die, den aktuellen State in einem Funktionspointer zu halten und
für jeden State eine eigene Funktion zu schreiben.
static void State_Zu(enum Ereignis);
static void State_Auf(enum Ereignis)
static void (*currentState)(enum Ereignis) = State_Zu;
static void State_Zu(enum Ereignis)
{
if (Ereignis = Auf)
{
machwas...
currentState = State_Auf;
}
}
static void State_Auf(enum Ereignis)
{
if (Ereignis = Zu)
{
machwasanderes...
currentState = State_Zu;
}
}
void Statemachine(enum Ereignis)
{
currentState(Ereignis);
}
...
Gruß Martin
Karl H. schrieb:> Ich frage mich gerade, ob es nicht einfacher wäre, für jeden Zustand> eine eigene Tabelle (Array) zu benutzen.
so weit dachte ich auch schon im Sinne einer Wahrheitstabelle
kann aber sein das mir da noch jedes Verständnis fehlt.
Ich habe ja auch noch einige Programme zu erstellen wo mittlerweile das
größte Problem ist alle Zustände zu erfassen bzw. zu berück
sichtigen.
egal wie ich die ifs verschachtele, einer ist immer falsch.
Mit if else komme ich da nicht weiter oder es wird ein unübersichtlicher
Bandwurm mit doppelten Codeteilen, aber in Funktionen auslagern, dazu
sind es zu viele Variablen, alle globals mitnehmen ist auch nicht toll,
alle Variablen der Funktion übergeben auch nicht bzw. return, bliebe nur
noch die Adressen aller beteiligter Variablen was es noch
unübersichtlicher macht wer was wo ändert.
Joachim B. schrieb:> wo und wie ist LightState definiert und initialisiert?> wo und wie ist Event definiert und initialisiert?> dito LIGHT_UNDEFINED und andere?
In den enum typedefs ganz oben im Code.
Karl H. schrieb:> Ich frage mich gerade, ob es nicht einfacher wäre, für jeden Zustand> eine eigene Tabelle (Array) zu benutzen.
In diesem Fall sind die 3 FSMs so klein (jeweils 2 Zustände und pro
Zustand ein Event das zu einem Zustandswechsel führt), dass sich das
nicht/kaum lohnt. Aber im Allgemeinen ist das schon ein guter Ansatz.
Martin K. schrieb:> Eine recht übersichtliche und von der Laufzeit her schöne Methode ist> auch die, den aktuellen State in einem Funktionspointer zu halten und> für jeden State eine eigene Funktion zu schreiben.
Ja, und in C++ könnte man das dann in einem Functor packen.
Es gibt letztendlich viele Wege die nach Rom führen :-)
Wir Lernen uns empor! (frei nach Harald Lesch :-)
Auch wenn's hier manchmal ein bissel Drunter und Drüber geht - ich liebe
dieses Forum.
Telekolleg Mikrocontroller... Heute: Elegantes Coden für State-Machines.
Großen Dank für die kreativen Beträge, besonders von Eric und
Karl-Heinz.
Joachim B. schrieb:> Ich habe ja auch noch einige Programme zu erstellen wo mittlerweile das> größte Problem ist alle Zustände zu erfassen bzw. zu berück> sichtigen.
Eine Technik die ich vor Jahren bei einem Projekt das erste mal gesehen
habe:
Wenn es geht, erstelle für einzelne Subsysteme eigene State-maschines.
Ich kannte diese Technik damals auch noch nicht. Es hat aber nicht lang
gedauert, bis ich begriffen habe, wie elegant damit das Gesamtsystem
plötzlich wird. Die Maschine, die es zu steuern galt, lies sich in
diverse einzelne Subsysteme zerlegen. Die Statemaschines haben sich über
globale Variablen gegenseitig ihre Endzustände mitgeteilt. Die
Statemaschines wurden ganz einfach Round Robin immer reihum
abgearbeitet. Die Statmaschine, welches den Vorschub des Bandes regelte
musste sich nicht darum kümmern, wie die Statemaschine, die nacheinander
alle Positionen auf dem Bandabschnitt ansteuert das genau macht. Wenn
alle Positionen abgefahren waren, hat die eine Statemaschine der anderen
signalsiert, dass sie fertig wäre. Die Positionsabfahr-Maschine hingegen
kümmerte sich nicht darum, wie genau die Position angefahren wurden. Das
machte eine eigene, die über Motoren, deren Beschleunigungsverhalten,
Bremsverhalten etc. Bescheid wusste. Die Positionmaschine signalisierte
der Motormaschine, wo sie hin will und wenn die Position anliegt (bzw.
eigentlich schon davor, denn zu diesem Zeitpunkt musste eine Kamera
eingeschaltet werden), dann meldete sich die andere Maschine (wieder
über globale Variablen), dass die Position anliegt. Die
Positioniermaschine 'verharrte' dazu einfach so lange in einem
Wartezustand, bis von der anderen Maschine das Freizeichen kam.
In gewisser Weise ist das das Pedant zu kooperativem Multitasking.
Als mir der damals mit dem Projekt betraute die Sache soweit klar
gemacht hatte, hab ich auch gedacht: Puh, was für ein Aufwand.
Aber - ich muss gestehen ich hab das unterschätzt. Die einzelnen
Maschinen waren simpel und einfach genug, dass es ein Klacks war, da
Erweiterungen vorzunehmen. Unser Job war, die Zykluszeit schneller zu
machen, indem so viele Vorgänge wie möglich parallel ablaufen sollten.
Während das Band noch in seine nächste Halteposition vorschiebt, fährt
bereits der Kameraarm in Position. Wenn irgendetwas dabei schief geht,
dann warten die einzelnen Subsysteme ganz automatisch aufeinander.
Reisst das Fürderband, dann wird auch seine Halteposition nicht
erreicht, wodurch die Positioniermaschine ihr Freizeichen nicht kriegt,
die wiederrum dem Arm nicht die Erlaubnis gibt, die Prüfsonden
kameragesteuert abzusenken.
Gut, wir waren auf einem PC, der das alles mit links stemmt. Solange man
es nicht übertreibt, würde ich heute auf einem µC mehr oder weniger so
ziemlich dasselbe machen. Die Vorteile in der Wartung bzw. bei
Änderungen waren einfach unübersehbar. Die Aufteilung garantierte, dass
wir uns nicht in irgendeinem anderen Subsystem Ärger einhandeln würden.
Solange wir an der Kommunikation untereinander nichts änderten, konnten
wir in den Subsystemen schalten und walten, wie wir wollten.
>Wenn es geht, erstelle für einzelne Subsysteme eigene State-maschines.
So ist das auch üblich. Es gibt eine Art Hauptschrittkette für die
Maschine. Diese triggert nur andere Schrittketten an, irgendwas zu tun.
Und wartet einfach als eigene Transition auf das Fertig der anderen
Schrittkette..
Karl H. schrieb:> Unser Job war, die Zykluszeit schneller zu> machen, indem so viele Vorgänge wie möglich parallel ablaufen sollten.> Gut, wir waren auf einem PC, der das alles mit links stemmt.
erinnert mich an meine Industriezeit als ich Tastwahlbock prüfen sollte,
die Wartezeit Vorwahlpause 800ms konnte ich nutzen um den
Sperrwiderstand vom FET zu messen, mein Vorgänger hat doch echt
sequenziell abgearbeitet und so Zeit vertrödelt, war aber auf dem CBM
(6502 8-bit 32KB Ram 1 MHz) :)
Am µC mache ich es ja so, im IRQ wird gezählt lcd_upd-- wann 330ms um
sind wenn 0 LCD refresh, im loop ist es ja egal wann genau der
stattfindet, nur wenn er erfolgt ist wird lcd_upd wieder initialisiert.
PeDa hat ja auch einen Scheduler für den AVR geschrieben, ich wollte mir
den immer schon mal ansehen.
Joachim B. schrieb:> Karl H. schrieb:>> Unser Job war, die Zykluszeit schneller zu>> machen, indem so viele Vorgänge wie möglich parallel ablaufen sollten.>> Gut, wir waren auf einem PC, der das alles mit links stemmt.>> erinnert mich an meine Industriezeit als ich Tastwahlbock prüfen sollte,
Bei mir waren es frisch gebondete RFID-Dies.
Den Asiaten war jeder einzelne Chip pro Sekunde mehr bares Geld wert :-)
Matthias L. schrieb:>>Wenn es geht, erstelle für einzelne Subsysteme eigene State-maschines.>> So ist das auch üblich.
Ich kannte SM damals auch nur aus der 'reinen Lehre'.
Da kommt dieser Aspekt oft zu kurz. Zumindest während meiner
Ausbildungszeit war das noch so.
Karl H. schrieb:> Ich kannte SM damals auch nur aus der 'reinen Lehre'.> Da kommt dieser Aspekt oft zu kurz. Zumindest während meiner> Ausbildungszeit war das noch so.
Da hast Du wohl recht. Wir hatten in der Technikerschule mal eine
Schrittkette mit AWL programmiert. Weil man da von ST und CASE().. noch
nie gehört hatte. Da hatte man viel Zeit und Tipperei verplempert um
eine Variable mit CMP zu vergleichen und immer paar Zeilen (über den
Code des States) zu springen.
Völlig absurd.
Karl H. schrieb:> Joachim B. schrieb:>> Eric B. schrieb:>>> Danke für die Blumen :-)>>>> nicht abheben :-)>> zum besseren Verständnis fehlt mir noch>> Nur zum Verständnis.
Ja... Verständnis - oder vielmehr Unverständnis - ist das
richtige Stichwort: Wieso benötigt man, um DREI BIT zu
verarbeiten, Zieh-Scharp, CORBA, JavaBeans und D flat major?
Ausgangssignal ist im Beispiel eine boolsche Variable "LichtAn".
Ein Bit.
Zustandsvariablen sind "Tag" und "Da", also zwei Bit.
Über die Eingangssignale ist nix gesagt; man kann aber aufgrund
der Zustände davon ausgehen, dass Eingangssignale und Zustände
korrespondieren - mithin die Überführungsfunktion die triviale
Funktion ist.
Die Ausgangssignale sind den Kanten, d.h. den Zustandsübergängen
zugeordnet, es wird also ein MEALY-Automat gewünscht.
Jede Kante ist durch Start- und Zielzustand eindeutig beschrieben;
bei vier Zuständen gibt es also 16 Kanten (einschließlich der
Selbstschleifen); das kann im gezeichneten Graphen überprüft
werden.
Die Ausgabefunktion kann also als Tabelle mit 16 Zeilen
definiert werden; der Index wird durch die Verkettung von
Start- und Zielzustandscode gebildet und läuft von "00 00" bis
"11 11".
Von den 16 Kanten rufen allerdings nur zwei ein aktives Ausgangs-
signal hervor, und diese beiden Kanten haben überdies die
Besonderheit, dass sie in "benachbarten" Zuständen beginnen und
im selben Endzustand enden. (Benachbarte Felder im Karnaugh-Plan
bzw. ein "-" in der Ternervektorliste.)
Die Ausgabefunktion ist also, wenn ich keinen Fehler gemacht
habe, so vollständig beschrieben:
IF ((AlterZustand=Weg) AND (NeuerZustand=Nacht/Da))
THEN LichtAn
ELSE LichtAus
;
Wo ist das Problem? Ich versteh's nicht.
Possetitjel schrieb:> IF ((AlterZustand=Weg) AND (NeuerZustand=Nacht/Da))> THEN LichtAn> ELSE LichtAus> ;>> Wo ist das Problem? Ich versteh's nicht.
Es gibt kein Problem, nur viele unterschiedliche Lösungen :-P
Edit: Und deine ist nicht richtig. Licht soll zB auch an wenn
AlterZustand == Tag/Da und NeuerZustand == Nacht/Da
Eric B. schrieb:> Edit: Und deine ist nicht richtig. Licht soll zB auch an wenn> AlterZustand == Tag/Da und NeuerZustand == Nacht/Da
Nicht im gezeichneten Graphen. Dort ist die Kante von Tag/Da
zu Nacht/Da mit "Off" beschriftet.
Possetitjel schrieb:> Eric B. schrieb:>>> Edit: Und deine ist nicht richtig. Licht soll zB auch an wenn>> AlterZustand == Tag/Da und NeuerZustand == Nacht/Da>> Nicht im gezeichneten Graphen. Dort ist die Kante von Tag/Da> zu Nacht/Da mit "Off" beschriftet.
Hah, haste Recht! Dann sind alle meine Statemaschinen weiter oben falsch
:-D
Possetitjel schrieb:> Wo ist das Problem? Ich versteh's nicht.
Das Problem ist, dass man in der Lernphase oft mit Beispielen
konfrontiert ist, bei denen man sich fragt, warum man da jetzt mit
Kanonen auf Spatzen schiessen soll.
Sieh es als Vorstudie, mit der man Techniken erlernt, die man dann bei
komplexeren Beispielen einsetzen kann, weil man schon weiss wie es geht,
bzw. wie eine bestimmte Technik funktioniert.
Das Beispiel des TO ist von dieser Sorte. Kein normal denkender
Entwickler würde sich bei der Komplexität (übrigens: schöne Analyse)
eine komplette Statemaschine antun.
Matthias L. schrieb:> Wir hatten in der Technikerschule mal eine Schrittkette> mit AWL programmiert. Weil man da von ST und CASE().. noch> nie gehört hatte. Da hatte man viel Zeit und Tipperei> verplempert um eine Variable mit CMP zu vergleichen und> immer paar Zeilen (über den Code des States) zu springen.
Hmm. Was stört Dich denn an Schrittketten in AWL?
Schätzungsweise laufen Tausende Maschinen so (und das
durchaus zuverlässig).
Ich möchte AWL gar nicht übermäßig verteidigen (AWL wird in
Eleganz und Lesbarkeit wohl nur von Brainfuck übertroffen),
aber ich fand es durchaus nützlich, Automatentheorie
sozusagen auf Gatterniveau zu betreiben, ohne wirklich
Gatter verdrahten zu müssen.
Und überdies habe ich den Verdacht, dass macher High-Level-
Programmierer seinen Programmierstil STARK überdenken
würde, hätte er mal eine Weile ERNSTHAFT klassische
Steuerungsprogrammierung gemacht.
>hätte er mal eine Weile ERNSTHAFT klassische Steuerungsprogrammierung >gemacht.
Wenn das Ganze als Grundlagenlehre dient, ist das Ok. Ich habe zB selbst
in der Ausbildung ASM gelernt und Quellcode mit acht Schaltern
"programmiert". Für reine Grundlagen sehr lehrreich.
Ebenfalls kein Problem wenn in SPS-Technik AWL gebracht wird. Aber
darauf nun als Stand der Technik arbeiten zu wollen, ist doch ziemlich
veraltet.
>Was stört Dich denn an Schrittketten in AWL?
Mich hat damals gestört, das viel Zeit und Energie für den
"Programmrumpf" aufgebraucht wurde, der sonst einfach durch das
Hinschreiben von
1
Switch(Status)
entsteht. Und auf die Frage nach ST zum Programmieren sah man mich an,
als ob ich die Lottozahlen von morgen wissen wolle...
Karl H. schrieb:> Possetitjel schrieb:>>> Wo ist das Problem? Ich versteh's nicht.>> [...]> Sieh es als Vorstudie, mit der man Techniken erlernt, die> man dann bei komplexeren Beispielen einsetzen kann, weil> man schon weiss wie es geht, bzw. wie eine bestimmte Technik> funktioniert.
Ich muss zurückrudern.
Eric hat - von dem Flüchtigkeitsfehler abgesehen - ziemlich
genau das gemacht, was mir vorschwebt; ich habe es beim ersten
Durchlesen nur nicht verstanden.
Was ich wirklich fürchterlich finde, das sind die Ansätze,
endliche Automaten durch einen Dschungel von Fallunterscheidungen
zu implementieren - aber ich vermute, da sind wir ohnehin
einer Meinung (?!).
Zwei Anmerkungen trotzdem.
Du hast Eric kritisiert, er hätte gar keine "richtige state
machine" implementiert. Das liegt aber nicht an Eric, sondern
an der Aufgabenstellung - in der gibt's nämlich keine
Eingangssignale; gegeben sind dort schon die Zustandsvariablen.
Die Fragestellung des TO bezog sich im Grunde auf das rein
kombinatorische Problem, aus altem und neuem Zustand das
Ausgangssignal zu bestimmen.
Zum anderen ist Dein Einwand weiter oben, große Automaten ließen
sich auf Tabellenbasis schlecht implementieren, zwar prinzipiell
richtig - er wird aber von der Tatsache überdeckt, dass sich sehr
"große" Automaten auch nicht sinnvoll SPEZIFIZIEREN lassen: Ein
Automat mit 12 binären Eingangssignalen und 12 binären Zustands-
variablen hat 16 Millionen Übergänge. Die Überführungsfunktion
braucht also 32 MByte in Tabellenform. Das wäre noch machbar -
aber wer will die 250 Aktenordner mit je 500 doppelseitig bedruckten
Blättern für die Spezifikation erstellen?
Man MUSS große Automaten also zerlegen (oder besser "komprimierbare"
Beschreibungen finden) - nicht primär, weil die Maschine sie nicht
beherrschen könnte, sondern weil der Mensch es nicht kann.
Hallo,
weil ich mir Boost::MSM schon lange mal angeschaut haben wollte, anbei
ein Beispiel in C++ mit ebenjenem Boost::MSM. Das ist für die hier
gestellte Aufgabe natürlich mit Kanonen auf Spatzen geschossen, IMHO
aber eine sehr saubere, les- und vor allem erweiterbare Veranstaltung.
Und klein ist sie obendrein: mit "-Os -flto" kompiliert und mit "strip"
behandelt, hat das Binary am Ende gerade mal 36K.
Liebe Grüße,
Karl
Erst mal minimiert man die Zustände, dann kloppt man das in ein Array
und gut ists, sowas macht man automatisch mit einem entspr.
Modellierungstool, alles andere ist fehleranfällig und vertrödelt Zeit.
Selbst die Varianten mit dem Pseudoeventsystem lässt man sich
generieren.
Und den Extremmurks mit XML vergessen wir mal ganz schnell wieder...
Mal ehrlich, wer das heute noch als Profi wo Zeit=Geld ist noch von Hand
reinkloppt hat den Schuss noch nicht gehört.
Automatentheoretiker schrieb:> Und den Extremmurks mit XML vergessen wir mal ganz schnell wieder...
Nehme die Aussage zurück, habe mal angeschaut was dort gemacht wurde,
das ist ja nix anderes als ein Codegentool, dachte da erst an was
anderes als ich XML las.