SRF04 Source Code ;//////////////////////////////////////////////////////////////////////////// ;// ;// Ultrasonic rangefinder Software ;// ;// Written by Gerald Coe - May 2000 ;// Tidied up for publication - 12th July 2000 ;// ;// Private and Educational use only is permitted ;// Commercial use of this software is prohibited. ;// ;//////////////////////////////////////////////////////////////////////////// processor 12c508 __config 0feeh ; Internal Osc, WDT Enabled, not code protected include "p12c508.inc" #define RAMSTART 07h radix dec #define trig GPIO,0 ; trigger input from host #define pulse GPIO,1 ; timing pulse output to host #define echo GPIO,2 ; echo signals from comparitor #define nc GPIO,3 ; Unused - do not connect. #define tx2 GPIO,4 ; Tx phase 2 #define tx1 GPIO,5 ; Tx phase 1 #define _C STATUS,C ;///////////////////////////////////////////////////////////////////////////// org RAMSTART loop res 1 ; loop counter dlyctr res 1 ; delay counter tone_cnt res 1 ; count echo cycles period res 1 ; received burst cycle period from tmr0 ;///////////////////////////////////////////////////////////////////////////// org 0 ;start address 0 movwf OSCCAL ; use microchip's calibration value movlw 89h option ;assign 1:2 prescaler to watchdog movlw 0dh tris GPIO ;GPIO 1, 4 & 5 are outputs movwf 0 bcf pulse ;//////////////////////////////////////////////////////////////////////////// ; ; The main loop controls the range finder. In response to a low going trigger ; input, its calls "burst" to send out 8 cycles of 40khz. It then raises the ; pulse line so the host can begin timing. ; There is a choice of two tone detect routines, the simplest is currently set. ; It then clears the output pulse so the host can complete timing, and loops ; around to wait for the next cycle. ; If an echo is not detected then the watchdog timer will reset the PIC after ; about 30mS, and the pulse line will be cleared. Therefore a very long pulse ; should be interpreted as "nothing detected" main: clrwdt btfss trig ; wait for trigger signal from user to go high goto main ; from previous measurement. m2: clrwdt btfsc trig ; wait for trigger signal from user goto m2 call burst ; send the ultra-sonic burst bsf pulse ; start the output timing pulse ; OK, here's the cheap-n-easy way to detect the echo, just wait for a transition ; on the echo line. Though not really detecting a tone, it is very effective. ; The transducers provide the selectivity. m1: btfsc echo goto m1 ; wait for low bcf pulse ; end the output timing pulse ; And here is the "proper" tone detecter. It detects 3 cycles of 40khz to ; give a valid output. It works but is still experimental. It is not as effective ; as just detecting the first edge, particually in the first few cm. ; ; call tone ; validate 3 cycles of 40khz ; bcf pulse ; end the output timing pulse ; goto main ;//////////////////////////////////////////////////////////////////////////// ; ; The burst routine generates an acurately times 40khz burst of 8 cycles. ; Since a 4Mhz PIC (1uS instruction rate) cannot gerenate timings of less ; than 1uS, the high half cycle is 12uS and the low half cycle 13uS. ; That's good enough. burst: clrf loop movlw 8 ; number of cycles in burst movwf loop burst1: movlw 0x10 ; 1st half cycle movwf GPIO movlw 3 ; (3 * 3inst * 1uS) -1uS = 8uS movwf dlyctr ; 8uS + (4*1uS) = 12uS burst2: decfsz dlyctr,f goto burst2 movlw 0x20 movwf GPIO movlw 2 ; (2 * 3inst * 1uS) -1uS = 5uS movwf dlyctr ; 5uS + (8*1uS) = 13uS burst3: decfsz dlyctr,f goto burst3 nop decfsz loop,f goto burst1 movlw 0x00 ; set both drives low movwf GPIO retlw 0 ;//////////////////////////////////////////////////////////////////////////// ; ; The timing for this routine is critical. Our little PIC is only chugging ; along at 4Mhz, or 1uS per instruction. The longest path though this code ; is 19uS, out of the 25uS available - thats tight and why I only wait for a ; low on the echo line and not a high as well. tone: clrf TMR0 t1: btfsc echo goto t1 ; wait for low movfw TMR0 clrf TMR0 movwf period ; store timer0 value movlw 21 ; if(period>22 && period<30) subwf period,w btfss _C goto t2 movlw 30 subwf period,f btfsc _C goto t2 decfsz tone_cnt,f ; 25uS period OK, so goto t1 ; if not yet 3 of them, keep looking retlw 0 ; else - success - return t2: movlw 3 ; failed to detect 25uS period, so reset tone detect movwf tone_cnt ; to 3 and keep looking goto t1 ;//////////////////////////////////////////////////////////////////////////// end ;//////////////////////////////////////////////////////////////////////////// Top of Form Bottom of Form