| |
Allgemeines
umFish30.DLL ist durch Trennung von Zugriff auf das Interface und den Zugriff
der Anwendung auf die Interface Werte threadfähig. Das geschieht durch
Auslagerung des Interfacezugriffs in einen eigenen Poll-Thread des Steuerung
über den MultiMediaTimer erfolgt. Im Poll-Thread werden die Daten des
Interfaces in regelmäßigen Intervallen abgefragt und gleichzeitig die
Aufträge der Anwendung übermittelt. Die Kommunikation mit der Anwendung
erfolgt über einen Kontrollblock (den ftiDCB), der von der Anwendung asynchron
ausgelesen bzw. besetzt wird.
So ist es möglich auf ein Interface ( ggf. mit angeschlossenem Slave
(Extension Module) unabhängig aus verschiedenen Threads zuzugreifen. Der
eigentliche Zugriff auf die nur einmal vorhandene Resource Interface erfolgt
immer über den ebenfalls nur einmal vorhandenen Poll-Thread. Der Zugriff auf
einzelne Ein- bzw. Ausgänge ist ohne weitere Maßnahmen möglich. Beim
gleichzeitigen Zugriff auf alle M-Ausgänge ist eine Maskierung der vom eigenen
Thread nicht genutzten M-Ausgänge im MotorStatus-Wort erforderlich, da
umFish30.DLL keine Verwaltung von TeilResourcen bietet. Maskierung meint hier
Erhalt des Status der "fremden" M-Ausgänge.
Die nachfolgenden Beispiele beziehen sich auf C++Builder-Programme mit
Thread-Klassen die von der (VCL)Klasse TThread abgeleitet wurden. Ein direktes
Arbeiten mit den Win-API-Funktionen ist in gleicher Weise möglich, es bietet noch mehr Möglichkeiten (siehe auch Robot-Plant).
Programm RobStanze
Die Programme AmpelThread und RobStanze haben die gleiche Struktur.
AmpelThread ist im Test wesentlich nervenschonender (es verhakt da nichts) und
sollte der Ausgangspunkt eigener Bemühungen sein. RobStanze ist das
attraktivere Modell, deswegen wird es hier besprochen. Bei den vorliegenden
Programmen wird bei AmpelThread mit einem Intelligent Interface plus Extension
Module an COM1 gearbeitet, bei RobStanze sind es Intelligent Interfaces an COM1
und COM2 (weil die Modelle so aufgebaut waren und weil die Verkabelung so
einfacher ist (das Verbindungskabel des Extensionmodules ist zu kurz)) :
frmThreadMain
|
Der Hauptthread mit Form und Gesamtsteuerung |
ftR |
Instanz der Klasse TFishFace zur Rob-Steuerung |
ftS |
Instanz der Klasse TFishFace zur Stanz-Steuerung |
umFish30.DLL |
im Hintergrund : mit dem Poll-Thread |
RobReady |
Event : Roboter hat Teil plaziert
Standard Security, autoReset, not signaled |
StanzeReady |
Event : Stanze kann neues Teil verarbeiten
Standard Security, autoReset, not signaled |
RobThread |
Thread mit der Robotersteuerung |
StanzThread |
Thread mit dem Stanzprogramm |
TfrmThreadMain::cmdActionClick
- Anlegen der ftR und ftS Instanzen :
ftR = new TFishFace(false, false, 0);
ftS = new TFishFace(false, false, 0);
ohne AnalogScan, ohne Slave, mit default PollIntervall
- Herstellen der Verbindung zu den Interfaces :
ftR->OpenInterface("COM2"), false);
ftS->OPenInterface("COM1", false);
ohne Unterbrechung durch Application.ProcessMessages();
in einer try - catch Klammer um Openfehler abzufangen. Weitere try/catch
wären sinnvoll, aber man hört es auch so laut genug.
- Anlegen der Threads für Rob/Stanze
RobThread = new TRobThread(true);
StanzThread = new TStanzThread(true);
ohne sie zu starten
- Zuordnen der EndeRoutinen
RobThread->OnTerminate = RobEnde;
StanzThread->OnTerminate = StanzEnde;
- Starten der Threads
RobThread->Suspended = false;
StanzThread->Suspended = false;
TRobThread::Execute
Die Nutzroutine des Threads.
- Anfahren der Home Position
ftR->SetMotor(mSaule, ftiLinks, 15, 999);
ftR->SetMotor(mArmV, ftiLinks, 15, 999);
ftR->SetMotor(mArmH, ftiLinks, 15, 999);
ftR->SetMotor(mGreifer, ftiLinks, 15, 999);
ftR->WaitForMotors(0, mSaule, mArmV, mArmH, mGreifer);
Alle vier Motoren des Robot werden simultan mit voller
Geschwindigkeit gestartet (15), sie sollen 999 Impulse oder bis zum
Erreichen des zugehörenden Endtasters laufen (ca. 360 Impulse sind eine
volle Drehung, also bis zu den Endtastern). WaitFor wartet auf das Erreichen
aller vier Endpositionen eine unbegrenzte Zeit (0).
- BetriebsSchleife
do {} while(!Terminated)
wird durchlaufen bis der Thread von außen einen EndeWunsch empfängt
(siehe auch cmdEndClick).
- In der Betriebsschleife
frmThreadMain->lblStatus->Caption = "...."
Anzeige des aktuellen Status
ftR->SetMotor(...
ftR->SetMotor(...
ft->WaitForMotors(0, ...);
Ausführen der Teilsschritte Greifen des Teils, Weg zur Ablage auf
dem Transportband,
- Weiter mit Warten auf StanzeReady
while(!StanzeReady-WaitFor(100) == wrSignaled);
Ablegen auf dem Transportband nach dem Signal
Nach dem Ablegen : Setzen Signal RobReady
RobReady->SetEvent();
und ohne Halt zurück zum Magazin.
- Und nach Erhalt des Terminate-Wunsches
Fahren des Robots auf eine Ruheposition.
TStanzThread::Execute
Nutzroutine des Threads, ähnlich wie TRobThread.
- Herstellen der Startposition
- Betriebsschleife
- In der Betriebsschleife
Gleich zu Anfang Warten auf RobReady und anschließendes
Signalisieren StanzeReady
- Weiter in der Betriebsschleife
- Und nach Erhalt des Terminate-Wunsches
Abstellen der Lampen.
TfrmThreadMain::cmdEndeClick
Kunstvolles Beenden des Stanzbetriebes :
- Terminate-Wunsch an Robot
RobThread-Terminate();
StanzeReady-SetEvent();
RobThread-WaitFor();
Der Ende-Wunsch wird zunächst nicht vom Thread erkannt, da er im
Wait auf StanzeReady hängenbleibt, deswegen ein künstliches StanzeReady
und dann warten, dass ers kapiert. d.h. der RobThread wird regulär zu Ende
gefahren.
- Terminate-Wunsch an Stanze
analog Robot
daran denken es wird noch ein Teil benötigt, wenn die Testbefehle
ftS->WaitForLow(ePhotoV);
ftS->Pause(1234);
noch vorhanden sind.
- Abschlußarbeiten.
Anmerkungen
Threadfestigkeit : umFish30.DLL ist es, s.o. Die VCL-Umgebung (die
Windowsoberfläche) nicht immer, dann hilft Synchronize(.....); Oder ein
Ausweichen auf eine threadfeste Alternative (z.B. TThreadListe ...). Weiteres
siehe Handbuch/Hilfe Kapitel 7.
Globale Variable : frmThreadMain, ftR, ftS sind solche und damit recht
praktisch und deswegen folgerichtig nichts für Puristen. frmThreadMain ist höhere Gewalt, aber ftR, ftS kann man auch dem Thread-Konstruktur als Parameter
mitgeben (und dann gleich auch noch lblStatus.). |