My interpretation of the code of the smoothing example, is that each iteration of loop the latest sensor reading (t) is added to a running total, and the t - 1 reading is subtracted from the total. For a running average, shouldn't the oldest sensor reading be subtracted instead? I'm probably missing something really basic..
I was looking through these examples to try to find an efficient way to implement a weighted moving average for sensor data (both positive and negative from an IMU) in float.
Thanks for responding. Don't want to take too much of your time, but just in case you look at this. I still don't understand why. For example when the readindex is at 4, we add the latest sensor reading to the total (and save it at index 4) and subtract the reading which was saved at readindex 3, which is from the previous sensor read?
Thanks for the note on the 2nd example. Is there a way to get around multiplication/division to speed up the code. I'm still quite new at this, but I read that maths in floats is very slow.
You're not thinking in a circular fashion.
Start at index zero, and see what happens.
When the index is at four, you subtract the reading at four from the total, write the new reading at four, add the new reading to the total, and then increment the index for the next time around the loop.
(Also, the for loop in the setup function is superfluous)
For high frequency electronic noise, it is enough to take a number of samples without the need of an array. See my example: averageRead.ino
For example when reading a voltage from a battery, then that is enough.
For a sensor with a acceleration, gyro, magnetometer, there are a number of mathematical filters, such as AHRS. It works very well because of Sensor Fusion (the disadvantages of each sensor is compensated by the other sensors).
A simple low-pass filter with a float variable is as you showed. Often 1% or less of the new data is used for the average.
// global variable for average
float average;
// in the loop()
int rawADC = analogRead();
float newValue = (float) rawADC;
average = (0.99 * average) + (0.01 * newValue);
That works really well, and no array is needed. It can be used in combination with a millis-timer, to get a new sample every 10ms for example.
Reducing the mains 50Hz or 60Hz is not so easy. Trying to reduce that noise with shielding or a hardware filter might be needed.
What I wrote here is just a very small part of the smoothing possibilities. It depends on your project what the best smoothing is.
Yes, and that form of low pass filter can easily be made using only integer arithmetic, or even bit shifting in some cases - making it tens or hundreds of times faster.
Thank you, @Koepel for taking the time to reply.
Lots of useful info. It's basically angular velocity vectors, which are rotated by quaternions that I get from sensor fusion. These angular velocity vectors, are going to serve as inputs for the mouse library to move the mouse around. But I'm trying to smooth them out bit, so the device feels better to use. I think I should have been clearer, that what I'm trying to accomplish is to basically find a way to to the weighted average in some other way than float multiplication, since I read that's slow.
@anon57585045 Wow, that's a huge difference. Would you be able to share some link for this?
With integers, keep the actual number in bits somewhat to the left and use the lower bits as bits behind the decimal dot.
Which library do you use ? Please give a link to it.
It starts with a good sensor
I hope you are not using a fake, old, noisy MPU-6050
Do you use a 5V (Pro) Micro board with a 3.3V sensor ? then you should fix the voltage mismatch of the I2C bus.
@Koepel thank you again for replying. I'm using a BMX160 sensor and an arduino nano. This library. Sorry I'm a bit of a newbie, still not sure how I would implement your advice. I'm more than happy to look at some link/do research, just not sure where to start.