728x90

728x90

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

320x50

Search This Blog

tyro-728x90