Interfacing HC-SR04 Ultrasonic Sensor with PIC Microcontroller

Interfacing HC-SR04 Ultrasonic Sensor with PIC Microcontroller

Contents

HC-SR04 Ultrasonic Sensor

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.

HC-SR04 module has 4 pins :

  • VCC – 5V, +ive of the power supply
  • TRIG – Trigger Pin
  • ECHO – Echo Pin
  • GND – -ive of the power supply

TRIG and ECHO pins can be used to interface this module with a microcontroller unit. These are TTL (0 – 5V) input output pins.


HC-SR04 Ultrasonic Module Working

Ultrasonic Module Operation
Ultrasonic Module Operation
  1. Provide TRIGGER signal, atleast 10μS High Level (5V) pulse.
  2. The module will automatically transmit eight 40KHz ultrasonic burst.
  3. If there is an obstacle in-front of the module, it will reflect the ultrasonic burst.
  4. 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 150μS to 25mS and if no obstacle is detected, the echo pulse width will be about 38ms.
Working of HC-SR04 Ultrasonic Sensor
Working of HC-SR04 Ultrasonic Sensor

Interfacing with PIC Microcontroller

Circuit Diagram

Interfacing HC-SR04 Ultrasonic Distance Sensor with PIC Microcontroller
Interfacing HC-SR04 Ultrasonic Distance Sensor with PIC Microcontroller

PIC 16F877A is the heart of this circuit. VDD and VSS of PIC Microcontroller is connected to +5V and GND respectively which will provide necessary power for its operation. A 8MHz crystal is connected to OSC1 and OSC2 pins of PIC, to provide clock for its operation. 22pF capacitors connected along with the crystal will stabilize the oscillations generated by the crystal. 16×2 LCD is connected to PORTD which is interfaced using 4 bit mode communication. 10KΩ preset is used to adjust the contrast of the LCD. A 100Ω resistor is used to limit current through the LCD back-light LED.

TRIGGER pin of HC-SR04 sensor is connected to RB0 (pin 33) of PIC which is to be configured as an Output PIN (TRIS bit is 0) and ECHO pin is connected to RB4 (pin 37) which is to be configured as an Input PIN (TRIS bit is 1).

Programming

Basic Steps :

  1. Provide TRIGGER to ultrasonic module
  2. Listen for Echo
  3. Start Timer when ECHO HIGH is received
  4. Stop Timer when ECHO goes LOW
  5. Read Timer Value
  6. Convert it to Distance
  7. Display it

Timer1 Module

Timer1 Module can be used as a 16 bit counter or timer. It consists of two 8 bit registers TMR1H and TMR1L which are readable and writable. The register pair, TMR1H:TMR1L increments from 0000H to FFFFH and rolls over to 0000H. If enabled Timer1 Overflow Interrupt is generated during rolls over to 0000H. Here we will use this module as a 16 bit Timer.

Timer1 Control Register
Timer1 Control Register
Timer1 Module Block Diagram
Timer1 Module Block Diagram

Since we are using Timer1 module as a Timer, we should use internal clock (Fosc/4), ie TMR1CS = 0. Prescaler is used to divide the internal clock (Fosc/4). Here we can set Prescaler as 2, ie T1CKPS1 = 0 & T1CKPS0 = 1. T1SYNC bit is ignored when TMR1CS = 0. As we are using internal clock (Fosc/4) we can disable oscillator, ie T1OSEN = 0. TMR1ON bit can be used to ON or OFF timer as per our requirements.

  • Thus we can initialize timer as : T1CON = 0x10
  • To TURN ON the Timer : T1CON.F0 = 1 or TMR1ON = 1
  • To TURN OFF the Timer : T1CON.F0 = 0 or TMR1ON = 0

Fosc is the oscillator frequency, here we are using 8MHz crystal hence Fosc = 8MHz.

Time = (TMR1H:TMR1L)*(1/Internal Clock)*Prescaler

Internal Clock = Fosc/4 = 8MHz/4 = 2MHz

Therefore, Time = (TMR1H:TMR1L)*2/(2000000) = (TMR1H:TMR1L)/1000000

Distance Calculation

  • Distance = Speed * Time
  • Let d be the distance between Ultrasonic Sensor and Target
  • Total distance traveled by the ultrasonic burst : 2d (forward and backward)
  • Speed of Sound in Air : 340 m/s = 34000 cm/s
  • Thus, d = (34000*Time)/2, where Time = (TMR1H:TMR1L)/(1000000)
  • Therefore, d = (TMR1H:TMR1L)/58.82 cm
  • TMR1H:TMR1L = TMR1L | (TMR1H<<8)

Simple Method – MikroC & MPLAB XC8 Program

MikroC Code

// LCD module connections
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections

void main()
{
  int a;
  char txt[7];
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);          // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);     // Cursor off

  TRISB = 0b00010000;           //RB4 as Input PIN (ECHO)

  Lcd_Out(1,1,"Developed By");
  Lcd_Out(2,1,"electroSome");

  Delay_ms(3000);
  Lcd_Cmd(_LCD_CLEAR);

  T1CON = 0x10;                 //Initialize Timer Module

  while(1)
  {
    TMR1H = 0;                  //Sets the Initial Value of Timer
    TMR1L = 0;                  //Sets the Initial Value of Timer

    PORTB.F0 = 1;               //TRIGGER HIGH
    Delay_us(10);               //10uS Delay
    PORTB.F0 = 0;               //TRIGGER LOW

    while(!PORTB.F4);           //Waiting for Echo
    T1CON.F0 = 1;               //Timer Starts
    while(PORTB.F4);            //Waiting for Echo goes LOW
    T1CON.F0 = 0;               //Timer Stops

    a = (TMR1L | (TMR1H<<8));   //Reads Timer Value
    a = a/58.82;                //Converts Time to Distance
    a = a + 1;                  //Distance Calibration
    if(a>=2 && a<=400)          //Check whether the result is valid or not
    {
      IntToStr(a,txt);
      Ltrim(txt);
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1,"Distance = ");
      Lcd_Out(1,12,txt);
      Lcd_Out(1,15,"cm");
    }
    else
    {
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1,"Out of Range");
    }
    Delay_ms(400);
  }
}

MPLAB XC8 Code

#define _XTAL_FREQ 8000000

#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7

#include <xc.h>
#include "lcd.h";
#include <pic16f877a.h>

// BEGIN CONFIG
#pragma config FOSC = HS   
#pragma config WDTE = OFF  
#pragma config PWRTE = OFF 
#pragma config BOREN = ON 
#pragma config LVP = OFF   
#pragma config CPD = OFF   
#pragma config WRT = OFF  
#pragma config CP = OFF    
//END CONFIG
void main()
{ 
  int a;

  TRISB = 0b00010000;         //RB4 as Input PIN (ECHO)
  TRISD = 0x00;               // LCD Pins as Output

  Lcd_Init();

  Lcd_Set_Cursor(1,1);
  Lcd_Write_String("Developed By");
  Lcd_Set_Cursor(2,1);
  Lcd_Write_String("electroSome");

  __delay_ms(3000);
  Lcd_Clear();

  T1CON = 0x10;               //Initialize Timer Module

  while(1)
  { 
    TMR1H = 0;                //Sets the Initial Value of Timer
    TMR1L = 0;                //Sets the Initial Value of Timer

    RB0 = 1;                  //TRIGGER HIGH
    __delay_us(10);           //10uS Delay 
    RB0 = 0;                  //TRIGGER LOW

    while(!RB4);              //Waiting for Echo
    TMR1ON = 1;               //Timer Starts
    while(RB4);               //Waiting for Echo goes LOW
    TMR1ON = 0;               //Timer Stops

    a = (TMR1L | (TMR1H<<8)); //Reads Timer Value
    a = a/58.82;              //Converts Time to Distance
    a = a + 1;                //Distance Calibration
    if(a>=2 && a<=400)        //Check whether the result is valid or not
    { 
      Lcd_Clear();
      Lcd_Set_Cursor(1,1);
      Lcd_Write_String("Distance = ");

      Lcd_Set_Cursor(1,14);
      Lcd_Write_Char(a%10 + 48);

      a = a/10;
      Lcd_Set_Cursor(1,13);
      Lcd_Write_Char(a%10 + 48);

      a = a/10;
      Lcd_Set_Cursor(1,12);
      Lcd_Write_Char(a%10 + 48);

      Lcd_Set_Cursor(1,15);
      Lcd_Write_String("cm");
    }  
    else
    {
      Lcd_Clear();
      Lcd_Set_Cursor(1,1);
      Lcd_Write_String("Out of Range");
    }
    __delay_ms(400);
  }
}

This program uses our LCD Library for MPLAB XC8. You need to download and include the header file “lcd.h”. For more information please read the tutorial, Interfacing LCD with PIC Microcontroller – MPLAB XC8.

I hope that you can understand the working of the above program through comments. If you have any doubts, just comment below.

Distance Calibration

For accurate distance measuring you may calibrate the obtained result. Here for making the displayed distance more accurate, I added 1 to the the measured distance. This constant of calibration can be find using a series of practical experiments with a ruler scale.

In the above program there is a small problem as it infinitely waiting for ECHO and to ECHO goes LOW. If HIGH echo pulse is not received due to any reason, the program may get stuck there. So it is not a good practice to infinitely wait for ECHO and to ECHO goes LOW.  The best solution is to use PORTB On-Change Interrupt feature of PIC Microcontroller.

PORTB On-Change Interrupt

Four pins of PORTB (RB4 – RB7) have interrupt on-change feature. Only those pins configured as INPUT PIN can cause this Interrupt while this interrupt is enabled. If the Logic State of any of these four pin changes (only Input Pins), interrupt will be generated.

PORTB On-Change Interrupt can be enabled by :

  • Set Global Interrupt Enable bit : INTCON.GIE = 1
  • Set PORTB On-Change Interrupt Enable Bit : INTCON.RBIE = 1

Note : PORTB On-Change Interrupt flag (INTCON.RBIF) will be set whenever this interrupt is generated and it should be cleared in software

Using Interrupt – MikroC & MPLAB XC8 Program

MikroC Code

// LCD module connections
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections

volatile int a;

//Interrupt function will be automatically executed on Interrupt
void interrupt() 
{
  if(INTCON.RBIF == 1)                 //Makes sure that it is PORTB On-Change Interrupt
  {
    INTCON.RBIE = 0;                   //Disable On-Change Interrupt
    if(PORTB.F4 == 1)                  //If ECHO is HIGH
      T1CON.F0 = 1;                    //Start Timer
    if(PORTB.F4 == 0)                  //If ECHO is LOW
    {
      T1CON.F0 = 0;                    //Stop Timer
      a = (TMR1L | (TMR1H<<8))/58.82;  //Calculate Distance
    }
  }
  INTCON.RBIF = 0;                     //Clear PORTB On-Change Interrupt flag
  INTCON.RBIE = 1;                     //Enable PORTB On-Change Interrupt
}
 
void main()
{
  char txt[7];
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);                 // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);            // Cursor off

  TRISB = 0b00010000;
  INTCON.GIE = 1;                      //Global Interrupt Enable
  INTCON.RBIF = 0;                     //Clear PORTB On-Change Interrupt Flag
  INTCON.RBIE = 1;                     //Enable PORTB On-Change Interrupt

  Lcd_Out(1,1,"Developed By");
  Lcd_Out(2,1,"electroSome");

  Delay_ms(3000);
  Lcd_Cmd(_LCD_CLEAR);

  T1CON = 0x10;                        //Initializing Timer Module

  while(1)
  { 
    TMR1H = 0;                         //Setting Initial Value of Timer
    TMR1L = 0;                         //Setting Initial Value of Timer

    a = 0;

    PORTB.F0 = 1;                      //TRIGGER HIGH
    Delay_us(10);                      //10uS Delay
    PORTB.F0 = 0;                      //TRIGGER LOW

    Delay_ms(100);                     //Waiting for ECHO
    a = a + 1;                         //Error Correction Constant
    if(a>2 && a<400)                   //Check whether the result is valid or not
    {
      IntToStr(a,txt);
      Ltrim(txt);
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1,"Distance = ");
      Lcd_Out(1,12,txt);
      Lcd_Out(1,15,"cm");
    }
    else
    {
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_Out(1,1,"Out of Range");
    }
    Delay_ms(400);
  }
}

MPLAB XC8 Code

#define _XTAL_FREQ 8000000

#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7

#include <xc.h>
#include "lcd.h";
#include <pic16f877a.h>

// BEGIN CONFIG
#pragma config FOSC = HS 
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON 
#pragma config LVP = OFF 
#pragma config CPD = OFF 
#pragma config WRT = OFF 
#pragma config CP = OFF
//END CONFIG

volatile int a;

void interrupt echo()
{
  if(RBIF == 1)                       //Makes sure that it is PORTB On-Change Interrupt
  {
    RBIE = 0;                         //Disable On-Change Interrupt
    if(RB4 == 1)                      //If ECHO is HIGH
    TMR1ON = 1;                       //Start Timer
    if(RB4 == 0)                      //If ECHO is LOW
    {
      TMR1ON = 0;                     //Stop Timer
      a = (TMR1L | (TMR1H<<8))/58.82; //Calculate Distance
    }
  }
  RBIF = 0;                           //Clear PORTB On-Change Interrupt flag
  RBIE = 1;                           //Enable PORTB On-Change Interrupt
}
void main()
{
  TRISB = 0b00010000;                 //RB4 as Input PIN (ECHO)
  TRISD = 0x00;                       // LCD Pins as Output
  GIE = 1;                            //Global Interrupt Enable
  RBIF = 0;                           //Clear PORTB On-Change Interrupt Flag
  RBIE = 1;                           //Enable PORTB On-Change Interrupt

  Lcd_Init();

  Lcd_Set_Cursor(1,1);
  Lcd_Write_String("Developed By");
  Lcd_Set_Cursor(2,1);
  Lcd_Write_String("electroSome");

  __delay_ms(3000);
  Lcd_Clear();

  T1CON = 0x10;                       //Initialize Timer Module

  while(1)
  {
    TMR1H = 0;                        //Sets the Initial Value of Timer
    TMR1L = 0;                        //Sets the Initial Value of Timer

    RB0 = 1;                          //TRIGGER HIGH
    __delay_us(10);                   //10uS Delay
    RB0 = 0;                          //TRIGGER LOW 

    __delay_ms(100);                  //Waiting for ECHO
    a = a + 1;                        //Error Correction Constant

    if(a>=2 && a<=400)                //Check whether the result is valid or not
    {
      Lcd_Clear();
      Lcd_Set_Cursor(1,1);
      Lcd_Write_String("Distance = ");

      Lcd_Set_Cursor(1,14);
      Lcd_Write_Char(a%10 + 48);

      a = a/10;
      Lcd_Set_Cursor(1,13);
      Lcd_Write_Char(a%10 + 48);

      a = a/10;
      Lcd_Set_Cursor(1,12);
      Lcd_Write_Char(a%10 + 48);

      Lcd_Set_Cursor(1,15);
      Lcd_Write_String("cm");
    }
    else
    {
      Lcd_Clear();
      Lcd_Set_Cursor(1,1);
      Lcd_Write_String("Out of Range");
    }
    __delay_ms(400);
  }
}

This program uses our LCD Library for MPLAB XC8. You need to download and include the header file “lcd.h”. For more information please read the tutorial, Interfacing LCD with PIC Microcontroller – MPLAB XC8.

Download

You can download entire project files here.

Want to See the Output ?

Share this post

  • Very good tutorial an the HC-SR04 – just some remarks:

    1) To avoid unexpected behaviour/results always use “volatile” for variables in context with interrupt routines:

    volatile unsigned int a;

    instead of:

    int a; // there are no negative numbers, so use “unsigned int”

    2) always add a counter to check how many times there was a timer overflow to get a correct result (even if in this case an overflow may not be expected)

    3) for measuring a pulse width you may also use the capture mode of the CCP module of your PIC (if available)

  • Yes you can add another one. Just read data from each sensors one by one instead of doing simultaneously. When you do it fast, it will appear as simultaneous for us.

  • Yes it does, however you will have to make some subtle changes. For example, instead of simply typing “RBIF”, you will need to type “INTCONbits.RBIF”. There are many place you will need to do this in the code, including doing the same thing with “TMR1ON” which you would frame as “T1CONbits.TMR1ON”. Once you do that you should be fine. If you paste your code I will be able to tell you exactly how to frame it. Otherwise simply search the word following PIC18 and the syntax should come up on some forum.

  • Hello. Thank you for providing this amazing tutorial, it is indeed very helpful.

    Will this program work with the PIC18F4620?

  • Can someone please explain to me how this was derived? d = (TMR1H:TMR1L)/58.82 cm
    especially the 58.82 part. I’m using a 20Mhz osci and I need to calculate my own values to use, but I don’t understand how.

  • What‘s difference between the simple and using interrupt methods? does the second method will be more accurate and real-time reaction than the first simple loop one? thanks

  • What’s the meaning of “Lcd_Write_Char(a%10 + 48)”, especially the “+48”? thanks!

  • Hi just a small question, can ADC also be used when using the Timer1? or does it cause problems? Many thanks and your tutorials are very good 🙂

  • void interrupt echo()
    {
    if(RBIF == 1){ //Makes sure that it is PORTB On-Change Interrupt
    RBIE = 0; //Disable On-Change Interrupt
    if(RB4 == 1) //If ECHO is HIGH
    TMR1ON = 1; //Start Timer
    if(RB4 == 0) //If ECHO is LOW
    {
    TMR1ON = 0; //Stop Timer
    a = (TMR1L | (TMR1H<<8))/58.82; //Calculate Distance } if(RB5 == 1) //If ECHO is HIGH TMR1ON = 1; //Start Timer if(RB5 == 0) //If ECHO is LOW { TMR1ON = 0; //Stop Timer b = (TMR1L | (TMR1H<<8))/58.82; //Calculate Distance } RBIF = 0; //Clear PORTB On-Change Interrupt flag RBIE = 1; //Enable PORTB On-Change Interrupt } is it possible to add a new HC-sr by doing this and using other 10us trigger function?

  • Please correct this line

    a = a + 1; //Distance Calibration

    Remove the at the end, kept me guessing for a while
    Perhaps a mention to include the Libraries for Conversion, C String and and LCD might help some others.
    Thanks

  • Do we put the interrupt and lcd in a separate source file and the ping sensor in a separate source file?

  • can someone tell me why is he dividing (time)/58cm for distance? distance formula is supposed to be speed*time. and where did the 58 come from? thanks for the help

  • hi guys; tried this code on the PIC16F877A and it works well. I’m using it in an application where I need to monitor a liquid level. A decrease in the liquid level (increase in distance) needs to trigger another routine.
    Could somebody please tell me how I can go about doing this. I know it sounds easy but I just can’t seem to do it. I’m using MPLABX, XC8. thanks in advance

  • I need to talk directly to the one who put the circuit
    I’ll tell you where is the problem
    NOBODY ever tried the circuit because it has a awful error!!!!!
    he said that we should connect the ECHO pin to the interrupt pin directly but he has done the exact opposit
    but this does not mean that the written program is written correct (which I do not understand!)
    So my friend where is the use of the interrupt???!!!!
    but it works but we did not learn any thing from it!

  • adjust the microcontroller settings you are not sellecting the specified microcontroller
    believe me I have faced this same error

  • I’ll tell you where is the problem
    NOBODY ever tried the circuit because it has a awful error!!!!!
    he said that we should connect the ECHO pin to the interrupt pin directly but he has done the exact opposit
    but this does not mean that the written program is written correct (which I do not understand!)

  • good evening dr. ligo
    may you modify the code of the ultrasonic sensors to 6 sensors and the results will go to the raspberry pi through spi using mplab x xc8
    also, may you give me ur email???
    thanks
    i am waiting ur replay
    faithful: john

  • I am using MikroC 6.6.3 and modified your code little bit

    want to control my motor on interrupt using ultrasound sensor that you used in your tutorial but when i complied my code it gives the error that ” ‘a’ Identifier redefined ”
    I am pasting the code

    motors are not properly reversing after getting the interrupt if I declare that “int a” inside the void interrupt()

    I am using 18F452 PIC micrfocontroller

    void Motor1_forward();
    void Motor1_backward();
    void Motor2_forward();
    void Motor2_backward();
    void Motor1_stop();
    void Motor2_stop();
    int a;

    void interrupt()
    {
    //int a;
    if(INTCON.RBIF == 1) //Makes sure that it is PORTB On-Change Interrupt
    {
    INTCON.RBIE = 0; //Disable On-Change Interrupt
    if(PORTB.F4 == 1) //If ECHO is HIGH
    T1CON.F0 = 1; //Start Timer
    if(PORTB.F4 == 0) //If ECHO is LOW
    {
    T1CON.F0 = 0; //Stop Timer
    a = (TMR1L | (TMR1H<<8))/58.82; //Calculate Distance
    if (a2 && a<400) //Check whether the result is valid or not

    // { //Check whether the result is valid or not
    // Motor1_backward();
    // Motor2_backward();
    // }

    /* Motor1_forward();
    Motor2_forward();
    Delay_ms(2000);

    Motor1_stop();
    Motor2_stop();
    Delay_ms(1000);

    Motor1_backward();
    Motor2_backward();
    Delay_ms(2000);

    Motor1_stop();
    Motor2_stop();
    Delay_ms(1000); */

    }while(1);

    }

    void Motor1_forward()
    {
    PORTB.B1 = 1; // Forward Motion
    PORTB.B2 = 0;
    }
    void Motor1_backward()
    {
    PORTB.B1 = 0; // Backward Motion
    PORTB.B2 = 1;
    }
    void Motor2_forward()
    {
    PORTB.B3 = 0; // Forward Motion
    PORTB.B5 = 1;
    }
    void Motor2_backward()
    {
    PORTB.B3 = 1; // Backward Motion
    PORTB.B5 = 0;
    }
    void Motor1_stop()
    {
    PORTB.B1 = 0; // Stop
    PORTB.B2 = 0;
    }
    void Motor2_stop()
    {
    PORTB.B3 = 0; // Stop
    PORTB.B5 = 0;
    }

  • Hi, good work. I have a question for you. What would be the modification to make the code so that the value of the distance has two decimal precision on the LCD. I use Mikroc. And sorry for my English.

  • What is the meaning of this : d = (TMR1H:TMR1L)/58.82 cm.

    And What is the meaning of: TMR1H:TMR1L = TMR1L | (TMR1H<<8)

  • Hello, I tried to do this. I used PIC 16F887 microcontroller and used the same ports of your sample, but it doesn’t work. This example I didn´t include LDC Display, my only indicator is a LED. When a object is nerby LED turns on.

  • I am only trying to find distance without LCD display. But a using pic16f690 it has an preset internal clock of 4 MHz will your code work or do I have to modify it. I am using Mikroc for programming

  • i tried to use the code of interrupt in above in 16f887 but it didn’t
    work . although the register of both ic are same…. Why ??? (I.E i used both ANSEL register zero for digital input )

  • Hi,Ligo George,thanks for the code.I used your logic to display the distance after every 1s on a serial terminal ‘hterm’.i used PIC18F26K22.The problem is I get decimal values like 2,3,4,5 on the serial terminal,which do not match with the actual distance I am measuring.Also the output changes by itself even when the distance to object is kept constant.Can you help?

  • hello sir…i have done make this project..but can add the distance 400 cm to 1000 cm or more

  • Hi ligo can u please give me your mail id
    i have some doubts regarding a project using RF communication
    can u please help me in suggesting!..

  • Dear Experts,

    I have just finished my project for measuring the distance using HC-SR04.
    My project is similar with the one described in this page.
    I used PIC 18F452 with 4 MHz HS crystal oscillator.

    I cannot understand why the code is not working without repeating the line:
    “dist = (TMR1L | (TMR1H<<8))/59; //Calculate Distance"
    Could you please find a explanation and share it to me?
    I found this solution by chance when I double written that line by mistake.

    Thank you in advance!
    Adrian

    Full code:
    // LCD module connections
    sbit LCD_RS at RD2_bit;
    sbit LCD_EN at RD3_bit;
    sbit LCD_D4 at RD4_bit;
    sbit LCD_D5 at RD5_bit;
    sbit LCD_D6 at RD6_bit;
    sbit LCD_D7 at RD7_bit;

    sbit LCD_RS_Direction at TRISD2_bit;
    sbit LCD_EN_Direction at TRISD3_bit;
    sbit LCD_D4_Direction at TRISD4_bit;
    sbit LCD_D5_Direction at TRISD5_bit;
    sbit LCD_D6_Direction at TRISD6_bit;
    sbit LCD_D7_Direction at TRISD7_bit;
    // End LCD module connections

    int time;
    int dist;

    //Interrupt function will be automatically executed on Interrupt
    void interrupt()
    {
    if(INTCON.RBIF == 1) //Makes sure that it is PORTB On-Change Interrupt
    {
    INTCON.RBIE = 0; //Disable On-Change Interrupt
    if(PORTB.F4 == 1) //If ECHO is HIGH
    T1CON.F0 = 1; //Start Timer
    if(PORTB.F4 == 0) //If ECHO is LOW
    {
    T1CON.F0 = 0; //Stop Timer
    dist = (TMR1L | (TMR1H<<8))/59; //Calculate Distance ????
    dist = (TMR1L | (TMR1H<<8))/59; //Calculate Distance
    time = (TMR1L | (TMR1H<2 && dist<400) //Check whether the result is valid or not
    {
    dist = dist + 1; //Error Correction Constant
    IntToStr(dist,txt);
    Ltrim(txt);
    Lcd_Out(1,1,"Distance = ");
    Lcd_Out(1,12,txt);
    Lcd_Out(1,15,"cm");
    }
    else
    {
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Out(1,1,"Out of Range");
    }

    IntToStr(time,txt);
    Ltrim(txt);
    Lcd_Out(2,1,"Time = ");
    Lcd_Out(2,8,txt);

    Delay_ms(400);
    }
    }

  • do you have the code in mplab ide form? i mean code to generate using mplab ide
    p/s : sorry for bad english

  • Hello,
    Above project is 100% working. Voltage on pins will vary depends on the type of signal on it.

    First try some LED blinking projects and verify everything is working fine.

  • Can i ask for the proteus library of hcsr04?I cant find anything that is not arduino compatible

  • I thank you for the program. Can I use the simple method with PORTC instaed of PORTB?

  • Hello, i have done the exact schematics and i have loaded the PIC16F877A with your hex (i have tried both versions)but all the PIC pins have between the 0.8V and 1V. The display even disconnected from the PIC it shows the below line fully black. Any suggestion? I’m programming the PIC with a Velleman K8076. Am i doing something wrong? What could cause this? I have also a PIC18F4550 and i have tried the same with the suggestions within the comments but still sam issue… I initially suspected the programmer kit but after being able to read from the chip the hex that i just downloaded it did not made any sense..

  • how can i write a code for hc-sr04 with led and buzzer instead of ldr? can you help plz?

  • #include

    #include

    #include”delay.h”

    #include”config.h”

    #include”uart.h”

    #include”lcd.h”

    #define Fosc 20000000 /* External crystal frequency */

    #define baud 9600 /* UART baud rate */

    #define config2 ((Fosc/baud/64)-1)

    unsigned char config1 = (USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW);

    int a;

    void interrupt echo()

    {

    if(RBIF == 1) //Makes sure that it is PORTB On-Change Interrupt

    {

    RBIE = 0; //Disable On-Change Interrupt

    if(RB4 == 1) //If ECHO is HIGH

    TMR1ON = 1; //Start Timer

    if(RB4 == 0) //If ECHO is LOW

    {

    TMR1ON = 0; //Stop Timer(TMR1L | (TMR1H<<8));

    a = (TMR1L| (TMR1H<=2 && a<=400)

    {

    Write_str("distance =");

    Write_LCD("Distance= ");

    Write(a/100 + 48);

    Data(a/100 +48);

    // Command(0x80);

    a = a%100;

    Write(a/10 + 48);

    Data(a/10 + 48);

    //Command(0x80);

    a = a%10;

    Write(a+48);

    Data(a+48);

    Write_LCD(" cm ");

    Command(0x80);

    }

    else

    {

    Write_str("Out of Range");

    Write_LCD("out of range");

    Command(0x80);

    }

    delay_ms(400);

    }

    }

  • you need to rename,config bits ,name of timer registers
    change the things like TRIS to DDRA
    include AVR header files
    and please cheak atmega 32 have interrupt on-change feature
    if not follow the first program.

    logic is same as above .

  • hi, im testing it in proteus, everything looks fine but after abaut 14sec i have error. And proteus just turn’s off. Can you help me solve the problem ?

  • Can this code be used with avr and/ atmega32 using Mikroc pro avr 2015 build6.1.0? what changes have to do?
    if only change TRIS to DDR,can i use?
    what does fusebits means?
    Plz help

  • you need to add header files for both delay and UART and also setup the config bits

  • Hi i am doing this program with Pic24.
    I have written the following Program and checking its output on Tera Term
    But I am not able to get the Sensor Output
    If Anybody can help

    Here’s the program

    #include “pic24_all.h”

    #include

    /** file

    * Measures the pulse width of a pushbutton switch using Timer2 without input capture.

    * CLOCK_CONFIG=PRIPLL_8MHzCrystal_40MHzFCY is defined in the MPLAB project.

    * Remove this macro if you wish to use the internal oscillator.

    */

    #define R2 _LATB2

    #define CONFIG_R2_DIG_OUTPUT() CONFIG_RB2_AS_DIG_OUTPUT()

    void CONFIG_ROW() {

    CONFIG_R2_DIG_OUTPUT();

    //CONFIG_R2_DIG_OUTPUT();

    }

    inline void CONFIG_SW1() {

    CONFIG_RB13_AS_DIG_INPUT(); //use RB13 for switch input

    ENABLE_RB13_PULLUP(); //enable the pullup

    }

    #define SW1 _RB13 //switch state

    #define SW1_PRESSED() SW1==0 //switch test

    #define SW1_RELEASED() SW1==1 //switch test

    void configTimer2(void) {

    T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF

    | T2_32BIT_MODE_OFF

    | T2_SOURCE_INT

    | T2_PS_1_256 ; //at 40 MHz, approx 420 ms period, 1 tick = 6.4 us

    PR2 = 0xFFFF; //maximum period

    TMR2 = 0; //clear timer2 value

    _T2IF = 0; //clear interrupt flag

    T2CONbits.TON = 1; //turn on the timer

    }

    /// Switch1 configuration

    int main (void) {

    CONFIG_ROW();

    uint16_t u16_start, u16_delta;

    uint32_t u32_pulseWidth;

    configBasic(HELLO_MSG);

    CONFIG_SW1(); //use RB13

    R2 = 1;

    DELAY_US(10);

    R2 = 0;

    configTimer2();

    while (1) {

    //outString(“Press button…”);

    while (SW1_RELEASED())doHeartbeat();

    u16_start = TMR2;

    while (SW1_PRESSED())doHeartbeat();

    u16_delta = TMR2 – u16_start; //works because using maximum PR2 value

    u32_pulseWidth = ticksToUs((uint32_t) u16_delta,getTimerPrescale(T2CONbits));

    u32_pulseWidth = (u32_pulseWidth/58);// DISTANCE IN CM

    printf(” %ld usn”,u32_pulseWidth);

    DELAY_MS(100);

    }

    }

  • For pic 18f4550 mplab xc8

    // add uart lib -(* _ *)-

    thanks LIGO for this awesome -(* _ *)-

    //Time = (TMR1H:TMR1L)*(1/Internal Clock)*Prescaler

    //internal clock=fosc/4 ie, your crystal freq/4

    #include

    #include

    #include”delay.h”

    #include”config.h”

    #include”uart.h”

    #define Fosc 20000000 /* External crystal frequency */

    #define baud 9600 /* UART baud rate */

    #define config2 ((Fosc/baud/64)-1)

    unsigned char config1 = (USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW);

    int a;

    void interrupt echo()

    {

    if(RBIF == 1) //Makes sure that it is PORTB On-Change Interrupt

    {

    RBIE = 0; //Disable On-Change Interrupt

    if(RB4 == 1) //If ECHO is HIGH

    TMR1ON = 1; //Start Timer

    if(RB4 == 0) //If ECHO is LOW

    {

    TMR1ON = 0; //Stop Timer(TMR1L | (TMR1H<<8));
    // config for timer with a 20MHz crystal
    a = (TMR1L| (TMR1H<=2 && a<=400)

    {

    Write_str("distance =");

    Write(a/100 + 48);

    a = a%100;

    Write(a/10 + 48);

    a = a%10;

    Write(a+48);

    }

    else

    {

    Write_str("Out of Range");

    }

    delay_ms(400);

    }

    }

  • Hey Ligo,
    The program is working although the clock cycle of HC-SR04 is 18KHz, the program runs at 40 KHz clock cycle.
    Due to this, we are able to get the exact distance estimation of rigid objects that are far, but not the ones that are near. Could you suggest any alternatives or how to tackle this problem??

  • Hey Ligo, thanks for your earlier response. 🙂

    I’m using a K150u programmer to read and write the code onto PIC16F877A micro-controller.
    I’m able to read and verify the code although when I remove the chip and place it on my bread board, I’m not getting any output. What do you think might be the fault?

  • bro i am able to load my code into pic microcontroller but lcd does not show anything its blank kindly plzz help asap

  • Please tell me how to interface ultrasonic sensor and Gsm Module with Micro controller . I want detect object and send data on mobile using GSM module. Please Guide me.

  • Could you please upload a tutorial of ‘how to interface SR-04 with PIC18F4550’ for measuring distance!

  • Hi, I’m trying to make it work on the PIC18f4431, but most of the time I only get the value 5 on “a”. Hope you can help me. Thanks.

    #include

    /*

    *

    */

    void delay_ms(unsigned int ms)

    {

    T0CON=0b11000011;

    for(int i=0;i<ms;i++)

    {

    TMR0L=131;

    do{}while(TMR0IF==0);

    TMR0IF=0;

    }

    }

    void delay_us(unsigned int us)

    {

    T0CON=0b10001011;

    for(int i=0;i<us;i++)

    {

    TMR0H=0xFF;

    TMR0L=0xFE;

    do{}while(TMR0IF==0);

    TMR0IF=0;

    }

    }

    unsigned int d;

    void interrupt echo()

    {

    if(RBIF == 1) //Makes sure that it is PORTB On-Change Interrupt

    {

    RBIE = 0; //Disable On-Change Interrupt

    if(PORTBbits.RB4 == 1) //If ECHO is HIGH

    TMR1ON = 1; //Start Timer

    if(PORTBbits.RB4 == 0) //If ECHO is LOW

    {

    TMR1ON = 0; //Stop Timer

    d = (TMR1L | (TMR1H<<8))*100/5882; //Calculate Distance

    }

    }

    RBIF = 0; //Clear PORTB On-Change Interrupt flag

    RBIE = 1; //Enable PORTB On-Change Interrupt

    }

    void main(void) {

    //OSCCONbits.IRCF = 0b111;

    TRISB = 0b00010000;

    TRISDbits.RD2=0; //LED

    T1CON=0x90;

    IPEN=1;

    GIE=1;

    GIEL=1;

    RBIE = 1; //Enable PORTB On-Change Interrupt

    RBIF = 0; //Clear PORTB On-Change Interrupt Flag

    while(1){

    TMR1H = 0; //Sets the Initial Value of Timer1

    TMR1L = 0; //Sets the Initial Value of Timer1

    PORTBbits.RB0 = 1; //TRIGGER HIGH

    delay_us(10);

    PORTBbits.RB0 = 0; //TRIGGER LOW

    delay_ms(100); //Waiting for ECHO

    d=d+1;

    delay_ms(400);

    }

    }

  • I am doing the same conections, and same programming and it doesn´t work… How can I get it right

  • Hi! This is a great post, here you show the code and the conections, which is hard to find in the same post together.

    I’m using the pic 18F4550 and the HC-SR04 sensor, with MPLAB X.

    I have a question. I tried to follow the steps you put here. The program compiles correctly but nothing appears in my display.

    I tried to use a 7 segment display to see only the numbers 1, 2 or 3 depending of the measure of the sensor, but again, nothing appears in the display.

    My question is the next:

    I saw that for my pic, I need to use the I2C communication, which is available in the SDA and SCL pins, and I saw also that SCL behave as trigger and SDA as eco. What do you think about to use this pins to make it work? You think that it is possible to send the trigger with SCL and listen the eco with SDA and use that value to see the measure?

    and the last one, you think that it is necessary to use the I2C bus to do this?

    I hope you can understand the question.

    Thanks in advance for your help.

  • Gentlemen, thnx for this post. I have problem loading the hex file to my pic16f877a MCU, im using pickit3, MPLABX V 1.60. It says:” Address: 0 Expected Value: 2ba3 Received Value: 2b20, failed to program device. ”

  • im trying to create xc8 code to interface GSM module with PIC16 Microcontroller – any help

  • Sorry, I don’t have time to do programming for you. I can only provide a little technical support.
    You can take the above logic and most parts of the code and implement it in your controller.

  • This is really cool.Can you help me with HC-SR04 interfacing with PIC16F690?

  • what is the use these two comands it compile shows error how to solve it

    IntToStr(a,txt);

    Ltrim(txt);

  • Hey I need a code for obstacle detection using HCSR04 and glowing of corresponding led’s.eg.if a obstacle is at a distance of 200m from sensor,then only 1 led should glow.For 180m,2 led’s should glow and so on…I am using PIC18F4520.Can you plz help me out.

  • Hi, I need the same code for PIC16F877A, could you help me?

    I’m using:

    MPLAB IDE

    Compiler Hi Tech C

    PIC16F877A

  • how can i do this ultrasonic interfacing using dspic30f4011 microcontroller. what wil be the change in mikroc code for timer part. plz help . thnk u 🙂

  • What if the sensor got disconnected? The program would simply hang in this line of code

    while(!PORTB.F4); //Waiting for Echo

    Go on waiting forever. No Sensor = No Echo.

    Rather it should show a NO SENSOR Error on such conditions.

  • hi ligo.i’m trying to config timer1 pic16f877a in mplabx with xc8 compiler.
    this one is my c code:
    T1CON=0b00011101;//T1CKPS1=0;T1CKPS0=1;T1OSCEN=0;T1SYNC=1;TMR1CS=0;TMR1ON=1;
    INTCON=0b11000000; //GIE=1; PEIE=1; T0IE=0; INTE=0; RBIE=0; T0IF=0; INTF=0; RBIF=0;
    PIE1=0b00000001;//TMR1IE=1
    PIR1=0b00000001;//TMR1IF=1;
    //OPTION_REG = 0b10000001; //RBPU’=1; INTEDG=0; T0CS=0,f_osc/4; T0SE=0; PSA=0,pre to timer0; PS=1/4
    but it doesnt work please help me more .

  • Can I use the same code for the ultrasonic Sensor that have three pins (5V, GND, SIG) ??
    I want to make a mikroC program using TMR1 to solve the distance Issue

  • You may use 8bit timer.. It is up to you.

    If you use same pins for triggering .. . all sensors will be triggered at the same time.. It will make difficult to read the response.

  • Hello there..Can you help me i try the programm on 18f4550 and it doesn’t works..May i make any changes?

  • Ligo George,what if i use 8bit timer2 of pic16877a…what difference will that make?

  • Thx,

    Now i am working for a procejt with mikrocontroller 16F887 and i’m using microC pro for pic. I have finished the code but i can’t put in real controller. If you can help with any information to do that.
    Thank you so much for all,
    Robert

  • hi ligo..please help me with the code (specially interrupt function) while interfacing two HC-SR04…like you said i used RB5 as a echo pin for 2nd sensor..but still m not getting the desired output..i want both the sensor to display same result on lcd simultaneously for the same obstacle..

  • hi ligo..please help me with the code (specially interrupt function) while interfacing two HC-SR04…like you said i used RB5 as a echo pin for 2nd sensor..but still m not getting the desired output..i want both the sensor to display same result on lcd simultaneously for the same obstacle..

  • hi, I like very much your project, nice.
    Can you help me for the sensor hc-sr04 in proteus. Where can found it?
    Thx.

  • For the correct distance measurement, you need to change the frequency in the program and constant for finding distance from timer value.

  • So the response time wont be affected by using a lower crystal . I am using 3.2768Mhz instead of 8Mhz

  • hi, will it make a difference , i am using the xtal 3.2768MHz, also i am get “not enough ram for call stack” when compiling in MikroC. thank you in advance

  • my code for HCSR04 FOR PIC18F26K80 USING MP LAB X IDE . XC8…

    I DIDNT GOT OUT PUT ………

    void delay_ms(unsigned char);

    #define TMR0TICKSEC 0.000001/// this depend on T0CON settings.

    void delaytimer0tick(unsigned char num);

    float a;

    float pulsewidth=0,distance=0;

    void main(void)

    {

    SWDTEN=0;

    PLLEN=1;

    TRISB = 0b00010001;

    LATB=0X11;

    PORTB=0X00;

    IPEN = 0;

    GIEH = 0;

    GIEL = 0;

    T0CON = 0xD3;//11010011, tick =1/( (64e6/4)/16) =

    while(1)

    {

    LATBbits.LATB0= 1;

    delaytimer0tick(10000); //10 ms delay = 100 * tick = 100* 0.000001 sec = 0.0001 sec ~ 100 usec

    LATBbits.LATB0=0;

    while(PORTBbits.RB4==1);//wait echo rising edge

    TMR0=0;

    while(PORTBbits.RB4==0);//wait till falling edge

    pulsewidth=(TMR0*TMR0TICKSEC);

    distance= (pulsewidth / 75.0);

    distance=0;

    }

    }

    void delaytimer0tick(unsigned char num)

    {

    TMR0=0;

    while(TMR0==num);

    }

  • The software might be easier if a PIC like the 12F683 or 16F688 is used. They have a T1G input which allows you to gate the Timer1 count. I have used both of those micros for this task and wired the INT (external interrupt) pin to the T1G pin. That allows the start of the echo pulse to turn on the gate while the end of the echo pulse turns off the gate and interrupts the micro. Works great. I do, of course, use a shift register (74164) to drive the LCD display so that I only need 3 pins for that function.

  • what wrong with me . on these code change mcu with 16f676

    #define _XTAL_FREQ 8000000

    #define RS RC5
    #define EN RC4
    #define D4 RC0
    #define D5 RC1
    #define D6 RC2
    #define D7 RC3

    //#include
    #include

    #include “lcd.h”;
    #include

    // BEGIN CONFIG
    #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
    //#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is

    digital I/O, HV on MCLR must be used for programming)
    #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
    //#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory

    may be written to by EECON control)
    #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
    //END CONFIG

    void delayMs(int x);

    void main()
    {
    int a;

    TRISA = 0b00010001; //RA0 as Input PIN (ECHO)
    TRISC = 0x00; // LCD Pins as Output

    Lcd_Init();

    Lcd_Set_Cursor(1,1);
    Lcd_Write_String(“Developed By”);
    Lcd_Set_Cursor(2,1);
    Lcd_Write_String(“electroSome”);

    delayMs(3000);
    Lcd_Clear();

    T1CON = 0x10; //Initialize Timer Module

    while(1)
    {
    TMR1H = 0; //Sets the Initial Value of Timer
    TMR1L = 0; //Sets the Initial Value of Timer

    RA0 = 1; //TRIGGER HIGH
    __delay_us(10); //10uS Delay
    RA0 = 0; //TRIGGER LOW

    while(!RA1); //Waiting for Echo
    TMR1ON = 1; //Timer Starts
    while(RA1); //Waiting for Echo goes LOW
    TMR1ON = 0; //Timer Stops

    a = (TMR1L | (TMR1H<=2 && a0;x–)
    {
    for (i=0;i<=110;i++);
    }
    }

    got error as

    Error [1347] ; 0. can't find 0x21 words (0x21 withtotal) for psect "text142" in segment "CODE" (largest unused contiguous range 0x1E)
    Error [1347] ; 0. can't find 0x12 words (0x12 withtotal) for psect "text140" in segment "CODE" (largest unused contiguous range 0x7)
    Error [1347] ; 0. can't find 0xF words (0xf withtotal) for psect "text144" in segment "CODE" (largest unused contiguous range 0x7)

  • errors” **” came in below prog ..while hcsr04 to pic18f26k80 on xc8 compiler can you please
    explai me…

    void _interrupt()

    {

    **if (INTCONbits.RBIF==1)

    {

    **INTCONbits.RBIE=0;

    **if(PORTBbits.RB4==1) //echo

    T0CON=0x10;

    **if(PORTBbits.RB4==0)

    {

    **T0CON=0x10;

    a = (TMR0L | (TMR0H<<8))/58.82;

    }

    }

    }

    void main(void)

    {

    SWDTEN=0;

    PLLEN=1;

    TRISB = 0X00;

    LATB=0X00;

    PORTB=0X00;

    IPEN = 1;

    GIEH = 1;

    GIEL = 1;

    T1CON = 0x10;

    while(1)

    {

    TMR1H = 0;

    TMR1L = 0;

    a = 0;

    ** PORTBbits.RB1 = 1;

    delay_ms(10);

    ** PORTBbits.RB1=0;

    delay_ms(100000);

    a = a + 1;

    }

    }

  • Hi, I need the same code for PIC18F4550, could you help me?

    I’m using:

    MPLAB X

    Compiler XC8

    PIC18F4550 with PIC Expert

  • we can’t Convert temperature float value to string ?

    Lcd_Set_Cursor(1,14);
    Lcd_Write_Char(a%10 + 48);

    a = a/10;
    Lcd_Set_Cursor(1,13);
    Lcd_Write_Char(a%10 + 48);

    a = a/10;
    Lcd_Set_Cursor(1,12);
    Lcd_Write_Char(a%10 + 48);

    .
    pl explane here how do it .

  • hi Ligo George i used first code with pic16f873a, it is wrong value is on LCD. I use PICC compilier. what is wrong. Can i share my source code.

  • I change this but the program is not good, the lcd display this: 1. Developed by electrosome 2. Out of range. and after this nothing happening.

  • I used the second code with pic16f887, what can i change to working this code ?? I use mikro c pro.

  • Try using the first program without using the interrupt.. you can see that the program gets stuck sometimes..
    I already described it in the above article, please read it carefully.

  • There are 2 VDD pins for PIC 16F877A, connecting any one will provide required power for its operation. So I haven’t connected pin 11 in my experiment. But it is recommended to connect it to VDD when you design PCB.

  • the device isn’t detect any object even if it is placed a cm away from it …. it is detecting things which are at a distance less than that …….. does frequency has anything to do with this … ??

  • The first program will get stuck if there is no obstacle in-front of ultrasonic sensor…. So use the second code.. .
    I published the first code just for the sake of explanation…

  • Hey, the first code in isn’t working with my pic …actually the problem is with configuring echo …. and waiting for it . Can you suggest what can be done to make it work proper (the value of RB4 …. i.e., in pic24f i replaced it with LATBbits.LAT4 isn’t changing ) … Thank you 🙂

  • Crystal will work without those capacitors…… using capacitors will improve crystal stability…
    PIN 11 is connected.. PINS D0 – D3 (7 – 10) may left unconnected..

  • Dear Ligo George

    I use the second mikroc code but when I try it my lcd write this: Out of range.
    What can i do to solve this problem.
    Thanks Andrew

  • As addition to my below note, I just noticed that on the video pin 11 is not connected and I can’t see any capacitors next to the crystal. Am I right?

  • I had a very similar problem. When I connect pin 11 to 5V, I get nothing. When I disconnect it, I get only the bottom line of LCD showing, first line is not coming on. Also it is not showing any measurement either.

  • You can adjust the results obtained from Ultrasonic Sensor with respect to actual desired results just by adding or subtracting a constant.
    This gives more accurate results, once it is calibrated.

  • i follow this circuit diagram and also micro c code..but i got black bar on first row on lcd(jhd162a)..how to solve?

  • i need 3 sonar in a project. but i am a novice,and i am not good in timer0 and timer2 module. can u help me pls?

  • TMR1L and TMR1H are two 8 bit registers…
    To get 16 bit count value like TMR1H:TMR1L we need to shift the value of TMR1H left 8 positions and add with the value of TMR1L.

  • i’m sorry , but i’m totally new with timer1..
    if this is the way to get count from 16bit timer register ” TMR1L | (TMR1H<<8) " ,
    then why " <<8 " used for , Sir ?


  • >