StirFry the Robot

StirFry is a simple autonomous robot based on the ATMega32 RISC Microcontroller from Atmel.

Complete parts list:


  • Sharp GP2D12 Infrared Ranger (x3)
  • Embmega32 Development Board from Futurlec (with programming cable).
  • Pololu Dual Serial Motor Controller
  • Solarbotics GM7 Motor (x2) with wheels (x2)
  • Acrylic sheet from TAP Plastics.
  • Solderless breadboard from Radio Shack.
  • Screws and spacers from Ace Hardware.
  • 2 CDS cells, two resistors (around 4.7kΩ), wire.
  • 6 NiMh AA batteries with connectors.
  • Tamiya ball caster.
  • 7845 5V regulator

Construction

Construction is simple. No soldering required if you buy the serial motor controller as a built unit. (I used a tiny bit of soldering to connect the wires from the batteries but it wasn't strictly necessary as I could have used the breadboard.)

The base is built from acrylic sheet. $1/lb from the scrap bin. Cut to shape by scoring the plastic and snapping it. I used a drill (Dremel) to make holes for screws. To hold everything together I used screws, and hot glue. This means that StirFry can be mostly diassembled if needed. However one or two parts needed to be held in place securely and for that I used Gorilla Glue.

Power

6 NiMh batteries. I used the new 15 minute recharge type available from just about anywhere. I use a 7845 5V regulator to provide power to the microcontroller and sensors. The motor controller gets power directly from the batteries as it has its own regulator. I ought to have placed some capacitors across the regulator but everything is well behaved without - even with the microcontroller running at 16MHz.

Sensors

For detecting light StirFry uses photocells arranged in series with a 4.7kΩ resistor as part of a potential divider with the ADC measuring the voltage across the photocell. The infrared sensors output a value that is a non-trivial function of distance. The closer the target the higher the output voltage and it shoots up rapidly as the target gets closer. The ATMega32 has 8 analogue inputs. That was one reason for choosing this particular device. The sensers just hook in directly to the terminals on the microcontroller board.

Motors

The motors are controlled by the Pololu serial motor controller. The ATMega32 has a serial port and this is simply hooked directly to the motor controller. The controller automatically senses baud rate. By hooking my PC to the serial pins on the board I could also view debugging info in a terminal emulator. The motor controller is connected directly to the ATMega32 output (pin 1 on PORTD) but the PC goes via a MAX232 on the board to ensure correct RS232 voltage levels. Pin 4 on PORTD is used to reset the motor controller and connects to the reset pin on that.

Programming

Using AVR-GCC under Windows XP. The ATMega32 has 32K of program space as well as 2K of RAM - plenty for programming in C or C++. In anticipation of doing some complicated development I used floating point arithmetic throughout the code. The required floating point routines provided by the gcc libraries all fit in 32K.

My goal was to make a light seeking obstacle avoiding robot. After playing with many fairly complex algorithms I eventually found an simple algorithm in the style of Braitenberg's

that behaves remarkably intelligently. Consider the input values from the ADCs to be in the range [0,1] and the motor output to be in the range [-1,1]. Then define

preference = 3*(leftRanger-rightRanger)-3*(leftEye-rightEye)
which is a measure of preference for turning right or left. The basic method is to drive the motors by

leftMotor = 0.5+0.5*preference

rightMotor = 0.5-0.5*preference
With these simple rules the robot is pretty smart. Some extra details are required to make things work well: I filter the inputs from all of the analogue-to-digital converters to eliminate spurious spikes. I used a very simply filter: at each step the output is the average of its previous value and the current input. So if adc(n) reads the input from ADC n and output is the filtered output then the algorithm is simply:

output = 0.5*(adc(n)+output)
I also applied a threshold to the input from the infrared rangers. If the input is less than 0.15 it is set to zero. Without this it is sensitive to obstacles that are far enough away they are safe enough to ignore. I also clamped things to sensible ranges to make sure the robot didn't travel backwards. One extra thing needed to be added: this doesn't deal with head on collisions. If the front infrared sensor shows that something is within range the robot simply backs up and turns a bit. The direction of turn comes from the preference variable. the preference variable can be viewed like a 4 input neuron in a neural network with weights 3,-3,3,-3. With those weights this robot can seek out a light source even when its path is littered with objects. It seems to intelligently work its way around and between them.

Code

Here is the main loop from the code demonstrating its simplicity.

/*
 * Main loop
 */
float ldist = 0,cdist = 0,rdist = 0;
float leye = 0,reye = 0;

for (;;) {
	ldelay(100);
	ldist = (ldist+adc(LEFT))*0.5f;
	cdist = (cdist+adc(CENTRE))*0.5f;
	rdist = (rdist+adc(RIGHT))*0.5f;
	leye = (leye+adc(LEYE))*0.5f;
	reye = (leye+adc(REYE))*0.5f;
	float l = threshold(0.15f,ldist);
	float r = threshold(0.15f,rdist);
	float pref = 3*(l-r)-3*(leye-reye);

	if (cdist>0.2) {
		set_motor(0,0);
		ldelay(500);
		if (pref>0) {
			set_motor(-0.5f,-1.0f);
		} else {
			set_motor(-1.0f,-0.5f);
		}
		ldelay(400);
	} else {
		set_motor(
				0.5f+sigma(pref,0.5f),
				0.5f+sigma(-pref,0.5f)
			 );
	}
}

Downloads

Video

Code

Contact

Feel free to email me (Dan Piponi) at stirfry (at) sigfpe.com.
Back to Robotics. Back to Home.