EMG filtering; highpass, notch, abs, moving average
Dependencies: HIDScope MODSERIAL- mbed-dsp mbed
Project_main.cpp
- Committer:
- Hooglugt
- Date:
- 2014-10-20
- Revision:
- 41:245f33fb2b8b
- Parent:
- 40:7e93c2f1c1e9
File content as of revision 41:245f33fb2b8b:
#include "mbed.h" #include "MODSERIAL.h" #include "HIDScope.h" #include "arm_math.h" #define TIMEB4NEXTCHOICE 1 // sec keuzelampje blijft aan #define TIMEBETWEENBLINK 20 // sec voor volgende blink //Define objects AnalogIn emg0(PTB1); //Analog input biceps float filemg_bifloat; //filtered emg-waarde biceps AnalogIn emg1(PTB2); //Analog input triceps float filemg_trifloat; //filtered emg-waarde triceps Ticker log_timer; Ticker reset_timer; MODSERIAL pc(USBTX,USBRX); HIDScope scope(2); arm_biquad_casd_df1_inst_f32 highpass; float highpass_const[] = {0.8751821104711265, -1.750364220942253, 0.8751821104711265, 1.7347238224240125 , -0.7660046194604936}; //highpass, Fc: 15 Hz, Fsample: 500Hz, Q = 0.7071 float highpass_states[4]; arm_biquad_casd_df1_inst_f32 notch; float notch_const[] = {0.9714498065192796, -1.5718388053127037, 0.9714498065192796, 1.5718388053127037 , -0.9428996130385592}; //notch, Fc: 50 Hz, Fsample: 500Hz, Q = 10 float notch_states[4]; // variables for biceps MAF float y0 = 0; float y1 = 0; float y2 = 0; float y3 = 0; float y4 = 0; float y5 = 0; float y6 = 0; float y7 = 0; float y8 = 0; float y9 = 0; // variables for triceps MAF float x0 = 0; float x1 = 0; float x2 = 0; float x3 = 0; float x4 = 0; float x5 = 0; float x6 = 0; float x7 = 0; float x8 = 0; float x9 = 0; PwmOut red(LED_RED); PwmOut green(LED_GREEN); PwmOut blue(LED_BLUE); uint8_t direction = 0; uint8_t force = 0; void looper() { //put raw emg value of biceps and triceps in emg_bifloat and emg_trifloat, respectively float emg_bifloat; //Float voor EMG-waarde biceps float emg_trifloat; //Float voor EMG-waarde triceps emg_bifloat = emg0.read(); // read float value (0..1 = 0..3.3V) biceps emg_trifloat = emg1.read(); // read float value (0..1 = 0..3.3V) triceps //process emg biceps arm_biquad_cascade_df1_f32(&highpass, &emg_bifloat, &filemg_bifloat, 1 ); arm_biquad_cascade_df1_f32(¬ch, &emg_bifloat, &filemg_bifloat, 1 ); y0 = fabs(filemg_bifloat); float bi_result = y0*0.1 +y1*0.1 + y2*0.1 + y3*0.1 + y4*0.1 + y5*0.1 + y6*0.1 + y7*0.1 + y8*0.1 + y9*0.1; y9=y8; y8=y7; y7=y6; y6=y5; y5=y4; y4=y3; y3=y2; y2=y1; y1=y0; //process emg triceps arm_biquad_cascade_df1_f32(&highpass, &emg_trifloat, &filemg_trifloat, 1 ); arm_biquad_cascade_df1_f32(¬ch, &emg_trifloat, &filemg_trifloat, 1 ); x0 = fabs(filemg_trifloat); float tri_result = x0*0.1 +x1*0.1 + x2*0.1 + x3*0.1 + x4*0.1 + x5*0.1 + x6*0.1 + x7*0.1 + x8*0.1 + x9*0.1; x9=x8; x8=x7; x7=x6; x6=x5; x5=x4; x4=x3; x3=x2; x2=x1; x1=x0; /*send value to PC. Line below is used to prevent buffer overrun */ if(pc.rxBufferGetSize(0)-pc.rxBufferGetCount() > 30) { scope.set(0,bi_result); scope.set(1,tri_result); scope.send(); } } /* void resetlooper() // VRAAG: wat gebeurt er wanneer en resetlooper en looper tegelijkertijd gecalled worden?! { if(filemg_trifloat.read()>0.8 && direction != 0) { //dit is alleen mogelijk wanneer directionchoice is gemaakt direction = 0; force = 0; // WEGHALEN, wanneer in uiteindelijke script na force keuzen niet meer gereset kan worden (voor nu wel handig) pc.printf("reset "); } } */ int main() { pc.baud(115200); //baudrate instellen log_timer.attach(looper, 0.002); // The looper() function will be called every 0.002 seconds (with the ticker object) //set up filters arm_biquad_cascade_df1_init_f32(¬ch, 1, notch_const, notch_states); arm_biquad_cascade_df1_init_f32(&highpass, 1, highpass_const, highpass_states); // reset_timer.attach(resetlooper, 0.1); // goto directionchoice; // goes to first while(1) for the deciding the direction while(1) { //Loop keuze DIRECTION directionchoice: for(int i=1; i<4; i++) { if(i==1) { //red red=0; green=1; blue=1; for (int lag=0; lag<TIMEBETWEENBLINK; lag++) { if(filemg_bifloat>0.8) { // 0.8 klopt niet als grenswaarde. #nofilter direction = 1; red=1; green = 0; blue = 0; pc.printf("links "); wait(TIMEB4NEXTCHOICE); // Tijdelijke wait om cyaan lampje aan te zetten ter controle selectie goto forcechoice; // goes to second while(1) for the deciding the force } else { wait(0.1); } } } if(i==2) { //green red =1; green=0; blue=1; for (int lag=0; lag<TIMEBETWEENBLINK; lag++) { if(filemg_bifloat>0.8) { //0.8 klopt niet als grenswaarde. #nofilter direction = 2; red=0; green = 1; blue = 0; pc.printf("mid "); wait(TIMEB4NEXTCHOICE); // Tijdelijke wait om paars lampje aan te zetten ter controle selectie goto forcechoice; } else { wait(0.1); } } } if(i==3) { //blue red=1; green=1; blue=0; for (int lag=0; lag<TIMEBETWEENBLINK; lag++) { if(filemg_bifloat>0.8) { //0.8 klopt niet als grenswaarde. #nofilter direction = 3; red=0; green = 0; blue = 1; pc.printf("rechts "); wait(TIMEB4NEXTCHOICE); // Tijdelijke wait om oranje lampje aan te zetten ter controle selectie goto forcechoice; } else { wait(0.1); } } } } } while(1) { //Loop keuze FORCE forcechoice: for(int j=1; j<4; j++) { if(j==1) { //red red=0; green=1; blue=1; if(direction==0) { //if statement die controleert of direction 0 is (dus of triceps gereset is) goto directionchoice; } for (int lag=0; lag<TIMEBETWEENBLINK; lag++) { if(filemg_bifloat>0.8) { // 0.8 klopt niet als grenswaarde. #nofilter force = 1; red=1; green = 0; blue = 0; pc.printf("zwak "); wait(TIMEB4NEXTCHOICE); // Tijdelijke wait om cyaan lampje aan te zetten ter controle selectie goto choicesmade; } else { wait(0.1); } } } if(j==2) { //green red =1; green=0; blue=1; if(direction==0) { //if statement die controleert of direction 0 is (dus of triceps gereset is) goto directionchoice; } for (int lag=0; lag<TIMEBETWEENBLINK; lag++) { if(filemg_bifloat>0.8) { //0.8 klopt niet als grenswaarde. #nofilter force = 2; red=0; green = 1; blue = 0; pc.printf("normaal "); wait(TIMEB4NEXTCHOICE); // Tijdelijke wait om paars lampje aan te zetten ter controle selectie goto choicesmade; } else { wait(0.1); } } } if(j==3) { //blue red=1; green=1; blue=0; if(direction==0) { //if statement die controleert of direction 0 is (dus of triceps gereset is) goto directionchoice; } for (int lag=0; lag<TIMEBETWEENBLINK; lag++) { if(filemg_bifloat>0.8) { //0.8 klopt niet als grenswaarde. #nofilter force = 3; red=0; green = 0; blue = 1; pc.printf("sterk "); wait(TIMEB4NEXTCHOICE); // Tijdelijke wait om oranje lampje aan te zetten ter controle selectie goto choicesmade; } else { wait(0.1); } } } } } choicesmade: red = 0; green = 0; blue = 0; // wit lampje /* Vanaf hier komt de aansturing van de motor (inclusief de controller)*/ if(direction == 1 && force == 1) { // links zwak pc.printf("links zwak "); wait(2); } if(direction == 1 && force == 2) { // links normaal pc.printf("links normaal "); } if(direction == 1 && force == 3) { // links sterk pc.printf("links sterk "); } if(direction == 2 && force == 1) { // mid zwak pc.printf("mid zwak "); } if(direction == 2 && force == 2) { // mid normaal pc.printf("mid normaal "); } if(direction == 2 && force == 3) { // mid sterk pc.printf("mid sterk "); } if(direction == 3 && force == 1) { // rechts zwak pc.printf("rechts zwak "); } if(direction == 3 && force == 2) { // rechts normaal pc.printf("rechts normaal "); } if(direction == 3 && force == 3) { // rechts sterk pc.printf("rechts sterk "); } if(direction == 0 || force == 0) { // wanneer de triceps in de korte tijd is aangespannen nadat beide keuzes zijn gemaakt pc.printf("error "); // mogelijkheid om een goto te maken naar directionchoice (opzich wel handig) } }