Skip to content

Commit e2e2628

Browse files
committed
Successful add of order 2 Butterworth notch.
1 parent 129e47c commit e2e2628

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

src/Devlpr.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Devlpr::Devlpr(int pin)
77
emgRunningSum = 0;
88
bufInd = BUFSIZE - 1;
99
numFuncs = 0;
10+
lastFiltVal = 0;
1011
}
1112

1213
void Devlpr::tick()
@@ -77,6 +78,11 @@ int Devlpr::lastValueCentered()
7778
return lastVal - wAvg;
7879
}
7980

81+
int Devlpr::lastValueFiltered()
82+
{
83+
return lastFiltVal;
84+
}
85+
8086
unsigned int Devlpr::windowPeakAmplitude()
8187
{
8288
// use the window average as the reference point (should be close to DC offset)
@@ -149,6 +155,8 @@ void Devlpr::readEMG()
149155
emgRunningSum = emgRunningSum - buf[bufInd] + emgVal;
150156
// now replace
151157
buf[bufInd] = emgVal;
158+
// and we need to calculate the filtered value every sample
159+
calcFiltered();
152160
}
153161

154162
void Devlpr::flexCheck(unsigned long currMicros)
@@ -169,3 +177,19 @@ void Devlpr::flexCheck(unsigned long currMicros)
169177
// need to update the current peak-to-peak for next time
170178
prevPeakToPeak = currPeakToPeak;
171179
}
180+
181+
void Devlpr::calcFiltered()
182+
{
183+
// NOTE: IIR filter is recurrent and needs to run every tick to work
184+
// we need to operate on 0-centered(ish) data and we will be doing float math
185+
float xn = lastValueCentered();
186+
// compute the recurrence by section
187+
for (int s = 0; s < N_SECTIONS; s++) {
188+
float xn_tmp = xn;
189+
xn = notch60[s][0] * xn_tmp + z[s][0];
190+
z[s][0] = (notch60[s][1] * xn_tmp - notch60[s][4] * xn + z[s][1]);
191+
z[s][1] = (notch60[s][2] * xn_tmp - notch60[s][5] * xn);
192+
}
193+
// and store our most recent value for reference later (as an int now)
194+
lastFiltVal = (int)xn;
195+
}

src/Devlpr.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Devlpr
1010
void tick();
1111
unsigned int lastValue();
1212
int lastValueCentered();
13+
int lastValueFiltered();
1314
unsigned int windowAvg();
1415
unsigned int windowPeakAmplitude();
1516
unsigned int windowPeakToPeakAmplitude();
@@ -26,6 +27,18 @@ class Devlpr
2627
unsigned int emgVal; // ATMEGA boards have 10-bit ADC (0-1023)
2728
unsigned int emgRunningSum; // if BUFSIZE is small, uint is fine
2829
void readEMG();
30+
// emg filtering
31+
void calcFiltered();
32+
int lastFiltVal;
33+
static const byte N_SECTIONS = 2; // 2nd order
34+
float notch60[2][6] = { // 2nd order Butterworth notch for 60Hz
35+
{0.95654323 ,-1.77962093 ,0.95654323 ,1. ,-1.80093517 ,0.95415195},
36+
{1. ,-1.860471 ,1. ,1. ,-1.83739919 ,0.95894143}
37+
};
38+
float z[2][2] = { // maintain recurrent state
39+
{0.0, 0.0},
40+
{0.0, 0.0}
41+
};
2942
// scheduling
3043
unsigned long lastTickMicros = 0L;
3144
// emg scheduling

0 commit comments

Comments
 (0)