You are on page 1of 6

Interf-PIC16 F877 with SR04 ultrasonic sensor MPLAB Projects

The HC-SR04 ultrasonic sensor module can measure distances form 2 cm to 400 cm (4 m) with
an accuracy of 3 mm. The HC-SR04 module includes ultrasonic transmitter, ultrasonic receiver
and control circuit.
This post shows how to make a simple distance meter using PIC16F887 microcontroller and HC-
SR04 ultrasonic sensor.
The compiler used in this project is Microchip MPLAB XC8 (MPLAB X IDE with MPLAB XC8
compiler).

The HC-SR04 ultrasonic sensor module has 4 pins as shown in the image below where:
VCC : Positive power supply (+5V)
Trig : Trigger input pin
Echo : Echo output pin
GND : Ground (0V)

Hardware Required:
A. PIC16F887 microcontroller —-> datasheet
B. HC-SR04 ultrasonic sensor
C. 16×2 LCD screen
D. 10k ohm variable resistor or potentiometer
E. 330 ohm resistor
F. 5V source
G. Breadboard
H. Jumper Wires
Interfacing PIC microcontroller with HC-SR04 ultrasonic sensor circuit:
Distance meter project circuit schematic diagram is shown below.
(All grounded terminals are connected together)
The HC-SR04 ultrasonic sensor board has 4 pins (from left to right): VCC (+5V), Trig (Trigger),
Echo and GND (ground).
The Trigger pin is connected to pin RB1 (#34) and Echo pin is connected to pin RB0 (#33) of the
PIC16F887 microcontroller.
The 16×2 LCD screen is connected to the PIC16F887 microcontroller as follows:
RS —> RD0 pin
E —> RD1 pin
D4 —> RD2 pin
D5 —> RD3 pin
D6 —> RD4 pin
D7 —> RD5 pin
VSS, RW, D0, D1, D2, D3 and K are connected to circuit GND (ground)
VEE to the variable resistor (or potentiometer) output pin
VDD to +5V and A to +5V through 330 ohm resistor
VEE pin is used to control the contrast of the LCD. A (anode) and K (cathode) are the back light
LED pins.
In this project the PIC16F887 microcontroller runs with its internal oscillator @ 8 MHz, MCLR
pin is configured as an input pin.
Interfacing PIC microcontroller with HC-SR04 ultrasonic sensor C code:
The C code below is for MPLAB XC8 compiler, it was tested with version 2.00 installed on
MPLAB X IDE version 5.05.
To be able to compile the C code, a small LCD library for MPLAB XC8 compiler is required which
can be downloaded from the following link:

MPLAB XC8 LCD Library


After the download, add the library file (LCD_Lib.c) to project folder. In this project I used
Timer1 module (16-bit timer) to measure signal widths (logic 1 and logic 0 widths), it is
configured to increment every 1 us (1 tick per microsecond). That means Timer 1 module clock
frequency is 1MHz.

Functions used in the code:


__bit wait_sensor(): this function waits for sensor’s response, it returns 1 if there has been a
response and 0 if time out. Here the time out is 1000 ticks = 1000 us = 1 ms.

__bit get_distance(uint16_t *ticks): this function measures the duration of the pulse sent by
the HC-SR04 sensor (in microseconds). This duration is stored in the variable *ticks. This
function returns 0 if OK and 1 if there is out of range or time out error. In this function Timer1
also is used to measure the pulse (high pulse) generated by the HC-SR04 sensor (Echo pulse).

Why 23200?
The actual distance (in cm) is equal to the width of the Echo pulse (in us) divided by 58. With
the maximum distance that the sensor can measure is 400 cm we get a maximum Echo pulse (in
us) of 400 x 58 = 23200
The connections between the microcontroller and the HC-SR04 sensor are defined as:

Where:

 In-Circuit Debugger disabled


 Low voltage programming disabled
 Fail-Safe Clock Monitor enabled
 Internal/External Switchover mode enabled
 Brown-out Reset (BOR) disabled
 Data memory code protection disabled
 Program memory code protection disabled
 RE3/MCLR pin function is digital input, MCLR internally tied to VDD
 Power-up Timer (PWRT) disabled
 Watchdog Timer (WDT) disabled
 INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on
RA7/OSC1/CLKIN
 Flash Program Memory Self Write disabled
 Brown-out Reset set to 4.0V

Full MPLAB XC8 code:

1 /*
2 * Distance meter using HC-SR04 ultrasonic sensor and PIC16F887 MCU.
3 * C Code for MPLAB XC8 compiler.
4 * Internal oscillator used @ 8MHz.
5 * This is a free software with NO WARRANTY.
6 * https://simple-circuit.com/
7 */
8
9 // set configuration words
10 #pragma config CONFIG1 = 0x2CD4
11 #pragma config CONFIG2 = 0x0700
12
13 // HC-SR Echo & Trigger pins are connected to RB0 & RB1 respectively
14 #define ECHO_PIN RB0
15 #define TRIGGER_PIN RB1
16
17 //LCD module connections
18 #define LCD_RS RD0
19 #define LCD_EN RD1
20 #define LCD_D4 RD2
21 #define LCD_D5 RD3
22 #define LCD_D6 RD4
23 #define LCD_D7 RD5
24 #define LCD_RS_DIR TRISD0
25 #define LCD_EN_DIR TRISD1
26 #define LCD_D4_DIR TRISD2
27 #define LCD_D5_DIR TRISD3
28 #define LCD_D6_DIR TRISD4
29 #define LCD_D7_DIR TRISD5
30 //End LCD module connections
31
32 #include <xc.h>
33 #define _XTAL_FREQ 8000000
34 #include <stdio.h> // for sprintf
35 #include <stdint.h> // include stdint header
36 #include "LCD_Lib.c" // include LCD driver source file
37
38 char text[13];
39
40 __bit wait_sensor()
41 {
42 uint16_t i = 0;
43 TMR1H = TMR1L = 0; // reset Timer1
44 TMR1ON = 1; // enable Timer1 module
45 while(!ECHO_PIN && (i < 1000))
46 i = ( TMR1H << 8 ) | TMR1L; // read Timer1 and store its value in i
47
48 if(i >= 1000)
49 return 0;
50
51 else
52 return 1;
53 }
54
55 __bit get_distance(uint16_t *ticks)
56 {
57 *ticks = 0;
58 TMR1H = TMR1L = 0; // reset Timer1
59
60 while( ECHO_PIN && (*ticks < 23200) )
61 *ticks = ( TMR1H << 8 ) | TMR1L; // read Timer1 value
62
63 TMR1ON = 0; // disable Timer1 module
64
65 if (*ticks >= 23200)
66 return 1;
67
68 else
69 return 0;
70 }
71
72 /*************************** main function *********************/
73 void main(void)
74 {
75 OSCCON = 0x70; // set internal oscillator to 8MHz
76 ANSELH = 0; // configure all PORTB pins as digital
77 PORTB = 0; // PORTB output is zero
78 TRISB1 = 0; // configure RB1 pin as input (HC-SR04 Echo pin)
79
80 T1CON = 0x10; // set Timer1 clock source to internal with 1:2 prescaler (Timer1 clock =
81 1MHz)
82 TMR1H = TMR1L = 0; // reset Timer1
83
84 __delay_ms(1000); // wait 1 second
85
86 LCD_Begin(); // initialize LCD module
87 LCD_Goto(4, 1); // move cursor to column 3, row 1
88 LCD_Print("Distance:");
89
90 while(1)
91 {
92 // send 10us pulse to HC-SR04 Trigger pin
93 TRIGGER_PIN = 0; // make sure trigger pin is low
94 __delay_us(2); // wait 2 us
95 TRIGGER_PIN = 1; // now generate the 10 us pulse
96 __delay_us(10);
97 TRIGGER_PIN = 0;
98
99 // read pulse comes from HC-SR04 Echo pin
100 if (wait_sensor())
101 { // if there is a response from the sensor
102
103 uint16_t distance;
104
105 if(get_distance(&distance))
106 { // if distance > 400 cm
107 LCD_Goto(3, 2); // move cursor to column 3 row 2
LCD_Print("Out of Range");
}
108
else
109
{
110
distance = distance / 58; // calculate the actual distance in cm
111
LCD_Goto(3, 2); // move cursor to column 6 row 2
112
sprintf(text, " %3u cm ", distance);
113
LCD_Print(text);
114
}
115
116
} // end if (wait_sensor())
117
118
else
119
{
120
LCD_Goto(3, 2); // move cursor to column 3 row 2
121
LCD_Print(" Time Out ");
122
}
123
124
__delay_ms(200); // wait 200 ms
125
126
}
127
128
}
129
130
/*************************** end main function ********************************/
131
132

You might also like