Currently, I'm working on a speedometer with Hall Effect sensor, and I have a variable which is the velocity.
I want to smooth out the sharp changes in the variable. For example: The wheel stands still, the value of the variable is 0. Then, I spin the wheel immediately, and it jumps up from 0 to like 20. What I'm trying to do is to make that jump a lot smoother, like it counts up to 20. Whenever a change occurs in the variable, I don't want to happen instantly. Another case: The wheel is spinning, the value is 20, then I hit the brake a little, and it goes down to 15. But that change is really sharp. Can it count down from 20 to 15?
Edit:
You have almost answered your own question. At any one time the actual speed will have a current value, say 20, and the displayed speed will have a value, say 0.
Now suppose that you want to display the speed every second. If every second you added 1 to the displayed speed then you will achieve the sort of effect you want. Of course, 1 second is probably too long but it will do as an example
So, the question is, how do you know that 1 seconds has elapsed whilst still measuring the speed ? The answer is not the delay() function, rather you can use the millis() function and arrange things so that operation of the program is not blocked as would be the case if the delay() function were used.
Store the last 5-10 readings and calculate the average of those readings.
#define NUM_READINGS 10;
int getReading()
{
static int values[NUM_READINGS] = {0};
static byte index = 0;
values[index++] = readSensor();
if (index >= NUM_READINGS) index = 0;
int result = 0;
for (byte i = 0; i < NUM_READINGS; i++) result += values[i];
return result / NUM_READINGS;
}
SwengX:
Currently, I'm working on a speedometer with Hall Effect sensor, and I have a variable which is the velocity.
I want to smooth out the sharp changes in the variable.
I always like the software low-pass filter.
int reading;
double smoothed_reading;
void loop() {
if(its time to take another reading) {
reading = read_the_sensor();
smoothed_reading = smoothed_reading * .95 + reading * .05;
}
}
It's important pay attention to timing - to take a reading only every 10ms, or whatever. That way the smoothed_reading approaches the current reading in a predictable way.
You can also do things like having two smoothed variables, one reacting quicker than the other. This will tell you something about the rate of change of the data.
I did a tacho thing myself, and I also used a ring buffer to smooth things out. Code is here.
The image in the first post shows the behavior of a simple moving average filter, and this is what the code posted by Danois implements.
Here's another more efficient implementation with an explanation and an Arduino example: Simple Moving Average example
The code posted by PaulMurrayCbr and RayLivingston implements an exponential moving average filter. It has an exponential step response, while the simple moving average filter has a linear step response.
Nice. Kinda expresses the idea that we are gradually sneaking up onto the new value, whereas my (less efficient) code more expresses the idea of a recursive filter Recursive Implementation. The numbers come out identically, sans floating point rounding.
PaulMurrayCbr:
Nice. Kinda expresses the idea that we are gradually sneaking up onto the new value, whereas my (less efficient) code more expresses the idea of a recursive filter Recursive Implementation. The numbers come out identically, sans floating point rounding.
And, if efficiency is a concern, you can use 32-bit integers, and fractional math, with power-of-twos coefficients to make it faster, by converting the multiplies to shifts, as long as you're careful about the dynamic range, and don't make the coefficient too small. In many cases, this will give even better precision than single-precision floats, with much less overhead, both in code size and speed.