728x90

728x90

Showing posts with label Distance Sensor. Show all posts
Showing posts with label Distance Sensor. Show all posts

Thursday, December 28, 2023

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8

Overview

HC-SR04 is an ultrasonic range finder. It uses sound wave traveling to find detected object distance. Its working range is between 4cm and 4m. To control and get distance data from this sensor we can use a digital circuit, or a microprocessor, or even manually by hand. Its echo output is a logic high level TTL signal with a specific period. A microprocessor's timer is used for calculating the timing signal associated with distance. For more details about using this sensor with a simple PIC16F84A micro-controller you can see this post.

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
PIC16F887 Prototyping Board

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
PIC16F887 Prototyping Board
 
PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
HC-SR04 Module Front

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
HC-SR04 Module Back

MPLABX IDE and XC8 C Programming

In this XC8 programming example, I use a PIC16F887 8-bit micro-controller to read distance data, and displaying its timing value with calculated distance on a 16x4 character LCD. I use Timer0 timer/counter to measure the sensor's TTL high pulse period.

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
Schematic and Program Simulation

An 8MHz internal RC oscillator is used for the system. Timer0 prescaler is set to 1:2 to get a 1µs timing ticks. Since this timer module is an 8-bit timer/counter I use TIMER0 interrupt to expand its timing period. Hence it becomes a 16-bit timer with the aid of timing interrupt. 

An 8-bit micro-controller is easy to program using C in MPLABX IDE and XC8 embedded C compiler from Microchip Technology. An HD44780 character LCD is very simple to interface and program. This character LCD is common operate in 4-bit data transfer mode.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on December 28, 2023, 9:51 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "lcd.h"
  11.  
  12. #include <stdio.h>
  13.  
  14. #define _XTAL_FREQ 8000000UL
  15.  
  16. #define TRIGGER RD6
  17. #define ECHO RD7
  18.  
  19. volatile uint8_t T0OV=0;
  20. volatile uint16_t myCounter=0;
  21. volatile uint16_t getDistance=0, temp=0;
  22.  
  23. void __interrupt() T0_ISR(){
  24. if(T0IF==1){
  25. T0OV+=1;
  26. myCounter++;
  27. T0IF=0;
  28. }
  29. }
  30.  
  31. void readDistance(void){
  32. char msg[8];
  33. TRIGGER=1;
  34. __delay_us(10);
  35. TRIGGER=0;
  36. __delay_us(30);
  37. while(ECHO==0){
  38. /*Waiting For High Pulse Response, Or Sensor Present*/
  39. temp++;
  40. __delay_us(10);
  41. if(temp>=20) break;
  42. }
  43. TMR0=0;
  44. T0OV=0;
  45. while(ECHO==1);
  46. temp=(T0OV<<8)+TMR0+14;
  47. getDistance=temp/58;
  48.  
  49. lcdXY(5,4);
  50. sprintf(msg,"%4d %cS ",temp,228);
  51. lcdString(msg);
  52. lcdXY(5,2);
  53. if(temp>=116&&getDistance<=400){
  54. sprintf(msg,"%3d",getDistance);
  55. lcdString(msg);
  56.  
  57. temp%=58;
  58. temp=(temp*100)/58;
  59. sprintf(msg,".%d%dcm",temp/10,temp%10);
  60. lcdString(msg);
  61. }else lcdString("Invalid");
  62. temp=0;
  63. T0OV=0;
  64. TMR0=0;
  65. }
  66.  
  67. void main(void) {
  68. /*8MHz internal oscillator*/
  69. OSCCONbits.IRCF=7;
  70. lcdInit();
  71. /*RD7 as input*/
  72. PORTD=0;
  73. TRISD=0x80;
  74. /*Select system clock*/
  75. T0CS=0;
  76. /*Timer0 Prescaler*/
  77. PSA=0;
  78. /*Select 1:2 Prescaler*/
  79. OPTION_REGbits.PS=0;
  80. /*Enable Timer0 Interrupt*/
  81. T0IE=1;
  82. GIE=1;
  83. T0IF=0;
  84.  
  85. lcdXY(5,1);
  86. lcdString("PIC16F887 ");
  87. lcdXY(1,2);
  88. lcdString("HC-SR04 Distance");
  89. lcdXY(2,3); lcdString("Sensor Example");
  90. lcdXY(2,4); lcdString("MPLABX IDE XC8");
  91. __delay_ms(2000);
  92. lcdCommand(0x0C);
  93. lcdCommand(0x01);
  94. __delay_ms(5);
  95. lcdXY(5,1);
  96. lcdString("Distance: ");
  97. lcdXY(1,3);
  98. lcdString("TIMER0 Duration:");
  99. TMR0=0;
  100. while(1){
  101. if(myCounter>=5000){
  102. readDistance();
  103. myCounter=0;
  104. }
  105. }
  106. return;
  107. }
  108.  
  109.  
  110.  

The Interrupt Service Routine (ISR) for PIC micro-controller in XC8 programming is differ depends on the version of the compiler. Some time the source codes can generate error in other version. In some case, it can be build but the ISR does not work during run-time. So we will need to read its compiler user manual. 

PIC16F887 HC-SR04 Distance Sensor LCD Using XC8
MPLABX IDE Dashboard

Click here to download its source file.




Thursday, November 9, 2023

PIC16F84A SR-HC04 And 3-Digit Multiplexing Display Using XC8

In previous post, I use a character LCD to display distance measurement result. However we can use a 7-Segment display instead because this display has a large size. Seven-Segment display is very very easy to find in most of local electronics components store.

 

PIC16F84A SR-HC04 And 3-Digit Multiplexing Display Using XC8
Simulating Program

This program is similar to the previous example. It uses the same timer and pre-scaler. I use timer 0 interrupt timer tick to drive the display. The timer interrupt period is 1µs tick. The distance measurement process use timer 0 interrupt flag counting. The polling method is use for getting the duration of the echo high TTL signal from the distance sensor in µs. Even timer 0 is 8-bit wide we can get a longer duration by using the timer0 interrupt service routine.

  1.  
  2. #include <xc.h>
  3.  
  4. // PIC16F84A Configuration Bit Settings
  5. // CONFIG
  6. #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
  7. #pragma config WDTE = OFF // Watchdog Timer (WDT disabled)
  8. #pragma config PWRTE = OFF // Power-up Timer Enable bit (Power-up Timer is disabled)
  9. #pragma config CP = OFF // Code Protection bit (Code protection disabled)
  10.  
  11. #define _XTAL_FREQ 4000000UL
  12. #define TRIGGER RA3
  13. #define ECHO RA4
  14.  
  15. volatile uint8_t T0OV=0;
  16. volatile uint16_t myCounter=0,myDisplayTime=0;
  17.  
  18. void interrupt T0_ISR(void){
  19. if(T0IF){
  20. T0OV+=1;
  21. myCounter++;
  22. myDisplayTime++;
  23. T0IF=0;
  24. }
  25. }
  26.  
  27. uint16_t getDistance=0,temp=0;
  28.  
  29. void readDistance(void){
  30. TRIGGER=1;
  31. __delay_us(10);
  32. TRIGGER=0;
  33. __delay_us(30);
  34. while(ECHO==0){
  35. /*Waiting For High Pulse Response, Or Sensor Present*/
  36. temp++;
  37. __delay_us(10);
  38. if(temp>=20) break;
  39. }
  40. TMR0=0;
  41. T0OV=0;
  42. while(ECHO==1);
  43. temp=(T0OV<<8)+TMR0+20;
  44. getDistance=temp/58;
  45.  
  46. if(getDistance>=433){
  47. getDistance=0;
  48. }
  49.  
  50. temp=0;
  51. T0OV=0;
  52. TMR0=0;
  53. }
  54.  
  55. int main(void){
  56. uint8_t data7[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
  57. PORTA=0;
  58. TRISA=0x10;
  59.  
  60. PORTB=0;
  61. TRISB=0;
  62. T0CS=0;
  63. PSA=1;
  64. OPTION_REGbits.PS=0;
  65. T0IE=1;
  66. GIE=1;
  67. T0IF=0;
  68.  
  69.  
  70. TMR0=0;
  71.  
  72. while(1){
  73. if(myCounter>=2000){
  74. readDistance();
  75. myCounter=0;
  76. }
  77. if(myDisplayTime>=60) myDisplayTime=0;
  78. switch(myDisplayTime){
  79. case 0:
  80. PORTA=0;
  81. PORTB=data7[getDistance/100];
  82. RA0=1;
  83. break;
  84. case 20:
  85. PORTA=0;
  86. PORTB=data7[(getDistance%100)/10];
  87. RA1=1;
  88. break;
  89. case 40:
  90. PORTA=0;
  91. PORTB=data7[getDistance%10];
  92. RA2=1;
  93. break;
  94. }
  95. }
  96. return 0;
  97. }

 

Click here to download its source file.

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.



320x50

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (57) AVR (58) CCS PICC (28) DAC (1) DHT11 (2) Display (106) Distance Sensor (3) DS18B20 (3) dsPIC (3) dsPIC30F1010 (3) dsPIC30F2010 (1) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (68) Interrupt (19) Keil (5) Keypad (10) LCD (48) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (73) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (10) PCD8544 (3) PCF8574 (5) PIC (108) PIC12F (3) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) PWM (11) RTC (9) Sensor (11) 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 (96)

tyro-728x90