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.
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.
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.
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.
#include <xc.h> #include "LCD4Bits.h" // PIC16F84A Configuration Bit Settings // CONFIG #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator) #pragma config WDTE = OFF // Watchdog Timer (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (Power-up Timer is disabled) #pragma config CP = OFF // Code Protection bit (Code protection disabled) #define _XTAL_FREQ 4000000UL #define TRIGGER RA1 #define ECHO RA0 volatile uint8_t T0OV=0; volatile uint16_t myCounter=0; void interrupt T0_ISR(void){ if(T0IF){ T0OV+=1; myCounter++; T0IF=0; } } uint16_t getDistance=0,temp=0; void readDistance(void){ TRIGGER=1; __delay_us(10); TRIGGER=0; __delay_us(30); while(ECHO==0){ /*Waiting For High Pulse Response, Or Sensor Present*/ temp++; __delay_us(10); if(temp>=20) break; } TMR0=0; T0OV=0; while(ECHO==1); temp=(T0OV<<8)+TMR0+20; getDistance=temp/58; lcdXY(8,2); if(temp>=10000) lcdData(48+temp/10000); else lcdData(' '); if(temp>=1000) lcdData(48+(temp%10000)/1000); else lcdData(' '); if(temp>=100) lcdData(48+(temp%1000)/100); else lcdData(' '); if(temp>=10) lcdData(48+(temp%100)/10); else lcdData(' '); lcdData(48+temp%10); lcdData(' '); lcdData(228); lcdData('S'); lcdXY(8,1); if(temp>=116&&getDistance<=400){ if(getDistance>=100) lcdData(48+getDistance/100); else lcdData(' '); if(getDistance>=10) lcdData(48+(getDistance%100)/10); else lcdData(' '); lcdData(48+getDistance%10); temp = temp%58; temp=(temp*100)/58; lcdData('.'); lcdData(48+(temp%100)/10); lcdData(48+temp%10); lcdData('c'); lcdData('m'); } else lcdString("Invalid "); temp=0; T0OV=0; TMR0=0; } int main(void){ PORTA=0; TRISA=0x01; PORTB=0; TRISB=0; T0CS=0; PSA=1; OPTION_REGbits.PS=0; T0IE=1; GIE=1; T0IF=0; lcdInit(); lcdXY(5,1); lcdString("PIC16F84A"); lcdXY(2,2); lcdString("HC-SR04 Example"); __delay_ms(2000); lcdCommand(CLEAR_SCREEN); __delay_ms(3); lcdString("Range: "); lcdXY(1,2); lcdString("Time : "); TMR0=0; while(1){ if(myCounter>=5000){ readDistance(); myCounter=0; } } return 0; }
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