Reading a battery voltage in an embedded device. However, the actual voltage varies greatly depending upon system load. We need a method to reduce the fluctuation of the voltage to display the best value.
Currently, we're using a rolling/moving average. However, over the last 15 readings, the result still fluctuates too much.
In reading about smoothing algorithms, it appears that b-splines, kernel filters, or some other smoothing algorithms would be ideal. However, I can't find a simple example that doesn't use numpy or intrinsic functions within mathcad or some such.
Anybody know of a simple-to-implement function that could help with this? This is a C++ project (using Qt 4.5) with just the bar minimum of libraries. I'd prefer to stay in the integer domain (showing the voltage in millivolts from 3300-4200).
TIA Mike
Well, it's a bit tough to tell what you need without specifics on your situation. For example, what is your sensor sampling rate, and how is the sensor fluctuation and noise that you're trying to remove characterized?
However, if you already have moving average implemented, I might recommend trying a moving median instead. (Median of the last n samples, rather than average.) This will tend to reduce the impact of large short-term aberrations from normal from your output.
If you can find parameters that work, it would be preferrable for CPU and memory requirements to use some form of a discrete-time low-pass filter. These are quite easy to implement, and only require knowledge of the previous output value and the current input to compute the current output. For example:
Y = Y[n-1] + A * (X - Y[n-1])
(Where Y
is the current output, Y[n-1]
is the last computed output, and X
is your latest sensor reading.)
A
is effectively the time constant of the low pass filter, but it's discrete time, so it depends on the sampling rate. Specifically, A = dt / tau
, where dt
is your sampling period in seconds, and tau
is roughly analagous to the continuous-time time constant.
you can find explanations and source code in classical NR book: http://apps.nrbook.com/c/index.html,
namely chapter 3: http://www.arcetri.astro.it/irlab/library/recipes/bookcpdf/c3-3.pdf
Have you considered simply applying a skew limit to the value?
new_val = Read_From_HW();
diff = new_val - prev_val;
if (diff > SKEW_LIMIT)
diff = SKEW_LIMIT;
else if (diff < -SKEW_LIMIT)
diff = -SKEW_LIMIT;
reported_val = prev_val + diff;
prev_val = reported_val;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With