Did you know...
|
|
Analog to Digital A/D First Order Filtering
A channel configured to CHANNEL_MODE_AD_1ST_ORDER
performs first order digital filtering on values input from an
A/D capable channel and provides the filtered value in its public
data buffer. The filter constant and sample rate are provided in
the initialization command. The filter constant is expressed as a
number of 65536ths. For example, to use a filter constant of .5,
a value of 36768 would be sent in the initialization command. The
sample period is expressed in frames, from 0 to 255. A value of 0
represents one sample per frame. A value of 1 represents a sample
every other frame. A value of 255 represents one sample every 256
frames. The public data buffer is initialized with the latest A/D
conversion at initialization. After each sample period has
elapsed the latest A/D sample is filtered into the public data
buffer according to the following formula:
Public_Data_Buffer = Public_Data_Buffer * filter_constant +
new_sample * ( 1 - filter_constant)
To configure a channel to CHANNEL_MODE_AD_1ST_ORDER,
send the following set of 8 bytes:
| Byte # |
Byte Value |
Description |
| 0 |
200 |
Configure pin |
| 1 |
pin# |
Physical Pin number |
| 2 |
7 |
Channel mode = CHANNEL_MODE_AD_1ST_ORDER |
| 3 |
Filter constant high byte |
(k * 65536) / 256 |
| 4 |
Filter constant low byte |
(k * 65536) modulo 256 |
| 5 |
Sample Time |
Number of frames between samples |
| 6 |
unused |
|
| 7 |
unused |
|
For example, to configure pin 2 to filter with constant .736 and
a sample time of every four frames send:
200 2 7 0xBC 0x6A 3 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.
#include "types.h"
#include "utilities.h"
#include "global_data.h"
#pragma code APPLICATION
#pragma romdata APPLICATION_DATA
void init_ad_filter_1st_order(void)
{
// Get the constant
tp.ad_filter_1st_order.k = RXBUFFER16(3);
if (tp.ad_filter_1st_order.k > 0)
{
tp.ad_filter_1st_order.kinv = 0xFFFF - tp.ad_filter_1st_order.k;
++ tp.ad_filter_1st_order.kinv;
}
// How often do we sample?
tp.ad_filter_1st_order.sampletime = rxbuffer[5];
// Set the countdown to that period
tp.ad_filter_1st_order.counter = rxbuffer[5];
// And initialize to the first sample
tp.generic.buffer = vread_ad();
}
void update_ad_filter_1st_order(void)
{
// Is it time to sample?
if (tp.ad_filter_1st_order.counter)
{
// No. Update countdown
-- tp.ad_filter_1st_order.counter;
}
else
{
// Yes! Reset the timer for next time
tp.ad_filter_1st_order.counter = tp.ad_filter_1st_order.sampletime;
// If k is zero, just set the buffer to the latest sample
if (tp.ad_filter_1st_order.k == 0)
{
tp.generic.buffer = vread_ad();
}
else
{
// Otherwise, mix the old and new data in proper
// proportions
//
// Using the TP2 space as temporary storage...
tp2.ad_filter_1st_order.temp32_1 = tp.generic.buffer;
tp2.ad_filter_1st_order.temp32_2.temp2 = vread_ad();
tp2.ad_filter_1st_order.temp32_1 *= tp.ad_filter_1st_order.k;
tp2.ad_filter_1st_order.temp32_2.temp2 *= tp.ad_filter_1st_order.kinv;
tp2.ad_filter_1st_order.temp32_2.temp2 += tp2.ad_filter_1st_order.temp32_1;
#ifdef LITTLE_ENDIAN_WOMBAT // This code assumes little endian
if (tp2.ad_filter_1st_order.temp32_2.bytes[1] & 0x80 && tp2.ad_filter_1st_order.temp32_2.words[1] != 0xFFFF)
{
++tp2.ad_filter_1st_order.temp32_2.words[1];
}
tp.generic.buffer = tp2.ad_filter_1st_order.temp32_2.words[1];
#else
#error
#endif
}
}
}
|
|