;////////////////////////////////////////////////////////////////////////////
;//
;// 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
;////////////////////////////////////////////////////////////////////////////