Skip to content

IIRfilter

Harry Broeders edited this page Jul 15, 2026 · 6 revisions

Aantekeningen bij het ontwikkelen van een IIR-filter met behulp van MATLAB's filterDesigner

Deze pagina is bedoeld voor studenten van de cursus DIS10 van de opleiding Elektrotechniek aan de Hogeschool Rotterdam of voor iedereen die IIR-filters wil ontwikkelen met behulp van MATLAB's filterontwerptool. Om de filters te implementeren en te testen, wordt een pc met diverse hulpprogramma's gebruikt. Een beschrijving van hoe je de juiste software installeert, vindt je hier: Software benodigd voor de Hardware opdrachten van DIS10. Omdat we het IIR-filter uiteindelijk ook op een microcontroller zonder hardwareondersteuning voor floating-point berekeningen willen kunnen uitvoeren, is ons uiteindelijke doel om het filter te implementeren met fixed-point berekeningen. Het implementeren van een IIR-filter met fixed-point berekeningen bleek moeilijker dan verwacht. Deze pagina beschrijft het gevonden probleem en de bijbehorende oplossing.

MATLAB's filterontwerptool

MATLAB biedt een filterontwerptool. Deze tool heet filerDesigner. Meer informatie over deze tool vind je hier:

Een IIR-filter ontwikkelen met een floating-point implementatie

We gaan eerst een IIR-filter ontworpen en implementeren met behulp van floating-point berekeningen met enkele precisie. Deze getallen worden gecodeerd in 32 bits en in de programmeertaal C worden deze getallen opgeslagen in het type float. Met behulp van de filterontwerptool van MATLAB is een laagdoorlaat Butterworth-filter van orde 2 met een samplefrequentie van 8 KHz en een afsnijfrequentie van 1 KHz ontworpen. De standaardimplementatie die door filterDesigner wordt gebruikt, is een direct-vorm II met secties van de tweede orde. Dit wordt omgezet in een directe vorm I door met de rechtermuisknop op de structuurinformatie in het huidige filterinformatievenster te klikken en Convert structure ... te kiezen.

Kies dan voor Direct-Form I, SOS .

Converteer nu de implementatie van SOS (Second-Order Sections) naar een enkele sectie door opnieuw met de rechtermuisknop op de structuurinformatie in het huidige filterinformatievenster te klikken en Convert to Single Section te kiezen.

De standaardimplementatie gebruikte floating-point berekeningen met dubbele precisie (64 bits), maar we willen rekenkundige bewerkingen met enkele precisie (32 bits) gebruiken. Dit kan worden gewijzigd door op de knop Set quantization parameters te klikken aan de linkerkant van de filterontwerptool te klikken.

Kies Single-precision floating-point in het pull-down menu.

Het resulterende filterontwerp wordt hieronder weergegeven. Het .fda-bestand dat in MATLAB kan worden geopend, is hier te vinden: filter1.fda.

De filtercoëfficiënten kunnen worden geëxporteerd naar een headerbestand met behulp van de menuoptie Targets, Generate C header ...:

Het gegenereerde headerbestand is hier te vinden: filter1.h.

Wanneer we dit filter implementeren met behulp van float-variabelen en de frequentieoverdracht meten met behulp van de soundcard oscilloscope, krijgen we het volgende resultaat.

Het filter werkt zoals verwacht.

Een IIR-filter ontwikkelen met een fixed-point implementatie

Omdat we het IIR-filter uiteindelijk ook op een microcontroller zonder hardwareondersteuning voor floating-point berekeningen willen kunnen uitvoeren, gaan we dit filter nu implementeren met fixed-point berekeningen.

Overstappen op een fixed-point implementatie van het tweede orde IIR-filter lijkt triviaal, maar we kwamen een probleem tegen. Door op de knop Set quantization parameters aan de linkerkant van de filterontwerptool te klikken, hebben we de berekening gewijzigd in Fixed-point. We schakelen de optie Scale the numerator coefficients to fully utilize the entire dynamic range moet uit omdat het filter anders in de doorlaatband gaat versterken.!

Het .fda-bestand dat in MATLAB kan worden geopend, is hier te vinden: filter2.fda. Het gegenereerde headerbestand is hier te vinden: filter2.h.

De belangrijkste onderdelen van dit headerbestand worden hieronder weergegeven:

#!C
/*
 * Discrete-Time IIR Filter (real)
 * -------------------------------
 * Filter Structure    : Direct-Form I
 * Numerator Length    : 3
 * Denominator Length  : 3
 * Stable              : Yes
 * Linear Phase        : No
 * Arithmetic          : fixed
 * Numerator           : s16,17 -> [-2.500000e-01 2.500000e-01)
 * Denominator         : s16,14 -> [-2 2)
 * Input               : s16,15 -> [-1 1)
 * Output              : s16,15 -> [-1 1)
 * Numerator Prod      : s32,32 -> [-5.000000e-01 5.000000e-01)
 * Denominator Prod    : s32,29 -> [-4 4)
 * Numerator Accum     : s34,32 -> [-2 2)
 * Denominator Accum   : s34,29 -> [-16 16)
 * Round Mode          : convergent
 * Overflow Mode       : wrap
 */

const int NL = 3;
const int16_T NUM[3] = {
     1600,   3199,   1600
};
const int DL = 3;
const int16_T DEN[3] = {
    16384, -15447,   5461
};

Het commentaar suggereert dat de tellercoëfficiënten zijn gecodeerd in s16.17 fixed-point notatie en dat de noemercoëfficiënten zijn gecodeerd in s16.14 fixed-point notatie. Daarom moet de optellingen van de vermenigvuldigingen met de tellers drie bits naar rechts worden verschoven voordat de vermenigvuldigingen met de noemers ervan af worden afgetrokken (de binaire punten moeten correct zijn uitgelijnd voordat er kan worden opgeteld of afgetrokken). Het implementeren van dit filter leidt echter ook niet tot het juiste gedrag!

Als we de gegenereerde floating-point coëfficiënten te vinden in filter1.h zelf omzetten naar fixed-point notatie, ontdekken we dat alle coëfficiënten in s16.14-notatie staan. Het op deze manier implementeren van de fixed-point berekeningen resulteert in een filter dat wel werkt zoals verwacht. De vereiste output en de daadwerkelijke output worden hieronder weergegeven.

De frequentieoverdracht is (bijna) exact gelijk aan de implementatie met floating-point getallen.

Clone this wiki locally