Introduction: Arduino, Mini Sonar Robot

About: Programmer, Arduino Fan

In this project I want to make a mini-sonar robot with arduino pro mini. Sonar or ultrasonic sensors work on a principle similar to radar or sonar, which evaluate attributes of a target by interpreting the echoes from radio or sound waves respectively. Active ultrasonic sensors generate high frequency sound waves and evaluate the echo which is received back by the sensor, measuring the time interval between sending the signal and receiving the echo to determine the distance to an object.
I've used a HC-SR04 sensor which is one of the cheapest price in this type. It has 4 pins Vcc 5V, Gnd and two other pins for trigger (out) and echo (in). The mechanism is simple, some wave triggers, the echo receives.

Needed parts:

  • 1x Arduino Pro mini
  • 1x Sonar sensor SR-04 (low price)
  • 2x Two-wheels gearbox pack + dc motor 3V~6V
  • 4x Plastic wheels
  • 1x Plastic box (depends on gearbox size)
  • 2x Double Battery pack AA
  • 4x Battery AA (Rechargeable is suggested)
  • 1x Mini speaker
  • 1x LED
  • 1x Resistor 470 ohm
  • 1x L293D IC
  • 1x IC Socket 16 pins
  • 2x Pin header (both F & M type)
  • 1x Mini switch
  • 1x Fiber board Wires + Soldering iron + cutting pliers + Superglue

Let me start the project with mechanical structure.

Step 1: Robot Body

Find a plastic box depend on the size of the gearbox pack. I've used an earphone box (2 pieces). Use the superglue to attach the parts as shown in the image.

Step 2: Circuit

Make the circuit as mentioned in the image. Someone may wants to depart the power supply of the motor and the logic (micro, ic, ...).

Actually it's recommended to have separate power supplies for the logic and high consuming part (electromechanical devices like as motors), but I think it's not so important for the low power arduino like as Pro-mini. At the other hand, having just 4 batteries, you can't do any other approach.

Step 3: Code

I've tried to write the code easy enough to be plain for the beginners too. But if you have any problems, questions and may suggestions, I like to know.
Some hints:

  • Minimum distance is the stopping distance to prevent crash. The best distance from any block to stop the robot, is depends on the gearbox speed.
  • Robot comes back to max distance.
  • backDist and turnDist should be customized depend on the robot speed.
  • A random behavior including a stop, melody and random movement has used.

//******************************

//* By: http://blog.mshams.ir *

//******************************

//pin numbers

const byte pinMotor1=4, pinMotor2=5, pinMotor3=6, pinMotor4=7;

const byte pinLed=8, pinTone=10, pinSonar1=11, pinSonar2=12;

//sound freq

const int toneFreq = 800;

//sonar distances

const byte minDistance = 45, maxDistance = 1000;

//motor states

const byte M_STOP = 0, M_GO = 1, M_BACK = 2, M_RIGHT = 3, M_LEFT = 4, M_RIGHT2X = 5, M_LEFT2X = 6;

//robot states

const byte R_START = 0, R_DRIVE = 1, R_BLOCK = 2, R_TURN = 3;

//detect hangover

const int hangoverWait = 5000;

//block detect go back

const int backDist = 1000, turnDist = 300;

//random behaviour

const int randomChance = 300, randomStopWait = 10000, randomTurnWait = 200;

byte state = R_START;

int i, counter = 0;

int dist;

void setup() {

randomSeed(analogRead(1));

//init motor pins

pinMode(pinMotor1, OUTPUT);

pinMode(pinMotor2, OUTPUT);

pinMode(pinMotor3, OUTPUT);

pinMode(pinMotor4, OUTPUT);

pinMode(pinSonar1, OUTPUT);

pinMode(pinSonar2, INPUT);

//init LED pin

pinMode(pinLed, OUTPUT);

}

void loop() {

switch (state){

case R_START:

Motor(M_GO);

Melody();

state = R_DRIVE;

break;

case R_DRIVE:

dist = Pingu();

if (dist < minDistance){

Motor(M_STOP);

state = R_BLOCK;

}

else if (random(0, randomChance) == 5) {

RandomTone();

Motor(M_STOP);

delay(randomStopWait);

Motor(random(M_BACK, M_LEFT2X+1));

delay(randomTurnWait);

Motor(M_GO);

}

break;

case R_BLOCK:

Beep();

Motor(M_BACK);

delay(backDist);

Motor(random(M_RIGHT2X, M_LEFT2X+1));

delay(turnDist);

state = R_TURN;

break;

case R_TURN:

dist = Pingu();

if (dist >= maxDistance){

Motor(M_STOP);

Motor(M_GO);

Beep();

state = R_DRIVE;

}

else{

counter +=1;

if (counter >= hangoverWait){

counter = 0;

Motor(M_STOP);

RandomTone();

state = R_BLOCK;

}

}

break;

}

}

void Blink(byte state){

digitalWrite(pinLed, state);

}

void Beep(){

Blink(1);

SpeakTone(2);

SpeakTone(1);

Blink(0);

}

void Melody(){

Blink(1);

for (int i=1; i<10; i++){

SpeakTone(i);

}

Blink(0);

}

void RandomTone(){

Blink(1);

for (int i=1; i<10; i++){

SpeakTone(random(1, 10));

}

Blink(0);

}

void SpeakTone(byte note){

tone(pinTone, toneFreq * note);

delay(100);

noTone(pinTone);

}

void Motor(byte state){

byte m1, m2, m3, m4;

switch (state){

case M_STOP:

m1 = m2 = m3 = m4 = LOW;

break;

case M_GO:

m1=HIGH;

m2=LOW;

m3=HIGH;

m4=LOW;

break;

case M_BACK:

m1=LOW;

m2=HIGH;

m3=LOW;

m4=HIGH;

break;

case M_RIGHT:

m1=HIGH;

m2=LOW;

m3=LOW;

m4=LOW;

break;

case M_LEFT:

m1=LOW;

m2=LOW;

m3=HIGH;

m4=LOW;

break;

case M_RIGHT2X:

m1=HIGH;

m2=LOW;

m3=LOW;

m4=HIGH;

break;

case M_LEFT2X:

m1=LOW;

m2=HIGH;

m3=HIGH;

m4=LOW;

break;

}

digitalWrite(pinMotor1, m1);

digitalWrite(pinMotor2, m2);

digitalWrite(pinMotor3, m3);

digitalWrite(pinMotor4, m4);

}

int Pingu(){

digitalWrite(pinSonar1, LOW);

delayMicroseconds(5);

digitalWrite(pinSonar1, HIGH);

delayMicroseconds(5);

digitalWrite(pinSonar1, LOW);

delayMicroseconds(2);

long duration = pulseIn(pinSonar2, HIGH);

return (duration / 29 /2);

}