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?
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.
Überforderter schrieb:> Nach welchen Stichworten kann ich googeln?
Hierarchischer Zustandsautomat?
Divide et impera!
Richtig 'teilen' will gelernt sein!
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...
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
Thomas schrieb:> Hast du nun deinen Zustandsautomaten vorab skizziert oder nicht?
Vielleicht braucht der TO noch einen Tipp, mit welcher SW er das machen
könnte.
Bei MatLab-Stateflow kommt man per Doppelclick auf einen State in das
Innere.
Aber Stateflow kann ich hier wohl kaum empfehlen.
Vielleicht hat jemand von Euch einen Tipp.
Ü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
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...
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.
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.
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.
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
Ü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).
BirgerT schrieb:> Aufteilung in Funktionsgruppen ist immer möglich
Sehe ich auch so.
5 Bänder ergibt schonmal 5 FSM und noch eine FSM obendrüber, die sie
aufruft.
Alles mit einer riesigen FSM zu erschlagen, gibt nur Chaos.
Thomas schrieb:> Bleistift, Papier und Radiergummi?
Nur so kommt man schnell zum Ziel. Auf Papier sieht man vieles besser,
als auf dem Bildschirm.
Überforderter schrieb:> 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.
Klingt sportlich.
Aber solange man das nicht mit Papier und Bleistift gelöst hat, kann das
eine beliebig teure Steuerung erst recht nicht.
>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?
gruss
gerhard
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.
Andreas S. schrieb:> 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.
Genau, die meint er.
>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
gerhard schrieb:>>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.
Vielleicht meint Andreas den Diagrammtyp 'Aktivitätsdiagramm' in UML?
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.
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.