Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: biquadFilter mbed
emg-utils.cpp@0:44d3f99b08c1, 2016-11-02 (annotated)
- Committer:
- ofosakar
- Date:
- Wed Nov 02 11:08:53 2016 +0000
- Revision:
- 0:44d3f99b08c1
- Child:
- 1:984b6b6812c7
EMG processing for two EMG signals.;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ofosakar | 0:44d3f99b08c1 | 1 | #include "mbed.h" |
ofosakar | 0:44d3f99b08c1 | 2 | #include "HIDScope.h" |
ofosakar | 0:44d3f99b08c1 | 3 | #include "BiQuad.h" |
ofosakar | 0:44d3f99b08c1 | 4 | #include "math.h" |
ofosakar | 0:44d3f99b08c1 | 5 | #include "emg-utils.h" |
ofosakar | 0:44d3f99b08c1 | 6 | |
ofosakar | 0:44d3f99b08c1 | 7 | |
ofosakar | 0:44d3f99b08c1 | 8 | AnalogIn emg1(A0); |
ofosakar | 0:44d3f99b08c1 | 9 | AnalogIn emg2(A1); |
ofosakar | 0:44d3f99b08c1 | 10 | |
ofosakar | 0:44d3f99b08c1 | 11 | HIDScope scope(6); |
ofosakar | 0:44d3f99b08c1 | 12 | Ticker ticker; |
ofosakar | 0:44d3f99b08c1 | 13 | |
ofosakar | 0:44d3f99b08c1 | 14 | BiQuadChain bqc1; |
ofosakar | 0:44d3f99b08c1 | 15 | BiQuadChain bqc2; |
ofosakar | 0:44d3f99b08c1 | 16 | |
ofosakar | 0:44d3f99b08c1 | 17 | // EMG BIQUAD 1 |
ofosakar | 0:44d3f99b08c1 | 18 | //Bandpass butterworth filter + Notch butterworth filter. |
ofosakar | 0:44d3f99b08c1 | 19 | //Bandpass: 10 --- 500 Hz |
ofosakar | 0:44d3f99b08c1 | 20 | //No Bandpass filters |
ofosakar | 0:44d3f99b08c1 | 21 | //Nothc: 50 +- 2 Hz |
ofosakar | 0:44d3f99b08c1 | 22 | BiQuad bq11( 9.93756e-01, -1.89024e+00, 9.93756e-01, -1.89024e+00, 9.87512e-01 ); |
ofosakar | 0:44d3f99b08c1 | 23 | |
ofosakar | 0:44d3f99b08c1 | 24 | // EMG BIQUAD 2 |
ofosakar | 0:44d3f99b08c1 | 25 | //Bandpass butterworth filter + Notch butterworth filter. |
ofosakar | 0:44d3f99b08c1 | 26 | //Bandpass: 10 --- 500 Hz |
ofosakar | 0:44d3f99b08c1 | 27 | //No Bandpass filters |
ofosakar | 0:44d3f99b08c1 | 28 | //Nothc: 50 +- 2 Hz |
ofosakar | 0:44d3f99b08c1 | 29 | BiQuad bq12( 9.93756e-01, -1.89024e+00, 9.93756e-01, -1.89024e+00, 9.87512e-01 ); |
ofosakar | 0:44d3f99b08c1 | 30 | |
ofosakar | 0:44d3f99b08c1 | 31 | |
ofosakar | 0:44d3f99b08c1 | 32 | volatile float TOTAL_SAMPLE_SUM = 0; |
ofosakar | 0:44d3f99b08c1 | 33 | volatile long NUMBER_SAMPLES = 0; |
ofosakar | 0:44d3f99b08c1 | 34 | |
ofosakar | 0:44d3f99b08c1 | 35 | const int numEmgCache = 50; |
ofosakar | 0:44d3f99b08c1 | 36 | float emgCache1[numEmgCache]; //sorted from new to old; |
ofosakar | 0:44d3f99b08c1 | 37 | float emgCache2[numEmgCache]; //sorted from new to old; |
ofosakar | 0:44d3f99b08c1 | 38 | |
ofosakar | 0:44d3f99b08c1 | 39 | void addFirst(float newValue, float array[], int size) { |
ofosakar | 0:44d3f99b08c1 | 40 | for (int i = size - 2; i >= 0; i--) { |
ofosakar | 0:44d3f99b08c1 | 41 | array[i+1] = array[i]; |
ofosakar | 0:44d3f99b08c1 | 42 | } |
ofosakar | 0:44d3f99b08c1 | 43 | array[0] = newValue; |
ofosakar | 0:44d3f99b08c1 | 44 | } |
ofosakar | 0:44d3f99b08c1 | 45 | |
ofosakar | 0:44d3f99b08c1 | 46 | float average(float newValue, float array[], int size) { |
ofosakar | 0:44d3f99b08c1 | 47 | float sum = 0; |
ofosakar | 0:44d3f99b08c1 | 48 | for (int i = size - 2; i >= 0; i--) { |
ofosakar | 0:44d3f99b08c1 | 49 | sum += array[i]; |
ofosakar | 0:44d3f99b08c1 | 50 | } |
ofosakar | 0:44d3f99b08c1 | 51 | // array[0] = newValue; |
ofosakar | 0:44d3f99b08c1 | 52 | sum += newValue; |
ofosakar | 0:44d3f99b08c1 | 53 | return sum / size; |
ofosakar | 0:44d3f99b08c1 | 54 | } |
ofosakar | 0:44d3f99b08c1 | 55 | |
ofosakar | 0:44d3f99b08c1 | 56 | //shifts the array by adding the new emg value up front. |
ofosakar | 0:44d3f99b08c1 | 57 | //returns the new calculated average |
ofosakar | 0:44d3f99b08c1 | 58 | float movingAverage(float newValue, float array[], int size) { |
ofosakar | 0:44d3f99b08c1 | 59 | float sum = 0; |
ofosakar | 0:44d3f99b08c1 | 60 | for (int i = size - 2; i >= 0; i--) { |
ofosakar | 0:44d3f99b08c1 | 61 | array[i+1] = array[i]; |
ofosakar | 0:44d3f99b08c1 | 62 | sum += array[i]; |
ofosakar | 0:44d3f99b08c1 | 63 | } |
ofosakar | 0:44d3f99b08c1 | 64 | array[0] = newValue; |
ofosakar | 0:44d3f99b08c1 | 65 | sum += newValue; |
ofosakar | 0:44d3f99b08c1 | 66 | return sum / size; |
ofosakar | 0:44d3f99b08c1 | 67 | } |
ofosakar | 0:44d3f99b08c1 | 68 | |
ofosakar | 0:44d3f99b08c1 | 69 | float sum(float array[], int size) { |
ofosakar | 0:44d3f99b08c1 | 70 | float sum = 0; |
ofosakar | 0:44d3f99b08c1 | 71 | for (int i = 0; i < size; i++) { |
ofosakar | 0:44d3f99b08c1 | 72 | sum += array[i]; |
ofosakar | 0:44d3f99b08c1 | 73 | } |
ofosakar | 0:44d3f99b08c1 | 74 | return sum; |
ofosakar | 0:44d3f99b08c1 | 75 | } |
ofosakar | 0:44d3f99b08c1 | 76 | |
ofosakar | 0:44d3f99b08c1 | 77 | float mean(float array[], int size) { |
ofosakar | 0:44d3f99b08c1 | 78 | return sum(array, size) / size; |
ofosakar | 0:44d3f99b08c1 | 79 | } |
ofosakar | 0:44d3f99b08c1 | 80 | |
ofosakar | 0:44d3f99b08c1 | 81 | float meanSquare(float array[], int size) { |
ofosakar | 0:44d3f99b08c1 | 82 | float naam[size]; |
ofosakar | 0:44d3f99b08c1 | 83 | for(int i = 0; i < size; i++) { |
ofosakar | 0:44d3f99b08c1 | 84 | naam[i] = pow(array[i], 2); |
ofosakar | 0:44d3f99b08c1 | 85 | } |
ofosakar | 0:44d3f99b08c1 | 86 | return sum(naam, size) / size; |
ofosakar | 0:44d3f99b08c1 | 87 | } |
ofosakar | 0:44d3f99b08c1 | 88 | |
ofosakar | 0:44d3f99b08c1 | 89 | float variance(float array[], int size, float avg) { |
ofosakar | 0:44d3f99b08c1 | 90 | float squaredDifferences[size]; |
ofosakar | 0:44d3f99b08c1 | 91 | for (int i = 0; i < size; i++) { |
ofosakar | 0:44d3f99b08c1 | 92 | float difference = array[i] - avg; |
ofosakar | 0:44d3f99b08c1 | 93 | squaredDifferences[i] = difference*difference; |
ofosakar | 0:44d3f99b08c1 | 94 | } |
ofosakar | 0:44d3f99b08c1 | 95 | return mean(squaredDifferences, size); |
ofosakar | 0:44d3f99b08c1 | 96 | } |
ofosakar | 0:44d3f99b08c1 | 97 | |
ofosakar | 0:44d3f99b08c1 | 98 | float standardDeviation(float array[], int size, float avg) { |
ofosakar | 0:44d3f99b08c1 | 99 | return sqrt(variance(array, size, avg)); |
ofosakar | 0:44d3f99b08c1 | 100 | } |
ofosakar | 0:44d3f99b08c1 | 101 | |
ofosakar | 0:44d3f99b08c1 | 102 | int decide(float value, float threshold) { |
ofosakar | 0:44d3f99b08c1 | 103 | return value < threshold ? 0 : 1; |
ofosakar | 0:44d3f99b08c1 | 104 | } |
ofosakar | 0:44d3f99b08c1 | 105 | |
ofosakar | 0:44d3f99b08c1 | 106 | float rectifier(float value) { |
ofosakar | 0:44d3f99b08c1 | 107 | return fabs(value - 0.5f)*2.0f; |
ofosakar | 0:44d3f99b08c1 | 108 | } |
ofosakar | 0:44d3f99b08c1 | 109 | |
ofosakar | 0:44d3f99b08c1 | 110 | void processEMG() { |
ofosakar | 0:44d3f99b08c1 | 111 | float emgOne = emg1.read(); |
ofosakar | 0:44d3f99b08c1 | 112 | scope.set(0, emgOne); |
ofosakar | 0:44d3f99b08c1 | 113 | float notch1 = bqc1.step( emgOne ); |
ofosakar | 0:44d3f99b08c1 | 114 | |
ofosakar | 0:44d3f99b08c1 | 115 | float emgTwo = emg2.read(); |
ofosakar | 0:44d3f99b08c1 | 116 | scope.set(1, emgTwo); |
ofosakar | 0:44d3f99b08c1 | 117 | float notch2 = bqc2.step( emgTwo ); |
ofosakar | 0:44d3f99b08c1 | 118 | |
ofosakar | 0:44d3f99b08c1 | 119 | |
ofosakar | 0:44d3f99b08c1 | 120 | |
ofosakar | 0:44d3f99b08c1 | 121 | float rect1 = rectifier(notch1); |
ofosakar | 0:44d3f99b08c1 | 122 | // scope.set(2, rect1); |
ofosakar | 0:44d3f99b08c1 | 123 | |
ofosakar | 0:44d3f99b08c1 | 124 | float rect2 = rectifier(notch2); |
ofosakar | 0:44d3f99b08c1 | 125 | // scope.set(3, rect2); |
ofosakar | 0:44d3f99b08c1 | 126 | |
ofosakar | 0:44d3f99b08c1 | 127 | |
ofosakar | 0:44d3f99b08c1 | 128 | float filtered1 = movingAverage( rect1, emgCache1, numEmgCache); |
ofosakar | 0:44d3f99b08c1 | 129 | scope.set(2, filtered1); |
ofosakar | 0:44d3f99b08c1 | 130 | |
ofosakar | 0:44d3f99b08c1 | 131 | float filtered2 = movingAverage( rect2, emgCache2, numEmgCache); |
ofosakar | 0:44d3f99b08c1 | 132 | scope.set(3, filtered2); |
ofosakar | 0:44d3f99b08c1 | 133 | |
ofosakar | 0:44d3f99b08c1 | 134 | float threshold1 = 0.114318; |
ofosakar | 0:44d3f99b08c1 | 135 | float threshold2 = 0.118785; |
ofosakar | 0:44d3f99b08c1 | 136 | int decide1 = decide(filtered1 , threshold1); |
ofosakar | 0:44d3f99b08c1 | 137 | scope.set(4, decide1); |
ofosakar | 0:44d3f99b08c1 | 138 | |
ofosakar | 0:44d3f99b08c1 | 139 | int decide2 = decide(filtered2 , threshold2); |
ofosakar | 0:44d3f99b08c1 | 140 | scope.set(5, decide2); |
ofosakar | 0:44d3f99b08c1 | 141 | |
ofosakar | 0:44d3f99b08c1 | 142 | |
ofosakar | 0:44d3f99b08c1 | 143 | scope.send(); |
ofosakar | 0:44d3f99b08c1 | 144 | } |
ofosakar | 0:44d3f99b08c1 | 145 | |
ofosakar | 0:44d3f99b08c1 | 146 | int main() |
ofosakar | 0:44d3f99b08c1 | 147 | { |
ofosakar | 0:44d3f99b08c1 | 148 | bqc1.add( &bq11 ); |
ofosakar | 0:44d3f99b08c1 | 149 | bqc2.add( &bq12 ); |
ofosakar | 0:44d3f99b08c1 | 150 | |
ofosakar | 0:44d3f99b08c1 | 151 | |
ofosakar | 0:44d3f99b08c1 | 152 | // bqc1.add( &bq11 ); |
ofosakar | 0:44d3f99b08c1 | 153 | // bqc2.add( &bq12 ); |
ofosakar | 0:44d3f99b08c1 | 154 | // 500 HZ Ticker |
ofosakar | 0:44d3f99b08c1 | 155 | ticker.attach(&processEMG, 0.002); |
ofosakar | 0:44d3f99b08c1 | 156 | while (true); |
ofosakar | 0:44d3f99b08c1 | 157 | } |