The
Ardubot PCB from
Sparkfun can be viewed as a
rather exotic Arduino shield. The
Arduino is placed upside down on top of the PCB, making it the brain of
a bot platform with lots of possibilities. The construction of the bot
itself is quite straightforward, as explained in the
tutorial, even
though the tutorial shows the now retired PCB. The new PCB adds some
nice features and fixes some annoying problems. But when the
construction work is finished, then what? The bot doesn't DO anything !
And no example software? My first desire was to get the motors running.
There seems to be some confusion concerning which motor is left and
which is right, but if we decide that the front of the bot is where the
the metal ball caster is, then what is left and what is right becomes
obvious. Turn the bot upside down and the naming of the motors should be
as on the picture below. We want to be able to control both direction
and speed for each motor individually. Motor direction is controlled by
giving the motor driver
chip the proper HIGH or LOW signals on its inputs, see the datasheet
for this chip. Controlling motor speed is something else since in this
particular construction, the motor driver chip has both its enable pins
connected to +5V and thus out of reach for a PWM signal. The speed
control problem can be solved by giving a PWM signal to one of the
inputs of the motor driver chip instead, see example below. When we want
the motor to change direction, we change the destination of the PWM
signal accordingly.
/*
(Copy and paste)
Sparkfun Ardubot
Basic control of speed and direction, march 12. 2011
The right motor is controlled by digital pins 9 and 6,
the left by digital pins 5 and 3.
The motor driver chip has both its enable pins connected to +5V,
normally these pins should be connected to a PWM signal
for speed control.
PWM motor speed control is still possible, see below.
*/
const byte right1 = 9; // Right motor control 1
const byte right2 = 6; // Right motor control 2
const byte left1 = 5; // Left motor control 1
const byte left2 = 3; // Left motor control 2
Now the Ardubot can actually do something,
but we want it to do more! There is room in the front section of the
ardubot for a small breadboard, a place for sensors of all kinds. Feed
the Arduino with sensor signals, let the programmed Arduino decide what
to do and make the Ardubot react (sense - think - act).
But how about a remotely controlled Ardubot? The wireless Nunchuck
gamecontroller for Nintendo Wii is perfect for this, easily available
and cheap. Place a
WiiChuck adapter in the receiver unit and connect it to the Arduino
as described below. Turn it on (red LED lit) and you have full remote
control of both speed and direction. The Nunchuck "Z"-button toggles
between standard joystick control and accelerometer control (blue LED
lit). Have fun!
/*
(Copy and paste)
Arduino UNO / Arduino 1.0.1
Sparkfun Ardubot + Nunchuck adapter + wireless Nunchuck controller from
Logic3
Adapted from :
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1259091426
Right motor is controlled by pin 9 and pin 6,
Left motor is controlled by pin 5 and pin 3
Nunchuck receiver power is connected to Arduino +3.3v and GND
SDA (data line) is connected to Arduino analog input pin 4,
SCL (clock line) is connected to Arduino analog input pin 5.
Button "Z" is used to switch between joystick (default) control and
accelerometer control
// read out a Wii Nunchuck controller
// adapted to work with wireless Nunchuck controllers of third party
vendors by Michael Dreher <michael@5dot1.de>
// use "The New Way" of initialization
<http://wiibrew.org/wiki/Wiimote#The_New_Way>
nunchuck_init(0); // send the initialization handshake
}
// params:
// timeout: abort when timeout (in ms) expires, 0 for unlimited timeout
// return: 0 == ok, 1 == timeout
byte nunchuck_init (unsigned short timeout)
{
byte rc = 1;
unsigned long time = millis();
do
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR); // transmit to device
0x52
Wire.write (0xF0); // sends memory address
Wire.write (0x55); // sends data.
if(Wire.endTransmission() == 0) // stop transmitting
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR); // transmit to device
0x52
Wire.write (0xFB); // sends memory address
Wire.write (0x00); // sends sent a zero.
if(Wire.endTransmission () == 0) // stop transmitting
{
rc = 0;
}
}
}
while (rc != 0 && (!timeout || ((millis() - time) < timeout)));
return rc;
}
void clearTwiInputBuffer(void)
{
// clear the receive buffer from any partial data
while( Wire.available ())
Wire.read ();
}
void send_zero ()
{
// I don't know why, but it only works correct when doing this exactly 3
times
// otherwise only each 3rd call reads data from the controller (cnt will
be 0 the other times)
for(byte i = 0; i < 3; i++)
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR); // transmit to device
0x52
Wire.write (0x00); // sends one byte
Wire.endTransmission (); // stop transmitting
//delay(1);
}
}
void loop (){
delay (100);
send_zero (); // send the request for next bytes
Wire.requestFrom (WII_NUNCHUCK_TWI_ADR, WII_TELEGRAM_LEN); // request
data from nunchuck
for (cnt = 0; (cnt < WII_TELEGRAM_LEN) && Wire.available (); cnt++)
{
outbuf[cnt] = Wire.read (); // receive byte as an integer
}
// debugging
clearTwiInputBuffer();
// If we received the 6 bytes, then use them ...
if (cnt >= WII_TELEGRAM_LEN){
button_state = bitRead(outbuf[5], 0); // Read input value
if (button_state == 0) { // Check if Z-button is pressed
// Yes, input is 0
// If LED is on, turn it off
// If LED is off, turn it on
if ((led_state == 0) && (change == 0)){
digitalWrite(13, HIGH); // turn LED ON, accel control
led_state = 1;
change = 1; // Set change, prevent new change
}
if ((led_state == 1) && (change == 0)){
digitalWrite(13, LOW); // turn LED OFF, joystick control
led_state = 0;
change = 1; // Set change, prevent new change
}
}
else { // Z-button released,
change = 0; // input is HIGH again, reset change,
} // allow new change