Steuerung der Eisenbahnanlage mit Echtzeitbetriebssystemen
Am Beispiel von QNX und DCL Rail
Falko Menge, Johannes Passing und Michael Perscheid
Agenda
- Übersicht DCL-Rail
- Problemstellung
- Echtzeitbetriebssystem QNX
- Projektverlauf
- Schichtenarchitektur
- Hardwareabstraktion
- API
- Client
- Performanz
- Fazit
Problemstellung
Performanz
- Geringer Durchsatz (Befehle pro Sekunde)
- Hohe zeitliche Varianz bei Bearbeitung von Befehlen
- Hohe Latenz bei Ausführung von Befehlen
- Overhead durch Statusermittlung durch Polling über .Net Remoting
- Performanz-Verlust durch intensive .Net Interop-Nutzung
Existierende Implementierung
- Geringe Abstraktion, Magic Numbers im Code
- Starke Bindung an .Net Remoting
Lösungsansätze
Betriebssystem
- Einsatz eines Echtzeit-Betriebssystems zur Reduzierung von Latenz und zeitlicher Varianz
- Auswahl zwischen Windows CE und QNX
- Entscheidung zugunsten QNX
Steuerungs-Software
- Effizientere Befehls-Verarbeitung
- Effizientere Status-Rückmeldungen
- keine Alternative zur seriellen Schnitstelle vorhanden
Echtzeit-Betriebssysteme
- Echtzeit bedeutet, dass binnen einer maximalen Latenzzeit
auf ein Ereignis reagiert wird
- harte Latenzzeit
- Einhaltung von Zeitanforderungen statisch definiert
- weiche Latenzzeit
- Einhalten von Zeitpunkten muss garantiert werden
QNX
- Echtzeit-Betriebssystem der kanadischen Firma QNX Software Systems Ltd.
- für verschiene Plattformen verfügbar, u.a. x86
- Vollwertiges 32-Bit Betriebssystem
- Implementiert den kompletten Posix-Standard
- Individuell stark anpassbar
QNX - Architektur
- Zwei fundamentale Prinzipien
- Nachrichtenbasierte Kommunikation zwischen den Prozessen
- QNX besteht aus einem kleinen Kern mit einer Gruppe kooperierender Prozesse
QNX - Zusammenfassung
- relativ einfache Installation
- leichtgewichtig
- flexibel konfigurierbar
- Orientiert sich an Industrie-Computer und Embedded-Devices
- Mit Momentics existiert eine vollwertige Eclipse-IDE
- Dokumentation zum Teil nicht ausreichend vorhanden
Projektumgebung
Voraussetzungen
- Jederzeit Zugang zur Eisenbahnanlage
- 2 zusätzliche QNX-Rechner
- Handbuch zum Märklin-Protokoll
- CVS-Repository vom Lehrstuhl
Organisation
- Wöchentliches Treffen
- Parallele Entwicklung auf beiden Rechnern
Projektverlauf
- Informationen über RS232-Programmierung besorgt
- Direkter Zugriff auf Controller, ohne Gerätetreiber
- Gute Tutorien für DOS vorhanden, wenig für QNX
- Testapplikationen geschrieben
- Experiment mit seriellem Lautsprecher
- Kommunikation zwischen 2 Ports über Nullmodemkabel
- Polling-Variante und Interrupt-Variante
- C Makros für Märklin Protokollformat geschrieben
- Erste Programme zur Kommunikation mit Modellbahn geschrieben
Schichtenarchitektur
- Dekomposition des Steuerungsprogramms in 3 Layer
Layer 0 - Hardwareabstraktion
Aufgaben
- Kommunikation mit Seriellem Port
- Asynchone Abarbeitung von Befehlen
Layer 0 - Arbeitsweise
- Befehle werden im Märklin-Format entegegengenommen und in Queue abgelegt
- Separater Thread bearbeitet Befehle der Queue
- Status der Anlage wird periodisch abgefragt
- Notifikationen an Layer 1 über asynchrone Callbacks
- Statusänderungen
- Erfolgreiche Abarbeitung von Befehlen
- Nutzung von 2 zusätzlichen Threads
Layer 0 - Implementierung
Layer 0 - API
typedef void ( *STATUS_CALLBACK )(
IN STATUS newStatus,
IN STATUS oldStatus );
RCSTATUS RailInitialize(
IN DWORD dwIoAddress,
IN DWORD dwReserved,
IN DWORD dwMaxPollInterval,
IN DWORD dwS88count,
IN STATUS_CALLBACK pfnStatusCallback );
RCSTATUS RailFinalize();
RCSTATUS RailEnqueueCommand(
IN DWORD dwCommand,
IN BOOL fPutInFront,
IN OPTIONAL COMMAND_CALLBACK pfn,
IN OPTIONAL DWORD dwCallbackCookie );
RCSTATUS RailClearQueue(
OUT OPTIONAL DWORD *pdwElemCleared );
Layer 0 - Beispiel
// Initialisierung und Konfiguration
RCSTATUS rcs = RailInitialize(
COM1_ADDRESS, // I/O-Adresse des COM-Port (COM1)
0, // Reserviert
100, // Max. Zeit zw. 2 Status-Polls
S88COUNT, // # S88-Module auf Anlage
StatusCallback ); // Callback-Funktionspointer
if ( RCSTATUS_SUCCESS != rcs ) { /* ... */ }
// Weichenstell-Befehl absetzen
rcs = RailEnqueueCommand(
COMMAND_SWITCH_CURVE(1), // Befehl - Weiche 1 stellen
FALSE, // ans Ende der Queue
NULL, // kein Callback erwuenscht
0 ); // kein Callback erwuenscht
if ( RCSTATUS_SUCCESS != rcs ) { /* ... */ }
// Ressourcen freigeben
rcs = RailFinalize();
if ( RCSTATUS_SUCCESS != rcs ) { /* ... */ }
Layer 1 - Programmierschnittstelle (API)
- Verkapselung der Details des Maerklin-Protokolls
- Abbildung der Bus-Befehle auf Methoden
- Analyse der Status-Rückmeldungen aus Layer 0
- Notifikationen über einzelne Statusänderungen an Applikaton
- Namen und Parameter der Methoden orientieren sich an bestehendem System
Layer 1 - Programmierschnittstelle (API)
bool initDCLRail(
unsigned long dwS88count,
DCLRAIL_STATUS_CALLBACK pfnDCLRailStatusCallback,
unsigned long dwMaxPollInterval,
unsigned long dwIoAddress);
bool closeDCLRail();
// ...
bool setTrain(
int trainID,
int speed,
bool function_on,
int priority);
bool setElement(
int elementid,
bool straightOrGreen,
int priority);
Layer 1 - Beispiel
// Initialisierung und Konfiguration
if ( ! initDCLRail(
4, // Anzahl der S88-Module
StatusCallback // Callback-Funktionspointer
100, // Maximale Zeit zwischen 2 Status-Polls (ms)
COM1_ADDRESS // I/O-Adresse des COM-Ports (COM1)
) )
{ /* ... */ }
// Befehl an einen Zug absetzen
if ( ! setTrain( 1, 7 ) )
{ /* ... */ }
// Ressourcen freigeben
if ( ! closeDCLRail() )
{ /* ... */ }
Layer 2 - Interaktive Shell
- Ermöglicht interaktive Steuerung der Anlage
- Basiert auf Layer 1-API
- Befehle sind mit bisherigen System und Simulator kompatibel
- verfügbare Befehle:
- load <scriptname>
- go <priority>
- stop <priority>
- settrain <trainid> <speed> <function_on> <priority>
- changetraindirection <trainid> <function_on> <priority>
- setelement <elementid> <geradegruen> <priority>
Performance-Vergleich
- Vergleich der QNX-Implementierung mit bestehender .NET-Implementierung
- Bremsweg-Experiment
- Anhalten einer Lok, sobald ein Sensor überfahren wird
- Messung des Bremsweges
Ausblick
- weiterer Ausbau der oberen Schichten
- Paper über das Projekt
- Portierung des Homerunners auf QNX
- Integration ins DCL
Literaturempfehlungen
zu QNX:
- http://www.qnx.com/
- http://www.uni-weimar.de/~sippach1/uni/qnx/
- http://www.michael-prokop.at/computer/qnx.html
- http://www.openqnx.org
- Interfacing The Serial/RS-232 Port - http://www.beyondlogic.org/serial/serial.htm
zum Projekt:
- http://www.dcl.hpi-uni-potsdam.de