Sphero RVR and Arduino Uno autonomous robot combination

Fully control Sphero RVR with just an Arduino Uno and the HC SR04 ultra-sonic range finder.

With the below code, the robot will look for an obstacle closer than 30 cm. If one is found, the robot will turn 90 degrees and check again. If again there is an obstacle, the robot will move to 270 degrees to try and find a clear route. If this way is also blocked, the robot will move to 180 to try and find a solution.

#include <SpheroRVR.h>
const int pingPin = 7; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 6;
long duration, inches, cm;
void setup() {
rvr.configUART(&Serial);
}
void searching() {
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
}
void loop() {
// reset the heading to zero
rvr.resetYaw();
searching();
if (cm < 30)
{
rvr.driveWithHeading(0, 90, static_cast(DriveFlags::none));
delay(2000);
searching();
if (cm < 30)
{
rvr.driveWithHeading(0, 270, static_cast(DriveFlags::none));
delay(2000);
}
else
{
rvr.driveWithHeading(0, 180, static_cast(DriveFlags::none));
delay(2000);
}
}
else {
rvr.driveWithHeading(34, 0, static_cast(DriveFlags::none));
delay(2000);
}
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}

In the above video compilation, my RVR is also using an 8by8 red LED matrix I bought from AZ delivery. I found an awesome and very helpful example code for this matrix that does NOT use a library, as unfortunately the LED-control library was not compatible with the Sphero RVR library. Or at least I couldn’t make it work anyway, although I am far from an expert.

I integrated this LED matrix example code, with the above movement code, so that when Sphero RVR detects a clear path, the heart beats brighter.

The code now looked like this:

#include
int DIN_PIN = 8; // data in pin
int CS_PIN = 9; // load (CS) pin
int CLK_PIN = 10; // clock pin
byte MAXREG_DECODEMODE = 0x09;
byte MAXREG_INTENSITY = 0x0a;
byte MAXREG_SCANLIMIT = 0x0b;
byte MAXREG_SHUTDOWN = 0x0c;
byte MAXREG_DISPTEST = 0x0f;
const unsigned char heart[] =
{
B01100110,
B11111111,
B11111111,
B11111111,
B01111110,
B00111100,
B00011000,
B00000000
};
int INTENSITYMIN = 0; // minimum brightness, valid range [0,15]
int INTENSITYMAX = 8; // maximum brightness, valid range [0,15]
const int pingPin = 7; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 6;
long duration, inches, cm;
void setup() {
// set up communication with the RVR
rvr.configUART(&Serial);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(DIN_PIN, OUTPUT);
pinMode(CLK_PIN, OUTPUT);
pinMode(CS_PIN, OUTPUT);
delay(50);
setRegistry(MAXREG_SCANLIMIT, 0x07);
setRegistry(MAXREG_DECODEMODE, 0x00); // using an led matrix (not digits)
setRegistry(MAXREG_SHUTDOWN, 0x01); // not in shutdown mode
setRegistry(MAXREG_DISPTEST, 0x00); // no display test
setRegistry(MAXREG_INTENSITY, 0x0f & INTENSITYMIN);
// draw heart
setRegistry(1, heart[0]);
setRegistry(2, heart[1]);
setRegistry(3, heart[2]);
setRegistry(4, heart[3]);
setRegistry(5, heart[4]);
setRegistry(6, heart[5]);
setRegistry(7, heart[6]);
setRegistry(8, heart[7]);
setRegistry(MAXREG_SHUTDOWN, 0x01);
setRegistry(MAXREG_INTENSITY, 0x0f & INTENSITYMIN);
}
void searching() {
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(10);
digitalWrite(pingPin, LOW);
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
cm = microsecondsToCentimeters(duration);
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
}
void setRegistry(byte reg, byte value)
{
digitalWrite(CS_PIN, LOW);
putByte(reg); // specify register
putByte(value); // send datadigitalWrite(CS_PIN, LOW);
digitalWrite(CS_PIN, HIGH);
}
void putByte(byte data)
{
byte i = 8;
byte mask;
while (i > 0)
{
mask = 0x01 << (i - 1); // get bitmask
digitalWrite( CLK_PIN, LOW); // tick
if (data & mask) // choose bit
digitalWrite(DIN_PIN, HIGH); // send 1
else
digitalWrite(DIN_PIN, LOW); // send 0
digitalWrite(CLK_PIN, HIGH); // tock
--i; // move to lesser bit
}
}
void loop() {
// reset the heading to zero
rvr.resetYaw();
setRegistry(MAXREG_INTENSITY, 0x0f & INTENSITYMIN);
searching();
if (cm < 30)
{
rvr.driveWithHeading(0, 90, static_cast(DriveFlags::none));
delay(2000);
searching();
if (cm < 30)
{
rvr.driveWithHeading(0, 270, static_cast(DriveFlags::none));
delay(2000);
}
else
{
rvr.driveWithHeading(0, 180, static_cast(DriveFlags::none));
delay(2000);
}
}
else {
setRegistry(MAXREG_INTENSITY, 0x0f & INTENSITYMAX);
delay(500);
rvr.driveWithHeading(34, 0, static_cast(DriveFlags::none));
delay(2000);
}
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}

One key point is that for the outdoor videos, I had to change the speed to 64 as otherwise it was a little too slow in longer grass and woodland tracks. The speed for using the robot inside is set at just 34 as I only have a small space to work in. The maximum speed number you can use for the Sphero RVR is 250!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s