Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smoothing function for battery voltage display to reduce spikes in embedded system

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

like image 318
Mike Crowe Avatar asked Apr 01 '11 17:04

Mike Crowe


3 Answers

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.

like image 191
potatoe Avatar answered Nov 13 '22 15:11

potatoe


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

like image 43
Anycorn Avatar answered Nov 13 '22 14:11

Anycorn


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;
like image 37
Tim Henigan Avatar answered Nov 13 '22 15:11

Tim Henigan