Komplexe Zustandsautomaten (FSM) implementieren

Gast #4202760
Lesenswert?

Welche Techniken verwendet ihr für komplexe Zustandsmaschinen? Also 
nicht die Kindergartenbeispiele mit 4 bis 5 Zuständen und zwei, drei 
Events.
Mir geht es um Automatisierung mit mehreren Motoren, 
Pneumatik-Zylindern, dutzende Sensoren etc. die alle voneinander 
abhängen, also Mechanismen die komplex zusammenwirken, so dass man keine 
eindeutigen Bereiche/Trennstellen bilden kann.

Selbst wenn man die Aufgabe in zwei, drei Teilaufgaben zerlegen kann, 
werden die Zustandsmaschinen umfangreich, unübersichtlich und 
unflexibel. Änderungen sind immer sehr aufwendig, und nach einem Jahr 
blickt kein Mensch mehr durch, was man da mal programmiert hat.

Im Laufe der Zeit habe ich verschiedene Programmier-Techniken probiert. 
Tabellen, Switch-Case, Objektorientiert nach Design-Patern und, und, 
und. Das Dilemma bleibt immer das gleiche: Ein Haufen unübersichtlicher 
und unflexibler Code, bzw. unbrauchbar für die "reale" Welt. Das Zeug 
skaliert einfach nicht, sondern explodiert exponentiell.

Gibt es vielleicht Alternativen zu FSM? Nach welchen Stichworten kann 
ich googeln? Was sag die aktuelle Forschung zu dem Thema?
#4203102
Lesenswert?

Es gibt ein paar nette Headerdateien, wo man den Zustandsautomaten in 
einer Pseudosyntax einträgt, und die dann zur Compilezeit ein 
switch/case draus bauen. Das hilft zwar bei der Übersichtlichkeit nicht 
unbedingt, aber dadurch kannst du 1:1 vom Diagramm in den Code und auch 
zurück vergleichen.
Gast #4203112
Lesenswert?

Hi,
das klingt nach einem interessanten Problem. Könntest du mal eine 
(Teil)-Aufgabe posten? Kann mir noch nicht genau vorstellen was du 
meinst...
Gehts um sowas:
-wenn Sensor A + B dann Motor C?

Bin gespannt...
Gast #4203321
Lesenswert?

bränko schrieb:
> das klingt nach einem interessanten Problem. Könntest du mal eine
> (Teil)-Aufgabe posten? Kann mir noch nicht genau vorstellen was du
> meinst...

Also, das könnte z.B. eine solche Aufgabe sein:
1
        
2
        Greifer
3
           |
4
           V
5
                    
6
      #________ ________#
7
        Band 1   Band 2
8
                   ^ 
9
                   |
10
     Sensor        |           Schott      
11
      Voll         |              |        
12
        o          v              |           * Taster
13
      #________ ________ ________ | ________ 
14
        Band 3   Band 2   Band 4  |  Band 5


- Alle Bänder können nach links oder rechts fahren.
- Band 2 ist ein Lift und kann zusätzlich komplett hoch und runter 
fahren.
- Für den Lift gibt es jeweils ein Sensor für oben und unten.
- '#' = mechanischer Anschlag. Da wo keiner ist, können Dinge vom Band 
fallen.
- Es gibt im System zwei Carrier, die Ware aufnehmen können und von den 
Bändern hin und her gefahren werden.
- Band 2 und 4 haben jeweils einen Sensor um zu erkennen ob ein Carrier 
in der Mitte steht. Steht ein Carrier aus der Mitte, aber noch auf dem 
Band, sieht der Sensor den Carrier nicht.
- Band 1 hat einen Sensor ganz links, der anzeigt dass ein Carrier am 
Anschlag steht. Steht ein Carrier in der Mitte oder rechts davon, zeigt 
der Sensor nichts an.
- Band 3 hat keinen Sensor für den Carrier selbst, aber einen Sensor 
der anzeigt, wenn der Carrier mit Ware beladen ist und ganz links am 
Anschlag steht.
- Band 5 hat einen Sensor, der anzeigt wenn der Carrier in der Mitte 
oder bis zur linken Kante (bei geschlossenem Schott) anzeigt.
- Das Schott kann auf und zugehen und hat jeweils einen Sensor für auf 
und zu.
- Lift und Schott arbeiten pneumatisch. Es gibt ein Signal wenn die 
Druckluftversorgung O.k. ist.
- Für alle Bänder gibt es ein Fehler-Signal, wenn irgendein elektrisches 
Problem (Unterspannung, Überstrom, Sicherung, etc.) vorliegt.
- Da die Sensoren über Feldbus(e) angeschlossen sind, gibt es für jeden 
Sensor ein Valid-Signal. Nur wenn der Feldbus Ok ist, ist das 
Sensor-Signal verlässlich.

Der Ablauf ist wie folgt:

- Auf Band 1 steht ein leerer Carrier.
- Das System meldet dem Greifer dass er Ware absetzen kann.
- Der Greifer setzt (möglicherweise) Ware auf den Carrier ab. Solange 
darf Band 1 sich nicht bewegen. Das System bekommt ein Signal, dass der 
Greifer etwas gemacht hat.
- Der Carrier mit Ware muss zu Band 5. Dort wird die Ware entnommen und 
danach vom Bediener der Taster gedrückt.
- Das Schott soll nur so kurz wie möglich offen sein.
- Bevor der beladene Carrier zum Band 5 fährt, soll auf Band 3 geprüft 
werden, ob wirklich Ware auf dem Carrier vorhanden ist.
- Wenn der Taster gedrückt wird, muss der Carrier erst zu Band 3, um zu 
prüfen ob die Ware entnommen wurde. Wenn nicht, muss der Carrier wieder 
zurück zu Band 5.
- Das ganze muss auch mit zwei Carrier funktionieren. Die Carrier müssen 
aneinander vorbei-jongliert werden.
- Die Carrier bleiben normalerweise auf den Bändern, aber ein Bediener 
könnte einen, oder beide Carrier einfach herunternehmen und später 
wieder auf eine beliebige Position zurückstellen. Wenn ein Bediener 
einen Carrier entfernt, gibt's natürlich eine Fehlermeldung. Aber der 
Bediener kann den Carrier an beliebiger Stelle wieder zurück stellen und 
das System muss den Carrier wieder an die richtige Stelle 
transportieren.
- Der Ablauf kann zu jeder Zeit abgebrochen werden. Danach muss das 
System beim Wiederstart die Carrier suchen, sie könnten neben einen 
Sensor gestellt worden sein, und untersuchen, ob und welcher Carrier mit 
Ware beladen ist.
- Wenn das System steht, kann im Handmodus alles bewegt und verstellt 
werden (Lift, Schott, Bänder, Greifer).
- Das System muss natürlich allen illegalen Zustände erkennen und 
"intelligent" reagieren, z.B. wenn ein dritter Carrier eingesetzt wird, 
oder wenn kein Carrier vorhanden ist. Bei einem gestörtem Lift oder Band 
1 bis 3 darf das Schott natürlich nicht offen bleiben etc.

So könnte eine solche Aufgabe sein. Und nein, man kann das System nicht 
umbauen oder neue Sensoren dazu. Und ja, manches erscheint in so einem 
System total unsinnig, kann aber aus anderen Gründen nicht geändert 
werden.

Zusammengefasst:

- 5 Sensoren auf den Bändern
- 2 Sensoren für den Lift
- 2 Sensoren für das Schott
- 1 Signal Feldbus Ok. (gültig für alle Sensoren)
= 10 Eingänge

- 5 Bänder a zwei Ausgänge (links, rechts)
- 5 Fehler-Signale der Elektrik für die Bänder
= 5 Eingänge + 10 Ausgänge

- Lift hoch und runter
- Schott auf und zu
- Druckluft Ok
= 1 Eingang + 4 Ausgänge

- Greifer-Kommunikation je ein Eingang und Ausgang
- Taster
- Reset-Eingang um Fehler zu quittieren
= 3 Eingänge + 4 Ausgänge

Alles zusammen: 19 Eingänge + 18 Ausgänge
Gast #4203439
Lesenswert?

Überforderter schrieb:
> Welche Techniken verwendet ihr für komplexe Zustandsmaschinen?
Schrittketten

> Mir geht es um Automatisierung mit mehreren Motoren,
> Pneumatik-Zylindern, dutzende Sensoren etc. die alle voneinander
> abhängen, also Mechanismen die komplex zusammenwirken, so dass man keine
> eindeutigen Bereiche/Trennstellen bilden kann.
Aufteilung in Funktionsgruppen ist immer möglich -
- Übergeordnete Freigabebedingung (Druckluft vorhanden, Strom vorhanden)
- Initialisierung der Komponenten/Funktionsgruppen (Band, Lift..)
- Zyklische Bearbeitung der Bereichsprogramme mit Befehlscode und 
Statusmeldung (Band1 Befehl TesteLadung -> Ladung oK/Leer)

> Selbst wenn man die Aufgabe in zwei, drei Teilaufgaben zerlegen kann,
> werden die Zustandsmaschinen umfangreich, unübersichtlich und
> unflexibel.
deshalb heissen sie ja auch "Endliche" Automaten

> Änderungen sind immer sehr aufwendig, und nach einem Jahr
> blickt kein Mensch mehr durch, was man da mal programmiert hat.
Weil keiner an die Dokumentation denkt, wenn's den mal läuft..

> Gibt es vielleicht Alternativen zu FSM? Nach welchen Stichworten kann
> ich googeln? Was sag die aktuelle Forschung zu dem Thema?
- Subsumption Architecture
- Grafcet
- Funktionsgraphen
- robotik
Gast #4203465
Lesenswert?

Erfahrungsgemäß zerfällt so eine Aufgabenstellung, wenn man erstmal 
sortiert, was überhaupt sinnvoll ist. Gerade so ein komplexer Aufbau, 
wie du ihn da beschreibst, wird in vielen Fällen in eine Sackgasse 
laufen.

Natürlich ist dein Eingangsvektor auf den ersten Blick riesig. Du hast 
von allen Antrieben schonmal Fehlersignale. Dazu die manuellen Eingriffe 
durch den Bediener. Prinzipiell müsstest du ja zu jedem Zustand des 
Aufbaus auf alle Signale reagieren gescheit weitermachen. Zumindest auf 
den ersten Blick.

Praktisch behaupte ich jetzt aber einfach mal, dass gefühlte 90% der 
Zustandsübergänge im Stillstand enden und nicht weiter ausgehandelt 
werden müssen/können.


Zum Beispiel mit dem manuellen Entnehmen und Dazustellen von Carriern. 
Wenn du als Eingangsvektor alles zulässt - kein Carrier, zu viele 
Carrier, irgendwo platziert - kannst du garnicht mehr darauf 
reagieren: Schon wenn ich zwei Carrier nicht mittig auf die Bänder 2 und 
4 stelle, dann ists vorbei. Entweder fährt ein Carrier gegen das Schott 
oder die beiden Carrier kollidieren.

Also räum das alles erstmal auf...
Gast #4203532
Lesenswert?

Für StateCharts kannst du irgendein UML Modeler nehmen: Altova uModel, 
Enterprise Architect, Modelio. Wie weit die das simulieren können, weiß 
ich nicht.

Alternativ kannst du auch Petri-Netze nehmen (Open-Source-Software 
PIPE), damit kannst du sogar die Dynamik simulieren. Ist aber recht 
abstrakt und nicht sonderlich intuitiv für Praktiker.
#4204220
Lesenswert?

Ich hab fuer mich mal einen Simulator geschrieben, der alle Pfade 
durchgehen kann, um zu schauen, ob
- alle Zustaende erreicht und verlassen werden koennen,
- es Endlosloops gibt, die nicht mehr verlassen werden koennen
- wie lange es dauert, um von jedem Zustand in den sicheren Zustand zu 
gehen,

usw.
Man muss so eine State Machine natuerlich auch im Prozess in Echtzeit 
debuggen koennen. Das ist unbedingt vorzusehen. Dazu muss man sich von 
jeder State - und Substatemachine den aktuellen und den letzten Zustand 
ausgeben lassen koennen.
#4204247
Lesenswert?

Ueber dieses Problem gibt es ein ganz nettes Buch von Miro Samek: 
Practical UML Statecharts in C/C++. Er stellt da ein ziemlich 
umfangreiches Framework vor mit dem man FSMs fuer eingebettete Systeme 
umsetzen kann.
Wir haben eine Untermenge davon in unserem System implementiert und sind 
sehr zufrieden.
Vielleicht sind eure Anwendungen noch komplexer, aber wir haben unter 
anderem erfolgreich eine hierarchische FSM mit insgesamt 24 States damit 
implementiert und es laesst sich auch ziemlich gut warten.
Wie bereits mehrfach von anderen angemerkt ist es dabei sehr wichtig 
vorher eine grafische Repraesentation zu erstellen und die auch synchron 
zum Code zu halten. Ich nutze dazu Dia, was zwar teilweise eine 
harkelige Bedienung hat, aber alles bietet was ich brauche.
(Firma: Torrox.de) #4204296
Lesenswert?

Kopf hoch Überforderter ;-)

Überforderter schrieb:
> Gibt es vielleicht Alternativen zu FSM? Nach welchen Stichworten kann
> ich googeln? Was sag die aktuelle Forschung zu dem Thema?

Evtl. würde es helfen, wenn Du den Automaten in einer eigenen Sprach 
beschreiben kannst? (Stichwort wäre: DSL).

Ansonsten:
- Automatische Tests. Die Problem, die Du hier beschreibst sind super 
gut für unit Tests geeignet. Test Driven Development (Stichwort TDD) 
macht ausserdem einfach sehr viel Spaßt. Wenn Du eine gute Testabdeckung 
hast, dann kannst Du Deine Implementierung später einfach austauschen 
oder siehst einfach, wo Änderungen ggf. etwas kaput machen.
- Versuchen Baugruppen zu finden, die ihren eigenen Automaten haben. 
Häufig sind dann im Gesamtkontext nur bestimmte Zustände / 
Zustandwechsel einer Baugruppe interessant (gestört / nicht gestört).

HTH
Torsten
#4204354
Lesenswert?

Überforderter schrieb:
> Gibt es vielleicht Alternativen zu FSM? Nach welchen Stichworten kann
> ich googeln? Was sag die aktuelle Forschung zu dem Thema?

Zum Gugglen: Systemarchitektur SysML.
Was du da vor dir hast ist zu komplex um nur mit ein paar 
Zustandsautomaten bewältigen zu können. Dein ganzes System kann 
beschrieben werden in einer Systemarchitektur, die das ganze in 
einzelnen Komponenten zerlegt. Für jeder dieser Komponenten kann dann 
eine Softwarearchitektur aufgesetzt werden (mit Ablaufdiagrammen, 
Zustandsautomaten und was sonst noch nötig ist).
(Firma: Schweigstill IT) Persönliche Seite #4204462
Lesenswert?

gerhard schrieb:
>>Evtl. würde es helfen, wenn Du den Automaten in einer eigenen Sprach
>>beschreiben kannst? (Stichwort wäre: DSL).
> ich denke du meintest SDL oder?

Nein, er meinte sicherlich eine sog. Domain Specific Language. Solche 
DSL werden verwendet, um mit einem optimalen Satz an Befehlen genau die 
Kategorie von Aufgaben zu bearbeiten, für die sie definiert wurde. 
Beispielsweise werden DSLs in der Bahntechnik verwendet, um damit 
SPS-Entwicklung für Stellwerke zu betreiben. Man erhofft sich, durch DSL 
die automatisierte Testbarkeit von Programmen verbessern zu können.

SDL (gemäß ITU-T X.100) war vor langer Zeit einmal der neueste Schrei 
für die Modellierung von Telekommunikationssystemen. ISDN und GSM wurden 
vom CCITT/ETSI in SDL beschrieben, und auch etliche Hersteller 
verwendeten SDL für die Entwicklung. Gebräulich waren z.B. Telelogic Tau 
SDL (mittlerweile IBM Rational Tau) und Cinderella, wobei letzteres auf 
dem SDL-Codegenerator der FU Berlin basierte.

Auch ich war "in meinem früheren" Leben sehr stark mit SDL bzw. dessen 
Codegenerierung und Systemintegration befasst. Damals wurde versucht, 
SDL in alle möglichen anderen Gebiete hineinzudrücken, was aber nur 
mäßig gelang, da sowohl die Sprache als auch die Tools ganz erhebliche 
Schwächen aufwiesen.

SDL lebt aber noch weiter, und zwar als der Diagrammtyp Statechart in 
UML.
Gast #4204548
Lesenswert?

>Gebräulich waren z.B. Telelogic Tau SDL (mittlerweile IBM Rational Tau) und 
>Cinderella, wobei letzteres auf dem SDL-Codegenerator der FU Berlin
>basierte.
zu ergänzen wäre noch Real Time Developer Studio von PragmaDev.


>Damals wurde versucht, SDL in alle möglichen anderen Gebiete >hineinzudrücken, 
was aber nur mäßig gelang, da sowohl die Sprache als auch >die Tools ganz 
erhebbliche Schwächen aufwiesen.
Die Tools kann ich nicht beurteilen aber welche Schwächen die "Sprache" 
haben soll ist mir nicht ganz klarr. Immerhn wurden damit ganze 
Sprachvermittlungssystem sepzeifiziert und auch umgesetzt.

>SDL lebt aber noch weiter, und zwar als der Diagrammtyp Statechart in
>UML.
Ein Statechart mit einem SDL-Digramm zu vergleichen ist doch etwas 
vermessen.

gruss
gerhard
#4205277
Lesenswert?

Nach meiner Erfahrung ist es am Besten einen eindeutigen Ablauf 
herauszuarbeiten und nicht zu versuchen auf verschiedene Zustände 
optimal zu reagieren. Die Schwierigkeit ist ja das gleichzeitige 
Abarbeiten von Bewegungen und die damit verbundene Erfassung der 
Zustände.

In deinem Beispiel sind es die beiden Werkstückträger, die 
Gleichzeitigkeiten hervorrufen, ansonsten kann man eigentlich einen 
linearen Ablauf implementieren. Für die beiden WTs würde ich also zwei 
Abläufe vorsehen, die parallel abgearbeitet werden aber auf Ereignisse 
des anderen Ablaufs warten. Beide Abläufe sind gleich, aber 
gewissermaßen Phasenverschoben.

Zunächst braucht man eine Grundstellung, die über den Ablauf der 
Grundstellungsfahrt erreicht wird. Da dieser Ablauf nur nach Fehlern 
oder beim Aufstarten angefahren wird, ist keine parrallele Abarbeitung 
notwendig (kein Zeitdruck).

Nach der Grundstellung kommt optional eine Initialisierungsfahrt die 
solange geht, bis die Entladenzustände erreicht sind, das kann auch Teil 
der Grundstellungsfahrt sein.

Grundstellung:
WT1 (leer) auf Band 1, WT2 (leer) auf Band 4. Band 2 in Stellung oben.

In diesem Zustand beginnen beide Abläufe in jeweils ihrem Startpunkt.

-> WT1 beladen (Greifer ab)
-> Warten auf Signal "Lift-down frei für WT1" (Teil der Grundstellung 
und sonst Signal von WT2 gesetzt)
-> WT1 auf Band 2 bewegen, Voraussetzung Band 2 oben und WT2 auf Band 4 
(Timeout)
-> Band 2 nach unten
-> WT1 auf Band 3 bewegen
-> Anwesenheit Werkstück testen, wenn vorhanden: Signal geben "Lift-up 
frei für WT2", sonst Schleife bis Werkstück vorhanden
-> Warten bis Signal "Unteres Deck frei für WT1 vorhanden"
-> WT1 zu Band 4 bewegen -> Schott öffnen -> zu Band 5 bewegen-> Schott 
schließen
-> Auf Starttaster warten -> Schott öffnen
-> WT1 zu Band 4 -> Schott schließen -> WT1 zu Band 3
-> Werkstück auf WT1 testen, Schleife bis leer
-> WT1 (leer) zu Band 4, Signal geben "Lift-down frei für WT2"
   *Hier ist Startpunkt von WT2
-> Warten auf Signal "Lift-up frei für WT1"
-> WT1 zu Band 2 -> Band 2 nach oben -> WT1 zu Band 1
Und hier gehts von vorne los

Dieser Ablauf ist also relativ übersichtlich darstellbar, Abfragen, 
Timeouts (bei allen Bewegungen) etc. kann man eine Ebene tiefer packen, 
um die Abstraktion zu erhalten. Tritt eine unvorhergesehene Situation 
auf, liegt ein Fehler vor und man muss mit einer Grundstellungsfahrt 
zurück auf Null.

Für den Fall, dass nur ein WT eingesetzt wird, gibt es einen gesonderten 
Ablauf. Die Anzahl der WTs kann in der Grundstellungsfahrt ermittelt 
werden.

Zusammengefasst heißt dass, ich würde nicht versuchen für jedes einzelne 
Band die Zustände zu erfassen und daraufhin eine Aktion auslösen, 
sondern vom Prozessfluss ausgehend einen (oder mehrere) Abläufe 
implementieren. In deinem Beispiel gibt es zwei Möglichkeiten, die WTs 
aneinander vorbeizujonglieren. Normalerweise reicht es, sich auf einen 
Fall zu beschränken, wie ich es im obigen Ablauf gemacht habe. Ein 
fehlerfreier Ablauf ist mehr wert wie eine minimale Taktzeitoptimierung.

Wichtig sind natürlich auch Standardbausteine für Timeouts, für 
Warteschleifen auf Signale, zur parallelen Abarbeitung von Abläufen etc.
#4205411
Lesenswert?

denk blos nicht dass hier jemand die Arbeit für dich macht. Eigentlich 
ist es nahezu egal mit welcher Sprache man eine Zustandsmaschine 
implementiert. Wichtig ist der sauberer Entwurf. Von Petrinetzen möchte 
ich dir abraten, da diese wegen der gleichzeitigkeit der Marken schnell 
unübersichtlich werden.

Tipp: Der Mensch bzw. normale Programmierer lässt sich von parallelen 
bzw. gleichzeitigen Vorgängen ziemlich verwirren.
Link: http://psychclassics.yorku.ca/Miller/

Hier setzt die Zustandsmaschine an. Merke stets: Für jeden Vorgang der 
gleichzeitig laufen kann, gibt es eine eigenen Zustandsmaschine. Es 
bedarf aber einiger Übung zu erkennen was ein gleichzeitig laufender 
Vorgang ist.
Kommt die Zustandsmaschine an eine Grenze weil etwas parallel gehen muß, 
mach dazu eine Neue auf. Bei Pneumatikzylindern geht das halbwegs, bei 
Behältern die umgefüllt werden ist es deutlich schwieriger. Also viele 
Zustandsdigagramme malen und die Synchronisierung untereinander öfters 
theoretisch durchspielen. Am Schluß ist das codieren nur noch ein 
formaler Vorgang.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren