#include ;#include "banks.inc" ; This header file defines configurations, registers, and other useful ; bits of information for the PIC18F4550 microcontroller. These names ; are taken to match the data sheets as closely as possible. CONFIG WDT = OFF; Disable watchdog timer CONFIG MCLRE = ON; MCLEAR Pin on CONFIG DEBUG = OFF; disable Debug Mode CONFIG LVP = OFF; Low-Voltage programming disabled CONFIG FOSC = HSPLL_HS; HS oscillator, PLL enabled, HS used by USB CONFIG PBADEN = OFF; PORTB<4:0> pins are configured as digital I/O on Reset CONFIG VREGEN = ON ; USB voltage regulator enabled CONFIG PLLDIV = 5 ; PLL prescaler Divide by 5 (20 MHz oscillator input) CONFIG USBDIV = 2 ; USB clock source comes from the 96 MHz PLL divided by 2 CONFIG CP0 = ON ; Code Protect CONFIG CP1 = ON CONFIG CP2 = ON CONFIG CPB = ON ; Boot Sect Code Protect CONFIG CPD = OFF ; EEPROM Data Protect CONFIG WRT0 = OFF ; Table Write Protect CONFIG WRT1 = OFF CONFIG WRT2 = OFF CONFIG WRTB = ON ; Boot Table Write Protest ;------sensa_bumper1.ASM--------------------------------------- ; robot maze traversal - using the front bumper ; for the pic18f4550 20Mhz -> 4Mhz -> 100Mhz processor ; 4/12/11 (efa) //works for my robot ;------------------------------------------------------ list p=18f4550 ;------------------------------------------------------- ; setup equates for ram memory -- Pic16f648: 0x20 to 0x7F (in bank 0), 0xA0 to 0xEF (in bank 1), ; 0x120 to 0x16F (in bank 2). 256 total ram count equ 0x20 ocount equ 0x21 ncount equ 0x22 ncount1 equ 0x23 ncount2 equ 0x24 ncount3 equ 0x25 seconds equ 0x26 tenths equ 0x27 sens equ 0x28 ;sensor status flag rt_sens, etc. LCD_tmp1 equ 0x29 nops equ 0x2a control equ 0x2b ;right or left wall-follow switch ;------------------- ; The following are variables used by music tone equ 0x30 ;set the tone for routine sound space1 equ 0x31 ;set the spacing dur equ 0x32 ;set the duration for routine sound count1 equ 0x33 ; counter may reuse note equ 0x34 ; musical note for play routine qcount equ 0x35 ; length offset of each note padsize equ 0x36 ; flag to determine if qcount has doubled ;------ constants ,not memory locations ------ null equ 0x00 ; zero or silence #define noteC 0x71 ;These are musical notes (sort of),not memory locations ---- #define noteCs 0x79 #define noteD 0x81 #define noteDs 0x88 #define noteE 0x8e #define noteF 0x95 #define noteFs 0x9b #define noteG 0xa0 #define noteGs 0xa6 #define noteA 0xab #define noteAs 0xb0 #define noteB 0xb4 #define noteC2 0xb8 ;---------------------------- LCD defines -------------------------------- ; see post includes for LCD control, at bottom of program... ; LCD and port defines #DEFINE LCD_D4 PORTA, 0 #DEFINE LCD_D5 PORTA, 1 #DEFINE LCD_D6 PORTA, 2 #DEFINE LCD_D7 PORTA, 3 #DEFINE LCD_RS PORTA, 4 ; Register Select, 0 = Command, 1 = Data #DEFINE LCD_E PORTA, 5 ; enable, strobe from 1 to 0 to send data ;--------------------- special registers and flags ------------------ porta equ PORTA portb equ PORTB portc equ PORTC portd equ PORTD porte equ PORTE w equ 0 f equ 1 FSR equ 04h EStrobe MACRO ; Strobe the "E" Bit BSF LCD_E call wait_ms ; wait 1 ms BCF LCD_E call wait_ms ; wait 1 ms ENDM ;------------------------------------------------------- ;---------------[ Boot Up Routine]---------------- ;------------------------------------------------------- ; org 0x800 ;reset starting address 00 goto begin org 0x804 ; define the interrupt, starts at 0x804 goto begin ; not currently used, just goto begin begin ; Initialize and setup processor to do work movlw 0x0F ; turn (A to D) off for port A, all pin are digital movwf ADCON1 movlw 0x00 ; load w with 0000 0000 - all outputs MOVWF TRISA movlw 0x00 ; load w with 0000 0000 - all outputs MOVWF TRISB movlw 0x00 ; load w with 0000 0000 - C0 (lft-IR), C6 (rt-IR) MOVWF TRISC movlw 0x30 ; load w with 0011 0000 - D4 (frt-bump), D5(fire) MOVWF TRISD movlw 0x04 ; load w with 0000 0100 - (IR detect) MOVWF TRISE bcf INTCON, GIE ;disable interrupts MOVLW 0x07 ; turn comparators off and MOVWF CMCON ; enable pins for I/O functions ;**************** Clear Ports ********************* clrf porta clrf portb clrf portc clrf portd clrf porte ;--------------------------------------------------------- ; written by JR update 4/28/09 (efa) ;--------------------------------------------------------- WAIT macro _dur ; Used to simplify the readablity of the code movlw _dur ; load 1/10 second to wait in w movwf tenths ; load w value to seconds call wait10th ; wait for alotted 1/10 seconds endm ;--------------------------------------------------------- NOP5 macro ;5 nops nop nop nop nop nop endm ;--------------------------------------------------------- TIME4 macro ;macro for 1/4 note wait call wait100th endm ;--------------------------------------------------------- TIME8 macro ;macro for 1/8 note wait call wait_ms call wait_ms call wait_ms call wait_ms call wait_ms endm ;--------------------------------------------------------- TIME16 macro ;macro for 1/16 note wait call wait_ms call wait_ms call wait_ms endm ;--------------------------------------------------------- SING macro _note movlw _note movwf note call play endm ;--------------------------------------------------------- SING2 macro _note, _dur movlw _note movwf tone movlw _dur movwf dur call sound endm ;--------------------------------------------------------- ;**** Charge tune macro (efa) 4/13/09 **** CHARGE macro SING2 noteC, 0x01 TIME8 SING2 noteE, 0x01 TIME8 SING2 noteF, 0x01 TIME8 SING2 noteG, 0x02 TIME8 SING2 noteE, 0x01 TIME8 SING2 noteG, 0x02 TIME4 endm ;------------------------------------------------------- ;---------------[ Main Program ]------------------- ;------------------------------------------------------- clrf sens ; clear sensors status flags call m_off ; turn motors off WAIT 0x04 ; wait for 4/10 of a second to allow the stopwatch to start. ;------------------------------------------------------- ;---------------[ Main Loop ]--------------------- ;------------------------------------------------------- loop1 call chk_sens ;check sensors and set sensor detect bits (1=lt_ir, 2=rt_ir, 3=bumper, 6-fire) ;------------------------------------------------------- ;============ React to fire sensor ================= btfsc sens,6 ; if(fire == TRUE) goto fire_true goto fire_false fire_true call follow_lt_wall ;follow the right_wall, reacting to fire event goto fire_endif fire_false call follow_rt_wall ;follow the left_wall, reacting to non-fire event goto fire_endif fire_endif ;------------------------------------------------------- call m_forward WAIT 0x01 ; wait for a time ; pause for 1/10 second goto loop1 ; infinite loop ;------------------------------------------------------- ;---------------[ End Main Loop ]--------------------- ;------------------------------------------------------- ; Check sensor status ; last updated 5/07/09 (efa) ;------------------------------------------------------- chk_sens call chk_fire ; check for fire call f_bump ; check front bumper return ;------------------------------------------------------- ; follow_lt_wall:: subroutine to follow the right wall ; 4/12/11 (efa) ;------------------------------------------------------- follow_lt_wall ;****** Check the front bumper ******* btfsc sens,3 ; if(f_bump == TRUE) goto lt_wall_if goto lt_wall_endif lt_wall_if call back_turn_right ;back turn right, we hit the wall lt_wall_endif return ;------------------------------------------------------- ; follow_rt_wall:: subroutine to follow the right wall ; 4/12/11 (efa) ;------------------------------------------------------- follow_rt_wall ;****** Check the front bumper ******* btfsc sens,3 ; if(f_bump == TRUE) goto rt_wall_if goto rt_wall_endif rt_wall_if call back_turn_left ;back turn left, we hit the wall rt_wall_endif return ;------------------------------------------------------- ; m_forward:: subroutine to turn the motors on (turning forward) ; 3/10/09 (efa) // might differ from board to board... ;------------------------------------------------------- m_forward bcf portc,2 ;disable motors (c2) bcf portd,0 ;m1 (off) (d0) left side motor bsf portd,2 ;m2 (on) (d2) bcf portd,1 ;m3 (off) (d1) right side motor bsf portd,3 ;m4 (on) (d3) bsf portc,2 ;enable motors (c2) return ;------------------------------------------------------- ; m_off:: subroutine to turn the motors off (full-stop) ; 3/23/09 (efa) ;------------------------------------------------------- m_off bcf portc,2 ;disable motors (c2) bcf portd,0 ;m1 (off) (d0) left side motor bcf portd,2 ;m2 (off) (d2) bcf portd,1 ;m3 (off) (d1) right side motor bcf portd,3 ;m4 (off) (d3) return ;------------------------------------------------------- ; m_back:: subroutine to turn the motors on (turning backwards) ; 3//09 () your_initials ;------------------------------------------------------- m_back bcf portc,2 ;disable motors (c2) bsf portd,0 ;m1 (on) (d0) left side motor bcf portd,2 ;m2 (off) (d2) bsf portd,1 ;m3 (on) (d1) right side motor bcf portd,3 ;m4 (off) (d3) bsf portc,2 ;enable motors (c2) return ;------------------------------------------------------- ; m_left:: subroutine to turn the motors on (turning left) ; 3/23/09 (efa) your_initials ;------------------------------------------------------- m_left bcf portc,2 ;disable motors (c2) bcf portd,0 ;m1 (off) (d0) left side motor bsf portd,2 ;m2 (on) (d2) bsf portd,1 ;m3 (on) (d1) right side motor bcf portd,3 ;m4 (off) (d3) bsf portc,2 ;enable motors (c2) return ;------------------------------------------------------- ; m_right:: subroutine to turn the motors on (turning right) ; 3/23/09 (efa) your_initials ;------------------------------------------------------- m_right bcf portc,2 ;disable motors (c2) bsf portd,0 ;m1 (on) (d0) left side motor bcf portd,2 ;m2 (off) (d2) bcf portd,1 ;m3 (off) (d1) right side motor bsf portd,3 ;m4 (on) (d3) bsf portc,2 ;enable motors (c2) return ;------------------------------------------------------- ; back_turn_left:: subroutine to backup turn left ; 9/10/00 (efa) ;------------------------------------------------------- back_turn_left call m_back ; backup WAIT 0x09 ; wait for 9/10 seconds call m_left ; motors on (turning left) WAIT 0x09 ; wait for 9/10 seconds return ;------------------------------------------------------- ; back_turn_right:: subroutine to backup turn right ; 9/10/00 (efa) ;------------------------------------------------------- back_turn_right call m_back ; backup WAIT 0x09 ; wait for 9/10 seconds call m_right ; motors on (turning left) WAIT 0x09 ; wait for 9/10 seconds return ;------------------------------------------------------- ; f_bump:: subroutine to Check front bumper ; 3/12/09 (efa) ;------------------------------------------------------- f_bump btfss portd,4 ; skip if bit4 is +5volts goto f_bump_if1 goto f_bump_else1 f_bump_if1 ; bsf sens,3 ; front bumper was bumped goto f_bump_endif1 f_bump_else1 bcf sens,3 ; front bumper not bumped f_bump_endif1 return ;------------------------------------------------------- ; chk_fire:: look at pin (d5) -- heat sensor ; 4/11/11 (efa) ; modified to only play "CHARGE" once (efa) 4/12/11 ;------------------------------------------------------- chk_fire btfss sens,6 ;if(chk_fire == TRUE) ;skip test once fire is seen goto chk_fire1 goto chk_fire_endif chk_fire1 btfss portd,5 ;if(chk_fire == TRUE) bit5 is not +5volts goto chk_fire_if goto chk_fire_else chk_fire_if bsf sens,6 ; set fire bit to true CHARGE ; play charge tune goto chk_fire_endif chk_fire_else bcf sens,6 ; set fire bit to false chk_fire_endif return ;------------------------------------------------------- ; play:: subroutine to play a note of space ; 11/29/00 (efa) ;------------------------------------------------------- play movf note,w ;was movfw note musical note or 0x00 to pause incf note decfsz note ;if(note == TRUE) goto play_if1 goto play_else1 play_if1 ;***** Play a note **** movf note,w ; set tone movwf tone ; load w value for sound() movlw 0x04 ; set duration to 16 10ths seconds movwf dur ; load w value for sound() call sound goto play_endif1 play_else1 ;***** Pause, no sound ***** ;---------------------------------------------------------- ; wait for a time---- time delay movlw 0x06 ; load wait for .6 seconds movwf tenths ; load w value to seconds call wait10th ; wait for alotted 1/10 seconds play_endif1 return ; subroutine return ;------------------------------------------------------- ; sound:: subroutine to sound for dur (duration) at tone. ; 4/12/09 (efa) not calibrated ;------------------------------------------------------- sound movf dur,w ;was movfw dur, duration of tone (count value) movwf ncount ;load number of counts movlw 0xff ;load max value to w movwf space1 ;load space1 with w movf tone,w ;move tone to w movwf qcount movf tone,w ;move tone to w subwf space1,f ;space1 = 255 - tone inner3 movlw 0x02 movwf padsize qinner bsf portc,7 ; ******* set bit 7 ******* movf space1,w ;space1 value movwf count ;load number of counts nop_lp1 NOP5 ; 5 nops as a time delay NOP5 ; 5 nops as a time delay NOP5 ; 5 nops as a time delay NOP5 ; 5 nops as a time delay decfsz count,f ; --count goto nop_lp1 ; nop_loop bcf portc,7 ; ******* clear bit 7 ****** movf space1,w ;load space1 to w movwf count1 ;load number of counts nop_lp2 NOP5 ; 5 nops as a time delay NOP5 ; 5 nops as a time delay NOP5 ; 5 nops as a time delay NOP5 ; 5 nops as a time delay decfsz count1,f ; --count goto nop_lp2 ; nop_loop decfsz qcount,f goto qinner decfsz padsize,f ;--padsize goto repad goto endpad repad movf tone,w movwf qcount goto qinner endpad decfsz ncount,f ; ++ncount goto inner3 ; inner loop return ; subroutine return ;------------------------------------------------------- ; wait:: subroutine to "wait" for up to 255 seconds. ; Wait routine uses "pause" and variable "seconds" ; 01/31/10 (efa) - calibrated (+/- .1%) ;------------------------------------------------------- wait movwf seconds ; wait for 1-255 seconds incf seconds,f ; start 1 second back... s_loop movlw 0x0a ;max value inner counter movwf ncount1 ;load value inner counter decfsz seconds,f ; --ncount goto start ; pause for a time return ; subroutine return start WAIT 0x0a ; wait for 10/10 seconds decfsz ncount1,f ; --ncount1 goto start ; inner1 loop goto s_loop ; go back to s_loop ;------------------------------------------------------- ; wait10th:: subroutine to "wait" for up to 255 (1/10) seconds. ; Wait routine uses "pause" and variable "seconds" ; 02/04/10 (efa) - calibrated ;------------------------------------------------------- wait10th movwf tenths ; wait for 1-255 (1/10) seconds incf tenths,f ; start 1 second back... s_loop1 movlw 0x0a ;max value inner counter movwf ncount2 ;load value inner counter decfsz tenths,f ; --ncount goto start1 ; pause for a time return ; subroutine return start1 call wait100th ; pause for .01 seconds decfsz ncount2,f ; --ncount1 goto start1 ; inner1 loop goto s_loop1 ; go back to s_loop ;------------------------------------------------------- ; wait100th:: subroutine to pause for 1/100 second ; To decrease pause decrease max value in outer loop ; 02/04/10 (efa) - calibrated ;------------------------------------------------------- wait100th movlw 0x0a ;max value outer counter (10) movwf ncount3 ;load value outer counter outer1 call wait_ms ; no operation, just a delay decfsz ncount3,f ; --ocount goto outer1 ; outer loop return ; subroutine return ;------------------------------------------------------- ; wait_ms:: subroutine to wait for 1/1000 second ; To decrease pause decrease max value in outer loop ; 1/30/10 (efa) calibrated ;------------------------------------------------------- wait_ms movlw 0x18 ;max value outer counter () movwf ocount ;load value outer counter outer movlw 0x7b ;max value inner counter movwf ncount ;load value inner counter inner nop ; no operation, just a delay decfsz ncount,f ; --ncount goto inner ; inner loop decfsz ocount,f ; --ocount goto outer ; outer loop return ; subroutine return ;------------------------------------------------------- end