234 lines
11 KiB
TeX
234 lines
11 KiB
TeX
\documentclass[german, a4paper, headheight=36pt, parskip=true]{scrartcl}
|
|
\usepackage{hs-el-text}
|
|
|
|
\modul{Echtzeitdatenverarbeitung}
|
|
\semester{Wintersemester 2020/21}
|
|
\thema{Dokumentation Bearbeiten}
|
|
\author{Charlotte Friedemann \und Johannes Theiner}
|
|
\gruppe{A5}
|
|
|
|
\begin{document}
|
|
|
|
\maketitle
|
|
|
|
\section{Tasks}\label{sec:tasks}
|
|
|
|
Um einen konsistenten Startpunkt zu erhalten werden bei allen Tasks zu Beginn sämtliche vom entsprechenden
|
|
Task verwendeten Aktoren auf Ausgangsposition zurückgesetzt.
|
|
|
|
\subsection{Drehteller}\label{subsec:task_turntable}
|
|
Nach dem Zurücksetzen vom Drehteller und des Auswerfers am Eingang fährt der Drehteller zuerst fünf Runden,
|
|
bei denen der Auswerfer am Ausgang bedingungslos betätigt wird,
|
|
um Teile die sich vielleicht noch in der Anlage befinden aus dieser zu entfernen.
|
|
|
|
Um eine Synchronisierung zu erlangen wird der Drehteller erst aktiv, wenn Prüfer, Bohrer und Auswerfer
|
|
mit einer Nachricht auf die Status Mailbox signalisiert haben das sie mit ihren Aktionen fertig sind.
|
|
|
|
Liegt auf mindestens einem Sensor(Eingang, Tester oder Bohrer) ein Teil wird der Drehteller
|
|
aktiviert und erst wieder deaktiviert, wenn dieser wieder in Position ist.
|
|
Nun wird den anderen Tasks über Nachrichten signalisiert das diese aktiv werden können
|
|
und der Prozess beginnt erneut.
|
|
|
|
\subsection{Prüfer}\label{subsec:task_tester}
|
|
Sobald der Prüfer aktiv werden darf(Nachricht auf Status Mailbox) wird überprüft ob
|
|
ein Teil auf dem Sensor liegt.
|
|
Liegt ein Teil auf dem Sensor, fährt der Prüfer aus und das Testergebnis wird dem
|
|
Bohrer über eine Nachricht mitgeteilt.
|
|
Nun wird der Prüfer eingefahren und der Drehteller kann wieder aktiv werden.
|
|
Der Prozess beginnt nun wieder von vorne.
|
|
|
|
\subsection{Bohrer}\label{subsec:task_drill}
|
|
Wird ein Werkstück durch den Sensor erkannt wird abhängig von der Nachricht des Prüfers der Bohrer
|
|
angeschaltet, heruntergefahren und das Werkstück festgehalten.
|
|
Nach einer kurzen Wartezeit wird der Bohrer wieder nach oben gefahren, ausgeschaltet und das Werkstück losgelassen.
|
|
Nachdem der Auswerfer über ein zu erwartendes Teil benachrichtigt wurde, wird die Kontrolle wieder an
|
|
den Drehteller übergeben.
|
|
|
|
\subsection{Auswerfer}\label{subsec:output}
|
|
Da für den Auswerfer keine Sensoren existieren sendet der Bohrer den Status seines Sensors per Nachricht
|
|
an den Auswerfer, der auf Basis dieser auslöst.
|
|
|
|
\subsection{Diagramme}\label{subsec:diagrams}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\begin{minipage}{.5\textwidth}
|
|
\centering
|
|
\begin{plantuml}
|
|
@startuml
|
|
scale 150 width
|
|
!include https://raw.githubusercontent.com/bharatrajagopalan/plantuml-styles/master/activity_skin.pu
|
|
start
|
|
:Drehteller ausschalten;
|
|
:Auswefer Eingang ausschalten;
|
|
repeat
|
|
:Drehteller kurz anschalten;
|
|
:Auswerfer kurz betätigen;
|
|
repeat while(5 Durchläufe ?)
|
|
|
|
repeat
|
|
:Prüfer fertig?<
|
|
:Bohrer fertig?<
|
|
:Auswerfer fertig?<
|
|
:Teil im Prüfer?<
|
|
:Teil im Bohrer?<
|
|
if(Teil auf einem Sensor ?) then (true)
|
|
:Drehteller anschalten;
|
|
if(Sensor Drehteller in Position ?) then (true)
|
|
:Drehteller auschalten;
|
|
endif
|
|
endif
|
|
:Drehteller fertig>
|
|
repeatwhile()
|
|
kill
|
|
@enduml
|
|
\end{plantuml}
|
|
\captionof{figure}{SDL Diagramm Drehteller}
|
|
\label{fig:sdl-turntable}
|
|
\end{minipage}%
|
|
\begin{minipage}{.5\textwidth}
|
|
\centering
|
|
\begin{plantuml}
|
|
@startuml
|
|
!include https://raw.githubusercontent.com/bharatrajagopalan/plantuml-styles/master/activity_skin.pu
|
|
start
|
|
:Prüfer einfahren;
|
|
:Prüfer fertig>
|
|
repeat
|
|
:Drehteller fertig?<
|
|
if(Werkstück vorhanden ?) then (ja)
|
|
:Prüfer ausfahren;
|
|
if(Werkstück in Normallage ?) then (ja)
|
|
:Sende Bohrer(an)>
|
|
else (nein)
|
|
:Sende Bohrer(aus)>
|
|
endif
|
|
:Prüfer einfahren;
|
|
else (nein)
|
|
endif
|
|
:Prüfer fertig>
|
|
repeatwhile()
|
|
kill
|
|
@enduml
|
|
\end{plantuml}
|
|
\captionof{figure}{SDL Diagramm Prüfer}
|
|
\label{fig:sdl-tester}
|
|
\end{minipage}
|
|
\end{figure}
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\begin{minipage}{.5\textwidth}
|
|
\centering
|
|
\begin{plantuml}
|
|
@startuml
|
|
scale 150 width
|
|
!include https://raw.githubusercontent.com/bharatrajagopalan/plantuml-styles/master/activity_skin.pu
|
|
start
|
|
:Bohrer ausschalten;
|
|
:Bohrer hochfahren;
|
|
:Werkstück loslassen;
|
|
:Bohrer fertig>
|
|
repeat
|
|
:Drehteller fertig?<
|
|
if(Werkstück vorhanden?) then(ja)
|
|
:Empfange Lage des Werkstücks<
|
|
:Sende Auswerfer>
|
|
if(Teil in Normallage?) then(ja)
|
|
:Werkstück festhalten;
|
|
:Bohrer anschalten;
|
|
:Bohrer herunterfahren;
|
|
:Warte bis Bohrer unten;
|
|
:Bohrer hochfahren;
|
|
:Warte bis Bohrer oben;
|
|
:Bohrer ausschalten;
|
|
:Werkstück loslassen;
|
|
else(nein)
|
|
endif
|
|
else (nein)
|
|
endif
|
|
:Bohrer fertig>
|
|
repeatwhile()
|
|
kill
|
|
@enduml
|
|
\end{plantuml}
|
|
\captionof{figure}{SDL Diagramm Bohrer}
|
|
\label{fig:sdl-drill}
|
|
\end{minipage}%
|
|
\begin{minipage}{.5\textwidth}
|
|
\centering
|
|
\begin{plantuml}
|
|
scale 250 width
|
|
@startuml
|
|
!include https://raw.githubusercontent.com/bharatrajagopalan/plantuml-styles/master/activity_skin.pu
|
|
start
|
|
:Auswerfer einfahren;
|
|
:Auswerfer fertig>
|
|
repeat
|
|
:Drehteller fertig?<
|
|
:Auswerfer<
|
|
if(Auswerfen ?) then (ja)
|
|
:Auswerfer betätigen;
|
|
endif
|
|
:Auswerfer fertig>
|
|
repeatwhile()
|
|
kill
|
|
@enduml
|
|
\end{plantuml}
|
|
\captionof{figure}{SDL Diagramm Auswerfer}
|
|
\label{fig:sdl-output}
|
|
\end{minipage}
|
|
\end{figure}
|
|
|
|
|
|
\section{Hilfsfunktionen}\label{sec:functions}
|
|
Zur Vereinfachung des Leseflusses und der besseren Nachvollziehbarkeit des Codes werden wiederkehrende Programmteile in Hilfsfunktionen ausgelagert.
|
|
Passiert während des Durchlaufens der einzelnen Funktionen ein Fehler,
|
|
so wird die erste hier beschriebene Hilfsfunktion aufgerufen.
|
|
|
|
\subsection{void end(bool fail)}\label{subsec:void end(bool fail)}
|
|
Bei Aufruf dieser Hilfsfunktion werden sämtliche Taks, Mailboxen, Modbus-Verbindungen und Semaphoren deinitialisiert und der Timer gestoppt.
|
|
Falls der Übergabeparameter \mintinline{c}{fail == true} ist, so wird eine entsprechende Nachricht auf der Konsole ausgegeben.
|
|
|
|
\subsection{int readAll(int type, int *result)}\label{subsec:int readAll(int type, int *result)}
|
|
Das Auslesen aller zur Verfügung stehenden Bits, abhängig vom Typ der Verbindung, erfolgt mithilfe der nicht Thread-sicheren Funktion readAll.
|
|
Dabei wird dieser Funktion sowohl der Verbindungs-Typ (\mintinline{c}{DIGITAL_IN, DIGITAL_OUT, ANALOG_IN, ANALOG_OUT}),
|
|
als auch ein Pointer auf den Speicherplatz übergeben, an welchem das Ergebnis gespeichert wird.
|
|
Bei erfolgreichem Durchlaufen dieser Funktion wird eine 0 zurückgegeben, ansonsten eine 1.
|
|
|
|
\subsection{int readData(int part)}\label{subsec:int readData(int part)}
|
|
Im Gegensatz zur Hilfsfunktion \mintinline{c}{readAll()} liest die Funktion readData nur ein einzelnes Bit aus und gibt dieses zurück.
|
|
Damit die Richtigkeit der Daten während des Auslesens gewährleistet werden kann,
|
|
ist diese Funktion mithilfe einer Semaphore Thread-sicher gemacht worden.
|
|
Nach dem Auslesen aller Bits des Modbus wird der Wert der Funktion \mintinline{c}{readAll()} mit der in \mintinline{c}{part} übergebenen Bitmaske verundet und somit isoliert.
|
|
Dieses einzelne Bit wird nun in \mintinline{c}{result} gespeichert und die Semaphore wieder freigegeben.
|
|
Bei fehlerfreiem Aufruf der \mintinline{c}{readAll()}-Funktion wird das spezifizierte einzelne Bit zurückgeben, falls nicht,
|
|
so wird in die \mintinline{c}{end()}-Hilfsfunktion gesprungen und alle Tasks, Mailboxen, etc deinitialisiert und gestoppt.
|
|
|
|
\subsection{void disable(int actor)}\label{subsec:void disable(int actor)}
|
|
Diese Funktion deaktiviert den im Übergabeparameter spezifizierten Aktor.
|
|
Da auch in diesem Fall die Daten aus dem Modbus während des Lesezugriffs nicht verändert werden dürfen ist diese Funktion Thread-sicher.
|
|
Zur Kommunikation mit dem jeweiligen Aktor wird die gesamte Bitfolge über \emph{readAll()} ausgelesen.
|
|
Ist dies ohne Fehler geschehen, so wird die empfangene Bitfolge mit der negierten Bitmaske des anzusprechenden Aktors verundet.
|
|
Diese neue, sich nur in einem Bit unterscheidende Bitfolge wird auf den Modbus geschrieben und die Semaphore freigegeben.
|
|
|
|
\subsection{void sendMail(MBX * mailbox, int msg)}\label{subsec:void sendMail(MBX * mailbox, int msg)}
|
|
Das Senden einer blockierenden Nachricht (\mintinline{c}{msg}) an eine über mailbox spezifierte Mailbox wird mithilfe dieser Funktion realisiert.
|
|
|
|
\subsection{void sendMailNonBlocking(MBX * mailbox, int msg)}\label{subsec:void sendMailNonBlocking(MBX * mailbox, int msg)}
|
|
Im Unterschied zur Funktion \mintinline{c}{sendMail()} wird hier eine nicht-blockierende Nachricht (msg) an die in mailbox spezifizierte Mailbox gesendet.
|
|
|
|
\subsection{int receiveMail(MBX * mailbox)}\label{subsec:int receiveMail(MBX * mailbox)}
|
|
Diese Hilfsfunktion fasst das Erhalten einer blockierenden Nachricht an der im Übergabeparameter spezifizierten Mailbox
|
|
zusammen und gibt den Nachrichteninhalt zurück.
|
|
|
|
\subsection{int receiveMailNonBlocking(MBX * mailbox)}\label{subsec:int receiveMailNonBlocking(MBX * mailbox)}
|
|
Analog zu \mintinline{c}{receiveMail()} wird auch hier einen Nachricht an der im Übergabeparamter spezifizierten Mailbox erhalten und deren Inhalt zurückgegeben,
|
|
jedoch ist diese nicht blockierend.
|
|
|
|
\subsection{void sleepMs(int ms)}\label{subsec:void sleepMs(int ms)}
|
|
Da bei der Kommunikation der Tasks untereinander oder der Abarbeitung an den einzelnen Stationen teilweise Pausen benötigt werden,
|
|
ist diese Funktion unerlässlich. Dabei wird mithilfe des Übergabeparameters festgelegt, für wie viele Millisekunden ein Tasks pausieren soll.
|
|
|
|
\end{document}
|