![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Cutoff frequency variable LPF and HPF by IIR 6th-order Butterworth filter for ST Nucleo F401RE.
Dependencies: UITDSP_ADDA UIT_ACM1602NI UIT_AQM1602 UIT_IIR_Filter mbed
Diff: main.cpp
- Revision:
- 0:33908268d9ea
diff -r 000000000000 -r 33908268d9ea main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Sep 11 09:54:45 2015 +0000 @@ -0,0 +1,119 @@ +//-------------------------------------------------------------- +// Cutoff frequency variable LPF and HPF by IIR 8th-order filter +// A0: Signal to be filtered +// A2: Value which controls cutoff frequency +// +// sw: 0, 2 Through +// 1: LPF +// 3: HPF +// 2015/09/11, Copyright (c) 2015 MIKAMI, Naoki +//-------------------------------------------------------------- + +#include "ADC_Interrupt.hpp" // for ADC using interrupt +#include "DAC_MCP4921.hpp" // for DAC MCP4921, MCP4922 +using namespace Mikami; + +#include "BilinearDesignLH.hpp" // for design of IIR filter +#include "IIR_Cascade.hpp" // for IIR filter of cascade structure + +// ACM1602Ni を使う場合は次の define 文をコメントにすること +#define AQM1602 + +#ifdef AQM1602 +#include "AQM1602.hpp" +Aqm1602 Lcd_; +#else +#include "ACM1602NI.hpp" +Acm1602Ni Lcd_; +#endif + +const int FS_ = 24000; // Sampling frequency: 24 kHz +ADC_Intr myAdc_(A0, FS_, A2); +DAC_MCP4921 myDac_; + +const int ORDER_ = 8; +IirCascade<ORDER_> iirLH_; // IIR filter object + +DigitalIn sw1_(D2, PullDown); // 0: disable filter + // 1: enable filter +DigitalIn sw2_(D3, PullDown); + +uint16_t a2_ = 0; // Inputted data from A2 pin + +// Interrupt service routine for ADC +void AdcIsr() +{ + float xn = myAdc_.Read(); // Read from A0 + + myAdc_.Select2ndChannel(); // Select A2 + myAdc_.SoftStart(); // ADC start for A2 input + + // Execute IIR filter + float yn = iirLH_.Execute(xn); + + if (sw1_ == 0) myDac_.Write(xn); // Using no filter + else myDac_.Write(yn); // Using filter + + // Read value which controls cutoff frequency + a2_ = myAdc_.ReadWait_u16(); + + myAdc_.Select1stChannel(); // Select A0 + myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt + // and enable ADC_IRQn +} + +int main() +{ + myDac_.ScfClockTim3(1000000); // cutoff frequency: 10 kHz + + BilinearDesign lpfDsgn(ORDER_, FS_, BilinearDesign::LPF); + BilinearDesign hpfDsgn(ORDER_, FS_, BilinearDesign::HPF); + + myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt + + float fc1 = 0; + while (true) + { + // fc: cutoff frequency, 100 -- 2000 Hz + float fc = 1900.0f*(a2_/4095.6f) + 100.0f; + + if (sw1_ == 0) + { + printf("Through\r\n"); + Lcd_.WriteStringXY("Through ", 0, 0); + wait(0.2f); + Lcd_.ClearLine(0); + fc1 = 0; + } + else + { + if (fabs(fc - fc1) > 10.0f) + { + char str[18]; + if (sw2_ == 0) sprintf(str, "LPF: fc=%4d Hz", int(fc+0.5f)); + else sprintf(str, "HPF: fc=%4d Hz", int(fc+0.5f)); + + printf("%s\r\n", str); + Lcd_.WriteStringXY(str, 0, 0); + fc1 = fc; + + // Design new coefficients based on new fc + BilinearDesign::Coefs coefs[ORDER_/2]; + float g0; + if (sw2_ == 0) lpfDsgn.Execute(fc, coefs, g0); + else hpfDsgn.Execute(fc, coefs, g0); + Biquad::Coefs coefsIir[ORDER_/2]; + // Update new coefficients + for (int n=0; n<ORDER_/2; n++) + { + coefsIir[n].a1 = coefs[n].a1; + coefsIir[n].a2 = coefs[n].a2; + coefsIir[n].b1 = coefs[n].b1; + coefsIir[n].b2 = 1.0f; + } + iirLH_.SetCoefs(g0, coefsIir); + } + } + wait(0.1f); + } +}