4 June 07

Error handling on the iRobot Create is a fun challenge. Even if you wrote your robot code in C++ and threw exceptions all over the place, you’d still need some way to communicate thos exceptions via the machine.

I wrote a little error function that stops the robot dead in its tracks, and alerts me to whatever kind of error I’ve got. It’ great for debugging, and to avoid sending bad data to the Open Interface.

What could go Wrong?

First, I define some error codes:

#define ERROR_LEFT_VELOCITY_TOO_LOW 0
#define ERROR_LEFT_VELOCITY_TOO_HIGH 1
#define ERROR_RIGHT_VELOCITY_TOO_LOW 2
#define ERROR_RIGHT_VELOCITY_TOO_HIGH 3
#define MAX_ERROR_CODE 16

That MAX_ERROR_CODE definition is there in case some part of the program tries to raise an error that I’m not prepared to deal with, as we’ll see.

Right now, I only want 4-bit error codes, but I could expand that later in the project if I needed to.

Beep!

The error function itself looks like this: (and I know some of the comments are getting eaten on the right, sorry about that).

void error(unsigned char error_code){
	signed char i;
	//stop driving
  drive(0,0);
  
	//play the error song
	byteTx(CmdPlay);
  byteTx(ERROR_SONG);
	
  if(error_code < MAX_ERROR_CODE){
		while(1)
		{
			for(i=3; i >= 0; i--){
			  //blink red for each 0 bit and amber for each 1 bit
				
				//do the bit
				byteTx(CmdLeds);
				byteTx(0x00);
				if(error_code & (1 << i)){
				  byteTx(24);
				}
				else{
				  byteTx(255);
				}
				byteTx(64);
				
				//wait
				delayAndUpdateSensors(300);
				
				//led off
				byteTx(CmdLeds);
				byteTx(0x00);
				byteTx(0);
				byteTx(0);
				
				//wait
				delayAndUpdateSensors(300);
			}
			//wait 1 second untill next repetition
			delayAndUpdateSensors(1000);
		}
  }
	else{
		
		//need to flesh this out; at the moment, if an error occurs, just set the led
		byteTx(CmdLeds);
		byteTx(0x00);
		byteTx(255);
		byteTx(64);
	}

  return;
}

I stop the robot, and then play a song so I know something bad happened. The song I defined is pretty ominous. A hint for the non-musical: this is a good place for tritones.

Here’s where the MAX_ERROR_CODE comes in to play. If for some reason the part of the program that called error tried to send an error that’s too large. I just hold a steady red LED.

If the error code is good, I leave the robot stuck, and flash the iRobot Create's power LED in a binary representation of the error code. Amber for 1, red for 0.

Raising an Error

Here’s my drive function, currently the only place error might be called from:

void drive(int16_t right_velocity, int16_t left_velocity)
{
	//nb - this is changed from the default drive command to control each wheel independantly

  //check for valid input - mins and maxes defined by iRobot
  if(left_velocity < -500){
    return error(ERROR_LEFT_VELOCITY_TOO_LOW);
  }else if(left_velocity > 500){
    return error(ERROR_LEFT_VELOCITY_TOO_HIGH);
  }else if(right_velocity < -500){
    return error(ERROR_RIGHT_VELOCITY_TOO_LOW);
  }else if(right_velocity > 500){
    return error(ERROR_RIGHT_VELOCITY_TOO_HIGH);
  }
  
  byteTx(CmdDriveWheels);
  byteTx((uint8_t)((right_velocity >> 8) & 0x00FF));
  byteTx((uint8_t)(right_velocity & 0x00FF));
  byteTx((uint8_t)((left_velocity >> 8) & 0x00FF));
  byteTx((uint8_t)(left_velocity & 0x00FF));

}

I do some quick checking of the input parameter before sending them to the motors, and that’s all!

Comments:

Textile Help