Im Rahmen meines Studiums der angewandten Informatik im Maschinenbau, haben wir an der FH Gelsenkirchen des öfteren mit dem kleinen Forschungsroboter Asuro der Firma Arexx gearbeitet.
Zugegebenermaßen ist der Asuro nicht mehr der aktuellste Robotorbausatz, aber um in die Welt der Robotik einzusteigen und sich am Löten zu versuchen ist der kleine immer noch sehr gut geeignet.
Auch ist der Einstiegspreis von 50-60€ je nach Anbieter angemessen.
Ein Projekt welches ich mithilfe des Asuro während meines Studiums umgesetzt habe war die drahtlose Steuerung über einen Nunchuck Controller der Nintendo Wii. Um dies umzusetzen galt es ersteinmal eine Bestandsaufnahme durchzuführen um zu sehen welche Möglichkeiten uns zur Verfügung stehen und somit den gewünschten Funktionsumfang zu bestimmen.
Den Funktionsumfang zu definieren war relativ einfach, der Asuro sollte über den analogen Joystick des Wii Nunchuck gesteuert werden und bei Druck auf die beiden Nunchuck Buttons aktionen wie eine 180° bzw. 360° Drehung ausführen.
Da wir nun wissen was wir wollen schauen wir nun wie wir dies erreichen können, fangen wir beim Asuro an:
Der Asuro bietet nur eine drahtlose Schnittstelle zur Aussenwelt, seinen IR- Empfänger bzw. IR- Diode. Diese Bauteile werden auch genutzt um die Firmware auf den Mikrocontroller des Asuro zu flashen. Infrarot ist zwar nicht die beste drahtlose Schnittstelle für unsere Aufgabe, aber man nimmt was man kriegen kann.
Schauen wir uns den Wii Nunchuck an. Eigentlich ein sehr nettes Teil was Nintendo dort verkauft. Ein analoger Joystick, zwei Bottons und innenliegend noch ein paar Beschleunigungssensoren. Blöd ist nur der proprietäre Anschluss bedeutet das man entweder den Stecker abschneiden muss, oder sich mit einem Adapter wie dem WiiChuck behilft. Ist diese Hardwarebarriere erst einmal überwunden so gibt der WiiChuck seine daten problemlos per I2C aus.
So nun haben wir einen Roboter der nur per Infrarot und einen Wii Nunchuck der nur per I2C Kommunizieren kann. Passt noch nicht so ganz zusammen und hier kommst der Arduino Uno ins Spiel. Ich muss sagen ich bin von der Arduino Plattform begeistert weil sie es sehr einfach macht solche Projekte umzusetzen. Das Arduino Board wird uns als Vermittler dienen indem es die Daten des Wii Nunchuck entgegen nimmt und diese per Infrarot an den Asuro weiter sendet. Dazu muss an das Arduino nur noch eine IR- Diode mit passendem Vorwiderstand angeschlossen werden.
Jetzt müssen wir nur noch klären wie wir die Steuerbefehle an den Asuro schicken wollen. Wir haben hier prinzipiell zwei möglichkeiten, wir können zwischen dem Asuro und dem Arduino eine serielle Verbindung via Infrarot aufbauen und die Steuerbefehle z.B. als Ascii zeichen versenden und auswerten oder wir benutzen das RC5 Protokoll welches auch bei Infrarot Fernbedienungen zum einsatz kommt. Im vorliegenden Fall habe ich mich für RC5 entschieden, ich muss allerdings auch zugeben auf die Lösung mit der seriellen Schnittstelle bin ich erst später gekommen 😉
So nun benötigt man noch ein bisschen Software welche auf den beiden Mikrocontrollern laufen soll. der Arduino nimmt also die Daten vom Wii Nunchuck entgegen, interpretiert Sie und sendet die Steuerbefehle an den Asuro, dieser reagiert auf diese. Da der Asuro per RC5 gesteuert wird kann man Ihn auch mit einer passend eingestellten Universalfernbedienung steuern.
Zum Glück gibt es hier einige Libraries (sowohl für den Asuro also auch für den Arduino) die uns das Leben einwenig einfacher machen:
Für den Asuro:
AsuroLib-v280rc1 Diese enthält eine passende Library zur Decodierung von RC5 Signalen
Für den Arduino:
ArduinoNunchuck von Gabriel Bianconi Diese ermöglicht uns das initialisieren und auslesen des Wii Nunchuck
IRemote Library von Ken Shirriff Mit dieser erzeugen wir die passenden Steuerbefehle
Die Projektseiten zeigen wie die Hardware miteinander verbunden werden muss.
Nun können wir unsere Software schreiben. Der Sourcecode sollte so dokumentiert sein das er keiner großen Erklärung bedarf:
Sourcecode für den Asuro:
/******************************************************************************* * * Beschreibung: Asuro von IR- Fernbedienung (RC5) bzw. Wii-Nunchuk gesteuert * Author: Björn Sengotta * Verwendet zusätzliche Libraries von http://sourceforge.net/projects/asuro/ * *****************************************************************************/ #include "asuro.h" //Library zur dekodierung von RC5 Fernbedienungscodes #include "rc5.h" #include //Zuweisung von Fernbedienungscodes zu besser verständlichen Begriffen #define VOR 0x1002 #define RUECK 0x1008 #define STOP 0x1005 #define RECHTS 0x1006 #define LRECHTS 0x1003 #define LRECHTSRW 0x1009 #define LINKS 0x1004 #define LLINKS 0x1001 #define LLINKSRW 0x1007 #define ONEEIGHTY 0x103F #define THREESIXTY 0x1026 //Lässt den Asuro geradeaus fahren, Motorgeschwindigkeiten manuell ermittelt void geradeaus() { BackLED(ON,ON); MotorDir(FWD,FWD); MotorSpeed(150,160); } //Stoppt den Asuro void anhalten() { BackLED(OFF,OFF); MotorSpeed (0,0); } //Lässt den Asuro rückwärts fahren, Motorgeschwindigkeiten manuell ermittelt void rueckwaerts() { BackLED(ON,ON); MotorDir(RWD,RWD); MotorSpeed(150,160); } //Asuro dreht sich auf der Stelle nach rechts void vollrechts() { BackLED(OFF,ON); MotorDir(FWD,FWD); MotorSpeed(150,0); } //Asuro dreht sich auf der Stelle nach links void volllinks() { BackLED(ON,OFF); MotorDir(FWD,FWD); MotorSpeed(0,160); } //Asuro fährt eine Rechtskurve void leichtrechts() { BackLED(OFF,ON); MotorDir(FWD,FWD); MotorSpeed(150,120); } //Asuro fährt eine Linkskurve void leichtlinks() { BackLED(ON,OFF); MotorDir(FWD,FWD); MotorSpeed(130,160); } //Asuro fährt Rückwärts eine Rechtskurve void leichtrechtsrw() { BackLED(OFF,ON); MotorDir(RWD,RWD); MotorSpeed(150,120); } //Asuro fährt Rückwärts eine Linkskurve void leichtlinksrw() { BackLED(ON,OFF); MotorDir(RWD,RWD); MotorSpeed(130,160); } //Asuro macht eine 180° Drehung void halbedrehung() { int i=0; BackLED(OFF,ON); MotorDir(FWD,RWD); MotorSpeed(150,160); for (i=0; i<90;i++) { Sleep(255); } MotorSpeed(0,0); } //Asuro macht eine 360° Drehung void volledrehung() { int i=0; BackLED(OFF,ON); MotorDir(FWD,RWD); MotorSpeed(150,160); for (i=0; i<180;i++) { Sleep(255); } MotorSpeed(0,0); } //Main Methode int main(void) { //variablen für die IR Kommandos static unsigned int ircmd; static unsigned int oldircmd; //Erstzuweisung des Kommandos "Stop" ircmd = 1005; oldircmd = 1005; //Initialisierungsmethoden für den Normalbetrieb und für die RC5 Klasse Init(); InitRC5(); //Serielle Ausgabe SerPrint("Asuro Ferngesteuert\r\n"); while(1) { //Zuweisung des letzten IR Kommandos auf die Variable oldircmd oldircmd =ircmd; //Lesen des IR Kommandos von der Fernbedienung und Verarbeitung mit der RC5_Mask ircmd = ReadRC5(); ircmd &= RC5_MASK; /*Wenn das alte und das neue IR Kommando verschieden sind springt das Programm in die Switchanweisung und führt die zum IR Kommando passende Funktion aus*/ if (ircmd!=oldircmd) switch(ircmd) { case VOR: geradeaus(); break; case STOP: anhalten(); break; case RUECK: rueckwaerts(); break; case RECHTS: vollrechts(); break; case LINKS: volllinks(); break; case LRECHTS: leichtrechts(); break; case LLINKS: leichtlinks(); break; case LRECHTSRW: leichtrechtsrw(); break; case LLINKSRW: leichtlinksrw(); break; case ONEEIGHTY: halbedrehung(); break; case THREESIXTY: volledrehung(); break; } //Sind ircmd und oldircmd identisch führt der Asuro die vorhergehende Aktion weiter aus else ; } return(0); }
Und hier für den Arduino:
/* * Beschreibung: Wii Nunchuck Fernsteuerung für den Asuro * Author: Björn Sengotta * Verwendet zusätzliche Libraries: * ArduinoNunchuk (zum Auslesen des Nunchuk via I2C) https://github.com/GabrielBianconi/ArduinoNunchuk * IRemote (zum Senden der RC5 IR Codes) http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html * */ #include //Libraries zum auslesen des Nunchuck und zum Senden der RC5 Codes einbinden #include #include //Baudrate für die serielle Verbindung setzen #define BAUDRATE 19200 //Nunchuk Objekt anlegen ArduinoNunchuk nunchuk = ArduinoNunchuk(); //Variablen für die Nullpunkt Koordinaten des Nunchuk Joysticks anlegen int analogXzero; int analogYzero; //Variable für den RC5 Code anlegen unsigned long code; //IRemote initialiseren IRsend irsend; //Setup Routine void setup() { //Serielle Verbindung aufbauen Serial.begin(BAUDRATE); //Nunchuck initialisieren nunchuk.init(); /*Das erste mal die Werte des Nunchuks einlesen und als Nullreferenz verwenden *da es sich nur um ganzzahlige Integerwerte handelt und diese auch sehr stabil *sind ist eine mittlung der Werte (z.B. durch eine for- Schleife) nicht notwendig */ nunchuk.update(); //Werte der Nullstellen den Variablen zuweisen analogXzero = nunchuk.analogX; analogYzero = nunchuk.analogY; } // Haiptprogramm void loop() { //Frische Werte vom Nunchuck holen nunchuk.update(); //Werte für X- Achse und Y-Achse des Joysticks auslesen und mit den Nullpunkten //verrechnen, auf diese Weise bekommen wir ungefähr Werte zwischen -127 und +127 int xValue = (nunchuk.analogX-analogXzero); int yValue = (nunchuk.analogY-analogYzero); //Prüfen ob einer der Knöpfe am Nunchuk gedrückt wurde if (nunchuk.cButton == 1 || nunchuk.zButton == 1) { //Wenn Knopf C am Nunchuck gedrückt wurde wird das RC5 Signal für eine 180° Drehung an den Asuro gesendet //und ein Text auf der seriellen Konsole ausgegeben if (nunchuk.cButton == 1) { code = 0x83F; sendCommand(code); Serial.print("180° \n"); } //Wenn Knopf Z am Nunchuck gedrückt wurde wird das RC5 Signal für eine 360° Drehung an den Asuro gesendet //und ein Text auf der seriellen Konsole ausgegeben else if (nunchuk.zButton == 1) { code = 0x826; sendCommand(code); Serial.print("360° \n"); } } else { //Testen ob sich der Joystick auf der X-Achse nahe des Mittelpunktes befindet if (xValue > -49 && xValue < 49) { //Testen ob sich der Joystick auf der Y-Achse nahe des Mittelpunktes befindet, ist dies der Fall wird das "Stop" //Kommando gesendet if (yValue > -49 && yValue < 49) { code = 0x805; sendCommand(code); Serial.print("STOP \n"); } //Testen ob sich der Joystick auf der Y-Achse im positiven Bereich (vom Körper weg) über dem Schwellenwert von 50 //liegt, ist dies der Fall wird das Kommando zum Vorwärtsfahren gesendet else if (yValue > 50) { code = 0x802; sendCommand(code); Serial.print("VOR \n"); } //Testen ob sich der Joystick auf der Y-Achse im negativen Bereich (zum Körper hin) unter dem Schwellenwert von -50 //liegt, ist dies der Fall wird das Kommando zum Rückwärtsfahren gesendet else if (yValue < -50) { code = 0x808; sendCommand(code); Serial.print("ZURUECK \n"); } } //Testen ob sich der Joystick auf der X-Achse im negativen Bereich unter dem Schwellenwert von -50 befindet, //dies bedeutet das der Joystick einen Ausschlag nach Links hat else if (xValue < -50) { //Testen ob sich der Joystick auf der Y-Achse zwischen den Schwellenwerten von -49 und +49 bewegt, //ist dies der Fall befindet sich der Joystick in einer Mittelstellung und das Kommando "LINKS" wird gesendet if (yValue > -49 && yValue < 49) { code = 0x804; sendCommand(code); Serial.print("LINKS \n"); } //Testen ob sich der Joystick auf der Y-Achse zwischen über dem Schwellenwert von 50 bewegt, //ist dies der Fall befindet sich der Joystick links oben und das Kommando "LINKS OBEN" wird gesendet else if (yValue > 50) { code = 0x801; sendCommand(code); Serial.print("LINKS OBEN\n"); } //Testen ob sich der Joystick auf der Y-Achse zwischen unter dem Schwellenwert von -50 bewegt, //ist dies der Fall befindet sich der Joystick links unten und das Kommando "LINKS UNTEN" wird gesendet else if (yValue < -50) { code = 0x807; sendCommand(code); Serial.print("LINKS UNTEN\n"); } } //Testen ob sich der Joystick auf der X-Achse im positiven Bereich über dem Schwellenwert von 50 befindet, //dies bedeutet das der Joystick einen Ausschlag nach Rechts hat else if (xValue > 50) { //Testen ob sich der Joystick auf der Y-Achse zwischen den Schwellenwerten von -49 und +49 bewegt, //ist dies der Fall befindet sich der Joystick in einer Mittelstellung und das Kommando "RECHTS" wird gesendet if (yValue > -49 && yValue < 49) { code = 0x806; sendCommand(code); Serial.print("RECHTS \n"); } //Testen ob sich der Joystick auf der Y-Achse zwischen über dem Schwellenwert von 50 bewegt, //ist dies der Fall befindet sich der Joystick rechts oben und das Kommando "RECHTS OBEN" wird gesendet else if (yValue > 50) { code = 0x803; sendCommand(code); Serial.print("RECHTS OBEN\n"); } //Testen ob sich der Joystick auf der Y-Achse zwischen unter dem Schwellenwert von -50 bewegt, //ist dies der Fall befindet sich der Joystick rechts unten und das Kommando "RECHTS UNTEN" wird gesendet else if (yValue < -50) { code = 0x809; sendCommand(code); Serial.print("RECHTS UNTEN\n"); } } //Falls alle Bedingungen nicht zutreffen (z.B. Nunchuck nicht angeschlossen) wird der Fehler auf der seriellen //seriellen Konsole ausgegeben else { Serial.print("Failure \n"); } } //Ausgabe der Nunchuk Werte zum debuggen Serial.print((nunchuk.analogX-analogXzero), DEC); Serial.print(' '); Serial.print((nunchuk.analogY-analogYzero), DEC); Serial.print(' '); Serial.print(nunchuk.zButton, DEC); Serial.print(' '); Serial.println(nunchuk.cButton, DEC); } //Funktion zum senden des RC5 Kommandos via IRemote Library, bekommt als Argument den RC5 Code mitgeteilt void sendCommand(unsigned long code) { //Der RC5 Standard sieht vor, das das Kommando 3 mal gesendet werden muss for (int i = 0; i < 3; i++) { irsend.sendRC5(code, 12); //Delay von 40ms vor dem erneuten senden des Kommandos delay(40); } }
Damit sollte der Asuro sich nun per Wii Nunchuck steuern lassen. Ein Problem ist natürlich die Reichweite der IR- Verbindung, diese ist nicht wirklich groß und hängt auch sehr stark von der Ausrichtung der IR Diode und des Empfängers ab.
Viel Spass beim nachmachen.