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: mbed HIDScope FXOS8700Q
main.cpp@3:15eeab5ba885, 2019-10-14 (annotated)
- Committer:
- AnaisChaumeil
- Date:
- Mon Oct 14 17:36:48 2019 +0000
- Revision:
- 3:15eeab5ba885
- Parent:
- 2:c177a3e9708e
- Child:
- 4:0d80d02a257c
link to HIDSCOPE added
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnaisChaumeil | 0:971166224b2d | 1 | #include "mbed.h" |
AnaisChaumeil | 0:971166224b2d | 2 | #include "math.h" |
AnaisChaumeil | 3:15eeab5ba885 | 3 | #include "HIDScope.h" |
AnaisChaumeil | 0:971166224b2d | 4 | |
AnaisChaumeil | 0:971166224b2d | 5 | // CODE THE PART WHERE WE PUT THE SIGNAL INTO RAW_SIGNAL |
AnaisChaumeil | 2:c177a3e9708e | 6 | // IF NEEDED WE CAN HAVE THE FILTERS OF SECOND ORDER |
AnaisChaumeil | 0:971166224b2d | 7 | |
AnaisChaumeil | 0:971166224b2d | 8 | // Defining objects |
AnaisChaumeil | 0:971166224b2d | 9 | |
AnaisChaumeil | 0:971166224b2d | 10 | AnalogIn emg0( A0 ); // for movement up/down, named A |
AnaisChaumeil | 0:971166224b2d | 11 | AnalogIn emg1( A1 ); |
AnaisChaumeil | 0:971166224b2d | 12 | |
AnaisChaumeil | 0:971166224b2d | 13 | AnalogIn emg2( A2 ); // for movement forward/backward, named B |
AnaisChaumeil | 0:971166224b2d | 14 | AnalogIn emg3( A3 ); |
AnaisChaumeil | 0:971166224b2d | 15 | |
AnaisChaumeil | 1:0b3280b1795e | 16 | //int mark=0; // allows us to know where we are exactly in the sampling process |
AnaisChaumeil | 0:971166224b2d | 17 | |
AnaisChaumeil | 0:971166224b2d | 18 | const double pi=3.14; |
AnaisChaumeil | 0:971166224b2d | 19 | |
AnaisChaumeil | 0:971166224b2d | 20 | // define two functions that will be attached to the tickers |
AnaisChaumeil | 0:971166224b2d | 21 | Ticker sampling; // ticker for the sampling of the signal, every 0.002s a value is sampled |
AnaisChaumeil | 0:971166224b2d | 22 | Ticker processing; //ticker that defines the signal processed, every second a signal is defined |
AnaisChaumeil | 0:971166224b2d | 23 | |
AnaisChaumeil | 2:c177a3e9708e | 24 | double raw_signal_0[2]; // has the values measured via the electrodes |
AnaisChaumeil | 2:c177a3e9708e | 25 | double raw_signal_1[2]; |
AnaisChaumeil | 2:c177a3e9708e | 26 | double raw_signal_2[2]; |
AnaisChaumeil | 2:c177a3e9708e | 27 | double raw_signal_3[2]; |
AnaisChaumeil | 0:971166224b2d | 28 | |
AnaisChaumeil | 2:c177a3e9708e | 29 | double filt0[2]; // raw_emg_1 filtered by high pass filter |
AnaisChaumeil | 2:c177a3e9708e | 30 | double filt1[2]; |
AnaisChaumeil | 2:c177a3e9708e | 31 | double filt2[2]; |
AnaisChaumeil | 2:c177a3e9708e | 32 | double filt3[2]; |
AnaisChaumeil | 0:971166224b2d | 33 | |
AnaisChaumeil | 2:c177a3e9708e | 34 | double filt_filt0[2]; // filt1 filtered by low pass filter |
AnaisChaumeil | 2:c177a3e9708e | 35 | double filt_filt1[2]; |
AnaisChaumeil | 2:c177a3e9708e | 36 | double filt_filt2[2]; |
AnaisChaumeil | 2:c177a3e9708e | 37 | double filt_filt3[2]; |
AnaisChaumeil | 0:971166224b2d | 38 | |
AnaisChaumeil | 2:c177a3e9708e | 39 | double emgA; // not an array |
AnaisChaumeil | 2:c177a3e9708e | 40 | double emgB; |
AnaisChaumeil | 0:971166224b2d | 41 | |
AnaisChaumeil | 2:c177a3e9708e | 42 | double emg_absA[2]; // absolute value applied to emg |
AnaisChaumeil | 2:c177a3e9708e | 43 | double emg_absB[2]; |
AnaisChaumeil | 0:971166224b2d | 44 | |
AnaisChaumeil | 2:c177a3e9708e | 45 | double emg_filtA[2]; |
AnaisChaumeil | 2:c177a3e9708e | 46 | double emg_filtB[2]; |
AnaisChaumeil | 0:971166224b2d | 47 | |
AnaisChaumeil | 2:c177a3e9708e | 48 | double emg_normA[2]; // normalization of emg_rms |
AnaisChaumeil | 2:c177a3e9708e | 49 | double emg_normB[2]; |
AnaisChaumeil | 0:971166224b2d | 50 | |
AnaisChaumeil | 1:0b3280b1795e | 51 | bool modeA= false; // running motor at intermediate speed, derived from threshold |
AnaisChaumeil | 1:0b3280b1795e | 52 | bool modeB= false; |
AnaisChaumeil | 0:971166224b2d | 53 | |
AnaisChaumeil | 1:0b3280b1795e | 54 | bool speedA= false; // running motor at high speed |
AnaisChaumeil | 1:0b3280b1795e | 55 | bool speedB= false; |
AnaisChaumeil | 0:971166224b2d | 56 | |
AnaisChaumeil | 0:971166224b2d | 57 | double T=0.002; // time between two samples |
AnaisChaumeil | 0:971166224b2d | 58 | |
AnaisChaumeil | 0:971166224b2d | 59 | |
AnaisChaumeil | 0:971166224b2d | 60 | void sample() |
AnaisChaumeil | 0:971166224b2d | 61 | { |
AnaisChaumeil | 2:c177a3e9708e | 62 | // raw_signal=[ value(T-2), value(T-1), value(T)] |
AnaisChaumeil | 2:c177a3e9708e | 63 | raw_signal_0[0]=raw_signal_0[1]; |
AnaisChaumeil | 2:c177a3e9708e | 64 | raw_signal_1[0]=raw_signal_1[1]; |
AnaisChaumeil | 2:c177a3e9708e | 65 | raw_signal_2[0]=raw_signal_2[1]; |
AnaisChaumeil | 2:c177a3e9708e | 66 | raw_signal_3[0]=raw_signal_3[1]; |
AnaisChaumeil | 2:c177a3e9708e | 67 | |
AnaisChaumeil | 2:c177a3e9708e | 68 | raw_signal_0[1]=emg0.read(); |
AnaisChaumeil | 2:c177a3e9708e | 69 | raw_signal_1[1]=emg1.read(); |
AnaisChaumeil | 2:c177a3e9708e | 70 | raw_signal_2[1]=emg2.read(); |
AnaisChaumeil | 2:c177a3e9708e | 71 | raw_signal_3[1]=emg3.read(); |
AnaisChaumeil | 3:15eeab5ba885 | 72 | |
AnaisChaumeil | 3:15eeab5ba885 | 73 | scope.set(0, fabs(emg0.read()- emg1.read() ); |
AnaisChaumeil | 3:15eeab5ba885 | 74 | scope.send(); |
AnaisChaumeil | 0:971166224b2d | 75 | } |
AnaisChaumeil | 0:971166224b2d | 76 | |
AnaisChaumeil | 0:971166224b2d | 77 | |
AnaisChaumeil | 0:971166224b2d | 78 | // BIG FUNCTION THAT INCLUDES EVERYTHING |
AnaisChaumeil | 0:971166224b2d | 79 | |
AnaisChaumeil | 0:971166224b2d | 80 | void processing_signals() |
AnaisChaumeil | 0:971166224b2d | 81 | { |
AnaisChaumeil | 2:c177a3e9708e | 82 | |
AnaisChaumeil | 0:971166224b2d | 83 | // LOWPASS FILTER |
AnaisChaumeil | 0:971166224b2d | 84 | double wclp=300*2*pi; // cutoff omega for low pass filter |
AnaisChaumeil | 0:971166224b2d | 85 | |
AnaisChaumeil | 0:971166224b2d | 86 | // initialization of the filt arrays |
AnaisChaumeil | 2:c177a3e9708e | 87 | filt0[0]=filt0[1]; |
AnaisChaumeil | 2:c177a3e9708e | 88 | filt1[0]=filt1[1]; |
AnaisChaumeil | 2:c177a3e9708e | 89 | filt2[0]=filt2[1]; |
AnaisChaumeil | 2:c177a3e9708e | 90 | filt3[0]=filt3[1]; |
AnaisChaumeil | 2:c177a3e9708e | 91 | |
AnaisChaumeil | 0:971166224b2d | 92 | |
AnaisChaumeil | 0:971166224b2d | 93 | // initialization of the parameters |
AnaisChaumeil | 0:971166224b2d | 94 | double b0=(wclp*T)/(wclp*T+2); |
AnaisChaumeil | 0:971166224b2d | 95 | double b1=(wclp*T)/(wclp*T+2); |
AnaisChaumeil | 0:971166224b2d | 96 | double a1=(wclp*T-2)/(wclp*T+2); |
AnaisChaumeil | 2:c177a3e9708e | 97 | |
AnaisChaumeil | 2:c177a3e9708e | 98 | filt0[1]=b0*raw_signal_0[1]+b1*raw_signal_0[0]-a1*filt0[0]; |
AnaisChaumeil | 2:c177a3e9708e | 99 | filt1[1]=b0*raw_signal_1[1]+b1*raw_signal_1[0]-a1*filt1[0]; |
AnaisChaumeil | 2:c177a3e9708e | 100 | filt2[1]=b0*raw_signal_2[1]+b1*raw_signal_2[0]-a1*filt2[0]; |
AnaisChaumeil | 2:c177a3e9708e | 101 | filt3[1]=b0*raw_signal_3[1]+b1*raw_signal_3[0]-a1*filt3[0]; |
AnaisChaumeil | 2:c177a3e9708e | 102 | |
AnaisChaumeil | 0:971166224b2d | 103 | |
AnaisChaumeil | 0:971166224b2d | 104 | // HIGH PASS FILTER |
AnaisChaumeil | 0:971166224b2d | 105 | double wchp=10*2*pi; |
AnaisChaumeil | 0:971166224b2d | 106 | |
AnaisChaumeil | 0:971166224b2d | 107 | // initialization by the mean of the two first values |
AnaisChaumeil | 2:c177a3e9708e | 108 | filt_filt0[0]=filt_filt0[1]; |
AnaisChaumeil | 2:c177a3e9708e | 109 | filt_filt1[0]=filt_filt1[1]; |
AnaisChaumeil | 2:c177a3e9708e | 110 | filt_filt2[0]=filt_filt2[1]; |
AnaisChaumeil | 2:c177a3e9708e | 111 | filt_filt4[0]=filt_filt3[1]; |
AnaisChaumeil | 0:971166224b2d | 112 | |
AnaisChaumeil | 0:971166224b2d | 113 | // initialization of the parameters |
AnaisChaumeil | 0:971166224b2d | 114 | double d0=2/(wchp*T+2); |
AnaisChaumeil | 0:971166224b2d | 115 | double d1=2/(wchp*T+2); |
AnaisChaumeil | 0:971166224b2d | 116 | double c1=(wchp*T-2)/(wchp*T+2); |
AnaisChaumeil | 2:c177a3e9708e | 117 | |
AnaisChaumeil | 2:c177a3e9708e | 118 | filt_filt0[1]=d0*filt0[1]+d1*filt0[0]-c1*filt_filt0[0]; |
AnaisChaumeil | 2:c177a3e9708e | 119 | filt_filt1[1]=d0*filt1[1]+d1*filt1[0]-c1*filt_filt1[0]; |
AnaisChaumeil | 2:c177a3e9708e | 120 | filt_filt2[1]=d0*filt2[1]+d1*filt2[0]-c1*filt_filt2[0]; |
AnaisChaumeil | 2:c177a3e9708e | 121 | filt_filt3[1]=d0*filt3[1]+d1*filt3[0]-c1*filt_filt3[0]; |
AnaisChaumeil | 2:c177a3e9708e | 122 | |
AnaisChaumeil | 0:971166224b2d | 123 | |
AnaisChaumeil | 0:971166224b2d | 124 | // DIFFERENCE OF THE SIGNALS AND ABSOLUTE VALUE |
AnaisChaumeil | 2:c177a3e9708e | 125 | |
AnaisChaumeil | 2:c177a3e9708e | 126 | emgA=filt_filt0[1]-filt_filt1[1]; |
AnaisChaumeil | 2:c177a3e9708e | 127 | emg_absA[0]=emg_absA[1]; |
AnaisChaumeil | 2:c177a3e9708e | 128 | emg_absA[1]=fabs(emgA); |
AnaisChaumeil | 0:971166224b2d | 129 | |
AnaisChaumeil | 2:c177a3e9708e | 130 | emgB=filt_filt2[1]-filt_filt3[1]; |
AnaisChaumeil | 2:c177a3e9708e | 131 | emg_absB[0]=emg_absB[1]; |
AnaisChaumeil | 2:c177a3e9708e | 132 | emg_absB[1]=fabs(emgB); |
AnaisChaumeil | 0:971166224b2d | 133 | |
AnaisChaumeil | 0:971166224b2d | 134 | |
AnaisChaumeil | 2:c177a3e9708e | 135 | // APPLYING ANOTHER LOW PASS FILTER WITH SUPER LOW CUTOFF FREQUENCY |
AnaisChaumeil | 0:971166224b2d | 136 | |
AnaisChaumeil | 2:c177a3e9708e | 137 | double wcllp=2*pi; // low low pass cutoff frequency |
AnaisChaumeil | 2:c177a3e9708e | 138 | |
AnaisChaumeil | 2:c177a3e9708e | 139 | emg_filtA[0]=(emg_absA[0]+emg_absA[1])/2; // we take the mean of the two first values to initialize the signal |
AnaisChaumeil | 2:c177a3e9708e | 140 | emg_filtB[0]=(emg_absB[0]+emg_absB[1])/2; |
AnaisChaumeil | 0:971166224b2d | 141 | |
AnaisChaumeil | 2:c177a3e9708e | 142 | double k0=(wcllp*T)/(wcllp*T+2); |
AnaisChaumeil | 2:c177a3e9708e | 143 | double k1=(wcllp*T)/(wcllp*T+2); |
AnaisChaumeil | 2:c177a3e9708e | 144 | double l1=(wcllp*T-2)/(wcllp*T+2); |
AnaisChaumeil | 2:c177a3e9708e | 145 | |
AnaisChaumeil | 2:c177a3e9708e | 146 | emg_filtA[0]=emg_filtA[1]; |
AnaisChaumeil | 2:c177a3e9708e | 147 | emg_filtB[0]=emg_filtB[1]; |
AnaisChaumeil | 0:971166224b2d | 148 | |
AnaisChaumeil | 2:c177a3e9708e | 149 | emg_filtA[1]=k0*emg_absA[1]+k1*emg_absA[0]-l1*emg_filtA[0]; |
AnaisChaumeil | 2:c177a3e9708e | 150 | emg_filtB[1]=k0*emg_absB[1]+k1*emg_absB[0]-l1*emg_filtB[0]; |
AnaisChaumeil | 0:971166224b2d | 151 | |
AnaisChaumeil | 3:15eeab5ba885 | 152 | scope.set(1, emg_filtA[1] ); |
AnaisChaumeil | 3:15eeab5ba885 | 153 | scope.send(); |
AnaisChaumeil | 3:15eeab5ba885 | 154 | |
AnaisChaumeil | 0:971166224b2d | 155 | |
AnaisChaumeil | 0:971166224b2d | 156 | int main() |
AnaisChaumeil | 0:971166224b2d | 157 | { |
AnaisChaumeil | 0:971166224b2d | 158 | sampling.attach(&sample, 0.002); |
AnaisChaumeil | 2:c177a3e9708e | 159 | processing.attach(&processing_signals, 0.002); |
AnaisChaumeil | 0:971166224b2d | 160 | |
AnaisChaumeil | 0:971166224b2d | 161 | while (true) |
AnaisChaumeil | 0:971166224b2d | 162 | { |
AnaisChaumeil | 0:971166224b2d | 163 | |
AnaisChaumeil | 0:971166224b2d | 164 | } |
AnaisChaumeil | 0:971166224b2d | 165 | return 0; |
AnaisChaumeil | 0:971166224b2d | 166 | } |