; irsens3.asm 3 channel IR sensor for robot ; Written for 12C508 PIC microcontroller ; by Dale A. Heatherington Sept 23 1999 ; ;--------------------------------------------------------------------- ; ; PIC12C508 pin assignments ; ; 1 +5v ; 2 OUT RIGHT (Right object detected, low true) ; 3 OUT LEFT ( Left object detected, low true) ; 4 IR receiver input (Low = pulse received) ; 5 Right LED drive (low true) ; 6 Center LED drive ; 7 Left LED drive ; 8 GND ; ;Note: Both pins 2 and 3 go low when a center object is detected ; ;;---------------------------------------------------------------------- ;;This program is free software; you can redistribute it and/or modify ;;it under the terms of the GNU General Public License as published by ;;the Free Software Foundation; either version 2 of the License, or ;;(at your option) any later version. ;; ;;This program is distributed in the hope that it will be useful, ;;but WITHOUT ANY WARRANTY; without even the implied warranty of ;;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;GNU General Public License for more details. ;;You should have received a copy of the GNU General Public License ;;along with this program; if not, write to the Free Software ;;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA ;;------------------------------------------------------------------------ RADIX dec processor 12c508 __CONFIG h'0FEA' ;Internal 4 RC mhz osc ;Chnage this to point to your mpasm include directory include "../../../mpasm/p12c508.inc" ;------------------------------------------------------------ ;GPIO input bits IR1 equ 3 ;IR sensor input (low true) ;GPIO output bits OUT_L equ 4 ;object detection output bits (low true) OUT_R equ 5 LED_L equ 0 LED_C equ 1 ;LED driver outputs (low true) LED_R equ 2 LEDs equ 7 ;variables i_main equ 10h integ_L equ 11h integ_C equ 12h integ_R equ 13h j_main equ 14h ;-------------------------------------------------- ; MACROS ;;Drive the integrator up 1 count if return pulse is present ;; but count down by 1 if the pulse is not present. integrate_pulse MACRO N,inbit local _ip_seen, _ip_done btfss GPIO,inbit ; //sample IR sensor (low = pulse seen) goto _ip_seen; movf N,w ; btfss STATUS,Z ; //Don't wrap below zero decf N,f; //Decrement integrator if pulse not there goto _ip_done; _ip_seen incf N,f; //increment if pulse is there nop btfsc STATUS,Z; //Don't wrap from 255 to 0 decf N,f; _ip_done ENDM ;;Drive the integrator up 1 count if pulse is NOT present ;; but decrement it if a pulse IS present. (pulse is not supposed to be here) integrate_space MACRO N,inbit local _is_seen, _is_done btfsc GPIO,inbit ; //sample IR sensor (high = pulse not seen) goto _is_seen; movf N,w; btfss STATUS,Z; //If it's zero don't decrement it decf N,f; goto _is_done; _is_seen incf N,f; nop btfsc STATUS,Z ; //Don't wrap around decf N,f; _is_done ENDM ;;Make the output go LOW (true) if the integrator ;;value is greater than 127. output MACRO N,outbit local _one_out, _output_done btfss N,7 goto _one_out bcf GPIO,outbit goto _output_done _one_out bsf GPIO,outbit _output_done endm ;;One cycle of 40 KHZ (less 10uS for overhead in other code) ;This take 15uS to execute. A complete cycle is 25 uS long. cycle_leds MACRO LED bcf GPIO,LED nop nop nop nop nop nop nop nop nop nop nop bsf GPIO,LED nop nop endm delay_16us MACRO local _loop movlw 4 movwf j_main _loop decfsz j_main goto _loop nop nop endm ;;Subtract 2 from the integrator leak_down MACRO N local _leak_exit movf N,f ;Test for zero btfsc STATUS,Z goto _leak_exit ;Don't go below zero decfsz N,f ;decrement by 2 decf N,f _leak_exit endm ;--------------------------------------------------------------------- ;Actual code starts here... ORG 0 main_code movwf OSCCAL ;Internal 4 mhz osc calibration value clrf STATUS movlw 0ffh movwf GPIO clrf integ_C clrf integ_L clrf integ_R movlw 8 ;Bit 3 is the IR sensor input tris GPIO ; movlw 0C0h option label_0001 ;Top of main loop ; Emit IR pulses on left LED and register response in integ_L. movlw 20 movwf i_main ; Loop 20 times for 20 cycles of 40 khz ; This makes a 500uS IR pulse pulse_loop_L cycle_leds LED_L integrate_pulse integ_L,IR1 decfsz i_main goto pulse_loop_L movlw 20 movwf i_main ;loop 20 times with LED OFF space_loop_L ;for about 500uS with no IR pulse delay_16us integrate_space integ_L,IR1 decfsz i_main goto space_loop_L ;Emit IR pulses on right LED and register response with integ_R. movlw 20 movwf i_main ; Loop 20 times for 20 cycles of 40 khz pulse_loop_R cycle_leds LED_R integrate_pulse integ_R,IR1 decfsz i_main goto pulse_loop_R movlw 20 movwf i_main ;loop 20 times with LEDs OFF space_loop_R delay_16us integrate_space integ_R,IR1 decfsz i_main goto space_loop_R ;Emit IR pulses on center LED and register response with integ_C. movlw 20 movwf i_main ; Loop 20 times for 20 cycles of 40 khz pulse_loop_C cycle_leds LED_C integrate_pulse integ_C,IR1 decfsz i_main goto pulse_loop_C movlw 20 movwf i_main ;loop 20 times with LEDs OFF space_loop_C delay_16us integrate_space integ_C,IR1 decfsz i_main goto space_loop_C ;;Now we check the integrators btfsc integ_C,7 ;See if Center integrator has crossed threshold goto out_center output integ_L,OUT_L ;Else output Left or right results output integ_R,OUT_R goto leak out_center bcf GPIO,OUT_L ;set both outputs low (TRUE) if center bcf GPIO,OUT_R leak leak_down integ_L ;Bias the integrators to the down side... leak_down integ_R ;...for random or no inputs. leak_down integ_C goto label_0001 ;Infinite main loop END