A simple software lowpass filter suits embeddedsystem applications
(EDIT: om ovanstående länk inte fungerar finns denna: Simple Software Lowpass Filter Preview)
(BUILDING A DIGITAL EQUIVALENT OF AN ANALOG
LOWPASS RC FILTER REQUIRES JUST A COUPLE
OF LINES OF FIXED-POINT C CODE)
De flesta av oss som jobbat med microcontrollers ett tag vet ju redan hur man gör lågpassfilter i mjukvara, men det finns säkert många här som kan ha nytta av artikeln. Ett lågpassfilter är perfekt om man tar in massor av samples från en ADC och vill plocka bort bruset. Filtret plockar inte enbart bort brus, det kan t.o.m öka antalet bitars noggrannhet utöver ADC:ns förmåga. En AVR-processor med 10-bitars ADC kan med ett sådant här filter läsa av signaler med noggrannhet upp till 11 eller ibland 12 bitar. Detta beror just på bruset! Genom att bruset är jämnt fördelat positivt och negativt så kommer man efter tillräckligt lång filtrering att ha fått fram medelvärdet på bruset -vilket resulterar i fler bitar. (Fast då får man modifiera koden lite och ta bort shiftoperationen i return-satsen - annars tappar man de vunna bitarna. Jag har själv bekräftat att det fungerar i praktiken med +2 bitar. (Förutsatt att den analoga biten inte har för mycket eller för litet brus. Det finns t.o.m exempel där man adderar brus för att skapa denna effekt om det saknas naturligt brus på ingången).
Koden: (Ändrade hans hemmasnickrade heltalstyper till AVR-typer)
Kod: Markera allt
#define FILTER_SHIFT 4 // Parameter K
// int32_t = Specify 32-bit integer
// int16_t Specify 16-bit integer
int32_t filter_reg; // Delay element – 32 bits
int16_t filter_input ; // Filter input – 16 bits
int16_t filter_output ; // Filter output – 16 bits
// Update filter with current sample.
filter_reg = filter_reg - ( filter_reg >> FILTER_SHIFT) + filter_input ;
// Scale output for unity gain.
output = filter_reg >> FILTER_SHIFT
insignal går från 0 till 1000 som när en brytare sluts. insignalen brusig. observera eftersläpningen. (FILTER_SHIFT = 4) samma insignal men FILTER_SHIFT = 3. Mindre eftersläpning men mer brus. Bruset är fortfarande bra dämpat. Det var kurvor genererade med rand(). Men här kommer ett verkligt exempel:
En 20 bitars ADC (MCP3550) kopplad till en 100k kolbane-pot med utslaget +/- 100%. Poten är inställd på mitten, dvs nära 0, och y-skalan visar avvikelsen i procent på ett antal samples, och efter filtering i AVR ned FILTER_SHIFT = 3: (100% utslag motsvarar 1.6 volt, så 0.0625% avvikelse motsvarar här 1 mV. Maximala avvikelsen efter filtrering är ca 0.0008% eller 0.128 mV (korrigerat för DC-offset som här låg på ca 0.087 mV).