Hessischer Bildungsserver / Arbeitsplattformen

Lego Mindstorms

Vor einiger Zeit brachte Lego das Mindstorms Robotics Invention System, kurz Lego Mindstorms genannt, auf den Markt. Es beinhaltet ein RCX (programmierbarer Baustein), einen Infrarotsender (Übertragen der Programme auf den RCX), eine Programmierumgebung und natürlich viele Legosteine, mit denen unterschiedliche Roboter gebaut werden können. In der Version 1.5 wird der Infrarotsender an die serielle Schnittstelle angeschlossen, ab V 2 an eine USB-Schnittstelle. Mitgeliefert wird in der Version 1.5 eine ActiveX - Komponente "Spirit.OCX", die es erlaubt, den Roboter unter Sprachen wie Delphi oder Visual Basic anzusteuern.

Als eine Möglichkeit, den Roboter zu programmieren, ist sicherlich die beigelegte graphische Programmierumgebung geeignet. Zusätzlich bietet Lego Dacta eine Software namens Robolab an, die speziell für die Schule konzipiert wurde und sicherlich einige Vorteile bietet.

Mittels einer Internetrecherche findet man schnell Programmierumgebungen, die auf einer Java verwandten Sprache aufbauen (Lejos oder NQC ("Not Quite C")). Java ist aber für den Einsatz in Schulen nur bedingt geeignet, so dass hierzu Alternativen nötig sind.

Delphi als gut strukturierte Sprache bietet sich hier an, auch weil es inzwischen in Schulen weite Verbreitung gefunden hat und den Quasi-Standard Pascal ablöst. Ich will hier einen Weg aufzeigen, den Roboter unter Delphi anzusteuern. Auf der CD mit der Version 1.5 des Robotics Invention Systems befindet sich die ActiveX - Komponente Spirit.OCX im Ordner System, die hierfür nötig ist. Diese Komponente muss unter Windows registriert und in Delphi importiert werden. Ersteres geschieht nach Kopieren der Datei in einen Ordner XXX mittels Start-Ausführen REGSVR32.EXE LW:XXXspirit.ocx, wobei LW die Laufwerksbezeichnung ist. Anschließend wird Delphi gestartet (ich habe die Version 5 getestet), dort unter dem Menüpunkt Komponente ActivX Importieren gewählt. Verlief die Registrierung unter Windows erfolgreich, so ist hier nun Lego PBrickControl, OLE Control Module (Version 1.0) zu finden, welches installiert werden muss. Im Anschluss daran steht die ActiveX Komponente zur Verfügung und kann in ein Formular eingefügt werden.

Um von der Legosoftware unabhängig zu werden, kann man die Firmware ebenfalls unter Delphi auf das RCX übertragen. Die entsprechende Datei ist im Ordner Firm auf der CD unter dem Namen FIRM0309.LGO zu finden.

Natürlich müssen die Lizenzbedingungen hierbei beachtet werden, für SPIRIT.OCX und FIRM0309.LGO hat Lego das Copyright!

Die Spirit-Komponente

Nach dem Einfügen der TSpirit-Komponente erscheint das Lego-Logo auf dem Formular, die entsprechenden Methoden stehen zur Verfügung.

  Im Quelltext der Unit erscheint dann:
type
TForm1 = class(TForm)
Spirit1: TSpirit;
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

  Im Objektinspektor nimmt man die nötigen Einstellungen vor, damit die Übertragung funktioniert.

TSpirit stellt eine Fülle von Funktionen und Prozeduren zur Verfügung, die alle in der Technischen Referenz beschrieben sind. Die Beschreibung knapp gehalten, ist aber durchaus hilfreich. Leider ist die Syntax, die für ein Nutzen von Spirit.Ocx nötig ist, sehr gewöhnungsbedürftig. Wichtig (und unbedingt anzusehen) sind die Parameter Tabellen auf den Seiten 9 und 10. Besonders verwirrend sind zunächst die diversen (knapp dokumentierten) Sources, deren genaue Beachtung sehr wichtig für die Programme ist.

Ein kleines Beispielprogramm soll die Arbeit damit erläutern:

procedure TForm1.Button1Click(Sender: TObject);
begin
Spirit1.InitComm;
if (Spirit1.towerAlive) and
(Spirit1.towerandcableconnected) and
(Spirit1.pbaliveornot)
then Button1.caption:='OK'
else Button2.caption:='Not OK';
end;
Die serielle Schnittstelle wird initialisiert und die Verbindung über den Infrarotsender getestet.
procedure TForm1.Button2Click(Sender: TObject);
begin
spirit1.InitComm;
spirit1.starttask(0);
end;
Das Programm wird gestartet (Task 0 kann auch über den RUN-Knopf des RCX gestartet werden.)
procedure TForm1.Button3Click(Sender: TObject);
begin
with
spirit1 do begin
selectprgm(3);
beginoftask(0);
setfwd('012');
on_('012');
wait(2,500);
off('012');
setrwd('012');
on_('012');
off('012');
setfwd('0');
setrwd('2');
on_('02');
wait(2,1000);
off('02');
endoftask;
end;
end;


Download des Programms auf den Programmplatz 4 (die interne Zählung beginnt bei 0!)

Es werden nur die Motoren ein- und ausgeschaltet sowie die Drehrichtung eingestellt.
procedure TForm1.Button9Click(Sender: TObject);
begin
with
spirit1 do begin
initcomm;
selectprgm(3);
beginoftask(0);
setfwd('012');
setvar(3,2,1);
while_(0,3,1,2,11);
on_('012');
wait(2,50);
off('02');
wait(2,50);
sumvar(3,2,1);
endwhile;
endoftask;
end;
end;
Hier wird die Möglichkeit demonstriert, eine WHILE-Schleife zu prgrammieren.
Syntax: while_(Source1, Wert, Vgl.operator, Source2, Wert)
Die Bedeutung der einzelnen Sources lässt sich aus den beiden o.a. Parametertabellen entnehmen: Variable - 0, Konstanten - 2, usw.

Die Variable 3 wird auf den Anfangswert (die Konstante) 1 gesetzt.
Solange die Variable 3 kleiner als die Konstante 11 ist wiederhole

Erhöhe die Variable 3 und 1
Ende der Schleife
procedure TForm1.Button10Click(Sender: TObject);
begin
with
spirit1 do begin
initcomm;
selectprgm(3);
beginoftask(0);
setfwd('012');
loop(2,5);
on_('012');
wait(2,50);
off('02');
wait(2,50);
endloop;
endoftask;
end;
end;
Loop liefert die Möglichkeit, eine Zählschleife zu erstellen.

Syntax: loop(SourceNr, Wert)

Der Zähler der Schleife wird durch die Konstante 5 festgelegt.
Diese Schritte werden wiederholt.


Ende der Schleife
procedure TForm1.Button11Click(Sender: TObject);
begin
with
spirit1 do begin
initcomm;
selectprgm(3);
beginoftask(0);
setsensortype(0,1);
setsensortype(1,3);
setsensortype(2,1);
setsensormode(0,1,0);
setsensormode(1,4,30);
setsensormode(2,1,0);
setfwd('02');
if_(9,0,2,2,1); on_('0');
else_; on_('2');
endif;
wait(2,500);
off('02');
endoftask;
end;
end;
Durch eine Abfrage der Sensoren (Source - 9) wird bestimmt, welcher der Motoren anlaufen soll. Ist Sensor 1 (interne Nummer 0) nicht gedrückt (Sensorwert 0), so wird Motor A eingeschaltet, sonst startet Motor C.





Syntax: IF_(Source1, Wert, Vgl.operator, Source2, Wert)
(Ist der Wert von Sensor 1 (9,0) gleich (2) der Konstanten 1 (2,1), so wird die Befehlsfolge bis else_ oder endif abgearbeitet.
ELSE_ - Teil
Ende IF
procedure TForm1.Button4Click(Sender: TObject);
begin
Spirit1.CloseComm;
halt;
end;
Beenden der Arbeit.
Eine alternative Möglichkeit

Als eine Möglichkeit den Roboter direkt vom PC aus zu steuern kann man in seine Programme auch die rcx.dll einbinden. Diese stellt einige wenige Prozeduren zur Steuerung zur Verfügung, kann also zu einem elementaren Einstieg dienen. Es ist also möglich, eine Art Fernsteuerung zu programmieren. Allerdings muss dann immer eine Übertragungsmöglichkeit PC - RCX bestehen. Verzichtet man in den unten stehenden Deklarationen auf eine Pfadangabe, so muss die DLL sich im gleichen Verzeichnis wie die Programmdateien befinden. Die DLL und viele nützliche Hinweis finden sich unter www.gajdaw.pl.

procedure RCXStart;StdCall;external 'rcx.dll';
procedure RCXStop;StdCall;external 'rcx.dll';
Diese Prozeduren dienen dazu, die Fernsteuerung zu starten und zu beenden.

procedure RCXSetSerialPort(no:smallint);StdCall;external 'rcx.dll';
Wahl der seriellen Schnittstelle
procedure RCXMotorOn(no:smallint);StdCall;external 'rcx.dll';
procedure RCXMotorOff(no:smallint);StdCall;external 'rcx.dll';
procedure RCXSetFwd(no:smallint);StdCall;external 'rcx.dll';
procedure RCXSetRwd(no:smallint);StdCall;external 'rcx.dll';
procedure RCXAlterDir(no:word);StdCall;external 'rcx.dll';
Prozeduren zur Motorensteuerung
function RCXSensor1:smallint;StdCall;external 'rcx.dll';
function RCXSensor2:smallint;StdCall;external 'rcx.dll';
function RCXSensor3:smallint;StdCall;external 'rcx.dll';
Abfrage der Sensoren
Überlegungen zum Unterricht

In Informatikkursen der SI bzw. SII, in denen Lego Minstorms eingesetzt werden soll, findet man sicherlich auf sehr unterschiedliche Vorkenntnisse in den relevanten Bereichen. Einige SchülerInnen haben grundlegendes bzw. erweitertes Wissen in Bezug auf eine Programmiersprache, das sinnvoll genutzt aber auch gefördert werden muss, andere wiederum haben vielleicht noch nie am PC mit der Absicht gesessen ein Programm zu erstellen. Nicht zu unterschätzen sind die Probleme, die sich aus einer eventuellen Unkenntnis technischer Prinzipien, die für die Bastelarbeit mit den Legosteinen unerlässlich sind, ergeben. Abgestufte Hilfestellungen in diesem Bereich sind nach meiner Ansicht unbedingt nötig. Dies könnten sein: Bauanleitungen für ein einfaches Getriebe, Antrieb mittels eines oder zweier Motoren, sinnvolle Möglichkeiten zur Montage der Sensoren u. ä.

In den Arbeitsgruppen können Probleme daraus entstehen, dass SpezialistInnen für einzelne Bereiche die alleinige Arbeit an sich reißen und den Rest "abhängen". So könnten die notwendigen Teilarbeiten (Modellieren, Programmieren, Bauen) nicht aufeinander abgestimmt nebeneinander herlaufen. Eine organisierte Gruppenarbeit mit wechselnden Aufgabenstellungen ist sicherlich hilfreich um die koordinierte Arbeit aufrecht zu erhalten.

Es erscheint mir wichtig, die Arbeit mit Lego Mindstorms um einige Aspekte zu erweitern. Nicht nur die Motivation, die durch die Programmierung eines Roboters erzeugt wird sollte im Mittelpunkt stehen, sondern es bietet sich die Gelegenheit wichtige Bestandteile des Softwareingeneering bzw. der objektorientierten Progammierung in den Unterricht einzubeziehen. Programmieren selbst ist hierbei nur der Teil des Softwareentwicklungszyklus, der der es den Schülerinnen und Schülern erlaubt, ihre Produkte überhaupt zu testen. Das bedeutet auch, die Fehlerfreiheit der in der immens wichtigen Modellierungsphase entwickelten Konzepte zu prüfen.

Ersteres ist durch eine Vorgehensweise zu erreichen, die an den Beginn der Arbeit, nach der Aufgabenstellung, eine Phase anschließt, in der die Aufgabe in konkrete Anforderungen an das Modell umgesetzt wird. Eine allgemeine Phrase wie "Der Roboter soll auf einem Tisch fahren ohne an der Kante abzustürzen" muss in eine detaillierte Folge von kleinen Schritten zerlegt werden. Beschrieben werden hier auch schon Einzelheiten der Konstruktion, nach der der Roboter gebaut werden soll. (Antrieb mittels zweier Motoren, Einsatz welcher Sensoren usw.)

Nachdem die Anforderung konkretisiert wurde, können die einzelnen Schritte des geplanten Ablaufs in Zustandsdiagramme umgesetzt werden, die eine objektorientierte Sichtweise nahe legen. Selbstverständlich können die Objekte mit ihren Attributen und Methoden in unterschiedlicher Form dargestellt werden. Eine Möglichkeit beschreibe ich unten.

Die Modellierung der Objekte wird immer die gleiche sein, es handelt sich um das RCX, die Motoren, die Sensoren und evtl. den Soundbaustein. Relevante Attribute und Methoden ergeben sich den Fragen an die Objekte nach den Merkmalen und den "Handlungsmöglichkeiten".

Einige Vorteile der Objetorientierung liegen auf der Hand:

  • Durch den Prozesscharakter der Aufgabenbearbeitung können neue Anforderungen auch während des Entwicklungsprozesses nachgereicht und vergleichsweise einfach integriert werden.
  • Die Kommunikation zwischen den schwerpunktmäßig als Softwareentwickler und Experten im Legobau tätigen Gruppenmitgliedern verbessert sich durch die menschengerechtere visuelle Sichtweise.
  • Die durchgängige Modellierung begünstigt die Qualität der Arbeitsergebnisse: Die einzelnen Entwicklungsschritte bleiben eher konsistent zueinander.
  • Die durchgängigen Konzepte in allen Arbeitsphasen vereinfachen die Entwicklung und verbessern die Dokumentation.
  • Die objektorientierten Abstraktionsmöglichkeiten ermöglichen eine bessere Wiederverwendung der Arbeitsergebnisse für andere Steuerungsprogramme.

Diese Objektorientierung ermöglicht eine statische Sicht auf die Datenbasis. Bei unterschiedlichen Gelegenheiten (Ereignissen) ändern sich allerdings die Werte der Attribute, Methoden "arbeiten". Beobachtet man das System zu bestimmten Zeitpunkten, so gewinnt man also einen Überblick über die Verantwortlichkeiten und Tätigkeiten der Objekte. Die einzelnen Zustände in ihrer notwendigen Abfolge, die das System so einnehmen kann, charakterisieren das Programm, das zur Steuerung des Roboters dient.

Die Zustandsdiagramme werden wie folgt erstellt: Im Mittelpunkt steht das RCX mit seinen Motoren und Sensoren, die Motoren haben eine Drehrichtung und eine Stärke, die Sensoren haben Werte. In einem Zustandsdiagramm ist dies enthalten. Ändert sich durch ein Ereignis etwas in der Form, dass das System einen neuen Zustand einnimmt, so wird ein neues Diagramm erstellt.

Das Beispiel zeigt ein Zustandsdiagramm mit RCX, an dem ein Motor mit Drehrichtung nach rechts, Stärke 1 und ein Drucksensor mit Wert 0 (nicht gedrückt) angeschlossen sind.

Die Schülerinnen und Schüler haben die Möglichkeit, diese Diagramme mit einer Digitalkamera abzufotografieren oder sie abzuzeichnen und so ihr Protokoll der Gruppenarbeit zu ergänzen. Diese Zustandsdiagramme dienen als Grundlage der Programmerstellung.

(Die einzelnen Elemente der für die SI gedachten Vorlage können in Folie eingeschweißt und an die SchülerInnen verteilt werden. Beherrschen die Schülerinnen und Schüler die Bedienung eines Grafikprogramms, so kann dieses zum Entwurf der Diagramme genutzt werden.)
  

Ich bin mir dessen bewusst, dass die Objektorientierung sich weder in der Programmierung mit Delphi noch in den beiden oben erwähnten grafischen Entwicklungsumgebungen, die für Lego Mindstorms zu erhalten sind, direkt in den Programmen dadurch widerspiegelt, dass die Schülerinnen und Schüler selbst Klassen definieren müssen. Dennoch halte ich die Unterstützung in der Phase der Modellierung und Programmentwicklung, die aus dem oben beschriebenen Ansatz ergibt, einer objektorientierten Denkweise für förderlich.

Dr. Jürgen Poloczek
09.06.2007