Cutoff frequency variable LPF by IIR 6th-order Butterworth filter for ST Nucleo F401RE.

Dependencies:   UIT_IIR_Filter UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602

Committer:
MikamiUitOpen
Date:
Thu Oct 23 06:44:40 2014 +0000
Revision:
0:a9412b9e85b7
Child:
1:e9b451a71ebf
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:a9412b9e85b7 1 //--------------------------------------------------------------
MikamiUitOpen 0:a9412b9e85b7 2 // Cutoff frequency variable LPF by IIR 6th-order filter
MikamiUitOpen 0:a9412b9e85b7 3 // A0: Signal to be filtered
MikamiUitOpen 0:a9412b9e85b7 4 // A2: Value which controls cutoff frequency
MikamiUitOpen 0:a9412b9e85b7 5 //
MikamiUitOpen 0:a9412b9e85b7 6 // 2014/10/23, Copyright (c) 2014 MIKAMI, Naoki
MikamiUitOpen 0:a9412b9e85b7 7 //--------------------------------------------------------------
MikamiUitOpen 0:a9412b9e85b7 8
MikamiUitOpen 0:a9412b9e85b7 9 #include "mbed.h"
MikamiUitOpen 0:a9412b9e85b7 10
MikamiUitOpen 0:a9412b9e85b7 11 #include "ADC_Interrupt.hpp" // for ADC using interrupt
MikamiUitOpen 0:a9412b9e85b7 12 #include "DAC_MCP4922.hpp" // for DAC MCP4922
MikamiUitOpen 0:a9412b9e85b7 13 #include "ScfClockTim3.hpp" // for clock supplied to SCF
MikamiUitOpen 0:a9412b9e85b7 14 #include "ACM1602NI.hpp" // for LCD display
MikamiUitOpen 0:a9412b9e85b7 15
MikamiUitOpen 0:a9412b9e85b7 16 #include "BilinearDesignLH.hpp" // for design of IIR filter
MikamiUitOpen 0:a9412b9e85b7 17 #include "IIR_Cascade.hpp" // for IIR filter of cascade structure
MikamiUitOpen 0:a9412b9e85b7 18
MikamiUitOpen 0:a9412b9e85b7 19 using namespace Mikami;
MikamiUitOpen 0:a9412b9e85b7 20
MikamiUitOpen 0:a9412b9e85b7 21 const int FS_ = 24000; // Sampling frequency: 24 kHz
MikamiUitOpen 0:a9412b9e85b7 22 ADC_Intr myAdc_(A0, FS_, A1, A2);
MikamiUitOpen 0:a9412b9e85b7 23 DAC_MCP4922 myDac_;
MikamiUitOpen 0:a9412b9e85b7 24
MikamiUitOpen 0:a9412b9e85b7 25 const int ORDER_ = 6;
MikamiUitOpen 0:a9412b9e85b7 26 IirCascade<ORDER_/2> iirLpf_; // IIR filter object
MikamiUitOpen 0:a9412b9e85b7 27
MikamiUitOpen 0:a9412b9e85b7 28 DigitalIn sw1_(D2, PullDown); // 0: disable filter
MikamiUitOpen 0:a9412b9e85b7 29 // 1: enable filter
MikamiUitOpen 0:a9412b9e85b7 30
MikamiUitOpen 0:a9412b9e85b7 31 uint16_t a2_ = 0; // Inputted data from A2 pin
MikamiUitOpen 0:a9412b9e85b7 32
MikamiUitOpen 0:a9412b9e85b7 33 // Interrupt service routine for ADC
MikamiUitOpen 0:a9412b9e85b7 34 void AdcIsr()
MikamiUitOpen 0:a9412b9e85b7 35 {
MikamiUitOpen 0:a9412b9e85b7 36 float xn = myAdc_.Read(); // Read from A0
MikamiUitOpen 0:a9412b9e85b7 37
MikamiUitOpen 0:a9412b9e85b7 38 myAdc_.Select3rdChannel(); // Select A2
MikamiUitOpen 0:a9412b9e85b7 39 myAdc_.SoftStart(); // ADC start for A2 input
MikamiUitOpen 0:a9412b9e85b7 40
MikamiUitOpen 0:a9412b9e85b7 41 // Execute IIR filter
MikamiUitOpen 0:a9412b9e85b7 42 float yn = iirLpf_.Execute(xn);
MikamiUitOpen 0:a9412b9e85b7 43
MikamiUitOpen 0:a9412b9e85b7 44 if (sw1_ == 0) myDac_.Write(xn); // Using no filter
MikamiUitOpen 0:a9412b9e85b7 45 else myDac_.Write(yn); // Using filter
MikamiUitOpen 0:a9412b9e85b7 46
MikamiUitOpen 0:a9412b9e85b7 47 // Read value which controls cutoff frequency
MikamiUitOpen 0:a9412b9e85b7 48 a2_ = myAdc_.ReadWait_u16();
MikamiUitOpen 0:a9412b9e85b7 49
MikamiUitOpen 0:a9412b9e85b7 50 myAdc_.Select1stChannel(); // Select A0
MikamiUitOpen 0:a9412b9e85b7 51 myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt
MikamiUitOpen 0:a9412b9e85b7 52 // and enable ADC_IRQn
MikamiUitOpen 0:a9412b9e85b7 53 }
MikamiUitOpen 0:a9412b9e85b7 54
MikamiUitOpen 0:a9412b9e85b7 55 int main()
MikamiUitOpen 0:a9412b9e85b7 56 {
MikamiUitOpen 0:a9412b9e85b7 57 const int ORDER = 6;
MikamiUitOpen 0:a9412b9e85b7 58 ScfClockTim3(1000000); // cutoff frequency: 10 kHz
MikamiUitOpen 0:a9412b9e85b7 59
MikamiUitOpen 0:a9412b9e85b7 60 BiliearDesign lpfDsgn(ORDER, FS_, BiliearDesign::LPF);
MikamiUitOpen 0:a9412b9e85b7 61 Acm1602Ni lcd; // objetc for display using LCD
MikamiUitOpen 0:a9412b9e85b7 62
MikamiUitOpen 0:a9412b9e85b7 63 myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt
MikamiUitOpen 0:a9412b9e85b7 64
MikamiUitOpen 0:a9412b9e85b7 65 float fc1 = 0;
MikamiUitOpen 0:a9412b9e85b7 66 while (true)
MikamiUitOpen 0:a9412b9e85b7 67 {
MikamiUitOpen 0:a9412b9e85b7 68 // fc: cutoff frequency, 200 -- 1000 Hz
MikamiUitOpen 0:a9412b9e85b7 69 float fc = 800.0f*(a2_/4095.6f) + 200.0f;
MikamiUitOpen 0:a9412b9e85b7 70
MikamiUitOpen 0:a9412b9e85b7 71 if (fabs(fc - fc1) > 10.0f)
MikamiUitOpen 0:a9412b9e85b7 72 {
MikamiUitOpen 0:a9412b9e85b7 73 printf("fc = %4d\r\n", int(fc+0.5f));
MikamiUitOpen 0:a9412b9e85b7 74 char str[18];
MikamiUitOpen 0:a9412b9e85b7 75 sprintf(str, "fc = %4d Hz", int(fc+0.5f));
MikamiUitOpen 0:a9412b9e85b7 76 lcd.SetXY(0, 0);
MikamiUitOpen 0:a9412b9e85b7 77 lcd.WriteString(str);
MikamiUitOpen 0:a9412b9e85b7 78 fc1 = fc;
MikamiUitOpen 0:a9412b9e85b7 79
MikamiUitOpen 0:a9412b9e85b7 80 // Design new coefficients based on new fc
MikamiUitOpen 0:a9412b9e85b7 81 BiliearDesign::Coefs coefsLpf[ORDER/2];
MikamiUitOpen 0:a9412b9e85b7 82 float g0;
MikamiUitOpen 0:a9412b9e85b7 83 lpfDsgn.Execute(fc, coefsLpf, g0);
MikamiUitOpen 0:a9412b9e85b7 84
MikamiUitOpen 0:a9412b9e85b7 85 // Update new coefficients
MikamiUitOpen 0:a9412b9e85b7 86 Biquad::Coefs coefsIir[ORDER/2];
MikamiUitOpen 0:a9412b9e85b7 87 for (int n=0; n<ORDER/2; n++)
MikamiUitOpen 0:a9412b9e85b7 88 {
MikamiUitOpen 0:a9412b9e85b7 89 coefsIir[n].a1 = coefsLpf[n].a1;
MikamiUitOpen 0:a9412b9e85b7 90 coefsIir[n].a2 = coefsLpf[n].a2;
MikamiUitOpen 0:a9412b9e85b7 91 coefsIir[n].b1 = coefsLpf[n].b1;
MikamiUitOpen 0:a9412b9e85b7 92 coefsIir[n].b2 = 1.0f;
MikamiUitOpen 0:a9412b9e85b7 93 }
MikamiUitOpen 0:a9412b9e85b7 94 iirLpf_.SetCoefs(g0, coefsIir);
MikamiUitOpen 0:a9412b9e85b7 95 }
MikamiUitOpen 0:a9412b9e85b7 96 wait(0.1f);
MikamiUitOpen 0:a9412b9e85b7 97 }
MikamiUitOpen 0:a9412b9e85b7 98 }