This seems to work, but is very slow to respond. How can I speed up the response?
float smooth ;
void loop()
{
SSerial.print(analogRead(5)); //show raw output of pot value
SSerial.print(" "); // add a space for readibility
smooth = 0.9 * smooth + 0.1 * analogRead(5);
SSerial_println(smooth); //show filtered output of pot value
delay (100);
}
I am getting speed readings several times each second from a transducer. Each of these readings tends to vary a bit from the prior one, and I just want to get a stable reading to use to present to the driver.
Seems like it can be used for minor potentiometer output jitter. If I initialize smooth to the same value of the pot, it starts the calculation there, which is good.
I now see the relationship between the two side of that formula. One side is fast to react, the other is slow but better at smoothing. Like the petrol needle in your car, very good at smoothing, but too slow to be used for updating a value based on a pot turning.
In case anyone wants to try this easily, here's my test code.
If you change the pot value - which has +5/-5 value jitter added - you'll quickly see the data output of 'smooth' stabilize.
float smooth;
int randomized_potval;
void setup()
{
smooth = analogRead(5); // grab sensor value to be initial value in calculation.
Serial.begin(115200);
}
void loop()
{
float potval = analogRead(5); // read pot on pin 5
randomized_potval = random( potval - 5, potval + 5); // add some jitter
smooth = (0.99 * smooth) + (0.01 * randomized_potval); // smooth it out
serial.print(randomized_potval); // show jittered version of analog 5 value
serial.print(" ");
serial.println(int(smooth)); // OUTPUT - we are looking for this smoothed number to be stable.
delay (2);
}
skyjumper:
Currently I am storing the last 20 samples and averaging them, but I have been looking for a way to achieve this without consuming 80 bytes (20 floats)... I am getting speed readings several times each second from a transducer. Each of these readings tends to vary a bit from the prior one, and I just want to get a stable reading to use to present to the driver.
α = 0.25 gives a window that almost decays away at 20 samples and can be implemented without floating-point. I think this will work...
unsigned long history;
unsigned short value;
void setup( void )
{
Serial.begin( 250000 );
history = analogRead( 0 ) * 4;
}
void loop( void )
{
history = analogRead( 0 ) + (((3 * history) + 2) / 4);
value = (history + 2) / 4;
Serial.println( value );
delay( 100 );
}
To make it fixed-point with eight bits for the fraction multiple both sides by 256 (2 to the power of 8)...
256v1 = 256 * { ((1/4) * analogRead) + ((3/4) * v0) }
256v1 = ((256/4) * analogRead) + ((3256/4) * v0)
256v1 = ((64) * analogRead) + ((3*64) * v0)
The right-side has "v0" not "256v0" so we have to perform the division when calculating the next value. The multiplication is performed first to preserve the precision...
256v1 = (64 * analogRead) + ((364v0) / 256)
Finally, to improve the accuracy we need to include rounding...
256v1 = (64 * analogRead) + (((364*v0)+(256/2)) / 256)
So, history is the "actual" value multiplied by 256. Another way to look it: history / 256 is the whole number part and history % 256 is the fractional part.