Thursday, November 9, 2023

PIC16F84A LCD And HC-SR04 Distance Sensor Using XC8

The SR-HC04 uses sound wave to measure detected object distance. It's simple to use with a small micro-controller especially the Arduino. The controller just trigger a logic high TTL signal to command this sensor to begin the detection. The output signal from this module is a TTL logic high signal that the controller need to measure its duration before distance data can be obtained.

PIC16F84A LCD And SR-HC04 Distance Sensor Using XC8
Simulating Program

In this example, I use PIC16F84A to interface with this distance sensor. Detected distance will show on a 16x2 character LCD. The controller uses a 4MHz external crystal oscillator. To measure external input pulse duration precisely we will need to use timer.

PIC16F84A LCD And SR-HC04 Distance Sensor Using XC8
SR-HC04 module from manufacturer's Datasheet

 

The micro-controller execution frequency is Fosc/4 that's 4MHz/4 is 1MHz. So its execution time is 1µs. PIC16F84A has one timer module - Timer 0. This timer is automatically increment is count register for every execution of micro-controller instruction with an appropriate clock pre-scaler. I need to make a 1:1 pre-scaler to get a 1µs timing unit.

PIC16F84A LCD And SR-HC04 Distance Sensor Using XC8
Timing Diagram

The detected distance can be obtained by is formula,

Distance (in cm) = High Level TTL Signal (in µs) / 58.

Using MPLABX IDE and XC8 compiler to write this program is pretty easy.

  1.  
  2. #include <xc.h>
  3. #include "LCD4Bits.h"
  4.  
  5. // PIC16F84A Configuration Bit Settings
  6. // CONFIG
  7. #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
  8. #pragma config WDTE = OFF // Watchdog Timer (WDT disabled)
  9. #pragma config PWRTE = OFF // Power-up Timer Enable bit (Power-up Timer is disabled)
  10. #pragma config CP = OFF // Code Protection bit (Code protection disabled)
  11.  
  12. #define _XTAL_FREQ 4000000UL
  13. #define TRIGGER RA1
  14. #define ECHO RA0
  15.  
  16. volatile uint8_t T0OV=0;
  17. volatile uint16_t myCounter=0;
  18.  
  19. void interrupt T0_ISR(void){
  20. if(T0IF){
  21. T0OV+=1;
  22. myCounter++;
  23. T0IF=0;
  24. }
  25. }
  26.  
  27. uint16_t getDistance=0,temp=0;
  28. void readDistance(void){
  29. TRIGGER=1;
  30. __delay_us(10);
  31. TRIGGER=0;
  32. __delay_us(30);
  33. while(ECHO==0){
  34. /*Waiting For High Pulse Response, Or Sensor Present*/
  35. temp++;
  36. __delay_us(10);
  37. if(temp>=20) break;
  38. }
  39. TMR0=0;
  40. T0OV=0;
  41. while(ECHO==1);
  42. temp=(T0OV<<8)+TMR0+20;
  43. getDistance=temp/58;
  44.  
  45. lcdXY(8,2);
  46. if(temp>=10000) lcdData(48+temp/10000); else lcdData(' ');
  47. if(temp>=1000) lcdData(48+(temp%10000)/1000); else lcdData(' ');
  48. if(temp>=100) lcdData(48+(temp%1000)/100); else lcdData(' ');
  49. if(temp>=10) lcdData(48+(temp%100)/10); else lcdData(' ');
  50. lcdData(48+temp%10);
  51.  
  52. lcdData(' ');
  53. lcdData(228);
  54. lcdData('S');
  55.  
  56. lcdXY(8,1);
  57. if(temp>=116&&getDistance<=400){
  58. if(getDistance>=100) lcdData(48+getDistance/100); else lcdData(' ');
  59. if(getDistance>=10) lcdData(48+(getDistance%100)/10); else lcdData(' ');
  60. lcdData(48+getDistance%10);
  61.  
  62. temp = temp%58;
  63. temp=(temp*100)/58;
  64. lcdData('.');
  65. lcdData(48+(temp%100)/10);
  66. lcdData(48+temp%10);
  67. lcdData('c');
  68. lcdData('m');
  69. }
  70. else lcdString("Invalid ");
  71.  
  72. temp=0;
  73. T0OV=0;
  74. TMR0=0;
  75. }
  76.  
  77. int main(void){
  78.  
  79. PORTA=0;
  80. TRISA=0x01;
  81.  
  82. PORTB=0;
  83. TRISB=0;
  84. T0CS=0;
  85. PSA=1;
  86. OPTION_REGbits.PS=0;
  87. T0IE=1;
  88. GIE=1;
  89. T0IF=0;
  90.  
  91. lcdInit();
  92. lcdXY(5,1);
  93. lcdString("PIC16F84A");
  94. lcdXY(2,2);
  95. lcdString("HC-SR04 Example");
  96. __delay_ms(2000);
  97. lcdCommand(CLEAR_SCREEN);
  98. __delay_ms(3);
  99. lcdString("Range: ");
  100. lcdXY(1,2);
  101. lcdString("Time : ");
  102. TMR0=0;
  103.  
  104. while(1){
  105. if(myCounter>=5000){
  106. readDistance();
  107. myCounter=0;
  108. }
  109. }
  110. return 0;
  111. }

 

This program requires a little amount of micro-controller resource. Click here to download its source file. We can also use a multiplexing 7-Segment display for better viewing.



No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (56) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (47) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (71) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)