Our device software
algorithm is relatively simple. We use the
Mega32 to:
1. Sample each analog channel at twice the maximum
signal frequency (Nyquist Rate).
2. Attempt to minimize time in between each channel
sample so as to make all 6-channel samples become an instantaneous event.
3. Construct data packets from the sampled channels.
4. Send data packets over a communications link at a
rate that ensures new data each frame cycle on the simulation software.
Thus, the majority of
software constraints come from timing issues.
The KXM52 accelerometers
are bandwidth limited to 50 Hz. Thus,
we choose a sampling frequency of 100 Hz to satisfy the Nyquist Rate. The goal is to achieve 1024-bit resolution
to allow for the greatest accuracy. We
implemented a method of over sampling and averaging by sampling the analog signals
at 4 times the sampling frequency. In
general, to increase the resolution of a measurement, by W bits, the over
sampling frequency must be:
Equation (11): Over sampling Frequency [s1]
Where, W was chosen to be
1, to allow for 11-bit resolution using the 1024 bit internal ADC on the Mega32. The 11th bit is later eliminated
by averaging the signal (divide by four).
Thus, the over sampling frequency is chosen to be 400 Hz. In this time interval, four independent
samples are taken for each channel, and averaged. A new average value is available at 100Hz.
Because we are sampling 6
channels, we need to change channels in between each sample. This is accomplished most easily by changing
the channel and then starting a sample.
The internal hardware will not actually start the sample until the new
channel is selected and the voltages settles (this takes about 13 cycles). It then takes about 13 cycles to sample the
data.
A faster sampling rate is
not possible to due speed constraints of the ADC on the Mega32. Where the maximum conversion rate, fSMAX
using a 125 KHz clock on the ADC is:
Equation (12): Maximum Sample Rate
Where
12-bit resolution would require:
Equation (13): 12-Bit resolution Sampling Rate
Thus, the sampling
algorithm is as follows:
1. For each analog channel:
2. Select the proper channel in ADMUX using a vector
in flash memory.
3. Start a new conversion by writing 1 to ADCSRA.6.
4. Poll for completion of the conversion (ADCSRA.6 is
0).
5. Read the 1024 bit data by reading ADCL first
followed by ADCH in left-adjusted format and add it to the data vector storing
that channel’s result.
6. Loop until each channel is done.
The value averaging occurs
upon data transmission, where the data vector is divided by four (averaged).
The RS-232 interface was
chosen to communicate to the PC. Using
the UART at 9600 baud, the communication algorithm must construct a data packet
and send it at an appropriate rate. A
transmission rate of 100Hz is chosen for two reasons:
1. This ensures that the playback software on the
computer will receive at least 1 data packet per 60Hz frame cycle
2. This ensures no data backup as a new [averaged]
sample is available at 100 Hz.
This means that the
maximum number of bytes that can be sent over the UART, NBMAX in
that time interval is:
Equation (14): Maximum Number of Data Bytes
Where, 1 start of frame
byte, followed by 6 1024-bit values must be sent. Obviously, the channel samples cannot take up two bytes, as it
will put the frame length up to 13 bytes.
So, the data is chopped up into pieces and sent over as a data
packet. The data packet is organized as
shown by figure (13).
Figure (13): Data Transmission Packet
Byte Number |
Label: |
Content: |
1 |
Start Of Frame (SOF) |
0x01 |
2 |
X1 Low Byte |
X1LB |
3 |
Y1 Low Byte |
Y1LB |
4 |
Z1 Low Byte |
Z1LB |
5 |
X2 Low Byte |
X2LB |
6 |
Y2 Low Byte |
Y2LB |
7 |
Z2 Low Byte |
Z2LB |
8 |
Upper Bits |
X1HB Y1HB Z1HB X2HB |
9 |
Upper Bits |
Y2HB Z2HB 0 0
0 0 |
Where a low byte (LB)
indicates the lower 8 bits of a 10-bit value and high byte (HB) indicates the
upper two bits of the 10-bit data. The
SOF byte is used to identify the beginning of a new packet. Because the application code is checking the
RS-232 Port at 60Hz and data transmission occurs at 100Hz, there is no
assurance that only full data packets will be received. A packet value of 0x01 is not allowed to be
transmitted over the port. Sending 0x01
for any byte field has extremely low probability. In the case that any byte field is 0x01, it is incremented to
0x02. The data packet is actually a
BYTE (unsigned char) array of length 10, where the final byte is
null-terminated to tell the transmit loop when to stop transmission. Thus, every packet byte is not allowed to
take the value 0x00, where it instead takes the value 0x02. Because of the rather small acceleration that
a human can have during simple motion, these constraints are well met and rarely
(if ever) does a packet have the value 0x00 or 0x01. There is, however, safety code on the receiving end.
The UART code written by
Professor Bruce Land for lab3 was used for data transmission [bl1]. There are 4 functions and several variables
used. The functions puts_int and
gets_int initialize transmit and receive operations respectively. Receive is never initialized. The interrupt uart_rec receives
characters and puts it into the character array r_buffer. The interrupt uart_send (called when
the UART TX register is empty, indicating a byte has finished being sent) loads
the next byte in t_buffer into the transmit register, or stops the send
loop at the end of a packet transmission via null-termination.
Although there currently
is never a case where the application software transmits information to the
device, the receive code was left intact for future modifications and
expansions.
If this project were to
take on a greater scale (or accuracy), then obviously a higher bandwidth
communication medium, such as USB, would be required. For this simple implementation, however, the RS-232 interface
works.
Timer0 is used to keep an
accurate time base for the system. The
timer generates compare match interrupts at half a millisecond. Choosing a timer clock of 250Khz and setting
the compare register to 125 generates the half a millisecond time base. Two variables, time0 and time1 keep track of
the timing intervals for both tasks (sampling and data transmission – respectively).
The final algorithm is as
follows:
1. Initialize all peripherals (Ports, Timer0, ADC,
UART) and variables.
2. Turn the protoboard LCD on by writing 0 to D.7
3. Loop forever
a. If time0 is 5 (2.5 milliseconds)
i.
Run the sampling code
b. If time1 is 20 (5 milliseconds)
i.
Divide the sample
averages by 4 (two bit-shifts right)
ii.
Build the data packet
iii.
Send the data
iv. Reset the sample averages to zero
4. On Timer0 interrupts:
a. Increment time0 variable
b. Increment time1 variable
5. On UART RX (transmission received)
a. Do nothing
6. On UART TX (transmission complete)
a. Send the next data byte
b. If there are no more data bytes to send
i. Turn off the TX loop