Software Design
Kernal: The kernel of the code just contains setup
code as well as various timers that refresh the button handler, the sensor
handler, and the servo controller. The kernel initializes timer 0 to interrupt
every 1 ms to keep an accurate time base. It also initializes Timer 1 to act as
a PWM in fast mode to control the servo. Since the opto-isolator in Figure 4
effectively inverts all of the signals going into it, I had to generate inverted
pulses for the servo control, so I set the output compare mode to set the output
line on a compare match and clear the output line when the timer reached the TOP
value. To properly generate the pulse train, I set WGM for Timer 1 to mode 14 so
that I could define both a TOP value and a output compare value. This way, I
could control both the duration of a pulse using the output compare value and
the period between pulses using the TOP value. The prescaler of Timer 1 was set
to 64, so each 250 ticks of the timer would represent 1 ms. The kernel also
initializes the ADC to have a sampling frequency of 125kHz and initializes PORT
B to be an input port for the buttons on the STK 500.
Button Handler: The button hander function contains
a state machine that will debounce the STK-500 push buttons connected to PORT B.
The kernel will refresh this state machine every 20 ms to see if a button has
been pushed. Once a button has been debouced, the handler will either increment
or decrement either a gain or one of the weights in the PID equation to change
the behavior of the light tracker in mid-operation.
Figure 5: Button debouce state machine.
Sensor Handler: This function gets the results from the ADC on PORT A pins 1 and 2 that are connected to the voltage dividers shown in Figure 1. After the values are obtained, one of the inputs is multiplied by a correction factor that corrects for the fact that the photo-resistors are not exactly matched. The value of this correction factor was determine experimentally by exposing each sensor to the same light and seeing what the resulting voltage was at the MCU input pin. The data from the two sensors were then subtracted from each other to obtain the error, since ideally the light sensors would have the same output when they are both facing the light source. This function also keeps track of the last sensor difference to calculate the derivative of the error using a divided difference approach.
I simplified this equation by assuming that the time step was equal to 1. The integral in the PID expression is calculated in this function by simply taking a running sum of the errors. I included a reset rate to clear the running sum every 8 calls to the sensor handler to prevent the integral term from growing continuously in the event that a small error could not be corrected due to a limitation in the servo step size. If there was no reset, it would cause the servo to oscillate very slowly around the light source.
Servo Controller: This controller uses the error, the derivative, and the integral generated by the sensor handler to calculate a correction to the servo position based on the PID expression shown in Equation 1. The position of the servo is controlled through varying the duty cycle of the pulse train being sent to the servo motor by setting the output control register for Timer 1. Since the prescaler for Timer 1 is set so that 250 ticks equals 1ms, the pulse width sent to the servo can be between 125 and 625 ticks, or between .5ms and 2.5 ms. Thus after the correction to the position is calculated, it is checked against the above bounds to make sure that the servo isn’t being overdriven beyond its operational range. The various weights in the PID control equation were determined through trial and error. Initially I tried to use all integer arithmetic to compute the PID calculations, however, the errors in most cases were so small that major round off issues cause the PID corrections to be quite small, which resulted in slow operation of the light tracker. Once I switched data types to ‘float’ instead of ‘int’ I immediately noticed much faster tracking of light sources.