|
| 1 | +template <int order> // order is 1 or 2 |
| 2 | +class LowPass |
| 3 | +{ |
| 4 | + private: |
| 5 | + float a[order]; |
| 6 | + float b[order+1]; |
| 7 | + float omega0; |
| 8 | + float dt; |
| 9 | + bool adapt; |
| 10 | + float tn1 = 0; |
| 11 | + float x[order+1]; // Raw values |
| 12 | + float y[order+1]; // Filtered values |
| 13 | + |
| 14 | + public: |
| 15 | + LowPass(float f0, float fs, bool adaptive){ |
| 16 | + // f0: cutoff frequency (Hz) |
| 17 | + // fs: sample frequency (Hz) |
| 18 | + // adaptive: boolean flag, if set to 1, the code will automatically set |
| 19 | + // the sample frequency based on the time history. |
| 20 | + |
| 21 | + omega0 = 6.28318530718*f0; |
| 22 | + dt = 1.0/fs; |
| 23 | + adapt = adaptive; |
| 24 | + tn1 = -dt; |
| 25 | + for(int k = 0; k < order+1; k++){ |
| 26 | + x[k] = 0; |
| 27 | + y[k] = 0; |
| 28 | + } |
| 29 | + setCoef(); |
| 30 | + } |
| 31 | + |
| 32 | + void setCoef(){ |
| 33 | + if(adapt){ |
| 34 | + float t = micros()/1.0e6; |
| 35 | + dt = t - tn1; |
| 36 | + tn1 = t; |
| 37 | + } |
| 38 | + |
| 39 | + float alpha = omega0*dt; |
| 40 | + if(order==1){ |
| 41 | + a[0] = -(alpha - 2.0)/(alpha+2.0); |
| 42 | + b[0] = alpha/(alpha+2.0); |
| 43 | + b[1] = alpha/(alpha+2.0); |
| 44 | + } |
| 45 | + if(order==2){ |
| 46 | + float c1 = 2*sqrt(2)/alpha; |
| 47 | + float c2 = 4/(alpha*alpha); |
| 48 | + float denom = 1.0+c1+c2; |
| 49 | + b[0] = 1.0/denom; |
| 50 | + b[1] = 2.0/denom; |
| 51 | + b[2] = b[0]; |
| 52 | + a[0] = -(2.0-2.0*c2)/denom; |
| 53 | + a[1] = -(1.0-c1+c2)/(1.0+c1+c2); |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + float filt(float xn){ |
| 58 | + // Provide me with the current raw value: x |
| 59 | + // I will give you the current filtered value: y |
| 60 | + if(adapt){ |
| 61 | + setCoef(); // Update coefficients if necessary |
| 62 | + } |
| 63 | + y[0] = 0; |
| 64 | + x[0] = xn; |
| 65 | + // Compute the filtered values |
| 66 | + for(int k = 0; k < order; k++){ |
| 67 | + y[0] += a[k]*y[k+1] + b[k]*x[k]; |
| 68 | + } |
| 69 | + y[0] += b[order]*x[order]; |
| 70 | + |
| 71 | + // Save the historical values |
| 72 | + for(int k = order; k > 0; k--){ |
| 73 | + y[k] = y[k-1]; |
| 74 | + x[k] = x[k-1]; |
| 75 | + } |
| 76 | + |
| 77 | + // Return the filtered value |
| 78 | + return y[0]; |
| 79 | + } |
| 80 | +}; |
| 81 | + |
| 82 | +// Filter instance |
| 83 | +LowPass<2> lp(3,1e3,true); |
| 84 | + |
| 85 | +void setup() { |
| 86 | + Serial.begin(115200); |
| 87 | +} |
| 88 | + |
| 89 | +void loop() { |
| 90 | + // Read pin A0 and compute current in mA |
| 91 | + // -- replace these two lines with your own sensor -- |
| 92 | + int analogValue = analogRead(A0); |
| 93 | + float xn = (analogValue*5.0/1023.0 - 2.503)/0.185*1000; |
| 94 | + |
| 95 | + // Compute the filtered signal |
| 96 | + float yn = lp.filt(xn); |
| 97 | + |
| 98 | + // Output |
| 99 | + Serial.print(xn); |
| 100 | + Serial.print(" "); |
| 101 | + Serial.print(yn); |
| 102 | + Serial.println(); |
| 103 | + delayMicroseconds(200); |
| 104 | +} |
0 commit comments