EMG filtering; highpass, notch, abs, moving average

Dependencies:   HIDScope MODSERIAL- mbed-dsp mbed

Project_main.cpp

Committer:
Hooglugt
Date:
2014-10-22
Revision:
42:f45e4dfbc26d
Parent:
41:245f33fb2b8b

File content as of revision 42:f45e4dfbc26d:

#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(&notch, &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(&notch, &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(&notch, 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)
    }

}