The project maze robot is mini sized arduino based robot which automatically find its route between the gaps of the maze. This intelligence is provide to this robot by the programming the arduino with c/c++ code. The arduino in this maze will acts brain of this robot and the LM296 driver is a dual H-Bridge motor driver which allows speed and direction control of two DC motors at the same time. The wheels are attached to the motor to activate the rotation by suppling the power from 12v battery. The battery and motors are connected LM296 driver. The direction of the wheel controlled by LM296 driver through motor.
PREREQUISITE KNOWLEDGE:
- Basic knowledge in c/c++
- `Basic of IoT
WORKING METHOD OF MAZE ROBOT
PROGRAMMING PLATFORM:
This Arduino code can be used to solve a simple maze. The code will also need to adapt from maze to maze, and it usually involves a lot of trial and error to have the robot navigate successfully.
After assembling the robot, upload the Maze solver source codeto your Arduino from the IDE.
- I have used the left side ultrasonic sensor as the supporting sensor to align the robot to the left sidewall. The robot always follows the left wall when solving the maze.
- If the front sensor detects an obstacle, the robot has to change direction immediately.
The microcontroller using in developing this maze robot is Arduino. We can programme Arduino using Arduino ide an open source platform for coding. By using simple C or C++ language we can code in Arduino ide which dumped in Arduino after successful stimulation by using the code Arduino can controls the motion and designation of robot by passing the instruction.
- SENSOR FUNCTION:
void readLFSsensors()
{
LFSensor[0] = digitalRead(lineFollowSensor0);
LFSensor[1] = digitalRead(lineFollowSensor1);
LFSensor[2] = digitalRead(lineFollowSensor2);
LFSensor[3] = digitalRead(lineFollowSensor3);
LFSensor[4] = digitalRead(lineFollowSensor4);
farRightSensor = analogRead(farRightSensorPin);
farLeftSensor = analogRead(farLeftSensorPin);
if ((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 1 )) {mode = CONT_LINE; error = 0;}
else if((LFSensor[0]== 0 )&& (farRightSensor < THRESHOLD)) {mode = RIGHT_TURN; error = 0;}
else if ((farLeftSensor < THRESHOLD) &&(LFSensor[4]== 0 )) {mode = LEFT_TURN; error = 0;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) {mode = NO_LINE; error = 0;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 1 )) {mode = FOLLOWING_LINE; error = 4;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 1 )) {mode = FOLLOWING_LINE; error = 3;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error = 2;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 1 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error = 1;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error = 0;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 1 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error =- 1;}
else if((LFSensor[0]== 0 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error = -2;}
else if((LFSensor[0]== 1 )&&(LFSensor[1]== 1 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error = -3;}
else if((LFSensor[0]== 1 )&&(LFSensor[1]== 0 )&&(LFSensor[2]== 0 )&&(LFSensor[3]== 0 )&&(LFSensor[4]== 0 )) {mode = FOLLOWING_LINE; error = -4;}
Serial.print (farLeftSensor);
Serial.print (" <== LEFT RIGH==> ");
Serial.print (farRightSensor);
Serial.print (" mode: ");
Serial.print (mode);
Serial.print (" error:");
Serial.println (error);
}
void readLateralSensors(void)
{
}
- MAZE FUNCTION:
void mazeSolve(void)
{
while (!status)
{
readLFSsensors();
switch (mode)
{
case NO_LINE:
motorStop();
goAndTurn (LEFT, 180);
recIntersection('B');
break;
case CONT_LINE:
runExtraInch();
readLFSsensors();
if (mode != CONT_LINE) {goAndTurn (LEFT, 90); recIntersection('L');} // or it is a "T" or "Cross"). In both cases, goes to LEFT
else mazeEnd();
break;
case RIGHT_TURN:
runExtraInch();
readLFSsensors();
if (mode == NO_LINE) {goAndTurn (RIGHT, 90); recIntersection('R');}
else recIntersection('S');
break;
case LEFT_TURN:
goAndTurn (LEFT, 90);
recIntersection('L');
break;
case FOLLOWING_LINE:
followingLine();
break;
}
}
}
void recIntersection(char direction)
{
path[pathLength] = direction; // Store the intersection in the path variable.
pathLength ++;
simplifyPath(); // Simplify the learned path.
}
void mazeEnd(void)
{
motorStop();
BT1.print("The End ==> Path: ");
for(int i=0;i<pathLength;i++)
BT1.print(path[i]);
//Serial.print(path[i]);
BT1.println("");
Serial.print(" pathLenght ==> ");
Serial.println(pathLength);
status = 1;
mode = STOPPED;
}
void followingLine(void)
{
calculatePID();
motorPIDcontrol();
}
void simplifyPath()
{
if(pathLength < 3 || path[pathLength-2] != 'B')
return;
int totalAngle = 0;
int i;
for(i=1;i<=3;i++)
{
switch(path[pathLength-i])
{
case 'R':
totalAngle += 90;
break;
case 'L':
totalAngle += 270;
break;
case 'B':
totalAngle += 180;
break;
}
}
totalAngle = totalAngle % 360;
switch(totalAngle)
{
case 0:
path[pathLength - 3] = 'S';
break;
case 90:
path[pathLength - 3] = 'R';
break;
case 180:
path[pathLength - 3] = 'B';
break;
case 270:
path[pathLength - 3] = 'L';
break;
}
pathLength -= 2;
}
void mazeOptimization (void)
{
while (!status)
{
readLFSsensors();
switch (mode)
{
case FOLLOWING_LINE:
followingLine();
break;
case CONT_LINE:
if (pathIndex >= pathLength) mazeEnd ();
else {mazeTurn (path[pathIndex]); pathIndex++;}
break;
case LEFT_TURN:
if (pathIndex >= pathLength) mazeEnd ();
else {mazeTurn (path[pathIndex]); pathIndex++;}
break;
case RIGHT_TURN:
if (pathIndex >= pathLength) mazeEnd ();
else {mazeTurn (path[pathIndex]); pathIndex++;}
break;
}
}
}
void mazeTurn (char dir)
{
switch(dir)
{
case 'L': // Turn Left
goAndTurn (LEFT, 90);
break;
case 'R': // Turn Right
goAndTurn (RIGHT, 90);
break;
case 'B': // Turn Back
goAndTurn (RIGHT, 800);
break;
case 'S': // Go Straight
runExtraInch();
break;
}
}
SOURCE CODE FOR MAZE ROBOT:
int motor_lA = 9;
int motor_lB = 10;
int motor_enableA = 11;
int motor_rA = 3;
int motor_rB = 4;
int motor_enableB = 5;
int trigger_front = A0;
int echo_front = A1;
int trigger_left = A2;
int echo_left = A3;
int trigger_right = A4;
int echo_right = A5;
void setup() {
// put your setup code here, to run once:
pinMode(motor_lA,OUTPUT); //left motors forward
pinMode(motor_lB,OUTPUT); //left motors reverse
pinMode(motor_enableA, OUTPUT);
pinMode(motor_rA,OUTPUT); //right motors forward
pinMode(motor_rB,OUTPUT); //rignt motors reverse
pinMode(motor_enableB, OUTPUT);
pinMode(trigger_front,OUTPUT);
pinMode(echo_front,INPUT);
pinMode(trigger_left,OUTPUT);
pinMode(echo_left,INPUT);
pinMode(trigger_right,OUTPUT);
pinMode(echo_right,INPUT);
analogWrite(motor_enableA, 80);
analogWrite(motor_enableB, 88);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.begin(9600);
long duration_front, distance_front, duration_left, distance_left, duration_right, distance_right;
//Calculating distance
digitalWrite(trigger_front, LOW);
delayMicroseconds(2);
digitalWrite(trigger_front, HIGH);
delayMicroseconds(10);
digitalWrite(trigger_front, LOW);
duration_front = pulseIn(echo_front, HIGH);
distance_front= duration_front*0.034/2;
digitalWrite(trigger_left, LOW);
delayMicroseconds(2);
digitalWrite(trigger_left, HIGH);
delayMicroseconds(10);
digitalWrite(trigger_left, LOW);
duration_left = pulseIn(echo_left, HIGH);
distance_left= duration_left*0.034/2;
digitalWrite(trigger_right, LOW);
delayMicroseconds(2);
digitalWrite(trigger_right, HIGH);
delayMicroseconds(10);
digitalWrite(trigger_right, LOW);
duration_right = pulseIn(echo_right, HIGH);
distance_right= duration_right*0.034/2;
Serial.print("front = ");
Serial.println(distance_front);
Serial.print("Left = ");
Serial.println(distance_left);
Serial.print("Right = ");
Serial.println(distance_right);
delay(50);
if (distance_front >20){
forward();
if(distance_left > 10&& distance_left<20){
forward();
}
if(distance_left >=20){
left();
delay(30);
forward();
}
if(distance_left<10 && distance_left>0){
right();
delay(30);
forward();
}
}
if(distance_front<=20&& distance_right > 20){
Stop();
delay(1000);
right();
delay(400);
}
if(distance_front<=20 && distance_right<20){
Stop();
delay(1000);
right();
delay(800);
}
}
void forward()
{
digitalWrite(motor_lA,1);
digitalWrite(motor_lB,0);
digitalWrite(motor_rA,1);
digitalWrite(motor_rB,0);
delay(1000);
}
void right(){
digitalWrite(motor_lA,1);
digitalWrite(motor_lB,0);
digitalWrite(motor_rA,0);
digitalWrite(motor_rB,1);
delay(10);
}
void left(){
digitalWrite(motor_lA,0);
digitalWrite(motor_lB,1);
digitalWrite(motor_rA,1);
digitalWrite(motor_rB,0);
delay(10);
}
void Stop(){
digitalWrite(motor_lA,0);
digitalWrite(motor_lB,0);
digitalWrite(motor_rA,0);
digitalWrite(motor_rB,0);
delay(300);
}
After successful stimulation, dump the code in the Arduino.
INSTRUCTION:
>Dump the code for maze robot in the Arduino using USB cable.
>Required components -
HARDWARE
- ARUDINO
- LM296 Driver
- Ultrasonic Distance sensor
- Motors
- 9 or 12V battery
- Breadboard
- Jumper wires
SOFTWARE
- Arduino ide
>Make the connection with LM296 driver,ultrasonic distance sensor, motors, battery by using jumper wires and breadboard by refering circuit diagram.
>Before connecting the components make sure that the compnents are good enough.
CIRCUIT DIAGRAM:
Interfacing Ultrasonic Sensors to Arduino
Wire the trigger pin and echo pin of the sensors to analog pins of the Arduino. To power up the sensors, connect all the ground pins to a common ground rail and all the 5V pins to a common 5V rail on the breadboard.
Interfacing the Motor Driver to Arduino
The motor driver has seven screw terminals, which makes the interfacing easy.
The L298N dual H-Bridge motor driver helps us to control the speed and direction of the two DC motors simultaneously. It acts as an interface between the motor and the Arduino. The motor driver has 4 input pins to control the rotational direction of the motor. ‘Enable A’ and ‘Enable B’ pins have the responsibility to enable and control the speed of the motors.
LM296 driver:
The LM2596 regulator is monolithic integrated circuit ideally suited for easy and convenient design of a step−down switching regulator (buck converter). It is capable of driving a 3.0 A load with excellent line and load regulation. This device is available in adjustable output version and it is internally compensated to minimize the number of external components to simplify the power supply design. Since LM2596 converter is a switch−mode power supply, its efficiency is significantly higher in comparison with popular three−terminal linear regulators, especially with higher input voltages. The LM2596 operates at a switching frequency of 150 kHz thus allowing smaller sized filter components than what would be needed with lower frequency switching regulators.
Ultrasonic sensor:
An ultrasonic sensor is an electronic device that measures the distance of a target object by emitting ultrasonic sound waves, and converts the reflected sound into an electrical signal. Ultrasonic waves travel faster than the speed of audible sound (i.e. the sound that humans can hear). Ultrasonic sensors have two main components: the transmitter (which emits the sound using piezoelectric crystals) and the receiver (which encounters the sound after it has travelled to and from the target).
The formula for this calculation is D = ½ T x C (where D is the distance, T is the time, and C is the speed of sound ~ 343 meters/second).
This above diagram illustrate the circuit diagram of the maze robot.
FINAL WORKING MODEL
This is the working model of the maze robot.
These types of autonomous mobile robots can be used in a wide variety of applications such as material handling, warehouse management, pipe inspection, and bomb disposal.