Implementierung eines Automaten



  • Hallo an alle.

    Ich habe im Laufe der Zeit diverse Maschinen ansteuern müssen. Als Steuereinheit wurde meist ein Atmel Controller verwendet mit GCC als Entwicklungsumgebung.

    Da ich die Steuerlogig gerne in mehrere Automaten packe bin ich immer wieder gezwungen diese in einem möglichst übersichtlichem Format zu implementieren. Allerdings bin ich von meiner derzeitigen Methode nicht vollständig überzeugt.

    enum{
          Zustand_1      = 0,
          Zustand_2      = 1,
          Zustand_3      = 2,
          ...
        }Zustand_Automat1;
    
    void Automat1(void)
    {
    
        switch( Zustand_Automat1 )
        {
            case Zustand_1:
                machwas...
                if( Bedingung1 )
                {
                    Zustand_Automat1 = Zustand_2 ;
                }
                break;
    
            case Zustand_2:
                machwas anderes.
                if( Bedingung2 )
                {
                    Zustand_Automat1 = ...;
                }
                break;
            ...
        }
    }
    

    Dadurch ergeben sich je nach Automatengröße nicht besonders übersichtliche Programmstücke. Natürlich verwende ich etwas aussagekräftigere Bezeichner aber ich will was besseres.

    Ich habe auch schon daran gedacht jeden Zustand als Funktion zu realisieren und als Status einen Funktionspointer zu nehmen, aber naja viel besser wirds dadurch nicht, denn dann habe ich 50 Funktionen welche einen Automaten darstellen.

    Vielleicht hat ja jemand ne bessere Idee.

    Babbage



  • Nein, Du hast leider recht, viel Eleganteres gibt es wahrscheinlich nicht:

    Entweder Du benennst Deine Zustände und gehst über switch/case oder jeder Zustand ist eine Funktion, die den Folgezustand als Funktionspointer zurückliefert.

    Ersteres ist bei einfachen Sachen leichter zu durchschauen, während die andere Methode "modularer" aussieht und etwas performanter ist.

    Ich habe auf der Suche nach eleganteren Möglichkeiten mal Sourceforge durchsucht, da gibt es ein paar Codegeneratoren für Automaten, die C oder C++ ausspucken. Gemeinsam ist jedoch allen Lösungen, daß sie sich im Grunde auch nur der beiden obigen Methoden bedienen und dafür katastrophal schlecht lesbaren Code abliefern.

    Ich bastel' also weiterhin per Hand ... 😉



  • ^^so'ne FSM kann man auch tabellengesteuert machen. ist manchmal übersichtlicher.
    ansonsten gibts noch tools, die dir den c-code generieren können. such mal nach 'visual state', 'ragel' oder 'libero'
    🙂



  • fricky schrieb:

    ^^so'ne FSM kann man auch tabellengesteuert machen. ist manchmal übersichtlicher. ansonsten gibts noch tools, die dir den c-code generieren können. such mal nach 'visual state', 'ragel' oder 'libero'
    🙂

    Das ist doch Käse, was da rausrappelt ist häßlich und schwer wartbar. Man muß die FSM voll ausdefinieren, bei Änderungen der ganze Zirkus nochmal? Unschön. Zumindest war`s das 2005.

    Tabellen muß man parsen, das ist vielleicht optisch elegant, aber SlowMotion- Zeugs im Vergleich zu Pointerthreading 😞 . Muß echt nicht sein.



  • Naja, alternativ kann man auch das State-Pattern verwenden. (http://en.wikipedia.org/wiki/State_pattern)

    Aber auch hier hat man das Problem der Übersichtlichkeit, denn man benötigt pro Zustand eine Klasse.



  • Danke für die Antworten, scheint ja doch ein Problem zu sein was noch einige kennen.
    Bei den Vorschlägen sind interessante Ideen dabei.
    Leider sind die Lösungen mit einem großen Overhead verbunden und oft in Verbindung mit C++. Diese Möglichkeiten stehen mir bei einer beschränkten Umgebung wie den Atmel Controllern nicht zur Verfügung.

    An Threads darf ich gar nicht erst denken. Ich muss ständig aufpassen das nicht ein Automat stecken bleibt und damit nicht das ganze System steht.

    Somit erscheint mir momentan für meine Zwecke das switch case Konststukt als kleinsten Übel.



  • Babbage schrieb:

    An Threads darf ich gar nicht erst denken. Ich muss ständig aufpassen das nicht ein Automat stecken bleibt und damit nicht das ganze System steht.

    auch hierfür gibts ne lösung: http://www.sics.se/~adam/pt/
    protothreads erleichtern auch die entwicklung von FSMs
    🙂



  • Babbage schrieb:

    Leider sind die Lösungen mit einem großen Overhead verbunden und oft in Verbindung mit C++.

    Das hab' ich gemeint. Zudem kann man das Projekt ohne diese Codegeneratoren nicht mehr richtig warten. Der Output besteht bei einigen z.B. aus einer Label/goto- Wüste.

    Babbage schrieb:

    An Threads darf ich gar nicht erst denken. Ich muss ständig aufpassen das nicht ein Automat stecken bleibt und damit nicht das ganze System steht.

    Ist wohl ein Mißverständnis, ich meinte kein OS- gestütztes Multithreading, sondern daß eine Zustandsfunktion einen Pointer auf die Folgezustandsfunktion zurückgibt. Anschaulich fädeln sich die Aufrufe so wie Perlen auf eine Kette. Kann man übersichtlich anlegen und ist ganz gut debugbar.

    Babbage schrieb:

    Somit erscheint mir momentan für meine Zwecke das switch case Konststukt als kleinsten Übel.

    Eigentlich nicht. Mit dem switch/case- Zeugs machst Du ja nichts anderes, als die Aufrufe zu tokenisieren und zur Laufzeit zu interpretieren. Die Vergleicherei kostet Rechenzeit, mehr als vier, fünf Vergleiche oder eine Bildschirmseite Source solltest Du nicht anlegen, besonders wenn Du mehrere Automaten am Laufen hast.

    fricky schrieb:

    protothreads erleichtern auch die entwicklung von FSMs

    fricky hat recht, Dir diese Seite ans Herz zu legen, da wird das Ganze konzeptionell ein wenig aufgebohrt dargelegt.


Log in to reply