Programmierung der Lego Mindstorms Roboter Dipl.-Inform. O. Taminé Gliederung Infrastruktur Aufbau, Vorbereitungen, WWW-Links NQC-Programmierung Vorbereitungen, Kommandozeilen-Programmierung, IDE-Oberflächen NQC-Sprachreferenz Beschreibung der NQC-Sprache
Teil I: Infrastruktur RCX-Baustein Hitachi H8-Prozessor 8 Bit, 16 Mhz 32 Kbyte RAM 16 Kbyte ROM je drei Ein-/Ausgänge Infrarot-Schnittstelle 5 Programmspeicher
Speicheraufbau 5x1,2 KByte RAM Programmspeicherplätze 32 Kbyte statisches RAM 16 Kbyte ROM 1 2 3 4 5 Firmware BIOS RCX-Display Batterieanzeige Kommunikation Aktiver Sensoranzeige Zeitanzeige Boot-Modus Ausgang View On/Off 1 2 3 ^ 00.00 ^ ^ 1 A B C Prgm Run
Infrarotsender Kommunikation PC -> Lego Mindstorms Anschluß an COM-Port (1) Übertragung der Firmware (2) Übertragung eigener Programme Stromversorgung 9 Volt (6x1,5 V Mignon Batterien) 1,5 V Alkaline NiCd Entladung
RCX-Code Lego-Programmiersprache WWW-Links Software, Dokumentationen, Büchertipps, WWW-Seiten, Teilnehmerlisten,... auf der Praktikumshomepage: http://i61www.ira.uka.de/users/tamine/lego/
Teil II: NQC-Programmierung Vorbereitung (Teil 1) Auf Lego-CD: System\spirit.ocx Firm\firm0309.lgo Download der RCX 2.0 Firmware: firm0328.lgo (Praktikumshomepage)
Software installieren (Teil 2) Installieren von Bricx Command Center: bricxcc.exe, Aktuelle Version: 3.3 Win 95/98/ME/2000/XP Download von Homepage Alternativ: Installieren von NQC: nqc-win-2-3-r1.zip, Aktuelle Version: 2.3 Download von Homepage Version 2.4 im Beta-Stadium Firmware übertragen (Teil 3) 1. Möglichkeit Bricx Command Center: Menü Tools/Download Firmware Datei firm0328.lgo auswählen 2. Möglichkeit: nqc -firmware pfad\firm0328.lgo oder: nqc -firmfast pfad\firm0328.lgo
Programmierumgebung I (1) NQC-Programm in Editor schreiben (2) DOS-Shell: Kompilieren + Übertragen an RCX Programmierumgebung II
Starten vom Bricx Command Center Suche nach eingeschaltetem Lego Mindstorms Roboter Falls Roboter nicht gefunden wird, sind nicht alle Funktionen verfügbar. Tool: Direct Control Direkte Steuerung der RCX-Komponenten: Sensoren: Typ + Modus der 3 Sensoren Motoren: Vorwärts, Rückwärts, Bremsen, Leerlauf Variablen: Wertzuweisung Tasks: Starten + Anhalten der 10 Tasks
Tool: Diagnostics Anzeige von: Status Firmware-Version Batteriestatus Anschlußport Aktueller Programmnr. Auschaltzeit Infrarotstärke Einschaltzeit Display-Anzeige Tool: Watching the RCX Beobachten folgender RCX-Werte: Variablen Sensoren Motoren Timer Infrarot Zähler
Weitere Tools Send Message RCX-Piano Joystick Teil III: NQC-Sprachreferenz
NQC Sprachkonstrukte NQC = Not quite C Lexikalische Strukturen Programmstrukturen Kontrollstrukturen RCX API Beispiele Lexikalische Strukturen Kommentare // Einzeiliger Kommentar /* Dieser Kommentar belegt mehrere Zeilen */ Leerzeichen nicht notwendig, aber hilfreich x=2; x = 2; Numerische Konstanten x = 10; // setzt x auf den Dezimalwert 10 x = 0x10; // setzt x auf den Dezimalwert 16 Präprozessorbefehle wie in C
Der Präprozessor Einbinden von Programmteilen #include part2.nqc Substitution von Werten #define SCHWARZ 800 Speicherreservierung #pragma reserve 0 1 2 notwendig bei Timern und Zählern Programmstrukturen I Tasks RCX ist multitaskingfähig unterstützt max. 10 Tasks Tasks werden durch start task_name gestartet und durch stop task_name beendet StopAllTasks(); beendet alle Tasks Beispiel: task main() { // Ein leerer Task }
Programmstrukturen II Unterprogramme max. 8 Stück keine Parameter keine Rückgabewerte keine Rekursion erlaubt keine anderen Unterprogrammaufrufe erlaubt nur 1 kompiliert (Speicherplatz sparend!) Beispiel: sub dummy() { // Ein leeres Unterprogramm } Programmstrukturen III Inline-Funktionen kein Rückgabewert Parameterübergabe per Wert und per Referenz Funktionen werden beim Kompilieren an die Aufrufstelle kopiert (Makro) Beispiel: void fkt(int x, int& y) { x = 3; y = 2; } task main() { int y = 1; int x = 2; fkt(x, y); }
Variablen nur 16-Bit Integer Variablen Arrays erlaubt Deklarationen wie in C Ausdrücke wie in C erlaubt (++, *=,, &&, >>, usw.) Beispiele: int a=1, x; x += a; a = 5 % 2; // modulo x = 31 1; // Or Globale und lokale Variablen unterstützt max. 32 globale Variablen max. 16 lokale Variablen Beispiel: int x = 0; // bin global task main() { int y; // bin lokal y = x; // ok } task move() { x = 5; // ok y = x; // nicht ok, y hier unbekannt }
Kontrollstrukturen if (Bedingung) Block1 else Block2 while (Bedingung) Block do Block while (Bedingung) repeat (Ausdruck) Block switch (Ausdruck) case until (Bedingung); Befehle break, continue, default usw. wie in C Beispiele: if (x==1) y = 3; else y = 4; while (x<10) { y *= 5; x++; } until (SENSOR_1 == 1); Motorsteuerung Konstanten: OUT_A, OUT_B, OUT_C Befehl Beschreibung On (const) schaltet Motor ein Off(const) schaltet Motor aus Float(const) schaltet auf Leerlauf Fwd(const) vorwärts Rev(const) rückwärts Toggle(const) wechselt Richtung OnFwd(const) ein + vorwärts OnRev(const) ein + rückwärts OnFor(const, time) vorwärts für time/100 sec SetPower(const, x) Geschwindigkeit (0-7)
Sensorik Berührungssensor Lichtsensor Ausgänge: SENSOR_1, SENSOR_2, SENSOR_3 Sensoren: SENSOR_TOUCH, SENSOR_LIGHT SetSensor(Ausgang, Sensor) setzt einen Ausgang auf einen bestimmten Sensortyp Der Sensor wird dabei in seinem Standardmodus betrieben Berührungssensor Was macht dieses Programm? task main() { SetSensor(SENSOR_1, SENSOR_TOUCH); OnFwd(OUT_A+OUT_C); until (SENSOR_1 == 1); Off(OUT_A+OUT_C); }
Sensor-Modi Const: SENSOR_TYPE_TOUCH, SENSOR_TYPE_LIGHT Befehl SetSensorType(Ausgang, const) SetSensorMode(Ausgang, mod) Beschreibung legt Sensortyp fest legt Sensormodus fest Modus Beschreibung SENSOR_MODE_RAW 0 bis 1023 SENSOR_MODE_BOOL 0 bis 1 SENSOR_MODE_EDGE zählt Zustandswechsel SENSOR_MODE_PULSE zählt Zustandsperioden SENSOR_MODE_PERCENT 0 bis 100 Prozent Funktionsweise eines Sensors SENSOR_MODE_RAW 1023 0 SENSOR_MODE_PERCENT: Transformation des Raw-Wertes in den Wertebereich 0-100 t
Boolescher Modus SENSOR_MODE_BOOL 1023 True False 0 t Zustandswechsel SENSOR_MODE_EDGE 1023 1 3 2 4 0 t
Periodenwechsel SENSOR_MODE_PULSE 1023 1 2 0 t RCX Events Befehl Beschreibung SetEvent(Nr, source, type) legt Sensorfest fest monitor(event_mask(nr)) überwacht Event Typ EVENT_TYPE_PRESSED EVENT_TYPE_RELEASED EVENT_TYPE_PULSE EVENT_TYPE_EDGE EVENT_TYPE_LOW EVENT_TYPE_NORMAL EVENT_TYPE_HIGH EVENT_TYPE_MESSAGE EVENT_TYPE_FASTCHANGE Beschreibung Gedrückt Nicht gedrückt Periodenwechsel Zustandswechsel Wechsel in Niedrigbereich Wechsel in Normalbereich Wechsel in Hochbereich IR-Nachricht empfangen Schneller Wertwechsel
Event Modus 1023 Hoch Normal 0 Niedrig Beispiel: Lichtsensor task main() { SetSensorType(SENSOR_2, SENSOR_LIGHT); SetEvent(1, SENSOR_2, EVENT_TYPE_HIGH); SetEvent(2, SENSOR_2, EVENT_TYPE_LOW); SetLowerLimit(2, 550); SetUpperLimit(1, 790); monitor(event_mask(1) EVENT_MASK(2)) { // tue was immer du willst... } catch (EVENT_MASK(1)) { // Schwarz gefunden } catch (EVENT_MASK(2)) { // Weiss gefunden } }
Kommunikation Befehle: id = Message(); id = 0: keinen Wert empfangen SendMessage(id); versendet id (0-255) ClearMessage(); löschst den Empfangspuffer SetTXPower(TX_POWER_LO) legt Sendestärke fest Beispiel Kommunikation #define NOTETIME 10 #define WAITTIME 12 task communication() { ClearMessage(); SendMessage(5); // Warte auf Antwort until (Message()!= 0); // ID empfangen if (Message() == 5) { // ID korrekt SendMessage(10); PlayTone(330,4* NOTETIME); Wait(4* WAITTIME); } else { // Falscher Partner OnRev(OUT_A+OUT_C); } } ClearMessage(); } task main() { start communication;}
Programmumschaltung 5 Programmspeicher Befehl SelectProgram(Nr) x = Program(); Beschreibung wechselt Programm und startet es (Nr: 0-4) liest aktuelle Programmnr. aus Weitere Befehle Musik Zähler Timer Display Datalog Random usw, usw., usw.
Letztes Beispiel: Semaphoren int sem; task main() { sem = 0; start move; SetSensor(SENSOR_1, SENSOR_TOUCH); while (true) { if (SENSOR_1 == 1) { until (sem == 0); sem = 1; OnRev(OUT_A); Wait(85); sem = 0; } } } task move() { while (true) { until (sem == 0); sem = 1; OnFwd(OUT_A); sem = 0; Wait(200); }} Viel Erfolg!!!!!!!