11#include " Arduino.h"
22#include " Devlpr.h"
33
4- Devlpr::Devlpr (int pin)
4+ Devlpr::Devlpr (int pin, int filterType )
55{
66 emgPin = pin;
7- emgRunningSum = 0 ;
7+ rawEmgRunningSum = 0 ;
88 bufInd = BUFSIZE - 1 ;
99 numFuncs = 0 ;
10- lastFiltVal = 0 ;
10+ if (filterType != FILTER_NONE) {
11+ doFilter = true ;
12+ initFilter (filterType);
13+ }
1114}
1215
1316void Devlpr::tick ()
@@ -22,7 +25,10 @@ void Devlpr::tick()
2225 microsSinceEMG += microsDelta;
2326 // check if enough time has passed to read EMG
2427 if (microsSinceEMG >= MICROS_SCHED_EMG) {
28+ unsigned long myStartMicros = micros ();
2529 readEMG ();
30+ unsigned long myDeltaMicros = micros () - myStartMicros;
31+ Serial.println (myDeltaMicros);
2632 // and update micros since
2733 microsSinceEMG = 0L ;
2834 // NOTE just a best effort to run on time
@@ -61,56 +67,86 @@ void Devlpr::tick()
6167 lastTickMicros = currMicros;
6268}
6369
64- unsigned int Devlpr::lastValue ()
70+ int Devlpr::lastValue (bool filtered )
6571{
72+ if (filtered) {
73+ return filterBuf[bufInd];
74+ }
6675 return buf[bufInd];
6776}
6877
69- unsigned int Devlpr::windowAvg ()
78+ int Devlpr::windowAvg (bool filtered )
7079{
71- return emgRunningSum / BUFSIZE;
80+ // int math should be good enough
81+ if (filtered) {
82+ return filterEmgRunningSum / BUFSIZE;
83+ }
84+ return rawEmgRunningSum / BUFSIZE;
7285}
7386
74- int Devlpr::lastValueCentered ()
87+ int Devlpr::lastValueCentered (bool filtered )
7588{
76- int lastVal = lastValue ();
77- int wAvg = windowAvg ();
89+ int lastVal = lastValue (filtered );
90+ int wAvg = windowAvg (filtered );
7891 return lastVal - wAvg;
7992}
8093
81- int Devlpr::lastValueFiltered ()
82- {
83- return lastFiltVal;
84- }
85-
86- unsigned int Devlpr::windowPeakAmplitude ()
94+ int Devlpr::windowPeakAmplitude (bool filtered)
8795{
8896 // use the window average as the reference point (should be close to DC offset)
89- int wAvg = windowAvg ();
97+ int wAvg = windowAvg (filtered );
9098 // and need to find the max absolute value from ref
91- unsigned int peak = 0 ;
92- for (int i = 0 ; i < BUFSIZE; i++) { // no need to start from bufInd
93- int currDiff = (int )buf[i] - wAvg;
94- int currAbs = abs (currDiff);
95- if (currAbs > peak) {
96- peak = currAbs;
99+ int peak = 0 ;
100+ // hear me out, I'm duplicating the loop to not determine the buffer each iteration
101+ // if it helps, I feel just awful about it
102+ if (filtered) {
103+ for (int i = 0 ; i < BUFSIZE; i++) { // no need to start from bufInd
104+ int currDiff = filterBuf[i] - wAvg;
105+ int currAbs = abs (currDiff);
106+ if (currAbs > peak) {
107+ peak = currAbs;
108+ }
109+ }
110+ }
111+ else {
112+ for (int i = 0 ; i < BUFSIZE; i++) { // no need to start from bufInd
113+ int currDiff = buf[i] - wAvg;
114+ int currAbs = abs (currDiff);
115+ if (currAbs > peak) {
116+ peak = currAbs;
117+ }
97118 }
98119 }
99120 return peak;
100121}
101122
102- unsigned int Devlpr::windowPeakToPeakAmplitude ()
123+ int Devlpr::windowPeakToPeakAmplitude (bool filtered )
103124{
104125 // and need to find the max absolute value from ref
105- unsigned int peak = 0 ;
106- unsigned int trough = 1023 ;
107- for (int i = 0 ; i < BUFSIZE; i++) { // no need to start from bufInd
108- unsigned int currVal = buf[i];
109- if (currVal > peak) {
110- peak = currVal;
126+ int peak = 0 ;
127+ int trough = 1023 ;
128+ // hear me out, I'm duplicating the loop to not determine the buffer each iteration
129+ // if it helps, I feel just awful about it
130+ if (filtered) {
131+ for (int i = 0 ; i < BUFSIZE; i++) { // no need to start from bufInd
132+ int currVal = filterBuf[i];
133+ if (currVal > peak) {
134+ peak = currVal;
135+ }
136+ if (currVal < trough) {
137+ trough = currVal;
138+ }
111139 }
112- if (currVal < trough) {
113- trough = currVal;
140+ }
141+ else {
142+ for (int i = 0 ; i < BUFSIZE; i++) { // no need to start from bufInd
143+ int currVal = buf[i];
144+ if (currVal > peak) {
145+ peak = currVal;
146+ }
147+ if (currVal < trough) {
148+ trough = currVal;
149+ }
114150 }
115151 }
116152 return peak - trough;
@@ -149,23 +185,27 @@ void Devlpr::readEMG()
149185 if (bufInd >= BUFSIZE) { // faster than mod
150186 bufInd = 0 ;
151187 }
152- // read our new value
188+ // read our new raw value
153189 emgVal = analogRead (emgPin);
154190 // before replacing the prev tail value though, update running sum
155- emgRunningSum = emgRunningSum - buf[bufInd] + emgVal;
191+ rawEmgRunningSum = rawEmgRunningSum - buf[bufInd];
192+ rawEmgRunningSum = rawEmgRunningSum + emgVal;
156193 // now replace
157194 buf[bufInd] = emgVal;
158- // and we need to calculate the filtered value every sample
159- calcFiltered ();
195+ // and handle all the filtering if set
196+ if (doFilter) {
197+ handleFiltered ();
198+ }
160199}
161200
162201void Devlpr::flexCheck (unsigned long currMicros)
163202{
164203 // to check cooldown
165204 unsigned long microsDelta = currMicros - prevFlexMicros;
166205 // the actual flex check
167- unsigned int peakToPeakThresh = prevPeakToPeak * flexThreshMultiple;
168- unsigned int currPeakToPeak = windowPeakToPeakAmplitude ();
206+ int peakToPeakThresh = prevPeakToPeak * flexThreshMultiple;
207+ // if filter is configured, base it on filtered values
208+ int currPeakToPeak = windowPeakToPeakAmplitude (doFilter);
169209 // need an attached function, cooldown passed, and a peak change
170210 if (onFlexFunc && microsDelta >= flexCooldownMicros &&
171211 currPeakToPeak >= peakToPeakThresh) {
@@ -178,18 +218,63 @@ void Devlpr::flexCheck(unsigned long currMicros)
178218 prevPeakToPeak = currPeakToPeak;
179219}
180220
181- void Devlpr::calcFiltered ()
221+ void Devlpr::handleFiltered ()
182222{
183223 // NOTE: IIR filter is recurrent and needs to run every tick to work
184224 // we need to operate on 0-centered(ish) data and we will be doing float math
185- float xn = lastValueCentered ();
225+ float xn = lastValueCentered (false ); // needs to be based on raw data
186226 // compute the recurrence by section
187227 for (int s = 0 ; s < N_SECTIONS; s++) {
188228 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);
229+ xn = filter[s][0 ] * xn_tmp + z[s][0 ];
230+ z[s][0 ] = (filter[s][1 ] * xn_tmp - filter[s][4 ] * xn + z[s][1 ]);
231+ z[s][1 ] = (filter[s][2 ] * xn_tmp - filter[s][5 ] * xn);
232+ }
233+ // and store our filtered value for reference later (as an int now)
234+ int filtVal = (int )xn;
235+ // before replacing the prev tail value though, update running sum
236+ filterEmgRunningSum = filterEmgRunningSum - filterBuf[bufInd];
237+ filterEmgRunningSum = filterEmgRunningSum + filtVal;
238+ // now replace
239+ filterBuf[bufInd] = filtVal;
240+ }
241+
242+ void Devlpr::initFilter (int filterType) {
243+ // NOTE: this is just a dumb way to not have to reference a different
244+ // filter array depending on the filter type selected at the start
245+
246+ // 2nd order Butterworth notch for 50Hz
247+ // {{0.95654323, -1.82035157, 0.95654323, 1., -1.84458768, 0.9536256},
248+ // { 1. , -1.90305207, 1. , 1., -1.87701816, 0.95947072}}
249+ // 2nd order Butterworth notch for 60Hz
250+ // {{0.95654323, -1.77962093, 0.95654323, 1., -1.80093517, 0.95415195},
251+ // { 1. , -1.860471 , 1. , 1., -1.83739919, 0.95894143}}
252+ if (filterType == FILTER_50HZ) {
253+ filter[0 ][0 ] = 0.95654323 ;
254+ filter[0 ][1 ] = -1.82035157 ;
255+ filter[0 ][2 ] = 0.95654323 ;
256+ filter[0 ][3 ] = 1 .;
257+ filter[0 ][4 ] = -1.84458768 ;
258+ filter[0 ][5 ] = 0.9536256 ;
259+ filter[1 ][0 ] = 1 .;
260+ filter[1 ][1 ] = -1.90305207 ;
261+ filter[1 ][2 ] = 1 .;
262+ filter[1 ][3 ] = 1 .;
263+ filter[1 ][4 ] = -1.87701816 ;
264+ filter[1 ][5 ] = 0.95947072 ;
265+ }
266+ if (filterType == FILTER_60HZ) {
267+ filter[0 ][0 ] = 0.95654323 ;
268+ filter[0 ][1 ] = -1.77962093 ;
269+ filter[0 ][2 ] = 0.95654323 ;
270+ filter[0 ][3 ] = 1 .;
271+ filter[0 ][4 ] = -1.80093517 ;
272+ filter[0 ][5 ] = 0.95415195 ;
273+ filter[1 ][0 ] = 1 .;
274+ filter[1 ][1 ] = -1.860471 ;
275+ filter[1 ][2 ] = 1 .;
276+ filter[1 ][3 ] = 1 .;
277+ filter[1 ][4 ] = -1.83739919 ;
278+ filter[1 ][5 ] = 0.95894143 ;
192279 }
193- // and store our most recent value for reference later (as an int now)
194- lastFiltVal = (int )xn;
195280}
0 commit comments