Greetings guys, its been a while since my last post but I’ll try to make it constant now, in our tutorial of today, we are going to be interfacing an ultrasonic distance sensor with a PIC16F877A microcontroller. The program will be written using MikroC Pro for pic.
We will be using the HC-SR04 ultrasound sensor for distance measurement. We are using this sensor because it is a low cost and easily available module. HC-SR04 Ultrasonic Distance Sensor is a popular and low cost solution for non-contact distance measurement function. It is able to measure distances from 2cm to 400cm with an accuracy of about 3mm. This module includes ultrasonic transmitter, ultrasonic receiver and its control circuit. As we can see on the figure below.
the HC-Sr04 ultrasonic sensor has four pins labeled
- VCC – 5V, positive of the power supply
- TRIG – Trigger Pin
- ECHO – Echo Pin
- GND – negaive of the power supply
The trigger and echo pins can be interfaced with a microcontroller because the function on 0 – 5V.
WORKING PRINCIPLE
As seen on the datasheet,
- Provide TRIGGER signal, atleast 10μS High Level (5V) pulse.
- The module will automatically transmit eight 40KHz ultrasonic burst.
- If there is an obstacle in-front of the module, it will reflect the ultrasonic burst.
- If the signal is back, ECHO output of the sensor will be in HIGH state (5V) for a duration of time taken for sending and receiving ultrasonic burst. Pulse width ranges from about 118μS to 24mS and if no obstacle is detected, the echo pulse width will be about 38ms.
This is a brief summary of how the sensor operates and its exactly what we are going to exploit in order to measure the distance. Other characteristics can be gotten from the datasheet or just search on Google and you’ll find a lot of data on this sensor.
CIRCUIT DIAGRAM
On the diagram above I connected the LCD on port B2 – B7, the trigger pin of the hc-sr04 to pin C3 and the echo pin to pin B0 which an external interrupt pin. Any digital pin can be used as trigger but I used B0 as echo because its capability of acting as an external interrupt comes in handy in this application.
PROCEDURE
- Send a pulse of at least 10 us through the trigger pin,
- Set pin B0 as interrupt on rising edge
- When interrupt occurs, clear timer 1 and start timer1
- Set pin B0 as interrupt on falling edge
- When interrupt occurs, read the value of timer1 and in a variable.
- Multiply the value of timer1 by 0.0034 (I’ll explain later)
- The final result gives your distance in centimeters. You can now display it
This are the procedures that I followed so I make use of timer 1 which is a 16bit timer, timer1 interrupt and external interrupt. I use timer1 interrupt because I noticed that timer1 overflows before 23 ms, hence it measures only a fraction of the distance. So using the interrupt, I was able to know exactly how many times the timer overflows and added it to the timer value. You will see me do that in the code.
I know you will be wondering where I got the figure 0.0034. lets explain it step by step.
I used 20MHz crystal so I have 20/4 = 5 million instructions per second.
Period = 0.2 us.
So timer increaments every 0.2 us
Time = TIMER1 * 0.2 us.
Distance = velocity*time (speed of sound is 340m/s)
Distance = TIMER1 * 340*0.2*10^-6
Distance = TIMER1*68*10^-6 (but the distance is through and fro. So we divide by 2)
Distance = TIMER1*34*10^-6 (we multiply by 100 to have it in cm)
Distance = TIMER1*0.0034.
Hope the calculation is explicit enough. Contact me if there is any doubt and note that for a different value of crystal, the values will change. Just follow the steps above and all will be fine.
SOURCE CODE
/*
distance measurement using hc-sr04 ultrasound sensor
using PIC16F877A
code written by Joel NGONGA
http://www.blogelect.wordpress.com
04-01-2016
The comments will guide you
*/
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
sbit TRIG at RC3_bit;
sbit TRIG_Direction at TRISC3_bit;
sbit ECHO at RC2_bit;
sbit ECHO_Direction at TRISC2_bit;
unsigned long int dist=0,cnt;
unsigned char txt[15];
void interrupt() {
if (INTCON.INTF == 1){ // detect rising edge
if (OPTION_REG.INTEDG ==1){
T1CON.TMR1ON = 1; // put on timer1
OPTION_REG.INTEDG = 0; // set interrupt on falling edge
}
else if (OPTION_REG.INTEDG == 0){ // detect falling edge
T1CON.TMR1ON = 0; // put off timer1
dist =((65536*cnt)+(TMR1L | (TMR1H<<8)))*0.0034;
TMR1L=0; // clear timer1L
TMR1H=0; // clear timer1H
cnt=0; // clear cnt variable
OPTION_REG.INTEDG = 1; // set interrupt on rising edge
}
INTCON.INTF = 0;
}
else if (PIR1.TMR1IF == 1){ // timer1 overflow
cnt++;
PIR1.TMR1IF =0;
}
}
void main() {
OPTION_REG.INTEDG = 1; //INTERRUPT ON RISING EDGE
T1CON = 0x09; // timer control register
INTCON = 0xD0; // interrupt control register
PIE1.TMR1IE=1; // timer1 interrupt enable bit
T1CON.TMR1ON = 0; // timer1 0ff initially
trisb0_bit=1;
trisc=0;
portc=0;
lcd_init();
Lcd_Cmd(_Lcd_Clear);
Lcd_Cmd(_Lcd_Cursor_off);
Lcd_out(1,1,”hello joel’s lab”);
Lcd_out(2,1,”distance measurm”);
delay_ms(1000);
Lcd_Cmd(_Lcd_Clear);
Lcd_out(2,1,”distance = “);
do{
Inttostr(dist,txt);
Ltrim(txt);
Lcd_out(2,11,txt);
Lcd_out_cp(” cm “);
TRIG=1;
delay_us(10);
TRIG=0;
delay_ms(100);
}while(1);
}
You can download the proteus library for hc-sr 04 from this link, the complete project can be downloaded from this link. I designed it using proteus 8.3. comment if you need the diagram with an earlier version of proteus
If any of the links are unavailable, just comment with your email and I will send you the project. Thanks for reading through and please leave a comment.
by Joel NGONGA
can you tell the changes required for displaying the same on 7 segment display instead of LCD
LikeLike
if u want to use a 7 segment display, u can just follow 1 of my old posts on that topic.https://blogelect.wordpress.com/2015/04/12/multiplexing-more-than-one-7-segment-display-with-microcontroller/
LikeLike
pule15@outlook.com
LikeLike
How can I use hc-sr04 with pic16f887,please send me a code if possible
LikeLike
Hc-sr04 interfacing it with microcontroller
Please send me a code and full project
LikeLike
nice project and very good explanation.
i wanted to interface pic16f84A with ultrasonic module. the microcontroller uses only timer0, how can i implement the same project using timer0? can you elp
LikeLike
sheriff if u wish to use timer, u will just need to do some extra calculations related to the timer. the code won’t change much
LikeLike
How do i interface two ultrasonic sensors to a PIC16F877A
LikeLike
I rewrote your code with MPlab and using a 8Mhz crystal, but one thing i dnt get, where did u get the 0.2us from …
LikeLike
n.mahdi14@gmail.com
here is me e-mail
please send me full project
LikeLike
can you add buzzer to the code
and in protues so i can test it
the buzzer peeps when distance is 5 cm for example ?
n.mahdi14@gmail.com
this is my e-mail
LikeLike
yes, code returns the distance before displaying it on LCD. you will just need to test the value using an ‘if’ statement and put on or off a particular port.
if u need faster response please write directly to ngongajoel@gmail.com
LikeLike
deepakkumar210594@gmail.com
send me full project with c file for pic18f4550
LikeLike
hai, can you email to me the complete project? its for my final project. thank you. this is my email nffaj66@gmail.com
LikeLike
Can I use it but instead of measuring the distance, I can measure the speed?
LikeLike
speed of what? more details please
LikeLike
Which compiler you’ve used to write the code?
LikeLike
milroc Pro for pic
LikeLike
there’s a link at the bottom of the page. use it to download the complete project
LikeLike
Please send me full project @ abhinav.singh516@gmail.com.
Thanku 🙂
LikeLike
you are welcomed
LikeLike
there is one thing i dont understand bro, have made the function void interrupt in the starting of the code before the main fnction. but in your d0 loop you havnt called that function for even once… i dont think that code would work. coz i chked it in my breadboard..you need to call that inrerrupt function again and again to calculate the distance every time… plz correct me if i m wrong..
LikeLike
an interrrupt is not a funtion like other functions. u can read more about interrupts on google
LikeLike
please sund to me your comlet project.
thank you!!
LikeLike
How can i connect two ultrasonic sensors with pic 16f877a microcontroller and the C code?
LikeLike
it is possible to do that. but u will need to do some small adjustment on my code and diagram
LikeLike