;-------------------------------------------------------------------------- ;****** FINAL PROJECT ;-------------------------------------------------------------------------- ;***** NOOR M. NORHALIM ;***** MAHADZIR MOHAMED ;***** EE476 Spring 1999 ;***** MICROCONTROLLER DRIVEN LEGO VEHICLE (MLV) ;***** Controls 3 motors, one DC (variable speed) and 2 stepper motors based on ;***** commands sent from 7 buttons ;***** Button 0: STOP 1:FORWARD 2:REVERSE 3:TURN RIGHT 4:TURN LEFT ;***** 5: TURN RIGHT 6: MOVE CAMERA MOUNTING UP 7:MOVE CAMERA MOUNTING DOWN ;***** LEDs are used to indicate which action/state(s) is/are performed/executed ;-------------------------------------------------------------------------- ;You will need to CHANGE this path .include "8535def.inc" .device AT90S8535 ; specifies to the assembler which chip we are using .def savREG =r1 ;SREG temp reg .def temp =r16 ;temporary register .def itemp =r17 ;interrupt temporary register .def itemp2 =r18 ;interrupt temporary register .def AnaLo =r19 ;A to D results .def AnaHi =r20 ; .def state =r21 ;Hold the transition state of the MLV .def debCntL =r22 ;Hold the low byte of the 16-bit counter .def debCntH =r23 ;Hold the high byte of the 16-bit counter .def turn =r24 ;Indicate turning direction .def steerStep=r25 ;Step Counter for steering and hand .equ off =0 ;Signal is off .equ stop =0 ;State Stop .equ forward =1 ;State Forward .equ reverse =2 ;State Reverse .equ NoTurn =0 ;No Turning .equ right =1 ;Turn Right .equ left =2 ;Turn Left .equ up =3 ;Hand move up .equ down =4 ;Hand move down .equ TCK2 =2 ;CLK/8 .equ TCK3 =3 ;CLK/64 ;***** Initialization .cseg .org $0000 rjmp RESET ;reset entry vector reti reti rjmp t2match ;Timer2 Compare Match Int Routine rjmp t2Ovf ;Timer2 Overflow Int Routine reti rjmp t1match ;Timer1 Compare Match Int Routine reti reti rjmp t0Ovf ;Timer0 Overflow Int Routine reti reti reti reti reti reti reti ;****** Step sequence tables for steering and hand UpSeq: .db 0b00000011, 0b00000110, 0b00001100, 0b00001001 DnSeq: .db 0b00001001, 0b00001100, 0b00000110, 0b00000011 RSeq: .db 0b00110000, 0b01100000, 0b11000000, 0b10010000 LSeq: .db 0b10010000, 0b11000000, 0b01100000, 0b00110000 RESET: ldi temp, LOW(RAMEND) ;Setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ;Set up ports DATA Direction Here to run LEDS ser temp ; out DDRB,temp ;Set PORTB to all outputs out DDRC, temp ;Set PORTC to all outputs clr temp out DDRD, temp ;Set PORTD to all inputs out PORTC, temp ;Set PORTC to all inputs out PORTB, temp ;Set up Timers ;Timer 2 to interrupt on compare match and overflow ;Timer 1 to interrupt on compare A match and set the compare time to 62500 ticks ;Timer 0 to interrupt on overflow ;Stop Timer0 and 2 ldi temp,0b11010001 ;enable t2, t2 match, t1 matchA & t0 interrupts out TIMSK, temp clr temp out TCCR0, temp ;Stop T0 out TCCR2, temp ;Stop T2 ldi temp, 0xf4 ;Set the match A register to out OCR1AH, temp ;62500 since 62500*16microsec=1sec ldi temp, 0x24 ;62500 = 0xf424 out OCR1AL, temp ldi temp,0b00001011 ;Prescale timer1 by 64 (one tick=16 microsec) out TCCR1B, temp ;and clear-on-matchA ;Set up analog converter to read channel seven ldi temp, 7 out ADMUX, temp ldi state, stop ;Initialize state with STOP ldi turn, NoTurn ;Initialize steering with NoTurn sei ;Enable all interrupts ;-------------------------------------------------------------------------- ;****** Main Program ;-------------------------------------------------------------------------- ;****** Branch Table ;Check which state the MLV is in start: cpi state, stop breq s_stop cpi state, forward breq s_moving cpi state, reverse breq s_moving rjmp start ;****** State STOP s_stop: cbi PORTB, 0 ;Turn off DC motor cbi PORTB, 1 clr temp out PORTC, temp ;Reset stepper motor step sequence cbi PORTB, 2 ;Turn on brake lights and turn off forward/reverse light cbi PORTB, 3 sbi PORTB, 4 sbi PORTB, 5 sbi PORTB, 6 sbi PORTB, 7 rcall steering ;Check if steering button is pressed rcall hand ;Check if hand button is pressed sbic PIND, 1 ;Wait for forward button press rjmp rev_but rcall debounce ;Debounce button sbic PIND, 1 rjmp rev_but ldi state, forward ;Load state with FORWARD rjmp start ;Jump back to branch table rev_but: sbic PIND, 2 ;Wait for reverse button press rjmp s_stop rcall debounce ;Debounce button sbic PIND, 2 rjmp s_stop ldi state, reverse ;Load state with Reverse rjmp start ;Jump back to branch table ;****** State FORWARD and REVERSE s_moving: rcall steering ;Check if steering button is pressed rcall hand ;Check if hand button is pressed cpi state, reverse breq mov_rev ;MLV is in Forward state sbi PORTB, 2 ;Turn off brake lights and/or reverse indicator sbi PORTB, 3 ;Turn on Forward indicator sbi PORTB, 4 sbi PORTB, 5 cbi PORTB, 6 cbi PORTB, 7 cbi PORTB, 1 ;Forward switches sbi PORTB, 0 ;Turn on DC motor rjmp s_mov_done ;MLV is in Reverse state mov_rev: sbi PORTB, 2 ;Turn off brake lights and/or forward indicator sbi PORTB, 3 ;Turn on reverse indicator cbi PORTB, 4 cbi PORTB, 5 sbi PORTB, 6 sbi PORTB, 7 cbi PORTB, 0 ;Turn on DC motor sbi PORTB, 1 ;Reverse switches s_mov_done: swait: in temp, ADCSR ;Wait for A to D start andi temp, 0b01000000;by checking if ADSC bit is set breq swait ;This bit is set by t1match interrupt wait: in temp, ADCSR ;Wait for A to D done andi temp, 0b01000000;by checking ADSC bit brne wait ;This bit is cleared by the AtoD hardware in AnaLo, ADCL ;Read the voltage in AnaHi, ADCH ;Set Timer2 OCR reg appropriately to PWM DC motor ldi temp, 2 out TCCR2, temp ;Set Timer2 to prescaler 2 ror Anahi ;Get the 8 MSB of the ADC ror Analo ror Anahi ror Analo out OCR2, AnaLo ;Set it to OCR2 rcall steering ;Check if steering button is pressed rcall hand ;Check if hand button is pressed sbic PIND, 0 ;Check if STOP button is pressed rjmp s_moving rcall debounce sbic PIND, 0 rjmp s_moving ldi state, stop ;Load state with STOP rjmp start ;Jump to branch table ;-------------------------------------------------------------------------- ;****** Subroutines ;-------------------------------------------------------------------------- ;****** Steer the front wheel to the right or left depending on which button is ;****** pressed steering: sbic PIND, 3 ;Check right steer button rjmp steerL rcall debounce ;Debounce sbic PIND, 3 rjmp steerL ldi turn, right ;Load turn with RIGHT ;Turn steering to Right, using T0 ldi temp, 5 ;Prescale Timer0 by 2 out TCCR0, temp clr steerStep ;Reset step counter contStR: sbis PIND, 3 ;Wait for right steer button release rjmp contStR clr temp ldi turn, NoTurn ;Load turn with NoTurn out TCCR0, temp ;Stop T0 rcall offSig ;Turn off right/left indicator ret steerL: sbic PIND, 4 ;Check left steer button ret rcall debounce ;Debounce sbic PIND, 4 ret ldi turn, left ;Load turn with LEFT ;Turn steering to Left, using T0 ldi temp, 5 ;Prescale Timer0 by 2 out TCCR0, temp clr steerStep ;Reset step counter contStL: sbis PIND, 4 ;Wait for left steer button release rjmp contStL clr temp ldi turn, NoTurn ;Load turn with NoTurn out TCCR0, temp ;Stop T0 rcall offSig ;Turn off right/left indicator ret ;****** Move the camera mounting up or down depending on which button is pressed hand: sbic PIND, 5 ;Check if up button is pressed rjmp handDOWN rcall debounce ;Debounce sbic PIND, 5 rjmp handDOWN ldi turn, up ;Load turn with UP ;turn hand up, using T0 ldi temp, 5 ;Prescale Timer0 by 2 out TCCR0, temp clr steerStep ;Reset step counter contUP: sbis PIND, 5 ;Check if up button is released rjmp contUP clr temp ldi turn, NoTurn ;Load turn with NoTurn out TCCR0, temp ;Stop T0 ret handDOWN: sbic PIND, 6 ;Check if down button is pressed ret rcall debounce ;Debounce sbic PIND, 6 ret ldi turn, down ;Load turn with DOWN ;turn hand down, using T0 ldi temp, 5 ;Prescale Timer0 by 2 out TCCR0, temp clr steerStep ;Reset step counter contDOWN: sbis PIND, 6 ;Check if down button is pressed rjmp contDOWN clr temp ldi turn, NoTurn ;Load turn with NoTurn out TCCR0, temp ;Stop T0 ret ;****** Debounce button press for ~5msec debounce: ;debounce for ~5 msec, 0.25usec/tick x 256 ticks x 78 = ~5 msec ldi debCntH, 78 ldi debCntL, 0xff loop: dec debCntL brne loop ldi debCntL, 0xff dec debCntH brne loop ret ;****** Turn OFF RIGHT/LEFT indicator OffSig: sbi PORTB, 6 ;turn off signals sbi PORTB, 7 ret ;-------------------------------------------------------------------------- ;****** Interrupt Routines ;-------------------------------------------------------------------------- ;****** timer 2 Compare Match (PWM --> TURN OFF DC motor) t2match:in savREG, SREG ;Save status register cpi state, forward ;Check which state MLV is in breq t2matchfwd cpi state, reverse breq t2matchrev rjmp t2matchdone t2matchfwd: ;MLV is in FORWARD state cbi PORTB, 0 ;TURN off DC motor cbi PORTB, 1 rjmp t2matchdone t2matchrev: ;MLV is in REVERSE state cbi PORTB, 0 ;TURN off DC motor cbi PORTB, 1 t2matchdone: out SREG, savREG ;Restore status register reti ;****** timer 2 Overflow (PWM --> TURN ON DC motor) t2Ovf: in savREG, SREG ;Save status register cpi state, forward ;Check which state MLV is in breq t2fwd cpi state, reverse breq t2rev rjmp t2done t2fwd: ;MLV is in FORWARD state cbi PORTB, 0 ;Turn on FORWARD switches sbi PORTB, 1 rjmp t2done t2rev: ;MLV is in REVERSE state sbi PORTB, 0 ;Turn on REVERSE state cbi PORTB, 1 t2done: out SREG, savREG ;Restore status register reti ;**** timer 1 compare A match 1/sec (Sample ADC every 1 sec) t1match:in savREG, SREG ;Save status register ldi itemp, 0b11000101 ;start A to D conversion out ADCSR, itemp out SREG, savREG ;Restore status register reti ;**** timer 0 Overflow (Send step sequence to stepper motors, steering and hand) t0Ovf: in savREG, SREG ;Save status register cpi turn, right ;Check which direction the stepper motors breq t0right ;should turn (right, left, up and down) cpi turn, left breq t0left cpi turn, up breq t0up cpi turn, down breq t0down rjmp t0done t0right:ldi ZL, low(RSeq*2) ;Get step sequence for RIGHT from table ldi ZH, high(RSeq*2) in itemp, PINB ;Do right signal ldi itemp2, 0b10000000 eor itemp, itemp2 out PORTB, itemp sbi PORTB, 6 rjmp t0setStep t0left: ldi ZL, low(LSeq*2) ;Get step sequence for LEFT from table ldi ZH, high(LSeq*2) in itemp, PINB ;Do left signal ldi itemp2, 0b01000000 eor itemp, itemp2 out PORTB, itemp sbi PORTB, 7 rjmp t0setStep t0up: ldi ZL, low(UpSeq*2) ;Get step sequence for UP from table ldi ZH, high(UpSeq*2) rjmp t0setStepUpDn t0down: ldi ZL, low(DnSeq*2) ;Get step sequence for DOWN from table ldi ZH, high(DnSeq*2) t0setStepUpDn: ;Send step sequence to hand stepper motor add ZL, steerStep lpm in itemp, PINC andi itemp,0b11110000 or itemp, r0 out PORTC, itemp cpi steerStep, 3 breq t0zeroStep inc steerStep rjmp t0done t0setStep: ;Send step sequence to steering stepper motor add ZL, steerStep lpm in itemp, PINC andi itemp,0b00001111 or itemp, r0 out PORTC, itemp cpi steerStep, 3 breq t0zeroStep inc steerStep rjmp t0done t0zeroStep: ;Reset step counter after every 4 steps clr steerStep t0done: out SREG, savREG ;Restore the status register reti