Im Programmierunterricht
an der Friedrich-Ebert-Schule wird ein Raupenroboter für verschiedene
Projekte eingesetzt. Dazu zählen autonome Steuerungen mit programmierbarer
Logik oder Mikrocontroller. Eine andere interessante Möglichkeit
ist die Steuerung des Roboters vom PC mit Microsofts Visual Studio.
Hier wird insbesondere die Steuerung mit dem kostenlosen Sprachpaket
Visual C# 2008-Express (gesprochen C-Sharp) vorgestellt.
Als Client-Hardware wird der Roboter mit dem Miniboard bestückt.

Der Roboter hat fest eingebaute Sensoren und Aktoren,
mit denen er mit seiner Umwelt interagieren kann:
- 3 Infrarot-Abstandssensoren um Hindernissen auszuweichen,
- 3 Infrarot-Reflextaster an der Unterseite, zur Linienverfolgung,
- 2 Endschalter zur Kollisionserkennung.
- 2 Gleichstrom-Antriebsmotoren die über zwei Transistorvollbrücken
(L298) in der Drehrichtung umgeschaltet werden. Durch Pulsweitenmodulation
können verschiedene Geschwindigkeitsstufen realisiert werden.
- 1 Beeper zur Ausgabe von Signaltönen.
Zusätzlich können die meisten im Miniboard vorhandenen
Baugruppen für Erweiterungen verwendet werden. 2 x Taster,
4 AD-Wandler, 1 DA-Wandler, SiebenSeg-Anzeige, diverse LED's oder
optional ein LC-Display.
Im Bild unten ist die Verkabelung der einzelnen Roboterbaugruppen
gezeigt.
Um die Beispiele nachvollziehen zu können, muss das Programm
Microsoft Visual C# 2008 Express Edition von folgendem Downloadlink
installiert werden:
http://www.microsoft.com/express/vcsharp/#webInstall
Die Steuerbefehle vom PC werden über die serielle Schnittstelle
übertragen. Ein Clientprogramm auf dem Mikrocontroller des
Roboters empfängt die Befehle und führt sie aus. Das Clientprogramm
muss auf den Roboter geladen werden:
VisualRoboter.hex
(Clientprogramm für Mikrocontroller)
VisualRoboterX1.hex
(mit Support für Kompass-Modul und Nintendo Nunchuk)
VisualRoboterX2.hex
(mit doppelter Baudrate 19200Baud)
Laden Sie die Hex-Datei mit dem Programm Flip auf den Mikrocontroller.
(Siehe Beschreibung!)
Programmieren des Mikrocontrollers (Beschreibung)

Erstellen eines neuen Roboter-Projekts
Im einfachsten Fall wird ein neues Projekt basierend auf
einer der Vorlagen erstellt:

1. Möglichkeit:
Auf der Startseite von Visual C# wird über Öffnen:
Projekt... Die Vorlage aus dem Dateisystem gewählt.
2. Möglichkeit:
Kopieren Sie eine der Vorlagendateien (nicht entpacken!!) in
den Ordner: "...\Eigene Dateien\Visual Studio 20010\Templates\ProjectTemplates".
Dann kann auf der Startseite mit Erstellen:
Projekt... die Vorlage gewählt
werden: 
Geben Sie hier der Robotersteuerung einen aussagekräftigen
Namen.
Im Projektmappen
Explorer sollte danach die nebenstehende Ansicht erscheinen. Die
Dateien im einzelnen:
1. Properties: Enthält alle Projekteigenschaften,
die für die Programmerstellung benötigt werden.
2. Verweise: Enthält die im Projekt verwendeten
Verweise auf Klassendefinitionen
3. Resources: Enhält weitere Dateien wie z.B. Bilder
die verwendet werden.
4. CRoboter.cs: Klassendefinition für die Roboterklasse
5. Form1.cs: Enthält das sichtbare Frontend des Programms
und den zugehörigen Code. In dieser Datei wird überwiegend
gearbeitet. 6. Program.cs: Enthält die Startmethode
main().

Die CRoboter-Klasse ist in der Datei CRoboter.cs definiert. Sie
implementiert die Grundfunktionen zur Steuerung des Roboters. Sie
muss in jedem Roboterprojekt vorhanden sein.
Dort sind die beiden Enumerationstypen mot und Sens
definiert: 
Diese Typen werden für die Parameterübergabe an, bzw.
von den CRoboter-Methoden benötigt. Um sie und die Robotermethoden
im eigenen Formular nutzen zu können, müssen zunächst
folgende Objekt-Verweise (Aliase) erstellt werden:

Das CRoboter-Objekt wird dann mit dem Konstruktor new
erzeugt:

Die CRoboter-Methoden im einzelnen sind:
 Bestimmt Richtung und Geschwindigkeit des Roboters.
Parameter richtung ist vom enum-Typ mot. Parameter speed
erlaubt die Werte 0 - 10 (stopp - max. Speed). Bsp.:
Bewegt den Roboter nach rechts. Speed = 8.
 Liest die 8 Sensoren des Roboters
in eine Variable vom enum-Typ Sens ein. Bsp.:
Sensor ist eine Objekt vom enum-Typ Sens (siehe
oben).
 Liest einen Analogwert vom AD-Wandler
des Roboters ein. Es sind die Analogports (PortNr) 0,1,2,3
vorhanden. Bsp.: Liest den Analogport 0 ein und speichert
das Ergebnis in der Variablen wert.
Gibt einen Analogwert am DA-Wandler-Port
des Roboters aus. AnalogWert: 0 = 0V .... 255 = 5V
Damit können die 16 digitalen
IO-Ports des Roboters einzeln eingelesen werden. PortNr
= 0...15
Die 8 IO-Ports mit der PortNr
9..15 können auch als Ausgänge verwendet werden. Wert
darf 0 oder 1 sein.
 Der Roboter gibt bei angeschlossenem Summer
einen Ton aus. Der Summer muss am Anschluß P2.4 des Roboters
angeschlossen werden.

Bei angeschlossenem Kompassmodul wird ein Richtungswert
(Winkel) zurückgegeben.
Rückgabewert
--> 0...3599 = 0...359,9°
Dabei gilt: 0° = Norden; 90° = Osten; 180° = Süden;
270° = Westen
Nach dem Einbau des Kompass in den Roboter sollte der Kompass
einmalig kalibriert werden. Dazu wird der Kompass nacheinander
möglichst genau in alle 4 Himmelsrichtungen ausgerichtet
(Reihenfolge beliebig) und jeweils die Methode mit dem Kal-Wert 0xff aufgerufen.
Am Ende wird die Kalibrierung gespeichert mit Kal = 0x00.
Ein am µC angeschlossener Nunchuk-Controller wird ausgelesen
und als nunchuk-Objekt zurückgegeben: nunchuk.button_z
und .button_c : 0 = betätigt oder 1 = unbetätigt
.joy_x und .joy_y : 0 = Anschlag Links(X), Vorne(Y) ca.
130 = Mittelstellung 255 = Anschlag Rechts(X), Hinten(Y)
.accel_x,.accel_y,.accel_z : ca.510 = waagerecht/gerade ca.720
= 90° ca.300 = -90° (Neigung in X,Yoder Z-Richtung)
Die
Datei Form1.cs enthält ein leeres Formular. Hier
wird der "sichtbare" Teil des Programms, die grafische
Benutzeroberfläche, erstellt. Dazu werden Schaltflächen,
Listenfelder, Bilder, usw. aus der Toolbox eingefügt.
und das Code-Grundgerüst für jedes Roboterprogramm:
Hier werden
die eigenen Roboter-Steuerroutinen eingefügt.

Im Folgenden wird gezeigt, wie der Roboter mit einfachen Steuerelementen
über die PC-Maus gesteuert werden kann. Öffnen Sie dazu
zunächst die Datei Form1.cs.
Holen Sie aus der
Toolbox ein Button-Steuerelement auf die leere Form.

In den Eigenschaften des Button-Steuerelements können Sie
die Text-Eigenschaft und den Namen des Steuerelements verändern.
Ändern der Text-Eigenschaft
Ändern der Name-Eigenschaft
Jetzt ist es an
der Zeit, das Verhalten der Schaltflächen zu programmieren.
In objektorientierten Sprachen bedeutet das, ein bestimmtes Ereigniss
auszuwerten. Für das Button-Steuerelement gibt es sehr viele
mögliche Ereignisse. Wir benötigen das MouseDown-
und das MouseUp-Ereignis. Klicken Sie die Schaltfläche
Vor einmal an und aktivieren Sie die Ereignisansicht (gelber
Blitz) im Eigenschaften-Fenster. Wählen Sie zunächst
das MouseDown-Ereignis und Doppelklicken Sie in das zugehörige
Eingabefeld.
Die Code-Ansicht mit dem Code-Grundgerüst wird geöffnet
und der Rumpf der sogenannten Ereignisprozedur wird in den Code
eingefügt. Der Name sollte nicht geändert werden, da Visual
Studio sonst durcheinder gerät.
Hier kann nun das Verhalten des
Roboters programmiert werden, wenn die Vor-Taste nach unten
gedrückt wird. In unserem Fall soll der Roboter mit Geschwindigkeitsstufe
8 vorwärts fahren. Hier nun die erste selbst geschriebene Codezeile:
Damit der Roboter beim Loslassen der Schaltfläche Vor
stehenbleibt, muss der gleiche Vorgang für das MouseUp-Ereignis
wiederholt werden. Mit dem Unterschied... Probieren Sie selbst!
Fügen Sie nun weitere Steuer-Schaltflächen ein!

Erzeugen Sie die abgebildeten Schaltflächen mit den Namen:
btnVor btnRechts btnLinks btnRueck Anmerkung:
Es ist äußerst hilfreich und macht einen Code besser
lesbar, anstelle der von Visual Studio automatisch vergebenen Namen
einen aussagekräftigen eigenen Namen zu wählen!
Aufgabe: Programmieren Sie jeweils die Ereigniss-Prozeduren.
(Hinweis: Bei den MouseDown-Ereignissen muss der Motor
immer stoppen. Damit man nicht 4 mal die gleiche Prozedur erzeugen
muss, kann im Ereignis-Dialog dem MouseDown -Ereignis der 3 neuen
Schaltflächen die bereits bestehende MouseDown-Prozedur der
Vor-Schaltfläche zugewiesen werden!))
Testen Sie auch die anderen Bewegungsrichtungen und Geschwindigkeiten
des Roboters.
Ergänzen wir nun das Programm mit einer komfortablen Geschwindigkeitssteuerung.
Fügen Sie aus der Toolbox ein NumericUpDown- und ein Label-Steuerelement
in die Form ein. 
Machen Sie im Eigenschafts-Dialog des NumericUpDown-Steuerelements
die dargestellten Änderungen
Gehen Sie in die
Code-Ansicht und ändern Sie die btnVor_MouseDown-Prozedur wie
abgebildet ab.
Hier wird zunächst eine Ganzzahl-Variable (Integer) angelegt.
Ihr wird dann der Wert des NumericUpDown-Steuerelements (abzurufen
über die Value-Eigenschaft) zugewiesen. Dazu muss der Value-Wert
aber noch in eine Integer-Variable umgewandelt werden. Die Methoden
von System.Convert. können eine Vielzahl von Typkonvertierungen
durchführen. Ergänzen Sie jetzt auch die anderen
3 MouseDown-Prozeduren.
Als nächsten Schritt fügen wir jetzt eine Tastatursteuerung
mit den Cursortasten hinzu. Dazu muss Form1 in der Formularansicht
angeklickt werden, so dass die Formularereignisse im Eigenschaftenfenster
bearbeitet werden können.
Fügen Sie dem
Code ein KeyDown-Ereignis hinzu: 
Der Übergabeparameter e des KeyDown-Ereignisses enthält
unter anderem auch den Tastaturcode (e.KeyValue-Eigenschaft)
der betätigten Taste. Mit der if ... else if ... -Konstruktion
wird abhängig vom Tastaturcode ein jeweils anderer Roboter-Befehl
ausgeführt. 
Damit das Form auf Tastendrücke reagiert, muss allerdings noch
die Eigenschaft KeyPreview des Formulars aktiviert werden.
Fügen Sie noch eine KeyUp-Ereignisprozedur hinzu!
Eventuell gibts mit den Cursor-Tasten Probleme. Versuchen SIe
doch die Steuerung über die Tasten w,a,s,d zu realisieren.
Überlegen Sie sich ein kurzes Programm, um die Tastaturcodes
dieser Tasten herauszufinden!
Eine andere elegante Möglichkeit für die Auswertung
der Variablen e.KeyValue ist die switch... case...- Konstruktion:
Machen Sie
sich die Wirkungsweise dieser Konstruktion klar!

Richtig interessant
wird es natürlich erst, wenn der Roboter seine Sensoren verwendet,
um bestimmte Aufgaben selbständig zu erledigen. Im Bild werden
die Reflextaster verwendet, um den Roboter auf einer schwarzen Linie
fahren zu lassen.
Zum Test der Sensorabfrage erstellen Sie ein neues Projekt aus
der Roboter-Vorlage. Fügen Sie 2 Label- und ein Button-Steuerelement
wie abgebildet ein.
Programmieren Sie die abgebildete
Click-Ereignisprozedur für den Button: 
Ein Programmlauf ergibt etwa folgendes Ergebnis:  Das bedeutet,
die Sensoren Infrarot-Abstandssensor Mitte, Endschalter Links und
Endschalter Rechts sind aktiviert.
Die Variable Sensor ist vom Enum-Typ Sens (Alias Bot) und besteht
genaugenommen aus einem Byte, also 8 Bit. Dabei gilt folgende Reihenfolge
der Bit inherhalb von Sensor:
Die Abfrage einzelner Sensoren kann über logische Verknüpfungen
realisiert werden, die immer einen boolschen Wahrheitswert, also
WAHR (TRUE) oder FALSCH (FALSE), ergeben müssen.
Als Beispiel soll der Roboter den linken Endschalter abfragen
und bei Betätigung den Roboter stoppen:
Innerhalb der Klammer
der if-Anweisung wird der boolsche Wahrheitswert gebildet.
Die Wirkung wird am Beispiel des betätigten Endschalter
Links (zusätzlich ist noch RflxL betätigt) gezeigt:
Um auf den rechten Endschalter ebenfalls reagieren zu können,
kann auf die gleiche Weise vorgegangen werden, oder beide Abfragen
können ODER-verknüpft werden. In C# lautet die Formulierung
dann so:
Eine etwas kürzere Möglichkeit ist:
Machen Sie sich die Funktion der Abfrage mit Hilfe der folgenden
Operatorenliste klar!
C# kennt folgende Operatoren für das Bitweise (logische)-Verknüpfen
von Byte-Werten, sowie das Verknüpfen von boolschen Wahrheitswerten:
Verknüpfung
|
Bitweise
|
Bool |
UND |
& |
&& |
ODER |
| |
|| |
Nicht |
! |
|
XOR |
^ |
|
Für die Bildung des boolschen Wahrheitswertes existieren
die relationalen Operatoren:
Test |
Operator |
Test |
Operator |
Gleichheit |
== |
Größer gleich |
>= |
Ungleichheit |
!= |
Kleiner gleich |
<= |
Größer als |
> |
Kleiner als |
< |
Die Klammern in den Wahrheitsausdrücken sind immer
dann nötig, wenn die gewünschte Reihenfolge der Auswertung
von der vorgegebenen Reihenfolge der Auswertung abweicht. In der
abgebildeten Tabelle hat sinkt der Vorrang von oben nach unten und
von Rechts nach Links:


Um
auf Hindernisse schnell reagieren zu können, müssen die
Sensoren in kurzen Zeitintervallen abgefragt werden. Dazu wird ein
Timer-Steuerelement verwendet. Erstellen Sie zunächst
ein neues Projekt und fügen Sie Label- und Checkbox-Steuerelemente,
wie abgebildet, in die Form ein. Um das Checkbox-Steuerelement
als Schaltfläche darzustellen, stellen Sie dessen Appearance-Eigenschaft
auf Button!
Das Timer-Steuerelement wird aus der Toolbox auf das Formular
gezogen. Es erscheint dann unterhalb des Forms im Komponentendock:

Es werden noch zwei Prozeduren benötigt, um einerseits den
Timer mit "Start/Stopp" zu starten und andererseits bei
jedem Timeraufruf (Tick) die Sensoren abzufragen und deren Wert
anzuzeigen:

Aufgaben:
- Der Roboter soll Geradeausfahren, solange
der mittlere Abstandssensor (IRM) kein Hindernis erkennt.
- Fügen Sie einen "Not-Stopp"
mit den Endschaltern ein (Siehe oben!).
- Ergänzen Sie eine Geschwindigkeitssteuerung!
- Programmieren Sie einen einfachen Ausweichroboter!
Ergänzen Sie die Timer-Tick-Prozedur durch die abgebildete
Switch-Abfrage!
Machen Sie sich die Funktion der Switch-Anweisung
klar!
Was passiert, wenn die erste
break-Anweisung weggelassen wird?
- Einige Sensor-Kombinationen sind noch
nicht codiert. Erweitern Sie die Steuerung durch Logische ODER-Verknüpfung
der Case-Bedingungen.
Bsp.: Die Bedingung Bot.IRL
| Bot.IRM frägt den Wert
00000110 der Sensor-Variablen ab! Überlegen Sie, wie der
Roboter "klug" reagieren soll!
- Um den Roboter bei Hindernissen "sensorlos"
zurückfahren zu lassen, kann man in den entsprechenden
case-Zweig eine Wartezeit einprogrammieren:
- Lassen Sie den Summer vor dem Rückfahren
3 x 0,5s beepen, mit jeweils 0,5s Pause!
- Überlegen Sie sich weitere Verbesserungen!

Die beiden LDR-Helligkeitssensoren
sind mit den Analogeingängen 2 (Links) und 3 (Rechts) verbunden.
Die Abfrage erfolgt über die getAnalogPort(n)-Methode
des robo-Objekts. Die Rückgabewerte liegen zwischen 0 (Hell)
und 255 (Dunkel).
Erstellen Sie zunächst das abgebildete Formular, mit den
Elementen: panel: panHellLinks, panHellRechts Helligkeitsanzeige
als Grau-Schattierung label: lblHellLinks, lblHellRechts
Helligkeitsanzeige als Zahlenwert checkbox: chbxReadHell
Starten der timergesteuerten Sensorabfrage
In der Timer-Tick-Prozedur werden zunächst zwei Integer-Variablen
(wertLinks und wertRechts) deklariert. In diese Variablen werden
dann nacheinander die Helligkeitswerte der beiden Senoren eingelesen.
Die Hintergrund-Schattierung der beiden Panel-Elemente erfolgt
durch die Übergabe des Analogwerts als Schattierung für
die Farbe Schwarz (Konstante: Color.Black).

Aufgaben:
Erstellen Sie eine Robotersteuerung die den Roboter:
- in Richtung der hellsten Lichtquelle
dreht!
- zur hellsten Lichtquelle fahren lässt.
(Z.B. Suchen einer Basisstation)
- vor der Lichtquelle stoppen lässt!
(Abfrage der IR-Sensoren)

|