#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-jr2.asm--------------------------------------- ; Robot maze program - by JR Vitoria and (efa) ; For the pic18f4550 20Mhz -> 4Mhz -> 100Mhz processor ; 4/30/10 (efa) //works for my robot ; --------------------------------------------------------- ; Known issues: ;---------------------------------------------------------- ; Fire sensor not working right.. ; Has an infinate loop problem. Works for a short while ; and then goes into infinate loop. I'll work on it... ; (efa) 4/01/10 ;------------------------------------------------------ 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; program starts at 0x800, the bootloader lives in the code space 0x0 to 0x7ff. 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 ;--------------------------------------------------------- ; wrriten by JR update 4/28/09 (efa) WAIT macro _dur ; Used to simplify the readablity of the code movlw _dur ; load 1 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 for a time ; pause for 1 second to allow the stopwatch to start. movlw 0x04 ; load a 4 second wait in w movwf tenths ; load w value to tenths call wait10th ; wait for alotted 1/10 seconds chk_sens ; First check sensor status ;------------------------------------------------------- ; Scan with each senor for objects or fire and react ;------------------------------------------------------- call f_bumper ; check front bumper for an object an instantly react btfss control, 1 ; if fire has been detected goto if_right ; false (right wall fallowing routine) goto if_left ; true (left wall following routine) if_right call look_fire ; check for fire and instantly react call look_rt ; look at right sensor call chk_rt ; react to right wall by turning slightly left movlw 0x01 ; load a 1 second wait in w movwf tenths ; load w value to tenths call wait10th ; this pause is critical to allowing the robot to favor one sensor over the other; call look_lt ; look at left sensor call chk_lt ; react to left wall by turning slightly right goto if_end if_left call look_lt ; look at left sensor call chk_lt ; react to left wall by turning slightly right movlw 0x01 ; load a 1 second wait in w movwf tenths ; load w value to tenths call wait10th ; this pause is critical to allowing the robot to favor one sensor over the other; call look_rt ; look at right sensor call chk_rt ; react to right wall by turning slightly left if_end ; end if statement ;------------------------------------------------------- ; Proceed when path is clear ;------------------------------------------------------- call m_forward WAIT 0x01 ; Primary efficency variable. Adjust to course requirments goto chk_sens ; infinite loop ;------------------------------------------------------- ;----------------[ Subroutines ]--------------------- ;------------------------------------------------------- ;------------------------------------------------------- ; chk_rt:: Check for right wall and instantly react ; JR routine 4/28/09 updated (efa) ;------------------------------------------------------- chk_rt btfsc sens,2 ; if(look_rt == TRUE) goto if1 goto endif1 if1 call m_left WAIT 0x01 ; pause for 1/10 second. Adjust to improve efficiency goto chk_sens endif1 return ;------------------------------------------------------- ; chk_lt:: Check for left wall and instantly react ; JR routine 4/28/09 updated (efa) ;------------------------------------------------------- chk_lt btfsc sens,1 ; if(look_lt == TRUE) goto if3 goto endif3 if3 call m_right WAIT 0x01 ; pause for 1/10 second. Adjust to improve efficiency goto chk_sens endif3 return ;------------------------------------------------------- ; chk_f_bumber:: Check the front bumper and instantly react ; JR routine 4/28/09 updated (efa) ;------------------------------------------------------- chk_f_bumper btfsc sens,3 ; if(f_bump == TRUE) goto if2 goto endif2 if2 btfss control, 1 call back_turn_left call back_turn_right endif2 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) 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_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) 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 ;------------------------------------------------------- ; m_right:: subroutine to turn the motors on (turning right) ; 3/23/09 (efa) your_initials ;------------------------------------------------------- m_right 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 ;------------------------------------------------------- ; back_turn_left:: subroutine to backup turn left ; 4/28/09 (efa) ;------------------------------------------------------- back_turn_left call m_back ; backup ; wait for a time ---- time backing up // best value ??? movlw 0x05 ; load 1/10 seconds to wait in w movwf tenths ; load w value to seconds call wait10th ; wait for alotted seconds call m_left ; motors on (turning left) ; wait for a time ---- time turning left //best value ??? movlw 0x01 ; load 1/10 seconds to wait in w movwf tenths ; load w value to seconds call wait10th ; wait for alotted seconds return ;------------------------------------------------------- ; back_turn_right:: subroutine to backup turn right ; 4/28/09 (efa) ;------------------------------------------------------- back_turn_right call m_back ; backup ; wait for a time ---- time backing up // best value ??? movlw 0x05 ; load 1/10 seconds to wait in w movwf tenths ; load w value to seconds call wait10th ; wait for alotted seconds call m_right ; motors on (turning left) ; wait for a time ---- time turning left //best value ??? movlw 0x01 ; load 1/10 seconds to wait in w movwf tenths ; load w value to seconds call wait10th ; wait for alotted seconds return ;------------------------------------------------------- ; f_bumper:: subroutine to Check front bumper ; 3/28/09 (efa) ;------------------------------------------------------- f_bumper 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 call chk_f_bumper return ;------------------------------------------------------- ; look_rt:: look right using right IR sensor ; 4/20/09 (efa) ;------------------------------------------------------- look_rt call rt_led_on ;Turn right IR led on call wait_ms ; allow time for the LED to ramp up btfss porte,2 ;if(look_rt == TRUE) porte bit2 is grounded goto look_rt_if goto look_rt_else look_rt_if ; bsf portd,6 ;led(on)(d6) backing up from right-sensor detect bsf sens,2 ; set look_rt, IR detected, to TRUE goto look_rt_endif look_rt_else ; bcf portd,6 ;led(on)(d6) backing up from right-sensor detect bcf sens,2 ; clear look_rt, IR detected, to FALSE look_rt_endif call leds_off ; Turn off all IR LEDs return ;------------------------------------------------------- ; look_lt:: look right using right IR sensor ; 3/30/09 (efa) ;------------------------------------------------------- look_lt call lt_led_on ;Turn right IR led on call wait_ms ; allow time for the LED to ramp up btfss porte,2 ;if(look_lt == TRUE) porte bit2 is grounded goto look_lt_if goto look_lt_else look_lt_if bsf sens,1 ; set look_lt, IR detected, to TRUE goto look_lt_endif look_lt_else bcf sens,1 ; clear look_lt, IR detected, to FALSE look_lt_endif call leds_off ; Turn off all IR LEDs return ;------------------------------------------------------- ;------------------------------------------------------- ; look_fire:: look at pin (d5) -- heat sensor ; 4/20/09 (efa) ;------------------------------------------------------- look_fire btfss portd,5 ;if(chk_fire == TRUE) bit5 is not +5volts goto look_fire_if goto look_fire_else look_fire_if bcf sens,6 ; clear fire, to TRUE call chk_fire ; react to fire goto look_fire_endif look_fire_else bsf sens,6 ; set fire, to FALSE look_fire_endif return ;------------------------------------------------------- ; rt_led_on:: subroutine to turn the right IR led on (inverted logic) ; 3/30/09(efa) ;------------------------------------------------------- rt_led_on bcf portc,6 ;rt_led (off!)(conducts more through ground)bit6 (c6) return ;------------------------------------------------------- ; lt_led_on:: subroutine to turn the left IR led on (inverted logic) ; 4/20/09(efa) ;------------------------------------------------------- lt_led_on bcf portc,0 ;lt_led (off!)(conducts more through ground)bit0 (c0) return ;------------------------------------------------------- ; leds_off:: subroutine to turn all IR leds off (inverted logic) ; 4/20/09(efa) ;------------------------------------------------------- leds_off bsf portc,0 ;lt_led (on!) bit0 (c0) bsf portc,6 ;rt_led (on!) bit6 (c6) return ;------------------------------------------------------- ; chk_fire:: check for a fire and react to it immediately. ; JR's rewriitten rountine updated 4/20/09 (efa) ;------------------------------------------------------- chk_fire btfsc sens,6 ; if(fire== TRUE) goto endif1b goto if1b if1b bsf control,1 ;set robot to left-wall-fallow (bit1 = 1) CHARGE ; play charge tune endif1b 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 movlw 0x01 ; load 1/10 seconds to wait in w movwf tenths ; load w value to seconds call wait10th ; pause for .1 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 ;------------------------------------------------------- ;; Final post-code includes ;; INCLUDE "lcd_4bit.inc" end