Zur Steuerung eines kleinen Roboters habe ich mir eine Nunchuck-Fernbedienung mit XBee-Funkübertragung überlegt.
Dabei kommen folgende Komponenten zum Einsatz:
Sender: Arduino + XBee + Nintendo Nunchuck + Akku
Der Sender liest den Nunchuck aus und sendet die Werte seriell, also über XBee zum Empfänger. Dieser erkennt wann die Übertragung eines Datensatzes vorbei ist, zerlegt diesen und steuert dann die Servos.
Hier der Code des Senders:
// Roboter ___ ___ Draufsicht Stecker
// Version 0.2 | 1 — 2 | 1 = Clock an Analog 5 2 = GND an Analog 2
// Befehle über Nunchuck | 3 4 | 3 = 5V an Analog 3 4 = Data an Analog 4
// SENDER ——————-
#include <Wire.h>
#include „nunchuck_funcs.h“
int loop_cnt=0;
byte accx,accy,accz,zbut,cbut,joyx,joyy;
int PowerLED = 13; // PowerLED
void setup()
{
pinMode(PowerLED, OUTPUT);
digitalWrite(PowerLED, HIGH);
Serial.begin(57600);
nunchuck_setpowerpins();
nunchuck_init();
}
void loop()
{
if ( loop_cnt > 50 ) { // every 100 msecs get new data
loop_cnt = 0;
nunchuck_get_data();
accx = nunchuck_accelx(); // ranges from approx 70 – 182
accy = nunchuck_accely(); // ranges from approx 65 – 173
accz = nunchuck_accelz();
zbut = nunchuck_zbutton();
cbut = nunchuck_cbutton();
joyx = nunchuck_joyx(); // 20-115-220 links-mitte-rechts
joyy = nunchuck_joyy(); // 36-136-232 unten-mitte-oben
Serial.print((byte)joyx,DEC);
Serial.print(„;“);
Serial.print((byte)joyy,DEC);
Serial.print(„;“);
Serial.print((byte)zbut,DEC);
Serial.print(„;“);
Serial.print((byte)cbut,DEC);
Serial.println(„*“); //116;136;0;0* <- Beispiel-Datensatz
}
loop_cnt++;
delay(1);
}
Hier der Code des Empfängers:
// Roboter
// Version 0.2
// Befehle über Nunchuck
// EMPFÄNGER
// Bot mit Servo-Antrieb
// 116;136;0;0*
// Servo Hardware einrichten
#include <Servo.h>
Servo servo_li;
Servo servo_re;
Servo servo_cam;
//Sonstige Hardware
int PowerLED = 13; // PowerLED
//Kommunikation via XBee
char current = 0; // Einzelzeichen über serial
char data[15] = „“; // Zeichenpuffer Gesamtdaten
int incount = 0; // Zähler für Pufferzeiger
bool lineComplete = false; // Merker ob Zeilenende erreicht wurde
char *X = 0; // X-Wert vom Nunchuck aus „data“
int xWert = 0; // integer X-Wert nach atoi Operation
char *Y = 0; // Y-Wert vom Nunchuck aus „data“
int yWert = 0; // integer Y-Wert nach atoi Operation
char *Z = 0; // Z-Taster vom Nunchuck aus „data“
int zTaster = 0;
char *C = 0; // X-Taster vom Nunchuck aus „data“
int cTaster = 0;
//Werte für die Servoeinstellungen
int campos = 95; // unten 50, oben 135
int servo_li_pos = 95; // Servo steht bei Wert 95, größer = vorwärts
int servo_re_pos = 98; // Servo steht bei Wert 98, kleiner = vorwärts
void setup()
{
servo_re.attach(9);
servo_li.attach(10);
servo_cam.attach(11);
pinMode(PowerLED, OUTPUT);
digitalWrite(PowerLED, HIGH);
servo_li.write(servo_li_pos);
servo_re.write(servo_re_pos);
Serial.begin(57600);
// Serial.println(„Roboter gestartet!!!“);
}
void loop()
{
while ( (Serial.available()) & (incount < 15) & (!lineComplete) )
{
current = Serial.read();
if (current != 42) //ASCII 42 == ‚*‘ // solange Zeichen lesen bis das Sternchen den Datensatz abschließt
{
data[incount] = current;
incount++;
}
else
{
data[incount] = ‚\0‘; // puffer mit NULL Zeichen abschließen, damit das Ende der Zeichenkette durch string Operationen erkannt wird
lineComplete = true;
}
}
if (lineComplete) // Wenn der volle Datensatz gelesen wurde
{
digitalWrite(PowerLED, HIGH);
//Serial.println(data); //zu testen ohne XBee kann man das board auch über die serielle konsole mit daten füttern
daten_auswerten();
werte_beurteilen();
werte_einstellen();
lineComplete = false;
incount = 0;
digitalWrite(PowerLED, LOW);
}
else if (incount >=15)
{
incount = 0;
lineComplete = false;
}
}
void daten_auswerten()
{
X = strtok ( data, „;“); // 116;136;0;0* // X = alle Zeichen vor dem ersten „;“ also im Beispiel (s. vorne) ‚116‘
Y = strtok ( NULL, „;“); // Y = alle Zeichen bis zum nächsten „;“ also ‚136‘
Z = strtok ( NULL, „;“); // Z = 0
C = strtok ( NULL, „*“); // C = 0
xWert = atoi (X); //umwandlung von string in Wert (zur weiteren berechnung)
yWert = atoi (Y);
zTaster = atoi (Z);
cTaster = atoi (C);
/*
Serial.println(X); //Datenausgabe zur Kontrolle (können abgeschaltet werden)
Serial.println(xWert);
Serial.println(Y);
Serial.println(yWert);
Serial.println(Z);
Serial.println(zTaster);
Serial.println(C);
Serial.println(cTaster);
*/
}
void werte_beurteilen() // entsprechend der werte den roboter steuern. AB HIER EIGENE DINGE MACHEN 😉
{
if ( (xWert < 135) && (xWert > 95) && (yWert < 171) && (yWert > 101)) {
// stop
servo_li_pos = 95;
servo_re_pos = 98;
}
if ( (yWert > 171) && (cTaster == 1) && (zTaster == 0) ) { //vorwärts
servo_li_pos = servo_li_pos + (yWert – 171);
servo_re_pos = servo_re_pos – (yWert – 171);
}
if ( (yWert < 101) && (cTaster == 1) && (zTaster == 0) ) { //rückwärts
servo_li_pos = servo_li_pos – (101 – yWert);
servo_re_pos = servo_re_pos + (101 – yWert);
}
if ( (xWert < 95) && (cTaster == 1 ) && (zTaster == 0) ) { //links
servo_li_pos = 95;
//servo_re_pos = servo_re_pos + (110 – xWert);
}
if ( (xWert > 135) && (cTaster == 1) && (zTaster == 0) ) { //rechts
servo_re_pos = 98;
}
if ( (yWert > 140) && (cTaster == 0) && (zTaster == 1) ) { //Cam up
campos = campos + 1;
}
if ( (yWert < 132) && (cTaster == 0) && (zTaster == 1) ) { //Cam down
campos = campos -1;
}
if (campos > 135) { campos = 135;}
if (campos < 50) { campos = 50;}
// 2 – vorwärts schnell
/* Serial.println(„move fast“);
servo_li_pos = 160;
servo_re_pos = 20;
// w – vorwärts
Serial.println(„move“);
servo_li_pos = 96;
servo_re_pos = 97;
// stop
servo_li_pos = 95;
servo_re_pos = 98;
// s – rückwärts
Serial.println(„back“);
servo_li_pos = 93;
servo_re_pos = 99;
// x – rückwärts schnell
Serial.println(„back fast“);
servo_li_pos = 20;
servo_re_pos = 160;
// a – links
Serial.println(„left“);
servo_li_pos = 95;
servo_re_pos = 97;
// d – rechts
Serial.println(„right“);
servo_li_pos = 96;
servo_re_pos = 98;
// +
Serial.println(„Cam up“);
campos = campos + 1;
// –
Serial.println(„Cam down“);
campos = campos – 1;
if (campos > 135) { campos = 135;}
if (campos < 50) { campos = 50;}
*/
}
void werte_einstellen() // Die empfangenen werte wurden ausgewerten und entschieden was der bot machen soll. nun werden die werte eingestellt
{
servo_li.write(servo_li_pos);
servo_re.write(servo_re_pos);
servo_cam.write(campos);
}