You don't really want a lowpass if you also want a fast response. Fast responses are only possible if you leave in the high-frequency components.
Of course, then the question becomes, "How fast do you really need?" Convert that to a frequency, add some margin, and see where the noise sits relative to that cutoff. If there's enough of a difference, then yes, a filter can work. But if the noise and signal are (close to) the same frequency, then you can't filter that.
In that case, there are practically two options left:
- Eliminate the noise itself, so that the filter isn't needed.
- Characterize the noise and the intended signal, so that you can more-or-less subtract a recording of noise without damaging the signal too much.
Option #1 is usually more effective, and a current loop on a twisted pair usually does a good job of that, which is what the 4-20mA signal is.*
(*or at least should be! I'm sure some uneducated sparky somewhere has make the mistake of pulling two separate spools of single wire, possibly alongside many more, and calling that a 4-20mA sensor run.)
If you must use a lowpass (or if you just want to put one on as a matter of course), then I think the easiest one to implement would be an exponential average, which is in DSP terms, a 1st order lowpass, and exactly equivalent to an analog R-C lowpass.**
(**provided that you haven't run afoul of some other DSP gotchas, like too-low sample rate causing what should have been filtered out to instead combine with the intended signal, which is normally known as "aliasing" and can only be eliminated by using a higher sample rate or an analog lowpass before the converter)
Anyway, a quick and easy way to do it is:
#define LOWPASS_SHIFT 9 //~10Hz cutoff, bigger number gives lower frequency
//1st-order IIR lowpass
//2^(-SHIFT) = 1 - e^(-2*pi * Fc/Fs)
//Fc = Fs * (-ln(1 - 2^(-SHIFT)) / (2*pi))
//Fs = 31.25kHz, Fc = -3dB cutoff frequency
#if LOWPASS_SHIFT < 0
#error LOWPASS_SHIFT must be positive
#endif
void process_sample(void)
{
output -= (output >> LOWPASS_SHIFT);
output += ( input >> LOWPASS_SHIFT);
}
That's copied (almost) directly from one of my projects, on a processor that can only add, subtract, and shift. (shifting is thus an easy way to divide, but limited to powers of 2) A bit of algebraic rearranging should show that this is equivalent to the canonical representation.
If you need a steeper rolloff, then you can cascade 2 of these to make a 2nd order lowpass, or you can use a different DSP algorithm to do it all at once.