< Main : High Level Design : Program Design : Hardware Design : Design Issues : Conclusion : Appendix >

# ( Program Design )
Final code: final1.c Test code, stepper motor control: steptest.c Test code, using light to control motors: litestep.c
LightRover has two major modes of operation: calibration, and follow. These modes are controlled by the main state machine. This organization, combined with the needfor timed motor, sensor, and LED control naturally lead to a timed based scheduler program. Only one ISR was necessary-Timer0 Clear on Compare Match, which interrupts every 1 ms and updates the timers used in the program. Our full feature set had four modes: Calibration, Follow, Menu, Program. However, we decided that working for a stable Follow Mode was more important than additional features, so Program, and Menu Modes were not included in the final design.

# Program Design Philosophy
Before writing any code, we sat down and discussed features we wanted to see and how they should work. Since the different features would use the same functions (such as sensing and motor control), our focus was to develop those functions to be as general as possible. For example, we have one function motorControl that takes in a desired direction (foward, left, right, stop) as a parameter and outputs the appropriate control signals. This allows the caller to specify its own timing.

# Initialization
The code will initialize various values, state variables, as well as Timer0 and the ADC upon booting. All these initializations are wrapped in the function initialize. When the initializations are complete, the code falls into the main while loop, where it stays for the remainder of the execution. LightRover's first action is to begin in calibration mode, where it will attempt to adjust to its surroundings.

# Calibration Mode
As previously mentioned, when the boot process concludes it enters Calibration Mode. This mode has three states: CALIB_INIT, CALIB_CHECK, and CALIB_DONE, and the state changes at 1.5 second intervals. Typically we begin in state CALIB_INIT to take an initial sensor reading and change to state CALIB_CHECK. 1.5 seconds later, in CALIB_CHECK, we take another sensor reading and compare it with the value previously obtained in CALIB_INIT. If the two results are deemed equivalent, the threshold value is calculated. We calculate the threshold light intensity to be 7% greater than the measured light. This requires a floating point multiply, which we are able to do because this mode is not time critical, and the states have a long 1.5 second interval. The read and comparison cycle is done first for the left sensor, then for the right; with LED's indicating the sensor. If the comparison fails (if there is a flickering light in the area, for example) then a retry counter is incremented and the process begins over again. However, if there are more than three consecutive calibration failures, the default threshold values are loaded and the program falls into Follow Mode.
This mode is in function calibrate. We discussed how the robot should handle different light environments and decided that it would be best for the robot itself to set itself. Calibration works very well, but one issue it does not address is what to do when there is too much light and we need to decrease the threshold value. It is very difficult to discern a very bright environment from a constant light signal. We were unable to come to a solution without making judgements on the usage of the robot (What if the user wished to have the robot follow the sun?).

Fig SW-1: Calibration Mode state diagram. Interval 1.5 sec

# Menu Mode (not featured in final design)
A working Program Mode required some method for the user to select either Program or Follow modes. To address this, LightRover was supposed to fall into Menu Mode after initialization and calibration. Shining a light at the left sensor would correspond to selecting Follow Mode, and the right sensor would select Program Mode. Although this was fully operation, the decision to remove Program Mode meant the removal of Menu Mode.

# Follow Mode
Follow Mode is the major operating mode and is our original vision: to have the robot detect and follow light. The sensors are handled by the function sensors which outputs a result (DETECTED_BOTH, DETECTED_LEFT, DETECTED_RIGHT, DETECTED_NONE). Function motorControl will take in the result and send the control to the appropriate motor.
We use two ADC channels (channel 0 for left, and channel 1 for right). Because it is not possible to perform two ADC conversions simultaneously, we take a reading and compare it with the previous reading of the opposing sensor. For example, if we were to read the left sensor, we would compare it with the right sensor's value taken from the previous cycle. The actual comparison is done by helper function compare. compare will check if the signal is above the threshold level then check to see if one reading is significantly greater than the opposite sensor's reading. Because it is unlikely for two sensors to receive the exact same sensor reading, we defined an acceptable range. The ADC provides 8-bit precision so the sensor reading will range from 0-255. We measured the difference in voltage between the two sensors using the multimeter. Using the formula (V/5)*(256) we calculated the ADC value. We found that the sensored differed about 0.02 volts or 1. This value was too strict to be usable, so we instead found a value through experimentation (which we found to be 10).
Function motorControl has gone through several revisions. We began by using a chain of if else statements (as seen in litestep.c), but since the implementation required that we be able to control each motor independently, we moved to using an array. Array steps[] holds the control signals and are used for both motors. By default the control signals are for the right motor, but since all the motor signals are output to a single PORTB, a simple left shift by 4 controls the left motor. The resulting code is very compact since we use the same single array to control both motors and use two step counters to enable independent motor control.
We found using the same timer for both the sensors and motor control resulted in very jerky movements. In the final design, each has its own timer so the MCU can send more stable control signals to the motor for a longer period of time. With the sensors originally reading at very fast pace, the motors would respond too quickly, resulting in robot that could do little more than tremble in the same place unless the light source was very close.

# Program Mode (not featured in final design)
Program Mode was an additional feature where the user could program the robot by light. This mode was desirable because it reused a lot of the functions used by Follow Mode, and it would have been interesting to see a robot programmed by unconventional means. Program Mode consisted of two states: PGM_PGM and PGM_PLAYBACK. PGM_PGM was the program state, where shining a light at a sensor corresponded to an "instruction" (see the table below)
Sensor Instruction
Left sensor Left turn
Right sensor Right turn
Both sensors Forward
No light detected No instruction
Fig SW-2: Program Mode "instruction set". Unfortunately the complexity proved to be too much for LightRover.
This mode was designed to be very simple, in fact, the distances were preset to be the turning radius of the robot. These instructions were to be stored in a five instruction array that would be played back in the PGM_PLAYBACK state when the array index reached maximum capacity.
PGM_PLAYBACK mode worked correctly if we hardcoded an array of instructions, but we did not have sufficient time to determine why the PGM_PGM mode did not work. Since the programming part of the Program Mode failed to function correctly, there was very little reason to keep around this mode.

4/22/2005 - Cornell University ECE 476 Final Design Project "LightRover"
Thientu Ho
David Shu