Did you know...
|
|
Analog Input Averaging
A channel configured to CHANNEL_MODE_AD_AVERAGE averages
some number of consecutive A/D samples and provides that
average in its public data buffer to be used by the host PC or by
another channel. When initializing the channel the host can
command the number of samples to be averaged. This number must be
a power of two between 0 and 15. Therefore, valid numbers of
samples are 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
4096, 8192, 16384 and 32768. Each sample contributing to the
average is taken when the channel is serviced. Therefore, an
average of 32 samples will be updated every 32ms if the frame
time is 1ms. Note that after the desired number of samples are
collected and the public data is updated, all past data is
discarded for the start of the next average. When a channel is
initialized to CHANNEL_MODE_AD_AVERAGE, its public
data is initialized to the current value of that channel's A/D
conversion.
To configure a channel to CHANNEL_MODE_AD_AVERAGE,
send the following set of 8 bytes:
| Byte # |
Byte Value |
Description |
| 0 |
200 |
Configure pin |
| 1 |
pin# |
Physical Pin number |
| 2 |
15 |
Channel mode = Average |
| 3 |
Number of samples |
Expressed as a power of two between 0 and 15,
inclusive. |
| 4 |
unused |
|
| 5 |
unused |
|
| 6 |
unused |
|
| 7 |
unused |
|
For example, to configure pin 2 to average 32 samples, the
following command would be send:
200 2 15 5 0x55 0x55 0x55 0x55
Return packet is an echo of the sent packet.
Pin Mode Source Code
The following code is what creates the pin mode for this function inside of the Wombat. You don't need to know this to use the pin mode, but some people find it interesting. See the SDK for some insight into how pin modes work. Hold your mouse over various words and variables for definitions.
#ifndef COMPILING_FIRMWARE
#include <stdio.h>
#endif
#include "types.h"
#include "utilities.h"
#include "global_data.h"
#ifdef COMPILING_FIRMWARE
#pragma code APPLICATION
#pragma romdata APPLICATION_DATA
#endif
void init_ad_average(void)
{
if (rxbuffer[0] == CONFIGURE_CHANNEL_MODE_0)
{
// Initialize the buffer with latest reading
tp.generic.buffer = vread_ad();
tp.ad_average.sum = 0;
tp.ad_average.count = 0;
if (rxbuffer[3] > 15)
{
tp.ad_average.samples = 15;
}
else
{
tp.ad_average.samples = rxbuffer[3];
}
}
}
void update_ad_average(void)
{
// Add to the sum, and the number of samples
tp.ad_average.sum += vread_ad();
++tp.ad_average.count;
// Get an integer which corresponds to 2^x
tp2.ad_average.temp16 = uint16_bitfield[tp.ad_average.samples];
if ( tp.ad_average.count >= tp2.ad_average.temp16)
{
// If we got enough samples, figure the average
tp2.ad_average.temp32 = tp.ad_average.sum;
// Since samples must be a power of 2, we can
// do a shift rather than a divide
tp.ad_average.sum >>= (tp.ad_average.samples );
tp.generic.buffer = tp.ad_average.sum;
// Round the result...
tp2.ad_average.temp16 >>= 1;
if ( tp.generic.buffer != 0xFFFF && (tp2.ad_average.temp32 & tp2.ad_average.temp16))
{
++tp.generic.buffer;
}
// And reset for next time
tp.ad_average.count = 0;
tp.ad_average.sum = 0;
tp.ad_average.source = virtual_pin;
}
}
/////////////////////////////////////////////////////////////////////////
// CODE FROM HERE DOWN IS TESTING CODE FOR USE ON PC, not FIRMWARE
#ifdef TEST_AD_AVERAGE
#define NUM_OF_TESTS 7
int test;
uint16 const test_vector[][7] = {
{0x8000,0x4000,0xC000,0x0000,20,4, 0x6000},
{0x8000,0x8000,0x8000,0x8000,20,4, 0x8000},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF,40000,15, 0xFFFF},
{0x8000,0x8000,0x7FFF,0x7FFF,40000,15, 0x8000},
{0x8000,0x7FFF,0x7FFF,0x7FFF,40000,15, 0x7FFF},
{0x1234,0x7FFF,0x7FFF,0x7FFF,1,15, 0x1234},
{0x0008,0x0002,0x9,17,3,1, 0x0005},
};
int test_iteration;
int main(void)
{
#define NUM_OF_SAMPLES 60
#define NUM_OF_SAMPLES_LOG_2 4
#define PIN 2
system_init();
for (test = 0; test < NUM_OF_TESTS; ++test)
{
printf ("Running test %d: values %d %d %d %d, iterations: %d samples: 2^ %d\n",
test,
test_vector[test][0],
test_vector[test][1],
test_vector[test][2],
test_vector[test][3],
test_vector[test][4],
test_vector[test][5]) ;
ADbuffer[map_physical_pin_ad(PIN)].u = test_vector[test][0];
rxbuffer[0] = CONFIGURE_CHANNEL_MODE_0;
rxbuffer[1] = PIN;
rxbuffer[2] = PIN_MODE_AD_AVERAGE;
rxbuffer[3] = test_vector[test][5];
process_rxbuffer();
for (test_iteration = 0; test_iteration < test_vector[test][4]; ++test_iteration)
{
ADbuffer[map_physical_pin_ad(PIN)].u = test_vector[test][test_iteration % 4];
process_pins();
}
if (get_buffer(map_pin(PIN)) != test_vector[test][6])
{
printf ("Test %d returned %d, expected %d\n",test, tp.generic.buffer, test_vector[test][6]);
return (1);
}
}
printf ("All tests passed.\n");
return (0);
}
#endif
|
|