Project tutorial
Measurement of Mobile Robots with Arduino and LM393 Sensors

Measurement of Mobile Robots with Arduino and LM393 Sensors © GPL3+

This project can help you measure the speed, distance and angle of the robot.

  • 4 views
  • 0 comments
  • 0 respects

Components and supplies

Necessary tools and machines

Apps and online services

About this project

LM393 Speed Sensor Module (H206)

Before we start the project's circuit diagram and code, let us understand the LM393 speed sensor module, because it plays a vital role in the project. H206 speed sensor module is composed of infrared light sensor and LM393 voltage comparator IC, so it is named as LM393 speed sensor. The module also includes a grid plate, which must be mounted on the rotating shaft of the motor. All components are marked in the image below.

The infrared light sensor is composed of infrared LED and phototransistor, separated by a small gap. As shown above, the entire sensor device is placed in a black housing. The grid plate is composed of grooves, and the plate is arranged between the gaps of the infrared light sensors so that the sensor can sense the gap in the grid plate. Each gap in the grid plate triggers the IR sensor when passing through the gap; a comparator is then used to convert these triggers into a voltage signal. The comparator uses ON Semiconductor's LM393 IC. The module has three pins, two of which are used to power the module, and one output pin is used to count the number of triggers.

H206 Sensor Installation

Installing these types of sensors is a bit tricky. It can only be installed on motors with shaft protruding on both sides. One side of the axle is connected to the wheel, while the other side is used to install the grid, as shown above.

Since the wheels and wheels are connected on the same axis, both rotate at the same speed, so by measuring the vehicle speed, we can measure the speed of the wheels. Make sure that the gap in the grid plate passes through the infrared sensor before the sensor can count the number of gaps that pass through. As long as the specified conditions are met, you can also set up your own mechanical device to install the sensor. Infrared sensors are commonly used in many robot projects to guide robots to understand obstacles.

The grid plate shown above has 20 slots (grids). This means that the sensor will find 20 gaps for one full rotation of the wheel. By calculating the number of gaps detected by the sensor, we can calculate the distance traveled by the wheel, and similarly by measuring the speed of the gap found by the sensor, we can detect the speed of the wheel. In our robot, we install this sensor on two wheels, so we can also find the angle of the robot. However, using an accelerometer or gyroscope can calculate the rotation angle more wisely. Here we learn to use the Arduino to interface the accelerometer with the gyroscope and try to use them to measure the rotation angle.

Schematic

The complete circuit diagram of the speed and distance sensing robot is shown below. The robot uses the Arduino Nano as its brain, and the two DC motors for the wheels are driven by the L298N H-bridge motor driver module. The joystick is used to control the speed and direction of the robot, and the two speed sensors H206 are used to measure the speed, distance and angle of the robot. Then, the measured value is displayed in the 1602 LCD module. The potentiometer connected to the LCD can be used to adjust the contrast of the LCD, and the resistor is used to limit the current flowing to the LCD backlight.

The entire circuit is powered by a 7.4V lithium battery. The 7.4V power supply is provided to the 12V pin of the motor driver module. The voltage regulator on the motor driver module then converts 7.4V to a regulated voltage + 5V for powering the Arduino, LCD, sensors and joystick.

The motor is controlled by Arduino digital pins 8, 9, 10 and 11. Since the speed of the motor must also be controlled, we should provide a PWM signal to the positive pole of the motor. Therefore, we have pins 9 and 10, which are both PWM pins. The X and Y values of the joystick are read using analog pins A2 and A3, respectively.

We know that the H206 sensor triggers when it detects gaps in the grid. Since these triggers cannot always be accurately read to calculate the correct speed and distance, the trigger (output) pins are connected to external interrupt pins 2 and 3 of the Arduino board. Assemble the entire circuit on the chassis and install the speed sensor according to the instructions. After the connection is completed, the robot will look like the following.

The hardware part has been completed. let's dive into how to measure the speed, distance and angle of the robot, and then enter the programming part.

The logic behind measuring speed with the H206 sensor

From the sensor installation settings, you should know that the H206 sensor only measures the gaps present in the grid. When installing, ensure that the wheels (whose speed should be measured) and the baffle rotate at the same speed. Just like here, since we install the wheels and wheels on the same shaft, they will all rotate at the same speed.

In our setup, we installed two sensors for each wheel to measure the angle of the robot. But if your goal is to measure only speed and distance, we can install the sensor on any wheel. The output of the sensor (trigger signal) is most often connected to the external interrupt pin of the microcontroller. Each time a gap in the grid is detected, an interrupt is triggered and the code in the ISR (Interrupt Service Routine) is executed. If we can calculate the time interval between two such triggers, we can calculate the speed of the wheel.

In Arduino, we can easily calculate this time interval using the millis () function. Since the device is powered on, this millisecond function will increase by 1 every millisecond. Therefore, when the first interrupt occurs, we can save the value of millis () in a dummy variable (such as pevtime in the code), and then when the second interrupt occurs, we can calculate to subtract from millis () The time required for the pevtime value.

Formula:

Time taken = current time – previous time

timetaken = millis()-pevtime; //timetaken in millisec

Once we have calculated the time used, we can simply calculate the value of rpm using the following formula, where (1000 / timetaken) gives RPS (revolutions per second) and multiplies it by 60 to convert RPS to RPM Revolutions per minute).

Formula:

rpm=(1000/timetaken)*60;

After calculating the speed, we can use the following formula to calculate the speed of the vehicle, provided that we know the radius of the wheel.

Formula:

Velocity = 2π × RPS × radius of wheel.

v = radius_of_wheel * rpm * 0.104

Note that the above formula is used to calculate the speed in m / s. If km / hr is to be used, replace 0.0104 with 0.376. If you want to know how to get the value 0.104, then try to simplify the formula V = 2π × RPS × wheel radius.

Even if a Hall sensor is used to measure the speed of a rotating object, the same technique is used. But there is a defect for the H206 sensor, the grid board has 20 slots, so the time used to measure the gap between the two slots will overload the microcontroller. Therefore, we only measure the speed when the wheel is fully rotated. Since each gap will generate two interruptions (one at the beginning and the other at the end of the gap), we will get a total of 40 interruptions to allow the wheel to complete a full rotation. So we wait for 40 interruptions before actually calculating the wheel speed. The code is as follows.

Code:

if(rotation>=40)

{

timetaken = millis()-pevtime; //timetaken in millisec

rpm=(1000/timetaken)*60; //formulae to calculate rpm

pevtime = millis();

rotation=0;

}

Another disadvantage of this method is that the speed value will not drop to zero, because the interruption will always wait for the wheel to complete a revolution to calculate the rpm value. This shortcoming can be easily overcome by adding a simple code that monitors the time interval between two interrupts. If it exceeds the normal value, then we can force the rpm and velocity values to zero. Link In the following code we use the variable dtime to check the time difference. If it exceeds 500 milliseconds, the speed and rpm values are forced to zero.

Code:

/*To drop to zero if vehicle stopped*/

if(millis()-dtime>500) //no inetrrupt found for 500ms

{

rpm= v = 0; // make rpm and velocity as zero

dtime=millis();

}

The logic behind measuring wheel travel distance

We already know that when the wheel completes a full rotation, the Arduino will sense 40 interruptions. Therefore, for each rotation made by the wheel, it is obvious that the distance traveled by the wheel is equal to the circumference of the wheel. Since we already know the radius of the wheel, we can easily calculate the covered distance using the following formula.

Distance = 2πr * number of rotations

distance = (2*3.141*radius_of_wheel) * (left_intr/40)

In the case of calculating the wheel circumference using the formula 2πr, then multiply by the number of revolutions of the wheel.

The logic behind measuring robot angle

There are many ways to determine the angle of the robot. Accelerometers and gyroscopes are commonly used to determine these values. But another cheap method is to use H206 sensors on both wheels. In this way, we can know the number of turns of each wheel. The figure below illustrates how to calculate the angle.

When the robot is initialized, the angle it faces is regarded as 0 °. From there when it rotates the left to initialize the robot, the angle it faces is regarded as 0 °. From there it rotates to the left, the angle increases negatively, and if it rotates to the right, the angle increases positive. For understanding, let us consider the range of -90 to +90, as shown. In this arrangement, since both wheels have the same diameter, if either wheel is fully rotated, we will turn at an angle of 90 °.

For example, if the left wheel completes one rotation (80 interruptions), the robot will turn 90 ° to the left, and if the right wheel completes one rotation (80 interruptions), the robot will turn 90 ° to the right. Now we know that if the Arduino detects 80 interruptions on one wheel, then the robot has turned 90 ° and we can judge whether the robot is rotating by positive (right) or negative (left). So you can use the following formula to calculate the left and right angles:

Formula:

int angle_left = (left_intr % 360) * (90/80) ;

int angle_right = (right_intr % 360) * (90/80) ;

90 is the angle covered when interrupting 80. The resulting value is multiplied by the number of interrupts. We also used a modulus of 360 so that the resulting value does not exceed 36. Once we have calculated the left and right corners, we can simply obtain the effective angle the robot is facing by subtracting the left corner from the right angle.

angle = angle_right - angle_left;

Arduino Programming

We start the program by defining digital I / O pins for the two motors. Please note that we must also control the speed of the motor, so the PWM pin on the Arduino must be used to control the motor. Pins 8, 9, 10 and 11 are used here.

Code:

#define LM_pos 9 // left motor

#define LM_neg 8 // left motor

#define RM_pos 10 // right motor

#define RM_neg 11 // right motor

#define joyX A2

#define joyY A3

To measure the speed and distance covered, we need to know the radius of the wheel, and the measured value is entered in meters as shown below. For robots, the radius is 0.033 meters, but depending on your robot, it may be different.

Code:

float radius_of_wheel = 0.033; //Measure the radius of your wheel and enter it here in cm

In the setup function, we initialize all the values to zero, and then display a brief text on the LCD. We also initialized the serial monitor for debugging. Then we mentioned that the speed sensor H206 is connected to pins 2 and 3 as an external interrupt. This is where the interruption is detected, and the ISR functions Left_ISR and Right_ISR will be executed accordingly.

Code:

void setup()

{

rotation = rpm = pevtime = 0; //Initialize all variable to zero

Serial.begin(9600);

lcd.begin(16, 2); //Initialise 16*2 LCD

lcd.print("Bot Monitor"); //Intro Message line 1

lcd.setCursor(0, 1);

lcd.print("-CircuitDigest "); //Intro Message line 2

delay(2000);

lcd.clear();

lcd.print("Lt: Rt: ");

lcd.setCursor(0, 1);

lcd.print("S: D: A: ");

pinMode(LM_pos, OUTPUT);

pinMode(LM_neg, OUTPUT);

pinMode(RM_pos, OUTPUT);

pinMode(RM_neg, OUTPUT);

digitalWrite(LM_neg, LOW);

digitalWrite(RM_neg, LOW);

attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //Left_ISR is called when left wheel sensor is triggered

attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//Right_ISR is called when right wheel sensor is triggered

}

In the Left_ISR function code, we simply add a variable named left_intr, which will be used later to measure the angle of the robot. Inside Right_ISR, we do the same thing, but in addition we are still calculating the speed here. Each interruption will increase the variable rotation, and then use the above logic to calculate the speed.

Code:

void Left_ISR()

{

left_intr++;delay(10);

}

void Right_ISR()

{

right_intr++; delay(10);

rotation++;

dtime=millis();

if(rotation>=40)

{

timetaken = millis()-pevtime; //timetaken in millisec

rpm=(1000/timetaken)*60; //formulae to calculate rpm

pevtime = millis();

rotation=0;

}

}

Within the main loop function, we monitor the values of X and Y in the joystick. Based on the value of the moving joystick, we control the robot accordingly. The speed of the robot depends on the pushing distance of the joystick.

Code:

int xValue = analogRead(joyX);

int yValue = analogRead(joyY);

int acceleration = map (xValue, 500, 0, 0, 200);

if (xValue<500)

{

analogWrite(LM_pos, acceleration);

analogWrite(RM_pos, acceleration);

}

else

{

analogWrite(LM_pos, 0);

analogWrite(RM_pos, 0);

}

if (yValue>550)

analogWrite(RM_pos, 80);

if (yValue<500)

analogWrite(LM_pos, 100);

The following function will help the user to move the robot and check whether the obtained value is as expected. Finally, we can use the above logic to calculate the speed, distance and angle of the robot, and use the following code to display it on the LCD.

Code:

v = radius_of_wheel * rpm * 0.104; //0.033 is the radius of the wheel in meter

distance = (2*3.141*radius_of_wheel) * (left_intr/40);

int angle_left = (left_intr % 360) * (90/80) ;

int angle_right = (right_intr % 360) * (90/80) ;

angle = angle_right - angle_left;

lcd.setCursor(3, 0); lcd.print(" "); lcd.setCursor(3, 0); lcd.print(left_intr);

lcd.setCursor(11, 0); lcd.print(" "); lcd.setCursor(11, 0);lcd.print(right_intr);

lcd.setCursor(2, 1); lcd.print(" "); lcd.setCursor(2, 1);lcd.print(v);

lcd.setCursor(9, 1); lcd.print(" "); lcd.setCursor(9, 1);lcd.print(distance);

lcd.setCursor(13, 1); lcd.print(" "); lcd.setCursor(13, 1);lcd.print(angle);

Test Arduino robot to measure distance, speed and angle

When the hardware is ready, upload the code to the Arduino and use the joystick to move the robot. The speed of the robot, the distance and angle it covers will be displayed on the LCD screen as shown below.

On the LCD, the terms Lt and Rt denote the left interrupt count and the right interrupt count, respectively. You can find that each gap detected by the sensor increases these values. Time S represents the speed of the robot in meters / second, and the term D represents the distance in meters. The angle of the robot is displayed at 0 ° as the end of a straight line, counterclockwise rotation is negative, and clockwise rotation is positive.

I hope you guys like this project, and if you do, you can also check this related post about wheel speed sensor. Enjoy Reading!

Code

Untitled fileArduino
#define LM_pos 9       // left motor
#define LM_neg 8       // left motor
#define RM_pos 10       // right motor
#define RM_neg 11       // right motor
#define joyX A2
#define joyY A3
float radius_of_wheel = 0.033;  //Measure the radius of your wheel and enter it here in cm
void setup()
{
  rotation = rpm = pevtime = 0; //Initialize all variable to zero
  Serial.begin(9600);
  lcd.begin(16, 2); //Initialise 16*2 LCD
  lcd.print("Bot Monitor"); //Intro Message line 1
  lcd.setCursor(0, 1);
  lcd.print("-CircuitDigest "); //Intro Message line 2
  delay(2000);
  lcd.clear();
  lcd.print("Lt:     Rt:    ");
  lcd.setCursor(0, 1);
  lcd.print("S:     D:  A:   ");

  pinMode(LM_pos, OUTPUT);
  pinMode(LM_neg, OUTPUT);

  pinMode(RM_pos, OUTPUT);
  pinMode(RM_neg, OUTPUT);

  digitalWrite(LM_neg, LOW);
  digitalWrite(RM_neg, LOW);

  attachInterrupt(digitalPinToInterrupt(2), Left_ISR, CHANGE); //Left_ISR is called when left wheel sensor is triggered
  attachInterrupt(digitalPinToInterrupt(3), Right_ISR, CHANGE);//Right_ISR is called when right wheel sensor is triggered
}
void Left_ISR()
{
  left_intr++;delay(10);
}


void Right_ISR()
{
  right_intr++; delay(10);

  rotation++;
  dtime=millis();
  if(rotation>=40)
  {
    timetaken = millis()-pevtime; //timetaken in millisec
    rpm=(1000/timetaken)*60;    //formulae to calculate rpm
    pevtime = millis();
    rotation=0;
  }
}
int xValue = analogRead(joyX);
 int yValue = analogRead(joyY);

int acceleration = map (xValue, 500, 0, 0, 200);

if (xValue<500)
{
analogWrite(LM_pos, acceleration);
analogWrite(RM_pos, acceleration);
}

else
{
analogWrite(LM_pos, 0);
analogWrite(RM_pos, 0);
}

if (yValue>550)
analogWrite(RM_pos, 80);

if (yValue<500)
analogWrite(LM_pos, 100);
v = radius_of_wheel * rpm * 0.104; //0.033 is the radius of the wheel in meter
 distance = (2*3.141*radius_of_wheel) * (left_intr/40);
 int angle_left = (left_intr % 360) * (90/80) ;
 int angle_right = (right_intr % 360) * (90/80) ;
 angle = angle_right - angle_left;

lcd.setCursor(3, 0); lcd.print("    "); lcd.setCursor(3, 0); lcd.print(left_intr);
lcd.setCursor(11, 0); lcd.print("    "); lcd.setCursor(11, 0);lcd.print(right_intr);
lcd.setCursor(2, 1); lcd.print("  "); lcd.setCursor(2, 1);lcd.print(v);
lcd.setCursor(9, 1); lcd.print("  "); lcd.setCursor(9, 1);lcd.print(distance);
lcd.setCursor(13, 1); lcd.print("   "); lcd.setCursor(13, 1);lcd.print(angle);

Schematics

schematic_pEct78xgP9.jpg
Schematic pect78xgp9

Comments

Similar projects you might like

GamePad using Android mobile sensors and Arduino

Project tutorial by Ashraf Nabil

  • 10,057 views
  • 7 comments
  • 20 respects

Walabot and Mobile App Controlled 3D-Printed Cars

Project tutorial by Jonathan Mendenhall

  • 8,338 views
  • 3 comments
  • 54 respects

Distance Measurement Vehicle via Websocket

Project tutorial by Matthew Lee

  • 16,328 views
  • 2 comments
  • 85 respects

IR Proximity Sensors with Simulink and Arduino (Part 1)

Project tutorial by Team MATLAB Makers

  • 7,867 views
  • 3 comments
  • 13 respects

Obstacle Avoidance Bot Using IR Sensors

Project tutorial by Chandran N

  • 5,968 views
  • 0 comments
  • 11 respects

IR Proximity Sensors With Simulink And Arduino (Part 2)

Project tutorial by Team MATLAB Makers

  • 2,827 views
  • 1 comment
  • 2 respects
Add projectSign up / Login