This is a little project I have been working on recently. It's my first real attempt at an arduino project.
I will have pictures and a site about it up soon.
Objective:
To control a robot built on the ardubot platform from a remote station with a Wiimote.
Hardware:
Ardubot platform-
Arduino Duemilanove
XBee Pro 900 XSC
9V battery pack
Ardubot basestation-
Arduino Duemilanove
XBee Pro 900 XSC
Wiimote (wired into an adafruit prototyping shield)
Code -
Here is the code for the ardubot platform. It's a bit rough, but so is my C.
/*
Ardubot v0.1
by Jon Heard
crow@inthecrowsnest.com
The bot side of the software reads the XBee serial data,
splits the string, and controls the motors through a case.
The data from the base station is transmitted in the
"A,255\r\n" format, the first character being the direction
of travel, and the interger being the PWM value to control
the motors. The PWM value is the radius of movement on the
Wiichuck mapped to values 0-255 as transmitted by the base
station.
Code adapted from
Didier Stevens
*/
int PIN_HBRIDGE_1A = 9;
int PIN_HBRIDGE_2A = 6;
int PIN_HBRIDGE_3A = 5;
int PIN_HBRIDGE_4A = 3;
char directions[6];
char dir;
int x;
int inByte = -1;
char inString[3];
int stringPos =0;
int radius;
void BotStop(){
digitalWrite(PIN_HBRIDGE_3A, LOW);
digitalWrite(PIN_HBRIDGE_4A, LOW);
digitalWrite(PIN_HBRIDGE_1A, LOW);
digitalWrite(PIN_HBRIDGE_2A, LOW);
}
void BotForward(){
digitalWrite(PIN_HBRIDGE_3A, HIGH);
digitalWrite(PIN_HBRIDGE_4A, LOW);
digitalWrite(PIN_HBRIDGE_1A, LOW);
digitalWrite(PIN_HBRIDGE_2A, HIGH);
}
void BotReverse(){
digitalWrite(PIN_HBRIDGE_3A, LOW);
digitalWrite(PIN_HBRIDGE_4A, HIGH);
digitalWrite(PIN_HBRIDGE_1A, HIGH);
digitalWrite(PIN_HBRIDGE_2A, LOW);
}
void BotRightTurn(int l, int r){
digitalWrite(PIN_HBRIDGE_4A, LOW);
digitalWrite(PIN_HBRIDGE_2A, LOW);
analogWrite(PIN_HBRIDGE_3A, l);
analogWrite(PIN_HBRIDGE_1A, r);
}
void BotLeftTurn(int l, int r){
digitalWrite(PIN_HBRIDGE_3A, LOW);
digitalWrite(PIN_HBRIDGE_1A, LOW);
analogWrite(PIN_HBRIDGE_4A, l);
analogWrite(PIN_HBRIDGE_2A, r);
}
void BotForwardRight(int r){
digitalWrite(PIN_HBRIDGE_3A, HIGH);
digitalWrite(PIN_HBRIDGE_4A, LOW);
digitalWrite(PIN_HBRIDGE_1A, LOW);
analogWrite(PIN_HBRIDGE_2A, r);
}
void BotForwardLeft(int l){
digitalWrite(PIN_HBRIDGE_1A, LOW);
digitalWrite(PIN_HBRIDGE_2A, HIGH);
analogWrite(PIN_HBRIDGE_3A, l);
digitalWrite(PIN_HBRIDGE_4A, LOW);
}
void BotReverseRight(int r){
digitalWrite(PIN_HBRIDGE_3A, LOW);
digitalWrite(PIN_HBRIDGE_2A, LOW);
digitalWrite(PIN_HBRIDGE_4A, HIGH);
analogWrite(PIN_HBRIDGE_1A, r);
}
void BotReverseLeft(int l){
digitalWrite(PIN_HBRIDGE_3A, LOW);
digitalWrite(PIN_HBRIDGE_2A, LOW);
digitalWrite(PIN_HBRIDGE_1A, HIGH);
analogWrite(PIN_HBRIDGE_4A, l);
}
void handleSerial(){
inByte = Serial.read();
if ((inByte >= 65) && (inByte <= 74)){
dir = inByte;
}
if (( inByte >= '0') && (inByte <= '9')){
inString[stringPos] = inByte;
stringPos++;
}
if (inByte == '\r'){
radius = atoi(inString);
stringPos = 0;
}
}
void setup() {
pinMode(PIN_HBRIDGE_1A, OUTPUT);
pinMode(PIN_HBRIDGE_2A, OUTPUT);
pinMode(PIN_HBRIDGE_3A, OUTPUT);
pinMode(PIN_HBRIDGE_4A, OUTPUT);
Serial.begin(9600);
Serial.print("Hail!");
BotStop();
}
void loop(){
handleSerial();
switch (dir) {
case 'A':
BotForward();
break;
case 'B':
BotReverse();
break;
case 'C':
BotRightTurn(radius, radius);
break;
case 'D':
BotLeftTurn(radius, radius);
break;
case 'E':
BotForwardRight(radius);
break;
case 'F':
BotForwardLeft(radius);
break;
case 'G':
BotReverseRight(radius);
break;
case 'H':
BotReverseLeft(radius);
break;
default:
BotStop();
}
}
Here is the code for basestation.
/*
Ardubot Base Station v 0.1
by Jon Heard
crow@inthecrowsnest.com
The base station code was borrowed heavily from
Tim Herzel. Much thanks to him.
The base station code reads the X,Y of the WiiChuck and analyses
the data, assigns a direction code, and then computes the radius
of the joysticks movement and maps it to values 0-255 for the PWM
of the ardubot motors.
*
* This file is an adaptation of the code by these authors:
* Tod E. Kurt
*
* The Wii Nunchuck reading code is taken from Windmeadow Labs
*
*/
#include <Wire.h>
#include <WiiChuck.h>
#include <math.h>
#define MAXANGLE 90
#define MINANGLE -90
WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;
long x;
long y;
long r;
int maxx;
int maxy;
char dir;
char dirState;
void setup() {
Serial.begin(9600);
chuck.begin();
chuck.update();
}
void loop() {
delay(20);
chuck.update();
x = (int)chuck.readJoyX() *2;
y = (int)chuck.readJoyY() *2;
if (y> 40 && -40<= x && x <= 40){
Serial.print("A");
} else {
if (y <-40 && -40 <= x && x <= 40){
Serial.print("B");
} else {
if (-40 < y && y <=40 && x >= 40){
Serial.print("C");
} else {
if (-40 < y && y <= 40 && x <= -40){
Serial.print("D");
} else {
if (y >= 40 && x>= 40){
Serial.print("E");
} else {
if (y >= 40 && x<-40){
Serial.print("F");
} else {
if (y < -40 && x >= 40){
Serial.print("G");
} else {
if (y < -40 && x < -40){
Serial.print("H");
} else {
Serial.print("I");
}
}
}
}
}
}
}
}
r = sqrt(sq(x) + sq(y));
r = map(r,0,220,0,255);
Serial.print(",");
Serial.println(r);
}
Initial results:
Control is good. I'm able to drive it around my house no problem. Battery life hasn't been tested and will be addressed at a later time.
Future improvements:
Addition of sensors, possibility of automation.
Possibly of a readout on the base station for the sensors.
Comments, Questions and Suggestions are welcome.