SIOS-Programmierung mit Delphi


Wer Windows-Programme schreiben will, aber die langwierige Einarbeitung in C++ vermeiden möchte, für den stellt Delphi eine echte Alternative dar, insbesondere dann, wenn schon Erfahrungen mit Turbo Pascal vorliegen. Bei der Ansteuerung von Interfaces und allgemein der Verwendung von Schnittstellen ist jedoch einiges zu beachten.

Das SIOS-Interface wird über die serielle Schnittstelle mit einzelnen Bytes angesteuert. Ein Hardware-Handshake ist nicht vorgesehen, so daß man nur die Leitungen TXD und RXD berücksichtigen muß. Auf der Software-Seite genügt eine Prozedur SendByte und eine Funktion ReadByte, jeweils zur Übertragung einzelner Bytes. Außerdem muß eine Prozedur zum Öffnen der Schnittstelle mit den vorgegebenen Parametern (19200,N,8,1) vorhanden sein. Prinzipiell kann man in Delphi Windows-API-Aufrufe zur Ansteuerung der Schnittstellen nutzen, dies ist jedoch nicht ganz einfach.

Ein leichterer Weg führt über die Verwendung einer DLL. Hier soll die RSAPI.DLL aus dem Buch "Messen, Steuern, Regeln mit Word und Excel" verwendet werden. Die folgenden Ausführungen beziehen sich auf die 32-Bit-Version der DLL und Delphi 4 unter Windows95/98. Die DLL bietet drei verschiedene Initialisierungs-Funktionen für allgemeine Zugriffe auf die RS232, für ein bestimmtes Interface wie CompuLAB, SIOS oder ZELLE und schließlich eine automatische Suchfunktion, die ein bekanntes Interface und die verwendete Schnittstelle findet.

1. Einbinden der DLL

Das erste Programmbeispiel soll das SIOS auf der untersten Ebene mit einzelnen Bytes ansteuern. Man braucht dazu nur OpenCOM, SendByte und readByte. Jede Prozedur oder Funktion einer DLL muß zunächst deklariert werden. Die Deklaration erfolgt in der Unit SIOSDLL.DCU und folgt im Aufbau einer normalen Prozedur oder Funktion, wobei mit EXTERNAL auf die DLL verwiesen wird. Die Deklarationen unterscheiden sich etwas zwischen den Programmiersprachen. Deshalb sollen hier die wichtigsten Einzelheiten genannt werden. Das zusätzliche Schlüsselwort STDCALL sorgt für die korrekte Übergabe von Parametern.

Listing 1 Quelltext der Unit SIOSDLL

 

Die RSAPI.DLL wurde in C geschrieben. Die Übergabe von Parametern aus Delphi ist nicht ganz einfach. Besondere Probleme macht die Übergabe von Textstrings. Nach einigen Versuchen wurde jedoch der richtige Weg gefunden: Bei der Einbindung der DLL-Funktion OPENCOM wird der Übergabetext als AnsiString deklariert. Beim eigentlichen Aufruf der Funktion muss der übergebene Text mit PCHAR in einen nullterminierten String nach C-Konvention umgewandelt werden.

Listing 2 Ein Beispielprogramm mit OpenCom

Im Beispiel nach Listing 2 wird zunächst die allgemeine OPENCOM-Funktion benutzt. Die Schnittstelle COM2 wird beim Start des Programms mit den erforderlichen Parametern initialisiert. Die Funktion liefert als Ergebnis n die Nummer der Schnittstelle oder Null, wenn das Öffnen nicht möglich war. Ein erster Test erfolgt mit einem Ausgabekommando an das SIOS-Interaface. Bei der Initialisierung wird ein Bitmuster an die digitalen Ausgänge gesandt. Am SIOS sieht man jede zweit LED angeschaltet und hat so bereits eine Rückmeldung über die erfolgreiche Initialisierung. Über eine Timerprozedur wird dann ein Analogwert vom Eingang A laufend abgefragt und in einem Ausgabefenster angezeigt.

Abb. 1 Messwertausgabe von Analogeingang 1

 

2. Interface-Spezifische Initialisierung

Ein zweiter Versuch verwendet die spezielle Initialisierungsfunktion INITSIOS. Dabei wird zum einen die Schnittstelle geöffnet und zum anderen ein Satz spezifischer Kommandos für das SIOS aktiviert. In Listing 1 wurden bereits die Funktionen DOUT, DIN, AOUT und AIN deklariert. In Listing 2 wird nun einen digitale Ausgabe mit DOUT durchgeführt und über AIN ein Analogwert gelesen.

Listing 3 Interface-spezifische Funktionen

Abb. 3 Programmtest mit InitSios und FindHard

In einem dritten Schritt soll die allgemeine Initialisierung mit FINDHARD erprobt werden. Mit einem Übergabeparameter "1" zeigt die Funktion das gefundene Interface und die verwendete Schnittstelle in einer Messagebox an. Das Programm funktioniert ohne Änderung für das CompuLAB, die MiniRS-Box, das SIOS und die ZELLE. Hier soll laufend ein Meßwert des ersten analogen Eingangskanals in einem Textfenster angezeigt werden. Die Messung und Ausgabe erfolgt daher in einer Timer-Prozedur.


Listing 4 Verwendung von FINDHARD

Abb. 3 Meldung des erkannten Interfaces

Abbildung 3 zeigt das Fenster die Meldung der Funktion FindHard. Mit dieser Funktion kann nun mit gleichem Erfolg auch die ZELLE, das CompuLab oder die MiniRS-Box eingesetzt werden. Die DLL merkt sich intern das gefundene Interface und verwendet automatisch die passenden Komandobytes.

Das gesamte Projekt unter dem Namen SIOSTEST kann übrigens auch über www.modul-bus.de geladen werden.

 

3. Zeitprobleme unter Windows

Windows ist nicht echtzeitfähig, das heißt man kann sich nicht auf ein bestimmtes Timing verlassen. Insbesondere seit Windows95 führt das verwendete Multitasking-Verfahren dazu, dass man sich nicht mehr auf einen bestimmten Zeitablauf verlassen kann. Dieses Problem tritt z.B. bei der Steuerung von Schrittmotoren auf. Einige kleine Vorsichtsmaßnahmen führen jedoch trotzdem zu brauchbaren Ergebnissen.

Hier soll ein Schrittmoor in einem älteren Aufzug-Modell gesteuert werden. Modul-Bus hat zwei Varianten eines Aufzugs gebaut. Die meisten der noch in den Schulen vorhandenen Aufzugsmodelle dürften mit dem hier vorgestellten Programm korrekt arbeiten.

Funktionsmodelle wie der Aufzug wurden in den Schulen häufig für Programmierübungen in Turbo Pascal eingesetzt. Da nun die Zeit der Programmierung unter DOS fast überall abgelaufen ist, sucht man nach neuen Wegen. In vielen Schulen hat sich Delphi bewährt. Daher erscheint es sinnvoll, auch ältere Modelle vom Staub zu befreien und unter Delphi wieder in Dienst zu stellen.

Listing 5 zeigt eine erste Lösung. Die Schnittstelle wird mit FindHard geöffnet, so dass von vornherein das SIOS, das CompuLAB mit der PowerBox und die die MiniRS-Box gleichberechtigt verwendet werden können. Die gültigen Bitmuster zur Steuerung des Schrittmotors werden beim Start des Programms in einem Array abgelegt. Die eigentliche Ausgabe erfolgt in einer Timerprozedur. Der verwendete Timer in Delphi arbeitet bis herab zu Intervallen von 20 ms. Man kann also bis zu 50 Schritte in einer Sekunde erreichen. Die Schrittgeschwindigkeit wird global durch einen Schieberegler vorgenommen.

Ein zweiter Schieberegler gestattet eine Feineinstellung der Schritte zwischen den Stockwerken. In der Praxis hängt der korrekte Wert etwas von der Motorachse und dem verwendeten Seilzug ab. Das Programm wird komplett über die Tastschalter im Modell gesteuert, mit denen man den Aufzug in jedes Stockwerk schicken kann.

Abb. 3 Das Aufzug-Steuerprogramm

 

Listing 5 Der erste Versuch zum Aufzug

Der erste Versuch zur Steuerung des Aufzugs ist eher enttäuschend: Der Motor rattert und ruckelt so vor sich hin. Mit diesem Aufzug möchte wirklich niemand fahren. Was ist hier falsch gelaufen? Es liegt am Timer! Windows kann einfach keinen gleichmäßigen Aufruf der Timerprozedur garantieren. Wenn irgendwelche wichtigen Prozesse vorhanden sind, dauert es einfach mal etwas länger. Man kann solche Prozesse auslösen, wenn man schnelle Bewegungen mit der Maus ausführt. Windows gerät dann in Zeitnöte und das Geruckel wird noch schlimmer.

Natürlich gibt es auch eine Lösung für das Problem. Solange eine Delphi-Prozedur nämlich noch läuft, hat sie eine sehr hohe Priorität und wird nur noch durch wenige, sehr schnelle Vorgänge unterbrochen. Die Bewegung des Mauszeigers wird weiterhin garantiert, ein Mausklick dagegen bleibt wirkungslos. Daher kann ein fehlerhaftes Programm auch zu einem "Hängen" des Systems führen, das nur noch durch den "Affengriff" Alt-Strg-Entf beendet werden kann.

Man muss also die vollständige Bewegung des Schrittmotors durchführen ohne die Prozedur zu verlassen. Listing 6 zeigt die entscheidende Änderung. Sobald sich der Aufzug auf den Weg zu einem neuen Stockwerk macht, werden alle erforderlichen Schritte in einer Schleife ausgeführt. Die Zeit zwischen den einzelnen Schritten wird nicht mehr durch die Timerprozedur festgelegt, sondern mit der DELAY-Prozedur aus der RSAPI.DLL. Alte Pascal-Programmierer werden sich freuen, dass Delay nun auch in Delphi wieder verwendbar ist. Außerdem lassen sich nun Verzögerungen bis herunter zu einer Millisekunde verwenden, so dass theoretisch bis zu 1000 Schritte pro Sekunde möglich werden. Der Aufzug wird wesentlich schneller.

Listing 6 Die veränderte Motorsteuerung

Es gibt übrigens Vorgänge, die noch wesentlich schneller ablaufen müssen als die Steuerung eines Schrittmotors. Man kann z.B. in Delphi einen Software-Frequenzzähler für reale Messungen bei Frequenzen bis zu 50 kHz realisieren. Solche Lösungen werden in dem Buch "PC-Schnittstellen unter Windows" im Elektor-Verlag beschrieben. Die Priorität eines eigenen Prozesses kann durch eine zusätzliche DLL-Prozedur "RealTime" vorübergehend weiter erhöht werden, so dass man zeitliche Konstanz bis in den Bereich von Mikrosekunden erzielen kann.