OO-RoboFace

ftComputing : Programme für die fischertechnik-Interfaces und -konstruktionskästen
  
ftComputing.de
Home
Back
Sitemap
Index
Links
Impressum
Mail
 

C# : Objekte anstelle von Methoden

C# Assembly RoboFa30.DLL : RoboFace.PDF -> Eine "Experimentalversion".

Soll heißen : Zu deren Betrieb ist ein wenig Fingerspitzengefühl erforderlich. Grund : Die vom Anwender geschriebenen Ereignis-Routinen liegen im gleichem Thread wie der Ereignis-Loop. D.h. sie müssen "klein" sein und dürfen keine Wait-Methoden verwenden (siehe Beispiele). Die Angelegenheit funktiontiert dann aber sehr schön und gibt einen guten Eindruck von den vielfältigen OO-Möglichkeiten von C#. 

RoboFace : Zentrale Klasse zur Beschreibung und Steuerung des Interfaces.

BinaryInput, Sensor, PhotoTransitor, ReedContact, ImpulseSensor : Objekte zum Betrieb der E-Eingänge

AnalogInput, PhotoResistor, NTC, PotentioMeter
Objekte zum Betrieb der Analog-Eingänge

DualOutput, Motor, RobMotor, DLamp, DMagnet, DPneuValve, Buzzer : Objekte zum Betrieb der M-Ausgänge

MonoOutput, Lamp, Magnet, PneuValve :
Objekte zur Beschreibung der "halben" M-Ausgänge

LightBarrier, LimitedMotor, RobMotors :
Objekte, die Ein- und Ausgänge zu einer Einheit zusammenfassen.

Die Klassenbibliothek FishFa30 wird für eine größere Anzahl von Programmiersprachen - auch für C# - einheitlich angeboten. FishFa30 basiert auf umFish30.DLL und bietet mit der zentralen Klasse FishFace eine Beschreibung des angeschlossenen Interfaces an. Die Ein- und Ausgänge des Interfaces werden über Methoden der Klasse FishFace angesteuert :

FishFace ft = new FishFace();

ft.SetMotor(Nr.M1, Dir.Links);

if(ft.GetInput(Nr.E1)) ft.SetMotor(Nr.M1, Dir.Off);

Die Methode SetMotor startet z.B. einen am Ausgang M1 angeschlossenen Motor in Drehrichtung Links.

Die Methode GetInput ermittelt den aktuellen Status des Einganges E1. Der Motor an M1 wird ggf. abgeschaltet.


Mit RoboFace sieht das dann so aus :

RoboFace ft = new RoboFace();
Motor Antrieb = new Motor(ft, 1);
Sensor Endtaster = new Sensor(ft, 1);

Antrieb.Left();

if(Endtaster.IsTrue) Antrieb.Off();

Das Motor-Objekt Antrieb wird in Drehrichtung links gestartet.

Der Status des Sensor-Objektes Endtaster wird ermittelt. Der Antrieb wird ggf. abgeschaltet.

Wenn man zusätzlich eine Ereignisroutine zuordnet, kann man eine Zustandsänderung von Endtaster (Ereignis) auch in einer zugehörenden Ereignisroutine erfahren und darauf reagieren :

Endtaster.ChangedToTrue += BinaryInput.Changed(AntriebLinks);

void AntriebLinks(object sender) {
    Antrieb.Off();}

Hier kann auf das if verzichtet werden, der Antrieb wird "hinter der Leinwand" abgeschaltet.

Beispiel Parkhausschranke aus dem Computing Starter Kit

  "Durch Betätigen des Tasters E3 soll die Schranke geöffnet werden. Ist die Schranke offen, leuchtet die Ampel grün. Erst wenn die Lichtschranke passiert wurde, springt die Ampel auf rot und die Schranke schließt wieder." Originaltext aus der Anleitung.

Die Schranke wird nun auf folgende Objekte abgebildet :

RoboFace ft = new RoboFace();
LimitedMotor Schranke = new LimitedMotor(ft, new Motor(ft, 3), new Sensor(ft, 5), 
   new Sensor(ft, 7));
LightBarrier Durchfahrt = new LightBarrier(ft, new DLamp(ft, 4), new PhotoTransistor(ft, 2));
Sensor Anforderung = new Sensor(ft, 1);
DLamp Rot = new DLamp(ft, 2);
DLamp Gruen = new DLampt(ft, 1);

Die Schranke besteht hier aus dem Objekt LimitedMotor mit den Objekten Motor an M3 und dem Endtaster für "geschlossen" an E5 und "offen" an E7
Die Lichtschranke besteht hier aus dem Objekt LightBarrier mit den Objekten DLamp an M4 und PhotoTransistor an E2)
Der Rest sind einfache Objekte.

Die Steuerung sieht dann so aus :

do {
    Schranke.GoLeft();
    Schranke.WaitForDone();
    Anforderung.WaitForHigh();
    Schranke.GoRight();
    Schranke.WaitForDone();
    Rot.Off();
    Gruen.On();
    Durchfahrt.WaitForPassed();
    Rot.On();
    Gruen.Off();
} while(!ft.Finish());

Die Steuerung läuft in einer Endlosschleife, die durch ESC abgebrochen werden kann. Der Reihe nach wird hier die Schranke geschlossen, auf eine Anforderung zu Durchfahrt gewartet, die Ampel geschaltet, die Durchfahrt abgewartet und wieder die Ampel geschaltet.

Und ereignisgesteuert :

private void SchrankeOeffnen(object sender){
	if(SchrankeBusy) return;
	SchrankeBusy = true;
	lblStatus.Text = "--- SchrankeBusy ---";
	Schranke.GoRight(); }
private void SchrankeFreigeben(object sender){
	Rot.Off();
	Gruen.On(); }
private void SchrankeSchliessen(object sender) {
	ft.Pause(555);
	Rot.On();
	Gruen.Off();
	Schranke.GoLeft(); }
private void SchrankeWarten(object sender) {
	SchrankeBusy = false;
	lblStatus.Text = "--- Schranke betriebsbereit ---"; }

Anstelle der Endlosschleife eine Folge von Ereignisroutinen, die das gleiche tun. Sie sind in der Reihenfolge ihrer Nutzung aufgeführt. Das vollständige Programm ist im Downloadpäckchen enthalten.

Zeitverhalten

RoboFace zeigt bei ereignisgesteuerten Programmen ein sehr gutes Zeigverhalten, wenn man die o.g. Restriktionen beachtet. Gemischte Programme (lineare Programme mit ereignisgesteuerter Anzeige von Werten) sind völlig unproblematisch. Bei rein linearen Programmen kann der Ereignis-Thread abgeschaltet werden (kein RoboStart();). Die Zeitaussagen beziehen sich auf einen 1,7 GHz-Rechner unter Windows 2000 SP4 und .NET Final SP2.

Downloads

Das vollständige Beispielprogramm, einschließlich einer ereignisgesteuerten Lösung und weiteren Beispielen und - natürlich - die übersetzte RoboFa30.DLL und die Sources dazu in RoboFace.ZIP, Die Dokumentation separat in RoboFace.PDF

Stand : 31.10.2004