Dokumentation: Drehteller, Prüfer & Auswerfer

This commit is contained in:
Johannes Theiner 2020-12-07 11:49:32 +01:00
parent 19b9c1d7c6
commit cc2fd89e8f
Signed by: joethei
GPG Key ID: 9D2B9A00FDA85BCD
3 changed files with 139 additions and 85 deletions

View File

@ -30,7 +30,8 @@
MODULE_LICENSE("GPL");
static RT_TASK turntable_task, drill_task, tester_task, output_task;
static MBX turntable_status_mbx, tester_status_mbx, output_status_mbx, drill_status_mbx;
static MBX turntable_status_mbx, tester_status_mbx;
static MBX output_status_mbx, drill_status_mbx;
static MBX output_data_mbx, drill_data_mbx, turntable_data_mbx;
static SEM semaphore;
@ -75,7 +76,8 @@ void end(bool fail) {
* @return status code(0: success, 1: failure)
*/
int readAll(int type, int *result) {
int res = rt_modbus_get(connection, type, 0, (unsigned short *) result);
int res = rt_modbus_get(connection, type, 0,
(unsigned short *) result);
return res;
}
@ -88,7 +90,8 @@ int readAll(int type, int *result) {
int readData(int part) {
int value = 0;
rt_sem_wait(&semaphore);
//the semaphore needs to be locked before this code executes, so we can't adhere to the ISO standard here.
//the semaphore needs to be locked before this code executes,
// so we can't adhere to the ISO standard here.
int code = readAll(DIGITAL_IN, &value);
int result = (part & value);
rt_sem_signal(&semaphore);
@ -106,7 +109,8 @@ void disable(int actor) {
rt_sem_wait(&semaphore);
if(readAll(DIGITAL_OUT, &value)) end(true);
else {
int result = rt_modbus_set(connection, DIGITAL_OUT, 0, value &= ~actor);
int result = rt_modbus_set(connection, DIGITAL_OUT, 0,
value &= ~actor);
rt_sem_signal(&semaphore);
if (result) end(true);
}
@ -122,7 +126,8 @@ void enable(int actor) {
rt_sem_wait(&semaphore);
if (readAll(DIGITAL_OUT, &output)) end(true);
else {
int result = rt_modbus_set(connection, DIGITAL_OUT, 0, output |= actor);
int result = rt_modbus_set(connection, DIGITAL_OUT, 0,
output |= actor);
rt_sem_signal(&semaphore);
if(result) end(true);
}
@ -211,7 +216,8 @@ static void turntable(long data) {
//always read from mailbox to make sure that no overflow occurs.
int msg1 = receiveMailNonBlocking(&turntable_data_mbx);
int msg2 = receiveMailNonBlocking(&turntable_data_mbx);
if(readData(SENSOR_PART_TURNTABLE) || msg1 || msg2) {//if a part is on any of the sensors
//if a part is on any of the sensors
if(readData(SENSOR_PART_TURNTABLE) || msg1 || msg2) {
enable(ACTOR_TURNTABLE);
sleepMs(100);
if (!readData(SENSOR_TURNTABLE_POS)) {
@ -242,10 +248,12 @@ static void tester(long data) {
while (1) {
receiveMail(&tester_status_mbx);
if(readData(SENSOR_PART_TESTER)) {
sendMailNonBlocking(&turntable_data_mbx, 1);//turntable should turn on the next turn.
//turntable should turn on the next turn.
sendMailNonBlocking(&turntable_data_mbx, 1);
enable(ACTOR_TESTER);
sleepMs(500);
if(readData(SENSOR_PART_TEST)) {//should the drill be active on the next turn ?
//should the drill be active on the next turn ?
if(readData(SENSOR_PART_TEST)) {
sendMailNonBlocking(&drill_data_mbx, 1);
}else {
sendMailNonBlocking(&drill_data_mbx, 0);
@ -277,9 +285,12 @@ static void drill(long data) {
//start processing
while (1) {
receiveMail(&drill_status_mbx);
if(readData(SENSOR_PART_DRILL)) {//if part is in drill
sendMailNonBlocking(&turntable_data_mbx, 1);//turntable should be active on the next turn.
if(receiveMailNonBlocking(&drill_data_mbx)) {//read test result from mailbox
//if part is in drill
if(readData(SENSOR_PART_DRILL)) {
//turntable should be active on the next turn.
sendMailNonBlocking(&turntable_data_mbx, 1);
//read test result from mailbox.
if(receiveMailNonBlocking(&drill_data_mbx)) {
enable(ACTOR_PART_HOLD);
enable(ACTOR_DRILL);
enable(ACTOR_DRILL_DOWN);
@ -300,7 +311,8 @@ static void drill(long data) {
disable(ACTOR_DRILL_UP);
disable(ACTOR_PART_HOLD);
}
sendMailNonBlocking(&output_data_mbx, 1);//should the output be active on the next turn ?
//should the output be active on the next turn ?
sendMailNonBlocking(&output_data_mbx, 1);
}
sendMail(&turntable_status_mbx, 1);
}
@ -317,7 +329,8 @@ static void output(long data) {
//start processing
while (1) {
receiveMail(&output_status_mbx);
if(receiveMailNonBlocking(&output_data_mbx)) {//should the output be activated
//should the output be activated
if(receiveMailNonBlocking(&output_data_mbx)) {
enable(ACTOR_EXIT);
sleepMs(500);
disable(ACTOR_EXIT);

View File

@ -1,9 +1,8 @@
%Copyright: 2020, Johannes Theiner <kontakt@joethei.de>
\ProvidesPackage{hs-el-text}
\RequirePackage{graphicx}
\RequirePackage[ngerman]{babel}
\RequirePackage[iso]{isodate}
\RequirePackage{graphicx}
\RequirePackage{amsmath}
\RequirePackage{amssymb}
\RequirePackage{amstext}
@ -38,14 +37,17 @@ anchorcolor = black]{hyperref}
\RequirePackage{makecell}
\RequirePackage{plantuml}
\RequirePackage{fontspec}
\RequirePackage{wrapfig}
\RequirePackage{lipsum}
\RequirePackage{subfig}
\usetikzlibrary{positioning, shapes.geometric}
\RequirePackage[final]{draftwatermark}
\RequirePackage[]{draftwatermark}
%watermark
\SetWatermarkText{Preview}
\SetWatermarkColor{gray}
\SetWatermarkColor{red}
\SetWatermarkFontSize{35.83pt}
\titlespacing\section{0pt}{12pt}{10pt}
@ -101,7 +103,6 @@ autogobble
\ofoot{Seite \thepage \hspace{1pt} von \pageref{LastPage}}
\makeindex
\isodate
\renewcommand*{\maketitle}{%

174
index.tex
View File

@ -1,7 +1,5 @@
\documentclass[german, a4paper, headheight=36pt, parskip=true]{scrartcl}
\usepackage{hs-el-text}
\usepackage{wrapfig}
\usepackage{lipsum}
\modul{Echtzeitdatenverarbeitung}
\semester{Wintersemester 2020/21}
@ -16,15 +14,22 @@
\section{Tasks}\label{sec:tasks}
\subsection{Drehteller}\label{subsec:task_turntable}
\begin{wrapfigure}{L}{0.5\textwidth}
\begin{figure}[H]
\centering
\begin{plantuml}
\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?<
@ -41,24 +46,23 @@
repeatwhile()
kill
@enduml
\end{plantuml}
\caption{SDL Diagramm Drehteller}
\label{fig:sdl-turntable}
\end{wrapfigure}
\lipsum[1-2]
\subsection{Prüfer}\label{subsec:task_tester}
\begin{wrapfigure}{R}{0.5\textwidth}
\begin{plantuml}
\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 Normallage ?) then (ja)
if(Werkstück in Normallage ?) then (ja)
:Sende Bohrer(an)>
else (nein)
:Sende Bohrer(aus)>
@ -70,72 +74,108 @@
repeatwhile()
kill
@enduml
\end{plantuml}
\caption{SDL Diagramm Prüfer}
\label{fig:sdl-tester}
\end{wrapfigure}
\end{plantuml}
\captionof{figure}{SDL Diagramm Prüfer}
\label{fig:sdl-tester}
\end{minipage}
\end{figure}
\lipsum[2-4]
\subsection{Bohrer}\label{subsec:task_drill}
\begin{wrapfigure}{L}{0.5\textwidth}
\begin{plantuml}
@startuml
scale 150 width
!include https://raw.githubusercontent.com/bharatrajagopalan/plantuml-styles/master/activity_skin.pu
:Bohrer ausschalten;
:Bohrer hochfahren;
:Werkstück loslassen;
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;
\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;
else(nein)
endif
else (nein)
endif
:Bohrer fertig>
repeatwhile()
kill
@enduml
\end{plantuml}
\caption{SDL Diagramm Bohrer}
\label{fig:sdl-drill}
\end{wrapfigure}
\lipsum[2-4]
\subsection{Auswerfer}\label{subsec:output}
\begin{wrapfigure}{R}{0.5\textwidth}
\begin{plantuml}
: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<
:Auswerfen;
if(Auswerfen ?) then (ja)
:Auswerfer betätigen;
endif
:Auswerfer fertig>
repeatwhile()
kill
@enduml
\end{plantuml}
\caption{SDL Diagramm Auswerfer}
\label{fig:sdl-output}
\end{wrapfigure}
\end{plantuml}
\captionof{figure}{SDL Diagramm Auswerfer}
\label{fig:sdl-output}
\end{minipage}
\end{figure}
\lipsum[2-4]
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 wieder eingefahren und der Drehteller kann wieder aktiv werden.
Der Prozess beginnt nun wieder von vorne.
\subsection{Bohrer}\label{subsec:task_drill}
\lipsum[2-3]
\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.
\section{Hilfsfunktionen}\label{sec:functions}
\lipsum[2-4]