Obviously most of us ever had a necessity to average continuous data reading, for example from temperature sensor, readings are jerky and to output steady indications, input data should be averaged. There is very simple method and I thought it was obvious to use but noticed unexpectedly many projects with different averaging method. Most of them just save reading in array and average them time by time. This method has at least two cons: array eats memory and first reading comes out only after several readings. So I think I should present that method I've using long time. Sure it was mentioned here many times and sorry for repeating but seems many Arduino fans missed it.
So, suppose we have reading:
float r=ReadData(); (ReadData is some function to get data reading, change is by yours) and need to get smoothed value of r -
Each time we get new r value, we just need to modify already calculated
We need smoothing speed coefficient -
k. It should be between 0 and 1.
k is 0, we'll get constant data when reading is ignored;
k is 1, we'll have no smoothing, so the less
k is the smoother is output.
And finally, whole code:
//initialization float avgr=0; float k=0.01; ... //loop float r=ReadData(); avgr = avgr * (1-k)+r*k;
How does it work? very simple, if reading is steady (therefore avgr = r) , then output also steady:
If reading changes rapidly, low k mixes is with small portions to averaged value and therefore output will be smooth. This method is very simple and resource-saving. It mimics analog devices like analog voltmeter or thermometer, also electrical condenser, so I call it condenser method (of course method isn't exact condenser simulation but with such small expenses we have very nice close results).
As noted in comments, there is way to do all this via integer types:
//initialization int avgr=0; int Scale=1000; int k=10; //0-1000 ... //loop float r=ReadData(); avgr = (avgr * (Scale-k)+r*k)/Scale;
And another little improvement that I like more:
//initialization int avg=0; int avgr; int Scale=1000; int k=10; //0-1000 ... //loop float r=ReadData(); avg = avg * (Scale-k)/Scale+r*k; //avg is scalled for better precision avgr = avg/Scale;
If you have time-dependent data, you may need to have variable k that will be depend on time passed from previous reading.