Tuesday, November 1, 2016

PIC16F84A with HC-SR04 ultrasonic sensor example


Interfacing PIC16F84A with HC-SR04 Ultrasonic Sensor
This post shows how to interface PIC16F84A microcontroller with HC-SR04 ultrasonic sensor and make a distance meter.
The ultrasonic sensor HC-SR04 can measure distances form 2cm to 400cm with an accuracy of 3mm. This sensor module includes ultrasonic transmitter, ultrasonic receiver and control circuit.
The HC-SR04 ultrasonic sensor has 4 pins as shown below where:
VCC - Positive power supply (+5V)
Trig - Trigger input pin
Echo - Echo output pin
GND - Ground (0V)
 HC-SR04 Ultrasonic sensor pinout
HC-SR04 ultrasonic sensor timing diagram:
The timing diagram of the HC-SR04 ultrasonic sensor is shown below.
First we have to supply the sensor trigger pin with a pulse of 10µs and the sensor will automatically send 8 cycles burst of ultrasound at 40 kHz and raise its echo pin. The Echo is a distance object that is pulse width and the range in proportion. You can calculate the range through the time interval between sending trigger signal and receiving echo signal. Formula: uS / 58 = centimeters or uS / 148 =inch; or:
the range = high level time * velocity (340M/S) / 2.
HC-SR04 Ultrasonic sensor timing
PIC16F84A with HC-SR04 ultrasonic sensor example circuit:
The following circuit schematic show he connection between the microcontroller PIC16F84A and the HC-SR04 sensor.
PIC16F84A with HC-SR04 ultrasonic sensor circuit
The 1602 LCD is used to display the measured distance in cm.
PIC16F84A with HC-SR04 ultrasonic sensor example CCS C code:
Here is the C code used for this project.
Timer0 is configured to increment by 1 every 1 us ( with mcu frequency of 8MHz). Timer0 is used the measure the pulse widths come from Echo pin of the HC-SR04 sensor.
Because of the Timer0 is an 8-bit timer only I used its interrupt (Timer0 interrupt) to count times more than 256us, and for that purpose I added a variable called count. So the pulse time of the Echo pin equals to :
count * 256 + get_timer0()
// Interfacing  PIC16F84A with HC-SR04 ultrasonic sensor CCS PIC C code
// http://ccspicc.blogspot.com/
// electronnote@gmail.com

//LCD module connections
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_ENABLE_PIN PIN_B2
#define LCD_DATA4 PIN_B3
#define LCD_DATA5 PIN_B4
#define LCD_DATA6 PIN_B5
#define LCD_DATA7 PIN_B6
//End LCD module connections

#include <16F84A.h>
#fuses HS,NOWDT,PUT,NOPROTECT
#use delay(clock = 8000000)
#include <lcd.c>
#use fast_io(A)

unsigned int8 count;
unsigned int16 i, distance;
#INT_TIMER0
void timer0_isr(){
  count++;
  clear_interrupt(INT_TIMER0);
}
int1 wait_sensor(){
  i = 0;
  set_timer0(0);
  count = 0;                             // Reset Timer0
  while(!input(PIN_A1) && (i < 1000))
    i = count * 256 + get_timer0();
  if(i > 990)
    return 0;
  else
    return 1;
}
unsigned int16 get_distance(){
  i = 0;
  set_timer0(0);
  count = 0;
  while(input(PIN_A1) && (i < 25000))
    i = count * 256 + get_timer0();
  return i;
}
void main(){
  output_a(0);
  set_tris_a(2);                                      // Configure RA1 as input
  lcd_init();                                         // Initialize LCD module
  lcd_putc('\f');                                     // LCD clear
  clear_interrupt(INT_TIMER0);
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_TIMER0);
  setup_timer_0 (T0_INTERNAL | T0_DIV_2);             // Configure Timer0 module
  lcd_gotoxy(4, 1);                                   // Go to column 4 row 1
  lcd_putc("Distance:");
  while(TRUE){
    // Send 10us pulse to HC-SR04 Trigger pin
    output_high(PIN_A0);
    delay_us(10);
    output_low(PIN_A0);
    // Read pulse comes from HC-SR04 Echo pin
    if(wait_sensor()) {
      distance = get_distance();
      if(distance > 24990) {
        lcd_gotoxy(3, 2);                             // Go to column 3 row 2
        lcd_putc("Out Of Range");
      }
      else {
        distance = i/58;                              // Calculate the distance
        lcd_gotoxy(3, 2);                             // Go to column 3 row 2
        lcd_putc("       cm   ");
        lcd_gotoxy(6, 2);                             // Go to column 6 row 2
        printf(lcd_putc,"%3Lu",distance);
      }
    }
    else {
      lcd_gotoxy(3, 2);                               // Go to column 3 row 2
      lcd_putc("  Time Out  ");
    }
  delay_ms(100);
  }
}
Example Video: