The tank is entirely made from SparkFun parts:
Arduino
Ardumoto
Dual Motor GearBox
Stackable Arduino Headers
Super Awesome Tank Treads
LiPoly Battery Charger
Batteries
Small Solar Panel
XBees
XBee USB board
XBee Explorer board
Also used a number of misc jumper wires, rubber bands, a block of wood and a few small pieces of aluminum (from the back of a PC).
Of course you will need an iPhone to get everything running exactly as I have setup, but you don't need to use an iPhone to control your tank, you could use a midi controller, a multi-touch screen, a random hardware controller, or really anything that can send serial, OSC or anything into Processing.
Here is the Source Code:
Source code for Arduino is from a Mechomaniac.com:
//-----------Start Arduino code ---------------
// Test program for SparkFun Ardumoto board
// Copyright (c) 2009 mechomaniac.com
// To use, connect the Arduino to a computer and send commands using a serial terminal.
// eg AR40# motor A forwards with a speed of 40
#define PwmPinMotorA 10
#define PwmPinMotorB 11
#define DirectionPinMotorA 12
#define DirectionPinMotorB 13
#define SerialSpeed 9600
#define BufferLength 16
#define LineEnd '#'
char inputBuffer[BufferLength];
void setup()
{
// motor pins must be outputs
pinMode(PwmPinMotorA, OUTPUT);
pinMode(PwmPinMotorB, OUTPUT);
pinMode(DirectionPinMotorA, OUTPUT);
pinMode(DirectionPinMotorB, OUTPUT);
Serial.begin(SerialSpeed);
}
// process a command string
void HandleCommand(char* input, int length)
{
Serial.println(input);
if (length < 2) { // not a valid command
return;
}
int value = 0;
// calculate number following command
if (length > 2) {
value = atoi(&input[2]);
}
int* command = (int*)input;
// check commands
// note that the two bytes are swapped, ie 'RA' means command AR
switch(*command) {
case 'FA':
// motor A forwards
analogWrite(PwmPinMotorA, value);
digitalWrite(DirectionPinMotorA, HIGH);
break;
case 'RA':
// motor A reverse
analogWrite(PwmPinMotorA, value);
digitalWrite(DirectionPinMotorA, LOW);
break;
case 'FB':
// motor B forwards
analogWrite(PwmPinMotorB, value);
digitalWrite(DirectionPinMotorB, LOW);
break;
case 'RB':
// motor B reverse
analogWrite(PwmPinMotorB, value);
digitalWrite(DirectionPinMotorB, HIGH);
break;
default:
break;
}
}
void loop()
{
// get a command string form the serial port
int inputLength = 0;
do {
while (!Serial.available()); // wait for input
inputBuffer[inputLength] = Serial.read(); // read it in
} while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
inputBuffer[inputLength] = 0; // add null terminator
HandleCommand(inputBuffer, inputLength);
}
//----------- End Arduino code ---------------
Processing code:
//----------- Start Processing code ----------------
import oscP5.*;
import netP5.*;
import processing.serial.*;
Serial arduinoPort;
OscP5 oscP5;
float [] fader = new float [3];
void setup() {
oscP5 = new OscP5(this,8000);
arduinoPort = new Serial(this, Serial.list()[0], 9600);
}
void oscEvent(OscMessage theOscMessage) {
String addr = theOscMessage.addrPattern();
if(addr.indexOf("/1/fader") !=-1){
String list[] = split(addr,'/');
int xfader = int(list[2].charAt(5) - 0x30);
if(theOscMessage.get(0).floatValue() !=0){
fader[xfader] = theOscMessage.get(0).floatValue();
}
}
}
void draw() {
//---------------------------------Motor A
if(fader[1] > 0.65){
arduinoPort.write("AF100#");
}
if(fader[1] < 0.35){
arduinoPort.write("AR100#");
}
//--------------------------------Motor B
if(fader[2] > 0.65){
arduinoPort.write("BF100#");
}
if(fader[2] < 0.35){
arduinoPort.write("BR100#");
}
//----------------------------stop commands
if(fader[1] < 0.65 && fader[1] > 0.35 ){
arduinoPort.write("AF0#");
}
if(fader[2] < 0.65 && fader[2] > 0.35 ){
arduinoPort.write("BF0#");
}
}
//---------------------- End Processing Code ------------------


