I have built a robot with another board I designed just for robots that has the same functionality as the Robot Builder's Shield. The difference between this special board called the uBotino and the RBS are:
- uBotino has only 5 servo connectors instead of 6
- pin D8 goes to the H-bridge instead of pin D4
- uBotino has an extra digital sensor connector, pin D4
The robot has the following features:
- digital bumper sensors on pins D18 and D19
- digital ultrasonic sensor on pin D14
- digital IR remote sensor on pin D15
- panning sevo on pin D9
- 2 geared motors (pins D5-D8)
- speaker on pin D4
- IR remote control for driving and to play a song
- autonomous object avoidance
Here is a video of the robot:
Here is the code (divided in 2 parts):
// Bot4Julia, a simple Start Here style robot, made with 2 CDs,
// 2 GM17 motors and wheels, one servo, one SeeedStudio US sensor,
// one battery box, one uBotino board
//
// uBotino board pinout:
//
// uBotino Funct Arduino ATmega168 Arduino Funct uBotino
// +-----\/----+
// Reset 1| PC6 PC5 |28 D19 A5 SCL RightBumper
// Rx D0 2| PD0 PC4 |27 D18 A4 SDA LeftBumper
// Tx D1 3| PD1 PC3 |26 D17 A3
// Int0 D2 4| PD2 PC2 |25 D16 A2
// Int1 D3 5| PD3 PC1 |24 D15 A1 IR sensor
// Spk D4 6| PD4 PC0 |23 D14 A0 Ping
// 7| VCC GND |22
// 8| GND AREF |21
// Xtal 9| PB6 AVCC |20
// Xtal 10| PB7 PB5 |19 D13 SCK LED
// M1A OC0B D5 11| PD5 PB4 |18 D12 MISO
// M2A OC0A D6 12| PD6 PB3 |17 D11 OC2A MOSI
// M2B D7 13| PD7 PB2 |16 D10 OC1B
// M1B D8 14| PB0 PB1 |15 D 9 OC1A Pan servo
// +-----------+
//
#include <Servo.h>
#include <Speaker.h>
//Inputs/outputs
//#define Encoder_1_ChA 2 // digital pin 2 // Right Encoder
//#define Encoder_2_ChA 3 // digital pin 3 // Left Encoder
#define Motor_1_PWM 5 // digital pin 5 // Right Motor
#define Motor_1_Dir 8 // digital pin 8
#define Motor_2_PWM 6 // digital pin 6 // Left Motor
#define Motor_2_Dir 7 // digital pin 7
#define PingPin 14 // digital pin 14 (analog pin 0)
#define IR_Pin 15 // digital pin 15 (analog pin 1)
#define LeftBumper 18
#define RightBumper 19
#define PanPin 9
#define SpeakerPin 4
#define LedPin 13
#define center 90
// Remote control buttons
#define btnPower 149
#define btnMute 148
#define btnPrevCh 187
#define btnDown 145
#define btnUp 144
#define btnLeft 147
#define btnRight 146
#define btnPlay 1434
#define btnStop 1432
#define btnRecord 1437
#define btnPause 1433
#define btnRew 1435
#define btnFwd 1436
#define btnInfo 186
#define btnSleep 182
#define btnInput 165
#define btnEnter 139
#define btn0 137
#define btn1 128
#define btn2 129
#define btn3 130
#define btn4 131
#define btn5 132
#define btn6 133
#define btn7 134
#define btn8 135
#define btn9 136
//Variables
byte dir=0;
byte speed1=230;
byte speed2=255;
int turn90=400;
int turn45=200;
int stopTime=200;
int USdistance=0;
int treshold=20; //20cm min distance
// remote control variables
#define start_bit 2200 // Start bit threshold (Microseconds)
#define bin_1 1000 // Binary 1 threshold (Microseconds)
#define bin_0 400 // Binary 0 threshold (Microseconds)
Servo Pan;
Speaker speaker = Speaker(SpeakerPin);
//-----------------------------------------------------------------------------
void setup() {
// set motor pins as output and LOW so the motors are breaked
pinMode(Motor_1_PWM, OUTPUT);
pinMode(Motor_1_Dir, OUTPUT);
pinMode(Motor_2_PWM, OUTPUT);
pinMode(Motor_2_Dir, OUTPUT);
Stop();
pinMode(IR_Pin, INPUT); // uses an analog pin so it has to be declared as digital in
pinMode(PingPin, OUTPUT);
digitalWrite(PingPin, LOW);
pinMode(LeftBumper, INPUT);
digitalWrite(LeftBumper, HIGH); //turn on pull ups
pinMode(RightBumper, INPUT);
digitalWrite(RightBumper, HIGH); //turn on pull ups
Pan.attach(PanPin);
Pan.write(center); //90
StepDelay();
pinMode(SpeakerPin, OUTPUT);
speaker.Beep();
pinMode(LedPin, OUTPUT);
digitalWrite(LedPin, LOW);
Serial.begin (19200);
Serial.println("start");
Forward();
}
void loop(){
Drive();
Get_IR_Command();
//square();
}
void Get_IR_Command() {
int key = getIRKey(); //Fetch the key
Serial.print("Key ");
Serial.println(key);
switch (key) {
case btnLeft:
Left();
delay(turn45);
Stop();
break;
case btnRight:
Right();
delay(turn45);
Stop();
break;
case btnUp:
Forward();
break;
case btnDown:
Reverse();
break;
case btnStop:
Stop();
break;
case btnMute:
speaker.PlayMelody();
break;
}
//StepDelay();
return;
}
//--------------------------
int getIRKey() {
int data[12];
int newdata=pulseIn(IR_Pin, LOW, 100000);
while(newdata>0 && newdata<start_bit) { //Wait for a start bit
newdata=pulseIn(IR_Pin, LOW, 100000);
}
if (newdata==0) return 0;
for(int i=0;i<11;i++){
data[i] = pulseIn(IR_Pin, LOW, 100000); //Start measuring bits, we only want low pulses
}
speaker.Beep();
for(int i=0;i<11;i++) { //Parse them
if(data[i] > bin_1) { //is it a 1?
data[i] = 1;
} else {
if(data[i] > bin_0) { //is it a 0?
data[i] = 0;
} else {
data[i] = 2; //Flag the data as invalid; I don't know what it is!
}
}
}
for(int i=0;i<11;i++) { //Pre-check data for errors
if(data[i] > 1) {
return -1; //Return -1 on invalid data
}
}
int result = 0;
int seed = 1;
for(int i=0;i<11;i++) { //Convert bits to integer
if(data[i] == 1) {
result += seed;
}
seed = seed * 2;
}
return result; //Return key number
}
void square(){
Forward();
delay(2000);
Stop();
delay(stopTime);
Right();
delay(turn90);
Stop();
delay(stopTime);
Forward();
delay(2000);
Stop();
delay(stopTime);
Right();
delay(turn90);
Stop();
delay(stopTime);
Forward();
delay(2000);
Stop();
delay(stopTime);
Right();
delay(turn90);
Stop();
delay(stopTime);
Forward();
delay(2000);
Stop();
delay(stopTime);
Right();
delay(turn90);
Stop();
delay(stopTime);
}
void Drive(){
if (digitalRead(LeftBumper)==LOW){
digitalWrite(LedPin, HIGH);
Stop();
speaker.Beep();
StepDelay();
digitalWrite(LedPin, LOW);
Reverse();
StepDelay();
Stop();
StepDelay();
Right();
delay(turn45); //turn45
Stop();
StepDelay();
Forward();
}
if (digitalRead(RightBumper)==LOW){
digitalWrite(LedPin, HIGH);
Stop();
speaker.Beep();
StepDelay();
digitalWrite(LedPin, LOW);
Reverse();
StepDelay();
Stop();
StepDelay();
Left();
delay(turn45); //turn45
Stop();
StepDelay();
Forward();
}
USdistance=Read_Ping_Sensor();
Serial.print("USdistance ");
Serial.println(USdistance);
if (USdistance<10){
Stop();
speaker.Beep();
StepDelay();
TurnAround();
}
if (USdistance<treshold){
Stop();
speaker.Beep();
StepDelay();
Avoid();
Forward();
}
delay(50);
}
void TurnAround(){
Reverse();
Pan.write(center);
StepDelay();
Stop();
Left();
delay(turn90);
delay(turn90);
Stop();
StepDelay();
Forward();
}
void Avoid(){
int prev=0;
dir=2;
for (byte i=0; i<5; i++){
Pan.write(i*45);
StepDelay();
StepDelay();
USdistance=Read_Ping_Sensor();
if (USdistance>prev){
dir=i;
prev=USdistance;
}
}
Pan.write(center);
StepDelay();
switch (dir){
case 0:
Right();
delay(turn90);
Stop();
speaker.Beep();
StepDelay();
break;
case 1:
Right();
delay(turn90); //turn45
Stop();
speaker.Beep();
StepDelay();
break;
case 2:
Forward();
break;
case 3:
Left();
delay(turn90); //turn45
Stop();
speaker.Beep();
StepDelay();
break;
case 4:
Left();
delay(turn90);
Stop();
speaker.Beep();
StepDelay();
break;
}
delay(500);
}
// Read Sensors
int Read_Ping_Sensor(){
//digitalWrite(LedPin, HIGH);
int cm=0;
//trigger the sensor
unsigned long value = 0;
pinMode(PingPin, OUTPUT);
digitalWrite(PingPin, LOW);
delayMicroseconds(2);
digitalWrite(PingPin, HIGH);
delayMicroseconds(10);
digitalWrite(PingPin, LOW);
//receive the echo
pinMode(PingPin, INPUT);
digitalWrite(PingPin, HIGH); // turn on pull up resistor
value = pulseIn(PingPin, HIGH);
value=value/58;
cm=int(value);
//digitalWrite(LedPin, LOW);
return cm;
}
void StepDelay() {
for (byte t=0; t<10; t++){
//SoftwareServo::refresh();
delay(20);
}
}