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

Committer:
MikamiUitOpen
Date:
Fri Sep 11 09:54:45 2015 +0000
Revision:
0:33908268d9ea
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:33908268d9ea 1 //--------------------------------------------------------------
MikamiUitOpen 0:33908268d9ea 2 // Cutoff frequency variable LPF and HPF by IIR 8th-order filter
MikamiUitOpen 0:33908268d9ea 3 // A0: Signal to be filtered
MikamiUitOpen 0:33908268d9ea 4 // A2: Value which controls cutoff frequency
MikamiUitOpen 0:33908268d9ea 5 //
MikamiUitOpen 0:33908268d9ea 6 // sw: 0, 2 Through
MikamiUitOpen 0:33908268d9ea 7 // 1: LPF
MikamiUitOpen 0:33908268d9ea 8 // 3: HPF
MikamiUitOpen 0:33908268d9ea 9 // 2015/09/11, Copyright (c) 2015 MIKAMI, Naoki
MikamiUitOpen 0:33908268d9ea 10 //--------------------------------------------------------------
MikamiUitOpen 0:33908268d9ea 11
MikamiUitOpen 0:33908268d9ea 12 #include "ADC_Interrupt.hpp" // for ADC using interrupt
MikamiUitOpen 0:33908268d9ea 13 #include "DAC_MCP4921.hpp" // for DAC MCP4921, MCP4922
MikamiUitOpen 0:33908268d9ea 14 using namespace Mikami;
MikamiUitOpen 0:33908268d9ea 15
MikamiUitOpen 0:33908268d9ea 16 #include "BilinearDesignLH.hpp" // for design of IIR filter
MikamiUitOpen 0:33908268d9ea 17 #include "IIR_Cascade.hpp" // for IIR filter of cascade structure
MikamiUitOpen 0:33908268d9ea 18
MikamiUitOpen 0:33908268d9ea 19 // ACM1602Ni を使う場合は次の define 文をコメントにすること
MikamiUitOpen 0:33908268d9ea 20 #define AQM1602
MikamiUitOpen 0:33908268d9ea 21
MikamiUitOpen 0:33908268d9ea 22 #ifdef AQM1602
MikamiUitOpen 0:33908268d9ea 23 #include "AQM1602.hpp"
MikamiUitOpen 0:33908268d9ea 24 Aqm1602 Lcd_;
MikamiUitOpen 0:33908268d9ea 25 #else
MikamiUitOpen 0:33908268d9ea 26 #include "ACM1602NI.hpp"
MikamiUitOpen 0:33908268d9ea 27 Acm1602Ni Lcd_;
MikamiUitOpen 0:33908268d9ea 28 #endif
MikamiUitOpen 0:33908268d9ea 29
MikamiUitOpen 0:33908268d9ea 30 const int FS_ = 24000; // Sampling frequency: 24 kHz
MikamiUitOpen 0:33908268d9ea 31 ADC_Intr myAdc_(A0, FS_, A2);
MikamiUitOpen 0:33908268d9ea 32 DAC_MCP4921 myDac_;
MikamiUitOpen 0:33908268d9ea 33
MikamiUitOpen 0:33908268d9ea 34 const int ORDER_ = 8;
MikamiUitOpen 0:33908268d9ea 35 IirCascade<ORDER_> iirLH_; // IIR filter object
MikamiUitOpen 0:33908268d9ea 36
MikamiUitOpen 0:33908268d9ea 37 DigitalIn sw1_(D2, PullDown); // 0: disable filter
MikamiUitOpen 0:33908268d9ea 38 // 1: enable filter
MikamiUitOpen 0:33908268d9ea 39 DigitalIn sw2_(D3, PullDown);
MikamiUitOpen 0:33908268d9ea 40
MikamiUitOpen 0:33908268d9ea 41 uint16_t a2_ = 0; // Inputted data from A2 pin
MikamiUitOpen 0:33908268d9ea 42
MikamiUitOpen 0:33908268d9ea 43 // Interrupt service routine for ADC
MikamiUitOpen 0:33908268d9ea 44 void AdcIsr()
MikamiUitOpen 0:33908268d9ea 45 {
MikamiUitOpen 0:33908268d9ea 46 float xn = myAdc_.Read(); // Read from A0
MikamiUitOpen 0:33908268d9ea 47
MikamiUitOpen 0:33908268d9ea 48 myAdc_.Select2ndChannel(); // Select A2
MikamiUitOpen 0:33908268d9ea 49 myAdc_.SoftStart(); // ADC start for A2 input
MikamiUitOpen 0:33908268d9ea 50
MikamiUitOpen 0:33908268d9ea 51 // Execute IIR filter
MikamiUitOpen 0:33908268d9ea 52 float yn = iirLH_.Execute(xn);
MikamiUitOpen 0:33908268d9ea 53
MikamiUitOpen 0:33908268d9ea 54 if (sw1_ == 0) myDac_.Write(xn); // Using no filter
MikamiUitOpen 0:33908268d9ea 55 else myDac_.Write(yn); // Using filter
MikamiUitOpen 0:33908268d9ea 56
MikamiUitOpen 0:33908268d9ea 57 // Read value which controls cutoff frequency
MikamiUitOpen 0:33908268d9ea 58 a2_ = myAdc_.ReadWait_u16();
MikamiUitOpen 0:33908268d9ea 59
MikamiUitOpen 0:33908268d9ea 60 myAdc_.Select1stChannel(); // Select A0
MikamiUitOpen 0:33908268d9ea 61 myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt
MikamiUitOpen 0:33908268d9ea 62 // and enable ADC_IRQn
MikamiUitOpen 0:33908268d9ea 63 }
MikamiUitOpen 0:33908268d9ea 64
MikamiUitOpen 0:33908268d9ea 65 int main()
MikamiUitOpen 0:33908268d9ea 66 {
MikamiUitOpen 0:33908268d9ea 67 myDac_.ScfClockTim3(1000000); // cutoff frequency: 10 kHz
MikamiUitOpen 0:33908268d9ea 68
MikamiUitOpen 0:33908268d9ea 69 BilinearDesign lpfDsgn(ORDER_, FS_, BilinearDesign::LPF);
MikamiUitOpen 0:33908268d9ea 70 BilinearDesign hpfDsgn(ORDER_, FS_, BilinearDesign::HPF);
MikamiUitOpen 0:33908268d9ea 71
MikamiUitOpen 0:33908268d9ea 72 myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt
MikamiUitOpen 0:33908268d9ea 73
MikamiUitOpen 0:33908268d9ea 74 float fc1 = 0;
MikamiUitOpen 0:33908268d9ea 75 while (true)
MikamiUitOpen 0:33908268d9ea 76 {
MikamiUitOpen 0:33908268d9ea 77 // fc: cutoff frequency, 100 -- 2000 Hz
MikamiUitOpen 0:33908268d9ea 78 float fc = 1900.0f*(a2_/4095.6f) + 100.0f;
MikamiUitOpen 0:33908268d9ea 79
MikamiUitOpen 0:33908268d9ea 80 if (sw1_ == 0)
MikamiUitOpen 0:33908268d9ea 81 {
MikamiUitOpen 0:33908268d9ea 82 printf("Through\r\n");
MikamiUitOpen 0:33908268d9ea 83 Lcd_.WriteStringXY("Through ", 0, 0);
MikamiUitOpen 0:33908268d9ea 84 wait(0.2f);
MikamiUitOpen 0:33908268d9ea 85 Lcd_.ClearLine(0);
MikamiUitOpen 0:33908268d9ea 86 fc1 = 0;
MikamiUitOpen 0:33908268d9ea 87 }
MikamiUitOpen 0:33908268d9ea 88 else
MikamiUitOpen 0:33908268d9ea 89 {
MikamiUitOpen 0:33908268d9ea 90 if (fabs(fc - fc1) > 10.0f)
MikamiUitOpen 0:33908268d9ea 91 {
MikamiUitOpen 0:33908268d9ea 92 char str[18];
MikamiUitOpen 0:33908268d9ea 93 if (sw2_ == 0) sprintf(str, "LPF: fc=%4d Hz", int(fc+0.5f));
MikamiUitOpen 0:33908268d9ea 94 else sprintf(str, "HPF: fc=%4d Hz", int(fc+0.5f));
MikamiUitOpen 0:33908268d9ea 95
MikamiUitOpen 0:33908268d9ea 96 printf("%s\r\n", str);
MikamiUitOpen 0:33908268d9ea 97 Lcd_.WriteStringXY(str, 0, 0);
MikamiUitOpen 0:33908268d9ea 98 fc1 = fc;
MikamiUitOpen 0:33908268d9ea 99
MikamiUitOpen 0:33908268d9ea 100 // Design new coefficients based on new fc
MikamiUitOpen 0:33908268d9ea 101 BilinearDesign::Coefs coefs[ORDER_/2];
MikamiUitOpen 0:33908268d9ea 102 float g0;
MikamiUitOpen 0:33908268d9ea 103 if (sw2_ == 0) lpfDsgn.Execute(fc, coefs, g0);
MikamiUitOpen 0:33908268d9ea 104 else hpfDsgn.Execute(fc, coefs, g0);
MikamiUitOpen 0:33908268d9ea 105 Biquad::Coefs coefsIir[ORDER_/2];
MikamiUitOpen 0:33908268d9ea 106 // Update new coefficients
MikamiUitOpen 0:33908268d9ea 107 for (int n=0; n<ORDER_/2; n++)
MikamiUitOpen 0:33908268d9ea 108 {
MikamiUitOpen 0:33908268d9ea 109 coefsIir[n].a1 = coefs[n].a1;
MikamiUitOpen 0:33908268d9ea 110 coefsIir[n].a2 = coefs[n].a2;
MikamiUitOpen 0:33908268d9ea 111 coefsIir[n].b1 = coefs[n].b1;
MikamiUitOpen 0:33908268d9ea 112 coefsIir[n].b2 = 1.0f;
MikamiUitOpen 0:33908268d9ea 113 }
MikamiUitOpen 0:33908268d9ea 114 iirLH_.SetCoefs(g0, coefsIir);
MikamiUitOpen 0:33908268d9ea 115 }
MikamiUitOpen 0:33908268d9ea 116 }
MikamiUitOpen 0:33908268d9ea 117 wait(0.1f);
MikamiUitOpen 0:33908268d9ea 118 }
MikamiUitOpen 0:33908268d9ea 119 }