For our project, we have two
separate programs: one for the transmitter and one for the receiver.
In the transmitter, we have three separate tasks running, all off of the
time base generated from timer0. To keep the time base, we used the timer0
overflow interrupt. The three tasks were to start the transmit interrupt,
read in user input, and run the power button debounce state machine.
The reason why our group needed a separate task to start and stop the
transmit interrupt was to keep the interrupt non-blocking. We used the data
register empty interrupt to tell when it was ready to send the next bit,
which under normal conditions is always faster than the 20 ms this task was
run at. However, we still used this interrupt to make sure that our code was
failsafe. The data register empty interrupt is triggered when a byte is
transmitted from the UART I/O Data Register (UDR) to the Transmit Shift
Register. We set the 8-bit UART BAUD Rate Register (UBRR) to 255 to send and
receive at a BAUD rate of 1953.13, the slowest possible BAUD rate with a
clock of 8 Mhz.
To read in the analog inputs generated by the user, we used two lookup
tables. The first lookup table was used to take the raw input voltage and
place it within a specified range to determine which of the 15 magnitudes to
set each motor to. The second lookup table was used to turn the magnitudes
into the correct transmission packets, without overwriting the opposite
engine’s information while updating each engine. This task ran at 50 ms.
Our last task is a simple four-state debounce state machine used for the
power button. This task ran at 30 ms.
For our receiver, we had only one task, running at 20 ms based off of
timer0. The job of this task was to receive the transmitted byte, parse
it, check if it is meant to turn on/off the hovercraft, and if not, to
convert into the appropriate signal for each of two motors. Our group once again used a
lookup table to determine exactly what signal to send to each motor. The
motors obtain their values by manipulating the timer1 Output Compare
Register A (OCR1A) for the right engine and timer1 Output Compare Register B
(OCR1B) for the left engine.
Timer1 is set to PWM mode, which generates a wave that counts from 0 to 255
and back down. Once the counter is the same as the value in the output
compare register, the resultant output wave transitions from high to low, or
low to high, depending on the current state. An OCR value of 255 will
generate a completely low output signal, resulting in a full forward value.
An OCR value of 128 will generate even square output wave, resulting in a
stop value, and an OCR value of 0 will generate a completely high output
wave, resulting in a full reverse signal. More details regarding the
operation of PWM can be found in the hardware design.
After OCR1A and OCRIB are updated, we enable the receive complete interrupt
to keep the code non-blocking and to make sure that the OCR1A and OCR1B
values do not change while updating them.
A few problems we ran into were due to the fact that when the transmitter
and receiver are reset, they both assume that the hovercraft is off. When
the hovercraft is off, none of the three motors can move. If only the
hovercraft and not the transmitter is reset, the hovercraft will think its
off but the transmitter will think it is on, and vice versa. Another problem
was that originally, if the hovercraft lost the receive signal, it would
keep its last signal and keep using that value over and over again. This
would not be good, for example, if you hovercraft went out of transmission
range and kept going and going and going… We fixed all these problems in the
final versions of the code.