Full Version : Norhalim-Mahdzir MCU Driven Lego Vehicle (ASM)
avr >>ROBOTS & AUTONOMOUS VEHICLES >>Norhalim-Mahdzir MCU Driven Lego Vehicle (ASM)


Admin5- 04-21-2006
Microcontroller-Driven Lego Vehicle by Lego Norhalim & Mahadzir

Introduction

For the final project, we designed a Microcontroller-driven Lego Vehicle (MLV). This project makes use of the ATMEL AT90S8535 8-bit RISC microcontroller unit. The microcontroller basically functions to determine the user input through button pushes, drive the DC and stepper motors to provide motion to the MLV as well as to set the speed of the vehicle through the use of the onboard Analog-to-Digital converter.

Our project involves a combination of hardware and software design. The hardware part includes building the mechanical model for the MLV and circuitry to drive the DC and stepper motors by providing the necessary power and voltage level, as well as providing electrical protection for the microcontroller unit. The software part involves designing the state machine for the steering and motion control of the MLV, providing the stepping sequence for the stepper motor and controlling the LED signals.

Features

6-button Input System
Steer Left, Steer Right, Forward, Reverse, Stop, Raise and Lower Tray.
2 Stepper Motors and a DC Motor
DC motor provides the forward and reverse movements while the 2 stepper motors are used to provide steering and raising/lowering camera mount rack respectively.
Speed control
Increase or decrease the speed of the vehicle by adjusting the trim-pot knob.
Light Indicator for different movements of the vehicle
Left and right blinking signal, forward and reverse and park light.
Planetary Gear System
Planetary gear system for forward and reverse movement for higher torque.
Differential Wheel System

High Level Design

The Microcontroller-driven Lego Vehicle (MLV) begins in a 'parking' condition where all of the motors sit idle and the stop lights turn on. It then wait for a user input through a button push. If the Forward button is pushed, the MLV moves forward and the forward headlights turn on. If the Reverse button is pushed, the MLV moves backward and the reverse lights turn on. Note however if the MLV is moving forward and the Reverse button is pushed, nothing will happen. The same goes when the MLV is going in reverse and the Forward button is pushed. This is done as a safety measure to protect the mechanical part of the vehicle. Pushing the left or right steering button makes the front wheel of the vehicle turn in the appropriate direction. Pushing the Raise and Lower button raises and lowers the camera mount. Steer Left or Right and Raise or Lower buttons produce motion when the vehicle is moving forward, backward or in a parking condition.


Software Design
We started our design by first figuring out the state transition diagram for the MLV. There are three states: stop, forward and reverse. We used a branch table to implement the state machine. In each state, the microcontroller sends different signals to the ports. At the same time, it also checks for 'steering' (for turning the front wheel right and left) and 'hand' (for moving the camera mounting up and down) button press if any by calling the appropriate subroutines.

(1) State: Stop
In this state, the MLV is not moving. The microcontroller turns off both the forward and the reverse switch, and lights up two LEDs to indicate this state. It then calls the 'steering' and 'hand' button press. If any of the four buttons (right and left for 'steering', and up and down for 'hand') is pressed, it executes the appropriate subroutine. After that it checks for 'forward' and 'reverse' button press. If any of these two buttons is pressed, it loads the new state before jumping back to the branch table.


(2) State: Forward In this state, the mictrocontroller first gets the ADC reading to determine the speed. Then it turns on the forward switches and lights up two LEDs to indicate that the MLV is in the forward state. Then, it calls the 'steering' and 'hand' subroutines and checks for stop button press. If there is no button press, it jumps in a loop and continously checks the speed specified by the ADC every one second. If the stop button is pressed, it loads the 'stop' state and jumps back to the branch table.

(3) State: Reverse
In this state, the microcontroller does the same thing as in state forward except that it turns on the reverse switch and lights up the reverse LEDs.

Timers
We practically used all the timers/counters available on 8535 chip. More specifically we used Timer2 and Timer0 Overflows, Timer2 and Timer1 Compare Match. The following discusses in more details what each timer does:

Timer2 Overflow and Compare Match
Timer2 is used to vary the speed of the DC motor via PWM. First Timer2 is set to prescaler 2 (clk/8) corresponds to an interrupt of every 512msec. Then the OCR2 register is loaded with the 8 MSB of the 10-bit ADC. When Timer2 Compare Match interrupts, the interrupt subroutine turns off the forward or the reverse switches depending on the state which the MLV is in. However, it does not reset TCNT2, and thus Timer2 will keep counting. When Timer2 Overflow interrupts, it turns the forward or the reverse switches back on. So, both Timer2 Compate Match and Timer2 Overflow are combined to pulse-width-modulate the voltage/current to the DC motor.

Timer1 Compare Match
Timer1 Compare Match is used to sample the ADC every 1 sec. Timer1 is set to prescaler 3 (clk/64) and the Match A register is set 62500. This corresponds to an interrupt every one second (62500*16microsec=1sec). The interrupt subroutine starts the ADC conversion and resets Timer1 counter to zero.

Timer0
Timer0 is used to send the four steps required by the stepper motors ('steering' and 'hand'). For both 'steering' and 'hand', Timer0 is set to prescaler 5. This is to produce very low step frequency so that the stepper motors will turn very slowly. The step sequence for both stepper motors are defined in tables in flash memory. A counter is used to read the step value from the tables.

Debounce
The button press is debounced for 5msec using two counters. This is to avoid spikes from being considered as a button press.

Subroutines
Steering
This subroutine will enable Timer0 and initialize the step counter to 0. It first checks the direction of the steering depending on which button (right or left) is pressed. If it is a right button, it lights up the right LED and loads 'right' to the register 'turn' and vice versa. When Timer0 interrupts, it will check the content of this register and assign the appropriate address of the step sequence table defined in flash.

Hand
This subroutine does exactly the same thing as the 'steering ' subroutine except that it loads the 'turn' register with 'up' or 'down' depending on which button is pressed. There is no LED indicator for 'up' and 'down' however. Timer0 will also check for this buttton and load the appropriate step sequence.

OffSignal
This subroutine simply turns off the turn 'right' or 'left' indicator. It is called when the any of the steering button is released.

Ports

PortA is only used for the ADC. ADMUX is set to 7 to sample from channel 7.
PortB:
PortB0 and Port1: Switches for the ADC motor
PortB3-to-PortB7: LEDs for 'stop', 'forward', 'reverse', 'right' and 'left' indicator.
PortC:
PortC0-to-PortC3: To control the 'steering' stepper motor
PortC4-to-PortC7: To control the 'hand' stepper motor

Hardware Design
Vehicle Chasis
We begin the hardware design part of this project by trying to figure out the best way to efficiently mount the motors. Multiple mechanical models were created and torn apart until an acceptable model was found. At the end, we decided to create the mechanical model using components from Lego Technic™ 'Turbo Command' package. It basically consists of 472 Lego pieces which include the components to build a differential wheel system. Epoxy is used to fix the Lego gear pieces to the drive shafts of two motors. Wires and polystrene is used to provide support and strengthen the mechanical model. Click here to see final mechanical model for the vehicle.

Transistor Switches
Transistor switches are used to provide the proper stepping sequence for the stepper motor. Since the output from the Atmel board is only 5V, transistor switches are used to provide 12V signal which is needed by the stepper motor to operate. Also, A H-bridge transistor switch network is used to enable forward and reverse movement of the DC motor. The circuit diagram for these switches can be found here. The transistor switches also provide electrical protection for the ATMEL microcontroller unit from the voltage spikes produced by the motors. The transistor used is TIP102 (npn).

Stepper Motor
The stepper motor we use has four coils which, when energized in the correct sequence, cause the permanent magnet attached to the shaft to rotate. Reversing the order of the steps in a sequence will reverse the direction of rotation. In our project we used the stepper motor to provide steering and also to move the camera mount rack. Since the mechanical design requires the stepper motor to have a big torque, we used the 'two-coil excitation' stepping sequence. In this stepping sequence, each successive pair of adjacent coils is energized in turn. Click here to see an animated picture of the stepping sequence. This stepping sequence however doesn't provide smooth movements and uses more power compared to the normal stepping sequence but produces greater torque.

DC Motor
We use a 3V DC motor to provide forward and reverse movement for the MLV. We found that this DC motor consumes a lot of power, thus very inefficient.

Planetary Gear System
A planetary gear train is a mechanism consisting of an assembly of meshed gears: the sun gear, the planet carrier, and the ring gear. A planetary gearset is used to reduce the 'weight' of the vehicle seen by the DC motor and increase its efficiency. Click here to see the internal mechanism of a planetary gear system.

Differential Wheel System
Differential wheel system is widely used in modern vehicle due to its safety features. We used the differential wheel system simply because it is included in the Lego package and it looks really cool! Click here to see a picture of the differential wheel system.

Results
The design goals were successfully met. The microcontroller unit appropriately scans for user input and drives the DC and stepper motors to provide motion to the vehicle. It successfully sets the speed of the vehicle from the value obtained from the onboard ADC and controls the signal lights.

The mechanical parts however proves to be quite a big challenge to us. With little mechanical experience, designing the model took a lot of our time. Mounting the motors on the vehicles produces inefficiencies that we didn't anticipated. However, after much tweaking we finally got a working model of the vehicle :)

Measurements

DC Motor
Voltage 4.5V
Current 500 - 800 mA
depending on the load

Stepper Motors
Voltage 12V
Current 200 - 500 mA
depending on the load

Link to Schematics: http://instruct1.cit.cornell.edu/courses/e.../s1999/mohamed/

Future Improvements
Given more time and resources, we would like to implement the following improvements:

A more robust mechanical model
The mechanical model of the vehicles seems a little bit flimsy since it was made out of Lego pieces. We would also want a higher efficiency gear/lever systems implemented.
Feedback control systems
The steering and camera mount would have a feedback control system that would give feedback if the maximum steering/height is reached. The feedback control system would turn the motor off to avoid damage to the mechanical parts.
LCD to display the current speed or condition of the vehicle.

Link:
http://instruct1.cit.cornell.edu/courses/e.../s1999/mohamed/
CODE

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






Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.