7. Example project: simple border-detecting sumo robot

Adding sensors to the Zumo allows it to sense and react to its surroundings. In a sumo competition where two robots try to push each other out of a circular ring, it is important for a robot to be able to detect the border of the ring so it can avoid driving over the edge. Since standard robot sumo rings are colored black with a white border around the edge, infrared reflectance sensors like our QTR sensors are great for this purpose. The Zumo Reflectance Sensor Array conveniently mounts six of these sensors in a module designed to plug directly into the front expansion header of the Zumo Shield (note: the pre-assembled version of the Zumo robot ships with this reflectance sensor array already installed).

A Zumo robot preparing to attack a Parallax SumoBot.
Zumo reflectance sensor array on a Zumo robot, bottom view.

The following example sketch demonstrates how to program an Arduino-controlled Zumo equipped with a reflectance sensor array to drive around and stay within a sumo ring. Note that it only uses the two outermost sensors on the array, which are sufficient for border detection.

First, install the Zumo Shield Libraries. Then, download and open ZumoBorderDetect.ino (2k ino) or copy the following code into a new sketch in the Arduino environment:

#include <ZumoBuzzer.h>
#include <ZumoMotors.h>
#include <Pushbutton.h>
#include <QTRSensors.h>
#include <ZumoReflectanceSensorArray.h>
 
#define LED 13
 
// this might need to be tuned for different lighting conditions, surfaces, etc.
#define QTR_THRESHOLD  1500 // microseconds
  
// these might need to be tuned for different motor types
#define REVERSE_SPEED     200 // 0 is stopped, 400 is full speed
#define TURN_SPEED        200
#define FORWARD_SPEED     200
#define REVERSE_DURATION  200 // ms
#define TURN_DURATION     400 // ms
 
ZumoBuzzer buzzer;
ZumoMotors motors;
Pushbutton button(ZUMO_BUTTON); // pushbutton on pin 12
 
#define NUM_SENSORS 6
unsigned int sensor_values[NUM_SENSORS];
 
ZumoReflectanceSensorArray sensors(QTR_NO_EMITTER_PIN);

void waitForButtonAndCountDown()
{
  digitalWrite(LED, HIGH);
  button.waitForButton();
  digitalWrite(LED, LOW);
   
  // play audible countdown
  for (int i = 0; i < 3; i++)
  {
    delay(1000);
    buzzer.playNote(NOTE_G(3), 200, 15);
  }
  delay(1000);
  buzzer.playNote(NOTE_G(4), 500, 15);  
  delay(1000);
}
 
void setup()
{
  // uncomment if necessary to correct motor directions
  //motors.flipLeftMotor(true);
  //motors.flipRightMotor(true);
   
  pinMode(LED, HIGH);
   
  waitForButtonAndCountDown();
}

void loop()
{
  if (button.isPressed())
  {
    // if button is pressed, stop and wait for another press to go again
    motors.setSpeeds(0, 0);
    button.waitForRelease();
    waitForButtonAndCountDown();
  }
   

  sensors.read(sensor_values);
  
  if (sensor_values[0] < QTR_THRESHOLD)
  {
    // if leftmost sensor detects line, reverse and turn to the right
    motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED);
    delay(200);
    motors.setSpeeds(TURN_SPEED, -TURN_SPEED);
    delay(300);
    motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED);
  }
  else if (sensor_values[5] < QTR_THRESHOLD)
  {
    // if rightmost sensor detects line, reverse and turn to the left
    motors.setSpeeds(-REVERSE_SPEED, -REVERSE_SPEED);
    delay(200);
    motors.setSpeeds(-TURN_SPEED, TURN_SPEED);
    delay(300);
    motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED);
  }
  else
  {
    // otherwise, go straight
    motors.setSpeeds(FORWARD_SPEED, FORWARD_SPEED);
  }
}

You might need to edit a few things in this sketch to make it work well with your Zumo:

  • If one or both of your motors have been connected backwards, uncomment lines 48 and/or 49 to correct their directions.
  • Adjust the speeds and durations in lines 13-17. Generally, lower speeds and shorter durations should work better with faster motors, while higher speeds and longer durations should be more appropriate for slower motors. We found that these default values worked well with a Zumo using 75:1 HP motors.
  • Finally, the sensor reading threshold used to differentiate between black and white surfaces, defined on line 10, might need to be changed to suit your environment.

Upload the sketch to an Arduino mounted on a Zumo, place the Zumo on a sumo ring (or a similar large dark surface with a light border), and press the user pushbutton. Be ready to catch the Zumo in case it drives off the ring! If everything works right, the Zumo should sound a countdown with its buzzer and then start driving forward until it detects the ring border; it should then back up, turn, and continue. If not, try adjusting some of the parameters as described above. Here are some specific troubleshooting tips:

  • If the Zumo overshoots the ring border, try lowering FORWARD_SPEED (especially if it is going very fast) or reducing QTR_THRESHOLD.
  • If the Zumo stops at the border but turns too much or not enough before continuing, adjust TURN_SPEED and/or TURN_DURATION.
  • If you do not hear any sound from the buzzer, make sure you have the buzzer control jumper configured correctly for your Arduino.

The ability to wander around while staying inside a sumo ring is enough to allow a Zumo to compete as a basic sumo robot, but a more advanced robot might be able to detect its opponent and drive toward it directly. As a next step, you might consider adding more sensors, such as range finders, to allow the Zumo to find its opponent instead of relying on luck to make contact.