De EMG Lowpass maakt alle signalen gelijk

Dependencies:   HIDScope biquadFilter mbed

Fork of EMGfilter by Pascal van Baardwijk

Committer:
NahuelM
Date:
Fri Oct 28 10:08:43 2016 +0000
Revision:
10:93ff2f23b901
Parent:
9:81637351bbd1
EMG HELEMAAL KAPOT!!!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pbaardwijk 0:ae0bec143f2d 1 #include "mbed.h"
pbaardwijk 0:ae0bec143f2d 2 #include "BiQuad.h"
pbaardwijk 0:ae0bec143f2d 3 #include "HIDScope.h"
pbaardwijk 0:ae0bec143f2d 4 //Enum with states
pbaardwijk 0:ae0bec143f2d 5 enum states {STATE_DEFAULT , STATE_CALIBRATION, STATE_RUN};
pbaardwijk 0:ae0bec143f2d 6
pbaardwijk 0:ae0bec143f2d 7 //Variable called 'state'
pbaardwijk 0:ae0bec143f2d 8 states state = STATE_DEFAULT;
pbaardwijk 0:ae0bec143f2d 9
pbaardwijk 0:ae0bec143f2d 10 //Creating two scope channels
NahuelM 10:93ff2f23b901 11 HIDScope scope(6);
pbaardwijk 6:da06585e106c 12
pbaardwijk 0:ae0bec143f2d 13 //Notch filter
NahuelM 10:93ff2f23b901 14 BiQuadChain notch_50_0;
NahuelM 10:93ff2f23b901 15 BiQuadChain notch_50_1;
NahuelM 10:93ff2f23b901 16 BiQuadChain notch_50_2;
pbaardwijk 7:a928724ef731 17 BiQuad bq3( 0.98116526140, 0.00000000044, 0.98116526140, 0.00000000043, 0.95391787621);
pbaardwijk 7:a928724ef731 18 BiQuad bq4( 0.97224232015, 0.00000000043, 0.97224232015, -0.04036799459, 0.97670000725);
pbaardwijk 7:a928724ef731 19 BiQuad bq5( 1.00000000000, 0.00000000044, 1.00000000000, 0.04036799547, 0.9767000072);
pbaardwijk 0:ae0bec143f2d 20
pbaardwijk 0:ae0bec143f2d 21 //High pass filter
NahuelM 10:93ff2f23b901 22 BiQuadChain high_pass_0;
NahuelM 10:93ff2f23b901 23 BiQuadChain high_pass_1;
NahuelM 10:93ff2f23b901 24 BiQuadChain high_pass_2;
pbaardwijk 7:a928724ef731 25 BiQuad bq6( 0.80254782780,-1.60509565560, 0.80254782780, -1.58011656361, 0.63006219630);
pbaardwijk 7:a928724ef731 26 BiQuad bq7( 0.90006571973,-1.80013143945, 0.900065719734, -1.77213098592, 0.8281459694);
pbaardwijk 7:a928724ef731 27 //BiQuad bq8( 0.92490714701,-1.84981429401, 0.92490714701, -1.90032503529, 0.9352152620);
pbaardwijk 0:ae0bec143f2d 28
pbaardwijk 5:02b3550e1ff0 29 //Low pass filter
NahuelM 10:93ff2f23b901 30 BiQuadChain low_pass_0;
NahuelM 10:93ff2f23b901 31 BiQuadChain low_pass_1;
NahuelM 10:93ff2f23b901 32 BiQuadChain low_pass_2;
pbaardwijk 7:a928724ef731 33 BiQuad bq9( 0.00801840797, 0.01603681594, 0.00801840797,-1.65212256130, 0.68416767240);
pbaardwijk 7:a928724ef731 34 BiQuad bq10( 0.00836524486, 0.01673048973, 0.00836524486,-1.72511837232, 0.75857933411);
pbaardwijk 7:a928724ef731 35 BiQuad bq11( 0.00905039996, 0.01810079992, 0.00905039996,-1.86807725180, 0.9043110909);
NahuelM 10:93ff2f23b901 36
NahuelM 10:93ff2f23b901 37
pbaardwijk 0:ae0bec143f2d 38 //Ticker
pbaardwijk 0:ae0bec143f2d 39 Ticker emgSampleTicker;
pbaardwijk 0:ae0bec143f2d 40
pbaardwijk 0:ae0bec143f2d 41 //Timeout to change state after 5 seconds
pbaardwijk 0:ae0bec143f2d 42 Timeout change_state;
pbaardwijk 0:ae0bec143f2d 43
pbaardwijk 1:7fb4a74d33ff 44 //Timeout to change state after 15 seconds
pbaardwijk 0:ae0bec143f2d 45 Timeout change_state2;
pbaardwijk 0:ae0bec143f2d 46
pbaardwijk 1:7fb4a74d33ff 47 //LED
pbaardwijk 1:7fb4a74d33ff 48 DigitalOut led(LED_RED);
pbaardwijk 1:7fb4a74d33ff 49
pbaardwijk 0:ae0bec143f2d 50 //Emg input
pbaardwijk 0:ae0bec143f2d 51 AnalogIn emg0( A0 );
pbaardwijk 0:ae0bec143f2d 52 AnalogIn emg1( A1 );
pbaardwijk 0:ae0bec143f2d 53 AnalogIn emg2( A2 );
pbaardwijk 0:ae0bec143f2d 54
pbaardwijk 9:81637351bbd1 55 //Go flag for emg sample
pbaardwijk 0:ae0bec143f2d 56 bool go_emgSample;
pbaardwijk 9:81637351bbd1 57
pbaardwijk 9:81637351bbd1 58 //Variables for intermediate filter values
pbaardwijk 0:ae0bec143f2d 59 double emg_sample[3];
pbaardwijk 6:da06585e106c 60 double emg_low_passed_200[3];
pbaardwijk 0:ae0bec143f2d 61 double emg_notch[3];
pbaardwijk 0:ae0bec143f2d 62 double emg_high_passed[3];
pbaardwijk 5:02b3550e1ff0 63 double emg_low_passed[3];
pbaardwijk 0:ae0bec143f2d 64 double min_emg[3];
pbaardwijk 0:ae0bec143f2d 65 double max_emg[3];
pbaardwijk 0:ae0bec143f2d 66
pbaardwijk 9:81637351bbd1 67 //Calculating normalized outputs
pbaardwijk 0:ae0bec143f2d 68 double input_force0;
pbaardwijk 0:ae0bec143f2d 69 double input_force1;
pbaardwijk 0:ae0bec143f2d 70 double input_force2;
pbaardwijk 0:ae0bec143f2d 71
pbaardwijk 0:ae0bec143f2d 72 //count for emg min max
pbaardwijk 0:ae0bec143f2d 73 int start_calibration = 0;
pbaardwijk 0:ae0bec143f2d 74
pbaardwijk 0:ae0bec143f2d 75 void emgSample() {
pbaardwijk 0:ae0bec143f2d 76 go_emgSample = true;
pbaardwijk 0:ae0bec143f2d 77 }
pbaardwijk 0:ae0bec143f2d 78
pbaardwijk 0:ae0bec143f2d 79 void calibrate() {
pbaardwijk 0:ae0bec143f2d 80 state = STATE_CALIBRATION;
pbaardwijk 1:7fb4a74d33ff 81 led.write(0);
pbaardwijk 0:ae0bec143f2d 82 }
pbaardwijk 0:ae0bec143f2d 83
pbaardwijk 0:ae0bec143f2d 84 void run() {
pbaardwijk 0:ae0bec143f2d 85 state = STATE_RUN;
pbaardwijk 1:7fb4a74d33ff 86 led.write(1);
pbaardwijk 0:ae0bec143f2d 87 }
pbaardwijk 0:ae0bec143f2d 88
pbaardwijk 0:ae0bec143f2d 89 void EMG_filter();
pbaardwijk 0:ae0bec143f2d 90
pbaardwijk 0:ae0bec143f2d 91 int main() {
pbaardwijk 0:ae0bec143f2d 92 //combine biquads in biquad chains for notch/high- low-pass filters
NahuelM 10:93ff2f23b901 93 notch_50_0.add( &bq3 ).add( &bq4 ).add( &bq5 );
NahuelM 10:93ff2f23b901 94 notch_50_1.add( &bq3 ).add( &bq4 ).add( &bq5 );
NahuelM 10:93ff2f23b901 95 notch_50_2.add( &bq3 ).add( &bq4 ).add( &bq5 );
NahuelM 10:93ff2f23b901 96 high_pass_0.add( &bq6 ).add( &bq7 );
NahuelM 10:93ff2f23b901 97 high_pass_1.add( &bq6 ).add( &bq7 );
NahuelM 10:93ff2f23b901 98 high_pass_2.add( &bq6 ).add( &bq7 );
NahuelM 10:93ff2f23b901 99 low_pass_0.add( &bq9 ).add( &bq10 ).add( &bq11 );
NahuelM 10:93ff2f23b901 100 low_pass_1.add( &bq9 ).add( &bq10 ).add( &bq11 );
NahuelM 10:93ff2f23b901 101 low_pass_2.add( &bq9 ).add( &bq10 ).add( &bq11 );
pbaardwijk 1:7fb4a74d33ff 102 led.write(1);
pbaardwijk 0:ae0bec143f2d 103
pbaardwijk 0:ae0bec143f2d 104 change_state.attach( &calibrate,5);
pbaardwijk 1:7fb4a74d33ff 105 change_state2.attach( &run,15);
pbaardwijk 7:a928724ef731 106 emgSampleTicker.attach( &emgSample, 0.005); //200Hz
pbaardwijk 0:ae0bec143f2d 107 while( true ){
pbaardwijk 0:ae0bec143f2d 108 if(go_emgSample == true){
pbaardwijk 0:ae0bec143f2d 109 EMG_filter();
pbaardwijk 0:ae0bec143f2d 110 }
pbaardwijk 0:ae0bec143f2d 111 }
pbaardwijk 0:ae0bec143f2d 112 }
pbaardwijk 0:ae0bec143f2d 113
pbaardwijk 0:ae0bec143f2d 114
pbaardwijk 0:ae0bec143f2d 115 void EMG_filter() {
pbaardwijk 0:ae0bec143f2d 116 if(go_emgSample == true){
pbaardwijk 0:ae0bec143f2d 117 //read the emg signal
pbaardwijk 0:ae0bec143f2d 118 emg_sample[0] = emg0.read();
pbaardwijk 0:ae0bec143f2d 119 emg_sample[1] = emg1.read();
pbaardwijk 0:ae0bec143f2d 120 emg_sample[2] = emg2.read();
NahuelM 10:93ff2f23b901 121 //pc.printf("%f - %f - %f \r\n", emg_sample[0], emg_sample[1], emg_sample[2]);
pbaardwijk 7:a928724ef731 122 //filter out the 50Hz components with a notch filter
NahuelM 10:93ff2f23b901 123 emg_notch[0] = notch_50_0.step(emg_sample[0]);
NahuelM 10:93ff2f23b901 124 emg_notch[1] = notch_50_1.step(emg_sample[1]);
NahuelM 10:93ff2f23b901 125 emg_notch[2] = notch_50_2.step(emg_sample[2]);
pbaardwijk 7:a928724ef731 126 //high pass the signal (removing motion artifacts and offset)
NahuelM 10:93ff2f23b901 127 emg_high_passed[0] = high_pass_0.step(emg_notch[0]);
NahuelM 10:93ff2f23b901 128 emg_high_passed[1] = high_pass_1.step(emg_notch[1]);
NahuelM 10:93ff2f23b901 129 emg_high_passed[2] = high_pass_2.step(emg_notch[2]);
NahuelM 10:93ff2f23b901 130 float emg_fabs[3];
NahuelM 10:93ff2f23b901 131 emg_fabs[0] = fabs(emg_high_passed[0]);
NahuelM 10:93ff2f23b901 132 emg_fabs[1] = fabs(emg_high_passed[1]);
NahuelM 10:93ff2f23b901 133 emg_fabs[2] = fabs(emg_high_passed[2]);
pbaardwijk 7:a928724ef731 134 //low pass the rectified emg signal
NahuelM 10:93ff2f23b901 135 emg_low_passed[0] = low_pass_0.step(emg_fabs[0]);
NahuelM 10:93ff2f23b901 136 emg_low_passed[1] = low_pass_1.step(emg_fabs[1]);
NahuelM 10:93ff2f23b901 137 emg_low_passed[2] = low_pass_2.step(emg_fabs[2]);
NahuelM 10:93ff2f23b901 138 // pc.printf("%f - %f - %f \r\n", emg_low_passed[0], emg_low_passed[1], emg_low_passed[2]);
pbaardwijk 0:ae0bec143f2d 139 //Calculating min value and max value of emg signal
pbaardwijk 0:ae0bec143f2d 140 if(state == STATE_CALIBRATION)
pbaardwijk 0:ae0bec143f2d 141 {
pbaardwijk 0:ae0bec143f2d 142 if (start_calibration == 0) {
pbaardwijk 9:81637351bbd1 143 min_emg[0] = emg_low_passed[0];
pbaardwijk 9:81637351bbd1 144 max_emg[0] = emg_low_passed[0];
pbaardwijk 9:81637351bbd1 145 min_emg[1] = emg_low_passed[1];
pbaardwijk 9:81637351bbd1 146 max_emg[1] = emg_low_passed[1];
pbaardwijk 9:81637351bbd1 147 min_emg[2] = emg_low_passed[2];
pbaardwijk 9:81637351bbd1 148 max_emg[2] = emg_low_passed[2];
pbaardwijk 0:ae0bec143f2d 149 start_calibration++;
pbaardwijk 0:ae0bec143f2d 150 }
pbaardwijk 0:ae0bec143f2d 151 else {
pbaardwijk 0:ae0bec143f2d 152 //finding min and max of emg0
pbaardwijk 9:81637351bbd1 153 if (emg_low_passed[0] < min_emg[0]) {
pbaardwijk 9:81637351bbd1 154 min_emg[0] = emg_low_passed[0];
pbaardwijk 0:ae0bec143f2d 155 }
pbaardwijk 9:81637351bbd1 156 else if (emg_low_passed[0] > max_emg[0]) {
pbaardwijk 9:81637351bbd1 157 max_emg[0] = emg_low_passed[0];
pbaardwijk 0:ae0bec143f2d 158 }
pbaardwijk 0:ae0bec143f2d 159
pbaardwijk 0:ae0bec143f2d 160 //finding min and max of emg1
pbaardwijk 9:81637351bbd1 161 if (emg_low_passed[1] < min_emg[1]) {
pbaardwijk 9:81637351bbd1 162 min_emg[1] = emg_low_passed[1];
pbaardwijk 0:ae0bec143f2d 163 }
pbaardwijk 9:81637351bbd1 164 else if (emg_low_passed[1] > max_emg[1]) {
pbaardwijk 9:81637351bbd1 165 max_emg[1] = emg_low_passed[1];
pbaardwijk 0:ae0bec143f2d 166 }
pbaardwijk 0:ae0bec143f2d 167
pbaardwijk 0:ae0bec143f2d 168 //finding min and max of emg2
pbaardwijk 9:81637351bbd1 169 if (emg_low_passed[2] < min_emg[2]) {
pbaardwijk 9:81637351bbd1 170 min_emg[2] = emg_low_passed[2];
pbaardwijk 0:ae0bec143f2d 171 }
pbaardwijk 9:81637351bbd1 172 else if (emg_low_passed[2] > max_emg[2]) {
pbaardwijk 9:81637351bbd1 173 max_emg[2] = emg_low_passed[2];
pbaardwijk 0:ae0bec143f2d 174 }
pbaardwijk 0:ae0bec143f2d 175 }
pbaardwijk 0:ae0bec143f2d 176 }
pbaardwijk 0:ae0bec143f2d 177
pbaardwijk 0:ae0bec143f2d 178 //calculating input_forces for controller
pbaardwijk 9:81637351bbd1 179 input_force0 = (emg_low_passed[0] - min_emg[0])/(max_emg[0]-min_emg[0]);
pbaardwijk 9:81637351bbd1 180 input_force1 = (emg_low_passed[1] - min_emg[1])/(max_emg[1]-min_emg[1]);
pbaardwijk 9:81637351bbd1 181 input_force2 = (emg_low_passed[2] - min_emg[2])/(max_emg[2]-min_emg[2]);
pbaardwijk 0:ae0bec143f2d 182
pbaardwijk 0:ae0bec143f2d 183 //Send scope data
NahuelM 10:93ff2f23b901 184 scope.set(0,emg_high_passed[0]);
NahuelM 10:93ff2f23b901 185 scope.set(1,emg_high_passed[1]);
NahuelM 10:93ff2f23b901 186 scope.set(2,emg_high_passed[2]);
NahuelM 10:93ff2f23b901 187 scope.set(3,emg_low_passed[0]);
NahuelM 10:93ff2f23b901 188 scope.set(4,emg_low_passed[1]);
NahuelM 10:93ff2f23b901 189 scope.set(5,emg_low_passed[2]);
NahuelM 10:93ff2f23b901 190 //scope.set(3,input_force0);
pbaardwijk 7:a928724ef731 191 //scope.set(2,emg_low_passed[0]);
pbaardwijk 0:ae0bec143f2d 192 //scope.set(3,input_force2);
pbaardwijk 0:ae0bec143f2d 193 scope.send();
pbaardwijk 0:ae0bec143f2d 194
pbaardwijk 0:ae0bec143f2d 195 go_emgSample = false;
pbaardwijk 0:ae0bec143f2d 196 }
pbaardwijk 0:ae0bec143f2d 197 }
pbaardwijk 0:ae0bec143f2d 198