Aufbau des Queue-Objekts Beim Start des Mikrocontrollers wird nach dem Übertragen der
Web-Informationen ein neuer Thread erstellt. In diesem Thread wird
zunächst ein Objekt angelegt, welches die gesamte Queue-Steuerung
einschließlich deren Erstellung beinhaltet. Im Konstruktor werden
die Ein- und Ausgansobjekte in Software aufgebaut und in zugriffsgeschützen
Arrays abgelegt. Der Konstruktor der Ausgangsobjekte sperrt
den Hardware-Motortreiber, sodass zu Beginn keine
Undefinierten Werte am Motortreiber anliegen können. Der
Motortreiber wird mit dem ersten Aktivieren wieder
freigeschalten. Die Start- und End-Elemente
vom Typ "commonElement" werden ebenso im Queue-Konstruktor für die unten und in der
Konzeptenwicklung beschriebene Queue angelegt. |
![IO-Objekte erstellen](images/PAP-Anlegen-der-IO-Objekte-SW.png) Abb.: IO-Objekte anlegen |
Aufbau der Queue
Im Thread der HMI wird nach dem vollständigen Einlesen des Programms in Form eines
Übertragungsstring (kurz: Ü-String, siehe Software-Dokumentation des Hautpdokuments) die Queue-Steuerung mit der
Methode "void SW_work()" aufgerufen. Als Übergabeparameter
erhält die Methode die Referenzen auf den Ü-String und auf den gemeinsamen Container (kurz: SHM von
Sharde Memory). Diese Methode ruft die Funktion "queue_creator"
auf. Diese Funktion bildet das vom Benutzer
erstellte Programm mit Hilfe des Ü-Strings virtuell in Form
einer verketteten Liste (Queue) ab (siehe auch
Konzeptentwicklung dieser Dokumentation). Die Elemente der
verketteten Liste "commonElement" sind Structs, welche alle
Informationen für den Programmablauf enthalten.
Diese Informationen sind:
- Eindeutiger Identifier um welchen Befehl es sich handelt ('M'-Motor, 'I'-If-Verzweigung, etc.)
- Zeiger auf das nachfolgende Element
- Zeiger auf das vorhergehende Element (wird u.a. zum Löschen der Queue benötigt)
- Sprungzeiger für Schleifen (While) und Verzweigungen (If)
- Verschiedene Speicher welche Werte und Informationen für den weiteren Programmablauf und die Pinansteuerung enthalten
(vgl. auch Software-Dokumentation des Hautpdokuments).
Download der Excel-Datei zur Entwicklung des "commonElement"
Wichtig sind die Verzweigungselemente "If" und "While",
sowie deren "EndIf" und "EndWhile". Beim Anlegen eines Ends wird
das zugehörige Verzweigungselement gesucht und in beiden
Elementen wechselseitig Sprungadressen abgelegt.
Unten ist der Programmablaufplan der Queue-Erstellung abgebildet.
![Übertragungsstring einlesen und Queue erstellen](images/PAP-Queue-erstellen-SW.png) Abb.: Übertragungsstring einlesen und Queue erstellen
Ausgabe der Queue (für Debugging)
Nach dem
Erstellen der Queue wird diese probehalber im seriellen Monitor
ausgegeben werden: Ein Zeiger auf das Startelement wird
erstellt. Über diesen Zeiger wird die ID und weitere
Informationen des Blocks ausgegeben. anschließend wird der
Zeiger auf das nachfolgende Element gelegt.
Abarbeiten der Queue
Anschließend wir die
Funktion "queueWorker" aufgerufen, welche das eigentliche
Programm ausführt. Der Zeiger "workPtr" wird auf das erste
Q-Element gelegt. Abhänig von der ID und den weiteren
Informationen werden Ausgänge gesetzt, Eingänge eingelesen oder
die Wartezeit gesetzt. Anschließend wird der Zeiger entweder
auf das Folgeobjekt gelegt oder bei "If" oder "While"
entsprechend der Bedingung auf das "EndIf" bzw. "EndWhile".
Im Verzweigungselement "If" wird ein vorgegebener Wert mit dem
Zustand eines Digital- oder Analogeingangs verglichen:
Bei "true": Zeiger wird auf das nachfolgende Q-Element gelegt
Bei "false": Zeiger wird auf das zugehörige End-Element gelegt Im
Schleifenelement "While" kann entweder ein vorgegebener Wert mit dem Zustand eines Digital- oder Analogeingangs verglichen werden:
Bei "true": Zeiger wird auf das nachfolgende Q-Element gelegt (Schleife betreten)
Bei "false": Zeiger wird auf das
Q-Element nach dem zugehörigen End-Element gelegt Oder die
Schleife ist eine Zählschleife, vergleichbar mit "for()" in C++.
Beim Q-Element "EndWhile" wird der Zeiger wieder auf das
zugehörige While-Element gelegt (daher der oben beschriebene
Sprung von While auf "eins nach EndWhile")
Am Ende wird geprüft, ob eine Wartezeit eingerichtet wurde:
"waitTime>0;". Falls ja, wird diese um 10ms reduziert und mit
"delay(10);" der Thread 10ms pausiert. Anschließend wird das
Pause-Flag aus dem SHM gelesen. Ist dieses gesetzt, werden alle
Ausgangsobjekte als Kopie gesichert und über die Ausgangspins
alle Aktoren gestoppt. In einer Dauerschleife wird dann alle
10ms im SHM abgefragt, ob das Pause-Flag aufgehoben oder das
Stop-Flat gesetzt ist. Beim Pausenende werden die
Ausgangsobjekte wieder zurückkopiert und mit "reRun()" die
Ausgangspins neu gesetzt. Falls Stopp gesetzt ist, wird die
gesamte Schleife beendet.
Unten ist der
PAP der Abarbeitung der Queue vereinfacht dargestellt:
![Queue abarbeiten](images/PAP-Queue-abarbeiten-SW.png) Abb.: Queue abarbeiten
Löschen der Queue
Nach vollständigem Ablaufen des Programms oder nach dem
gesetztes Stop-Flag über das SHM werden über die
Ausgangspins alle Aktoren gestoppt. Anschließend wird die Queue gelöscht
um den Heap-Speicher nicht zu blockieren. |
![Löschen der Queue](images/PAP-Queue-loeschen-SW.png) Abb.: Löschen der Queue |
|