Project 2 - Measuring distance of an object using ultrasonic sensor (HC-SR04)
/* PROJECT - 2 */
Overview of the Project :
In this project, the implementation of code for “Measuring distance of an object using ultrasonic distance sensor (HC-SR04).
Goals :
- Measuring the distance of an object using Ultrasonic Distance Sensor (HC-SR04).
- Usage of Input Capture Mode.
Key Highlights of the Project :
- Measuring the distance travelled by the wave to the object and gets bounced back from the object to sensor.
- Measuring Pulse width using Input Capture Mode.
Deliverables of this project :
- The distance travelled by a wave to the object for which we want to measure the distance using Ultrasonic Distance Sensor (HC-SR04).
- Measuring Pulse width using Input Capture Mode of Timer 1.
Expected Outcomes :
The students will get the Knowledge on Ultrasonic sensor (HC-SR04) to measure the distance travelled by wave to the object, the hardware connection of Atmega328p and HC-SR04 and how to use input capture mode of Timer1.
Ans :
To implement code for “Measuring distance of an object using ultrasonic distance sensor (HC-SR04). For that we required,
Components used in the Circuit :
1: AtMega 328 Microcontroller - 1
2: LCD Display Hd44780 (2 * 16) - 1
3: Ultrasonic distance sensor (HC-SR04) - 1
4: Potentiometer (1K ohm) - 1
6: Oscilloscope - 1
7: Power source - 1
8: Ground (0V) - 1
9: Connecting Wires - As required
Wiring Connections :
1: AtMega 328 Microcontroller :
- Connect the VCC pin to the positive terminal of the power source.
- Connect the GND pin to the negative terminal (common ground).
- Connect the necessary programming AtMega 328 pins (B0 to B7) to LCD pins (D0 to D7) and AtMega 328 pins (D0, D1, D2) to LCD pins (RS, RW, EN).
2: LCD Display (HD44780 - 2 * 16) :
- Connect the VCC and GND of the LCD to the corresponding power and ground.
- Connect the SDA (data) and SCL (clock) pins to the microcontroller's data and clock pins.
- Connect RW, RS, and EN pins to specified pins on the microcontroller.
3: Ultrasonic Distance Sensor (HC-SR04) :
- Connect VCC and GND to the power source and common ground.
- Connect the Trigger (Trig) pin to a specified pin on the microcontroller (C0).
- Connect the Echo pin to another specified pin on the microcontroller (C1).
4: Potentiometer (1K ohm) :
- Connect one end to Power Source (positive).
- Connect the other end to GND (negative).
- Connect the middle pin (wiper) to the contrast pin on the ultrasonic Distance.
5: Oscilloscope :
- Connect channel - 1 to the Trigger (Trig) pin of the sensor.
- Connect channel - 3 to the Echo pin of the sensor.
6: Power Source and Ground :
- Connect Power Source (positive) to one end of Potentiometer .
- Connect GND (negative 0V) to the other end of Potentiometer.
7: Connecting Wires :
- Use appropriate connecting wires to establish connections between components.
- Avoid overlapping wires and ensure proper insulation.
Explanation of the code :
- The code initializes and controls an LCD display and an Ultrasonic sensor using AVR microcontroller.
- Ultrasonic sensor functions are used to trigger pulses and measure pulse width for distance calculation.
- LCD functions are utilized for displaying distance and handling errors.
- The program runs indefinitely, continuously measuring and displaying distances.
Algorithm used :
1: Initialization :
- Initialize the LCD for display.
- Set up macros for controlling LCD pins (RS, EN, RW).
- Define macros and variables for Ultrasonic sensor configuration and distance values.
2: LCD Functions :
- Implement functions (lcd_cmd, lcd_data, lcd_init, cursorpos, lcd_out, lcd_clear) for controlling the LCD.
- These functions allow sending commands, data, initializing the LCD, positioning the cursor, and displaying strings.
3: Ultrasonic Sensor Functions :
Implement functions (HCSR04Init, HCSR04Trigger, GetPulseWidth) for interfacing with the Ultrasonic sensor.
- HCSR04Init : Initializes the Ultrasonic sensor by setting the trigger pin as an output.
- HCSR04Trigger : Triggers an ultrasonic pulse by sending a 10μs pulse on the trigger line.
- GetPulseWidth : Measures the width of the pulse received on the echo line and calculates the distance based on the speed of sound.
4: Main Function :
- Initialize the LCD and variables.
- Enter an infinite loop for continuous distance measurement and display.
5: Distance Measurement Loop :
- Trigger an ultrasonic pulse (HCSR04Trigger).
- Measure the pulse width (GetPulseWidth).
- Handle errors if there's no pulse or a timeout occurs.
- If a valid pulse is received, calculate the distance based on the pulse width.
- Display the distance on the LCD.
6: Delay and Update :
- Introduce a delay (_delay_ms(30)) to control the rate of distance measurement.
- Update the previous distance value for future comparisons.
Code :
#include <avr/io.h> /* Header Files includes the AVR I/O definitions, which contain register definitions for the specific AVR microcontroller being used */
#define F_CPU 16000000L /* It is a preprocessor directive commonly used in AVR microcontroller programming to define the CPU clock frequency */
#include <util/delay.h> /* Header Files includes the delay functions for creating time delays in milliseconds */
#define rs_high PORTD |= (1 << 0); /* MACRO DEFINE BIT FOR RS_HIGH */
#define rs_low PORTD &= ~(1 << 0); /* MACRO DEFINE BIT FOR RS_LOW */
#define en_high PORTD |= (1 << 2); /* MACRO DEFINE BIT FOR EN_HIGH */
#define en_low PORTD &= ~(1 << 2); /* MACRO DEFINE BIT FOR EN_LOW */
#define rw_high PORTD |= (1 << 1); /* MACRO DEFINE BIT FOR RW_HIGH */
#define rw_low PORTD &= ~(1 << 1); /* MACRO DEFINE BIT FOR RW_LOW */
#define US_ERROR -1 /* We're defining two more variables two know if the ultrasonic sensor is working or not */
#define US_NO_OBSTACLE -2 /* We defines this constant is likely used in the program to represent a specific condition or state */
#define US_PORT PORTC /* We have connected the Ultrasonic sensor on port C. to use the ultrasonic we need two pins of the ultrasonic to be connected on port C */
#define US_PIN PINC /* We need to initialize the pin resistor when we want to take input */
#define US_DDR DDRC /* We need data-direction-resistor (DDR) to set the direction of data flow. input or output. we will define it later, now we're just naming it */
#define US_TRIG_POS PC0 /* The trigger pin of ultrasonic sound sensor is connected to port C pin 0 */
#define US_ECHO_POS PC1 /* The echo pin of ultrasonic sound sensor is connected to port C pin 1 */
int distance, previous_distance; /* These variables are used to store information about the distance measured by an ultrasonic sensor */
void lcd_cmd(unsigned char cmd) /* LCD_COMMAND FUNCTION */
{
PORTB = cmd;
rs_low;
rw_high;
en_high;
_delay_ms(1);
en_low;
}
void lcd_data(unsigned char data) /* LCD DATA FUNCTION */
{
PORTB = data;
rw_low;
rs_high;
en_high;
_delay_ms(1);
en_low;
}
void lcd_init() /* LCD INITIALIZATION */
{
rw_high;
rs_high;
en_high;
PORTB = 0xff;
lcd_cmd(0x38);
_delay_ms(5);
lcd_cmd(0x02);
_delay_ms(5);
lcd_cmd(0x01);
_delay_ms(5);
lcd_cmd(0x0c);
_delay_ms(5);
lcd_cmd(0x06);
_delay_ms(5);
lcd_cmd(0x80);
_delay_ms(5);
}
void cursorpos(char x, char y) /* CURSOR POSITION FUNCTION */
{
if ((x < 1 || x > 2) || (y < 1 || y > 16))
{
x = 1;
y = 1;
}
if (x == 1)
{
lcd_cmd(0x7F + y);
}
else
{
lcd_cmd(0xBF + y);
}
}
void lcd_out(char a, char b, char *str) /* LCD OUT FUNCTION */
{
cursorpos(a, b);
while (*str)
{
lcd_data(*str);
str++;
}
}
void lcd_clear()
{
lcd_cmd(0x01); /* This line clears the LCD screen */
_delay_ms(2); /* Waits for two milliseconds */
lcd_cmd(0x80); /* This line sets the cursor to the row 1 column 1 */
}
void HCSR04Init() /* We're setting the trigger pin as output as it will generate ultrasonic sound wave */
{
US_DDR |= (1 << US_TRIG_POS);
}
void HCSR04Trigger() /* This function will generate ultrasonic sound wave for 15 microseconds. Send a 10uS pulse on trigger line */
{
US_PORT |= (1 << US_TRIG_POS); /* High */
_delay_us(15); /* Wait 15uS */
US_PORT &= ~(1 << US_TRIG_POS); /* Low */
}
uint16_t GetPulseWidth() /* This function will be used to measure the pulse duration. When the ultra sound echo back after hitting an object, the microcontroller will read the pulse using the echo pin of the ultrasonic sensor connected to it */
{
uint32_t i, result;
for (i = 0; i < 600000; i++) /* Section - 1: the following lines of code before the section - 2 are checking if the ultrasonic is working or not, it checks the echo pin for a certain amount of time. If there is no signal, it means the sensor is not working or not connected properly */
{
if (!(US_PIN & (1 << US_ECHO_POS)))
continue; /* Line is still low, so wait */
else
break; /* High edge detected, so break */
}
if (i == 600000)
return US_ERROR; /* Indicates time out */
TCCR1A = 0X00; /* High Edge Found, Section -2 : This section is all about preparing the timer for counting the time of the pulse. Timers in microcontrollers are used for timing operation. Setup Timer1 */
TCCR1B = (1 << CS11); /* This line sets the resolution of the timer. Maximum of how much value it should count */
TCNT1 = 0x00; /* This line starts the counter to start counting time */
for (i = 0; i < 600000; i++) /* Section -3 : This section checks whether there is any object or not, the 600000 value is used randomly to denote a very small amount of time, almost 40 milliseconds */
{
if (US_PIN & (1 << US_ECHO_POS))
{
if (TCNT1 > 60000)
break;
else
continue; /* if the TCNT1 value gets higher than 60000 it means there is not an object in the range of the sensor */
}
else
break;
}
if (i == 600000)
return US_NO_OBSTACLE; /*Indicates time out */
result = TCNT1; /* Falling edge found, microcontroller stores the value of the counted pulse time in the TCNT1 register. So, we're returning this value to the main function for utilizing it later stop Timer */
TCCR1B = 0x00;
if (result > 60000)
return US_NO_OBSTACLE; /* No obstacle */
else
return (result >> 1);
}
int main() /* In an AVR microcontroller program, the main function is the entry point of the program */
{
lcd_init(); /* we're initializing the LCD */
char numberString[4]; /* we're defining an array of characters. It will be utilized later to store an integer to be displayed on the LCD screen */
while (1) /* Enters an infinite loop */
{
uint16_t r;
_delay_ms(100); /* Let the LCD Module start. Set IO port direction of sensor */
HCSR04Init();
while (1) /* Enters an infinite loop */
{
HCSR04Trigger(); /* Send a trigger pulse, calling the ultrasonic sound wave generator function to Measure the width of the pulse */
r = GetPulseWidth(); /* Getting the duration of the ultrasound took to echo back after hitting the object */
if (r == US_ERROR) /*Handle Errors, if the microcontroller doesn't get any pulse then it will set the US_ERROR variable to -1 and the following code will check if there is an error then it will be displayed on the LCD screen */
{
cursorpos(1, 1); /* lcd_setCursor(column, row) */
char j[10] = "Error!";
lcd_out(1, 1, &j);
}
else
{
distance = (r * 0.034 / 2.0); /* This will give the distance in centimeters */
char f[15] = "Distance = ";
lcd_out(1, 0, &f);
itoa(distance, numberString, 10); /* Distance is an integer number, we cannot display an integer directly on the LCD. this line converts an integer into an array of characters */
lcd_out(2, 4, numberString);
char h[6] = " cm";
lcd_out(2, 10, &h);
previous_distance = distance;
_delay_ms(30); /* Delay to control the rate of distance measurement */
}
}
}
}
Uses :
1: Obstacle Detection and Avoidance :
The project can be used in robotics for obstacle detection. Robots equipped with ultrasonic sensors can navigate through an environment, avoiding obstacles by sensing and calculating distances.
2: Parking Assistance Systems :
In automotive applications, the project can be adapted for parking assistance systems. Ultrasonic sensors can be installed in vehicles to detect the distance from obstacles, providing feedback to the driver for safe parking.
3: Home Automation :
The distance measurement capabilities can be integrated into home automation systems. For example, the system can be used to control lighting or adjust the room temperature based on the presence or absence of individuals.
4: Security Systems :
Ultrasonic sensors can be used in security systems to detect unauthorized movement or intrusion. The distance measurement can help in determining the location and distance of the intruder.
5: Industrial Automation :
In industrial settings, the project can be employed for monitoring and controlling machinery. The distance information can be used to regulate the movement of robotic arms or other equipment.
6: Liquid Level Measurement :
With appropriate calibration, the project can be adapted for measuring the level of liquids in tanks. This is useful in various industries, such as manufacturing and agriculture.
7: Smart Appliances :
Distance measurement can be integrated into smart appliances, allowing for more intuitive and responsive interactions. For instance, a hands-free faucet could use distance sensing to start and stop water flow.
8: Education and Learning :
The project serves as an educational tool, helping students understand the principles of ultrasonic distance measurement, microcontroller programming, and sensor integration.
9: Research and Development :
Researchers and developers can utilize the project as a foundation for more advanced applications. It can be a starting point for developing more sophisticated distance measurement systems.
10: Accessibility Devices :
The technology can be incorporated into devices to assist individuals with visual impairments. For instance, it can be used to detect obstacles and provide feedback.
11: Precision Measurement Systems :
In certain applications where precision distance measurement is crucial, the project can be adapted and enhanced to meet specific requirements.