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.
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 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.
The button press is debounced for 5msec using two counters. This is to avoid spikes from being considered as a button press.
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.
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.
This subroutine simply turns off the turn 'right' or 'left' indicator. It is called when the any of the steering button is released.
- PortA is only used for the ADC. ADMUX is set to 7 to sample from channel 7.
PortB0 and Port1: Switches for the ADC motor
PortB3-to-PortB7: LEDs for 'stop', 'forward', 'reverse', 'right' and 'left' indicator.
PortC0-to-PortC3: To control the 'steering' stepper motor
PortC4-to-PortC7: To control the 'hand' stepper motor