Thanks to all the Freaks out there that have helped me in the past. This tutorial is my attempt to "pay it forward" so to speak.
I am sure this idea of a simple software filter must be taught in some kind of basic software engineering course. But I wouldn't know because I've never taken a software engineering course. I decided to post it anyway because I think that there must be a lot of hobbyists out there like me that could benefit this info. Also this tutorial looks best if you click the maximize button on the avrfreaks webpage.
So you just got your A/D and your sensor working and you find out that the signal from the sensor is quite noisy. You could try to cut traces and splice in a low pass filter, but that can get a little messy. Perhaps an easier solution is that you could add a few lines of code and filter the signal in software.
The basic concept behind the software filter I use is that you keep track of a weighted average of all the previous value with the most recent value carrying the most weight. Here two equations that describes this:
1) Sum = Sum*3/4 + Raw_Value
2) Filtered_Value = Sum/4
If these equations are executed over and over again, the "Filtered_Value" will contain the Raw_Value signal as if it had a low pass filter. In mechanical terms, Sum is like a heavy weight and Raw value is pushing on it with one quarter of it strength. Or in electrical terms, Sum is like the charge on the capacitor of a low pass filter that the sensor is trying to push through the resistor to change. If I am making your head spin right now then just skip to the next section.
Get to the code already!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
So here is the speedy code for the software low pass filter:
Sum = Sum - Filtered_Value + Raw_Value; //Make sure the Sum has a big enough variable type!!!! Filtered_Value = Sum>>(Filter_Strength); //This trick only works for positive integers
This code is pretty much the same as the previous example except for three changes:
1) In the previous example the filter strength was fixed at 4, in this example is set by the value of Filter_Strength
2) Instead of multiplying by 3/4 , we just subtract of the old filtered value, which will have the identical result. (3/4 = 1 - 1/4)
3) Instead of dividing, which takes many many clock cycles, we use the bit shift right.
Note that when using bit shift right the strength of the filter is proportional to 2^(Filter_Strength). This means that a Filter_Strength of 7 is twice as strong as a Filter_Strength of 6. Also, as I discuss later, the strength depends on how frequently the instruction are executed. Also note that for this to work properly this needs to be executed at regular intervals. I recommend using a timer driven A/D and place the code in the A/D interrupt service routine.
Correcting for Rounding Error:
Now if you really want to be anal or you want to use a very weak filter then you should correct for rounding like this:
Sum = Sum - Filtered_Value + Raw_Value; Filtered_Value = (Sum+(1<<(Filter_Strength - 1))>>(Filter_Strength);
How strong is my software filter?
The time constant for the software filter given by the following equation:
Tc = (2^Filter_Strength)/(Execution_Rate)
Execution_Rate is the number of times that the code is executed per second and Tc is the time constant. I not going to derive how I got this but you can easily check this against a theoretical RC filter in excel.
Pitfalls and Tips:
1) This code must be executed at regular intervals, make sure that you have some kind of interrupt firing at regular intervals.
2) Bit shift right dividing only works for positive integers
3) For large filters makes sure ï¿½Sumï¿½ is declared with a large enough type For example, with a 10 bit A/D raw value and a filter strength of 22, a uint32_t is just barely big enough for sum.
4) Remember that when your program first starts, it will take some time before sum catches up to the signal. If you know about where the operating point is then you should initialize Sum to its estimated typical value. This is especially true for very large filters.
5) For very small filters remember to correct the bit shift right for rounding error.
6) If you change the filter strength on the fly, your filtered value will jump then stabilize. If your smart you can counteract this.
Advantages of a Software Filter:
1) You can alter the filter strength on the fly.
2) You can create very large filters.
3) No extra components.
Disdvantages of a Software Filter:
1) If you have noise frequencies much higher than the A/D sampling frequency, a hardware filter can remove these without increasing the response time significantly.
I hope this is useful to someone.
edit: Fixed the not-so-smart characters.