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.
Fork of EMG by
main.cpp@18:e753220c7ba6, 2015-10-19 (annotated)
- Committer:
- AeroKev
- Date:
- Mon Oct 19 11:44:19 2015 +0000
- Revision:
- 18:e753220c7ba6
- Parent:
- 16:9f7797ffd0fb
a; ;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| vsluiter | 0:32bb76391d89 | 1 | #include "mbed.h" |
| vsluiter | 11:ce72ec658a95 | 2 | #include "HIDScope.h" |
| vsluiter | 0:32bb76391d89 | 3 | |
| AeroKev | 18:e753220c7ba6 | 4 | #define MOV_AVG_NUM 100 |
| AeroKev | 18:e753220c7ba6 | 5 | |
| vsluiter | 4:8b298dfada81 | 6 | //Define objects |
| tomlankhorst | 14:f83354387756 | 7 | AnalogIn emg(A0); //Analog input |
| tomlankhorst | 14:f83354387756 | 8 | Ticker sample_timer; |
| AeroKev | 18:e753220c7ba6 | 9 | HIDScope scope(2); |
| AeroKev | 18:e753220c7ba6 | 10 | |
| AeroKev | 18:e753220c7ba6 | 11 | double highV[4]; |
| AeroKev | 18:e753220c7ba6 | 12 | double lowV[4]; |
| AeroKev | 18:e753220c7ba6 | 13 | double lastOutputs[MOV_AVG_NUM-1]; |
| AeroKev | 18:e753220c7ba6 | 14 | |
| AeroKev | 18:e753220c7ba6 | 15 | double filter(double input, double coeff_input[], double coeff_output[], double prev_outputs[]) |
| AeroKev | 18:e753220c7ba6 | 16 | { |
| AeroKev | 18:e753220c7ba6 | 17 | double new_input = input; |
| AeroKev | 18:e753220c7ba6 | 18 | for(int i=1; i<5; i++) |
| AeroKev | 18:e753220c7ba6 | 19 | new_input -= coeff_input[i] * prev_outputs[i-1]; |
| AeroKev | 18:e753220c7ba6 | 20 | |
| AeroKev | 18:e753220c7ba6 | 21 | double new_output = coeff_output[0] * new_input; |
| AeroKev | 18:e753220c7ba6 | 22 | for(int i=1; i<5; i++) |
| AeroKev | 18:e753220c7ba6 | 23 | new_output += coeff_output[i] * prev_outputs[i-1]; |
| AeroKev | 18:e753220c7ba6 | 24 | |
| AeroKev | 18:e753220c7ba6 | 25 | // Set the new output as the first value of the 'recent outputs' |
| AeroKev | 18:e753220c7ba6 | 26 | for(int i = 3; i > 0; i--) |
| AeroKev | 18:e753220c7ba6 | 27 | prev_outputs[i] = prev_outputs[i-1]; |
| AeroKev | 18:e753220c7ba6 | 28 | prev_outputs[0] = new_input; |
| AeroKev | 18:e753220c7ba6 | 29 | return new_output; |
| AeroKev | 18:e753220c7ba6 | 30 | } |
| AeroKev | 18:e753220c7ba6 | 31 | |
| AeroKev | 18:e753220c7ba6 | 32 | double fh_b[]= {0.7602, -3.0406, 4.5609, -3.0406, 0.7602}; |
| AeroKev | 18:e753220c7ba6 | 33 | double fh_a[]= {1, -3.4532, 4.5041, -2.6273, 0.5778}; |
| AeroKev | 18:e753220c7ba6 | 34 | double highpass_filter(double u) |
| AeroKev | 18:e753220c7ba6 | 35 | { |
| AeroKev | 18:e753220c7ba6 | 36 | return filter(u, fh_a, fh_b, highV); |
| AeroKev | 18:e753220c7ba6 | 37 | } |
| AeroKev | 18:e753220c7ba6 | 38 | |
| AeroKev | 18:e753220c7ba6 | 39 | double fl_b[]= {0.00000658, 0.00002631, 0.00003947, 0.00002631, 0.00000658}; |
| AeroKev | 18:e753220c7ba6 | 40 | double fl_a[]= {1.0000, -3.7264, 5.2160, -3.2500, 0.7605}; |
| AeroKev | 18:e753220c7ba6 | 41 | double lowpass_filter(double u) |
| AeroKev | 18:e753220c7ba6 | 42 | { |
| AeroKev | 18:e753220c7ba6 | 43 | return filter(u, fl_a, fl_b, lowV); |
| AeroKev | 18:e753220c7ba6 | 44 | } |
| vsluiter | 2:e314bb3b2d99 | 45 | |
| tomlankhorst | 14:f83354387756 | 46 | /** Sample function |
| tomlankhorst | 14:f83354387756 | 47 | * this function samples the emg and sends it to HIDScope |
| tomlankhorst | 14:f83354387756 | 48 | **/ |
| tomlankhorst | 14:f83354387756 | 49 | void sample() |
| vsluiter | 2:e314bb3b2d99 | 50 | { |
| AeroKev | 18:e753220c7ba6 | 51 | double input = emg.read(); |
| AeroKev | 18:e753220c7ba6 | 52 | double output1 = highpass_filter(input); |
| AeroKev | 18:e753220c7ba6 | 53 | double output2 = fabs(output1); |
| AeroKev | 18:e753220c7ba6 | 54 | double output3 = lowpass_filter(output2); |
| AeroKev | 18:e753220c7ba6 | 55 | |
| AeroKev | 18:e753220c7ba6 | 56 | double tot = output3; |
| AeroKev | 18:e753220c7ba6 | 57 | for(int i=0; i<MOV_AVG_NUM-1; i++) { |
| AeroKev | 18:e753220c7ba6 | 58 | tot += lastOutputs[i]; |
| AeroKev | 18:e753220c7ba6 | 59 | if(i != 0) lastOutputs[i] = lastOutputs[i-1]; |
| AeroKev | 18:e753220c7ba6 | 60 | } |
| AeroKev | 18:e753220c7ba6 | 61 | lastOutputs[0] = output3; |
| AeroKev | 18:e753220c7ba6 | 62 | output3 = tot/MOV_AVG_NUM; |
| AeroKev | 18:e753220c7ba6 | 63 | |
| tomlankhorst | 14:f83354387756 | 64 | /* Second, set the sampled emg value in channel zero (the first channel) in the 'HIDScope' variable named 'scope' */ |
| AeroKev | 18:e753220c7ba6 | 65 | scope.set(0,input); |
| AeroKev | 18:e753220c7ba6 | 66 | scope.set(1,output3); |
| tomlankhorst | 16:9f7797ffd0fb | 67 | /* Repeat the step above if required for more channels (channel 0 up to 5 = 6 channels) */ |
| tomlankhorst | 14:f83354387756 | 68 | /* Finally, send all channels to the PC at once */ |
| vsluiter | 11:ce72ec658a95 | 69 | scope.send(); |
| vsluiter | 2:e314bb3b2d99 | 70 | } |
| vsluiter | 0:32bb76391d89 | 71 | |
| vsluiter | 0:32bb76391d89 | 72 | int main() |
| vsluiter | 0:32bb76391d89 | 73 | { |
| tomlankhorst | 14:f83354387756 | 74 | /**Attach the 'sample' function to the timer 'sample_timer'. |
| tomlankhorst | 14:f83354387756 | 75 | * this ensures that 'sample' is executed every... 0.002 seconds |
| vsluiter | 4:8b298dfada81 | 76 | */ |
| tomlankhorst | 14:f83354387756 | 77 | sample_timer.attach(&sample, 0.002); |
| tomlankhorst | 15:0da764eea774 | 78 | |
| tomlankhorst | 14:f83354387756 | 79 | /*empty loop, sample() is executed periodically*/ |
| tomlankhorst | 15:0da764eea774 | 80 | while(1) {} |
| vsluiter | 0:32bb76391d89 | 81 | } |
