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
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2015-09-11
- Revision:
- 0:33908268d9ea
File content as of revision 0:33908268d9ea:
//-------------------------------------------------------------- // 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); } }