Reputation: 2538
I'm sampling a real-world sensor, and I need to display its filtered value. The signal is sampled at a rate of 10 Hz and during that period it could rise as much as 80 per cent of the maximum range.
Earlier I've used Root Mean Square as a filter and just applying it to the last five values I've logged. For this application this wouldn't be good because I don't store unchanged values. In other words, I need to consider time in my filter...
I've read at DSP Guide, but I didn't get much out of it. Is there a tutorial that's pinned specifically at programmers, and not Mathcad engineers? Are there some simple code snippets that could help?
Update: After several spreadsheet tests I've taken the executive decision to log all samples, and apply a Butterworth filter.
Upvotes: 3
Views: 18551
Reputation: 31616
You always need to store some values (but not necessarily all input values). A filter's current output depends on a number of input values and possibly some past output values.
The simplest filter would be a first order Butterworth low-pass filter. This would only require you to store one past output value. The (current) output of the filter, y(n) is:
y(n) = x(n) - a1 * y(n-1)
where x(n) is the current input and y(n-1) is the previous output of the filter. a1 depends on the cut-off frequency and the sampling frequency. The cut-off frequency frequency must be less than 5 Hz (half the sampling frequency), sufficiently low to filter out the noise, but not so low that the output will be delayed with respect to the input. And of course not so low that the real signal is filtered out!
In code (mostly C#):
double a1 = 0.57; //0.57 is just an example value.
double lastY = 0.0;
while (true)
{
double x = <get an input value>;
double y = x - a1 * lastY;
<Use y somehow>
lastY = y;
}
Whether a first order filter is sufficient depends on your requirements and the characteristics of the input signal (a higher order filter may be able to suppress more of the noise at the expense of higher delay of the output signal).
For higher order filters, more values would have to be stored and the code becomes a little bit more complicated. Usually the values need to be shifted down in arrays; in an array for past y values and in an array for past x values.
Upvotes: 6
Reputation: 41858
I don't have a tutorial that will help you, but in C# you may want to consider using Reactive LINQ - see blog post Reactive programming (II.) - Introducing Reactive LINQ.
As a way to get the events, so you can do your processing without having to store all the values, it would just do the processing as you get the next event in.
To consider time, you could just use an exponential with a negative exponent to decrease the impact of the past measurements.
Upvotes: 2
Reputation: 9
Yes, for complex real-time systems sampling multiple streams of data, there could be an issue in the data processing (calculation and storage of data) and data consistency.
Upvotes: -1
Reputation: 75366
In DSP, the term "filter" usually refers to the amplification or attenuation (i.e. "lowering") of frequency components within a continuous signal. This is commonly done using Fast Fourier Transform (FFT). FFT starts with a signal recorded over a given length of time (the data are in what's called the "time domain") and transforms these values into what's called the "frequency domain", where the results indicate the strength of the signal in a series of frequency "bins" that range from 0 Hz up to the sampling rate (10 Hz in your case). So, as a rough example, an FFT of one second's worth of your data (10 samples) would tell you the strength of your signal at 0-2 Hz, 2-4 Hz, 4-6 Hz, 6-8 Hz, and 8-10 Hz.
To "filter" these data, you would increase or decrease any or all of these signal strength values, and then perform a reverse FFT to transform these values back into a time-domain signal. So, for example, let's say you wanted to do a lowpass filter on your transformed data, where the cutoff frequency was 6 Hz (in other words, you want to remove any frequency components in your signal above 6 Hz). You would programatically set the 6-8 Hz value to zero and set the 8-10 Hz value to 0, and then do a reverse FFT.
I mention all this because it doesn't sound like "filtering" is really what you want to do here. I think you just want to display the current value of your sensor, but you want to smooth out the results so that it doesn't respond excessively to transient fluctuations in the sensor's measured value. The best way to do this is with a simple running average, possibly with the more recent values weighted more heavily than older values.
A running average is very easy to program (much easier than FFT, trust me) by storing a collection of the most recent measurements. You mention that your app only stores values that are different from the prior value. Assuming you also store the time at which each value is recorded, it should be easy for your running average code to fill in the "missing values" by using the recorded prior values.
Upvotes: 5