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