Filter for EMG signals The signal will be filtered using a notch, highpass and lowpass filter. The filtered signal will be compared to a preset threshold and according to the strength of the signal the program will perform an action. In this case it will assign a colour to a led.

Dependencies:   HIDScope MODSERIAL mbed

Fork of EMGfilter24 by Steven Spoolder

main.cpp

Committer:
Iknowright
Date:
2016-10-27
Revision:
4:fcada70891c5
Parent:
3:faed8b7f6542
Child:
5:51a28834cd5b

File content as of revision 4:fcada70891c5:

#include "mbed.h"
#include "BiQuad.h"
#include "HIDScope.h"
#include "MODSERIAL.h"
#include <math.h>

MODSERIAL   pc(USBTX, USBRX);
Ticker      sampleTicker;//Ticker that measures the EMG signal every 0,002 seconds and filters it
Ticker      goTicker; //Ticker that checks if the signal threshold is reached each time a new filtered EMG signal comes in and determines if the motors are going to rotate
AnalogIn    emgl(A1);//Labels are attached to the olimex shields the left tricep should obviously be connected to the should with an L label on it
AnalogIn    emgr(A0);
DigitalOut  ledG(LED_GREEN);
DigitalOut  ledB(LED_BLUE);
DigitalOut  ledR(LED_RED);
HIDScope    scope(2); //scope has two ports for the two EMG signals

/*coefficients of each filter
    lno = left tricep notch filter
    lhf = left tricep high pass filter
    llf = left tricep lowpass filter
    same goes for rno etc.
    */
double lno_b0 = 0.9911;     
double lno_b1 = -1.6036;   
double lno_b2 = 0.9911;    
double lno_a1 = -1.603;    
double lno_a2 = 0.9822;    

double rno_b0 = 0.9911;     
double rno_b1 = -1.6036;   
double rno_b2 = 0.9911;    
double rno_a1 = -1.603;    
double rno_a2 = 0.9822;    


double lhf_b0 = 0.9355;    
double lhf_b1 = -1.8711;   
double lhf_b2 = 0.9355;    
double lhf_a1 = -1.8669;   
double lhf_a2 = 0.8752;   

double rhf_b0 = 0.9355;    
double rhf_b1 = -1.8711;   
double rhf_b2 = 0.9355;    
double rhf_a1 = -1.8669;   
double rhf_a2 = 0.8752;    


double llf_b0 = 8.7656e-5;
double llf_b1 = 1.17531e-4;
double llf_b2 = 8.7656e-5; 
double llf_a1 = -1.9733;  
double llf_a2 = 0.9737;    

double rlf_b0 = 8.7656e-5;
double rlf_b1 = 1.17531e-4;
double rlf_b2 = 8.7656e-5; 
double rlf_a1 = -1.9733;  
double rlf_a2 = 0.9737;    


//starting values of the biquads of the corresponding filters
double lno_v1 = 0, lno_v2 = 0;
double lhf_v1 = 0, lhf_v2 = 0;
double llf_v1 = 0, llf_v2 = 0;

double rno_v1 = 0, rno_v2 = 0;
double rhf_v1 = 0, rhf_v2 = 0;
double rlf_v1 = 0, rlf_v2 = 0;

/* declaration of the outputs of each biquad.
the output of the previous biquad is the input for the next biquad.
so lno_y goes into lhf_y etc.
*/ 
double lno_y;
double lhf_y;
double llf_y;
double lrect_y;
double rno_y;
double rhf_y;
double rlf_y;
double rrect_y;

// set the threshold value for the filtered signal
//if the signal exceeds this value the motors will start to rotate 
const double threshold_value = 0.05;

/* declaration of each biquad
The coefficients will be filled in later on in void scopeSend
As said before the input of each biquad is the output of the previous one 
The input of the first biquad is the raw EMG signal and the output of the last biquad is the filtered signal.
This is done for both left and right so this makes two chains of 3 biquads */

double biquad_lno(double u, double&v1 , double&v2 , const double a1 , const double a2 , const double b0 ,
    const double b1 , const double b2 )
{
    double v = u - a1*v1 - a2*v2;
    double y = b0*v + b1*v1 + b2*v2;
    v2 = v1;
    v1 = v;
    return y;
}

double biquad_lhf(double u, double&v1 , double&v2 , const double a1 , const double a2 , const double b0 ,
    const double b1 , const double b2 )
{
    double v = u - a1*v1 - a2*v2;
    double y = b0*v + b1*v1 + b2*v2;
    v2 = v1;
    v1 = v;
    return y;
}

double biquad_llf(double u, double&v1 , double&v2 , const double a1 , const double a2 , const double b0 ,
    const double b1 , const double b2 )
{
    double v = u - a1*v1 - a2*v2;
    double y = b0*v + b1*v1 + b2*v2;
    v2 = v1;
    v1 = v;
    return y;
}
double biquad_rno(double u, double&v1 , double&v2 , const double a1 , const double a2 , const double b0 ,
    const double b1 , const double b2 )
{
    double v = u - a1*v1 - a2*v2;
    double y = b0*v + b1*v1 + b2*v2;
    v2 = v1;
    v1 = v;
    return y;
}

double biquad_rhf(double u, double&v1 , double&v2 , const double a1 , const double a2 , const double b0 ,
    const double b1 , const double b2 )
{
    double v = u - a1*v1 - a2*v2;
    double y = b0*v + b1*v1 + b2*v2;
    v2 = v1;
    v1 = v;
    return y;
}

double biquad_rlf(double u, double&v1 , double&v2 , const double a1 , const double a2 , const double b0 ,
    const double b1 , const double b2 )
{
    double v = u - a1*v1 - a2*v2;
    double y = b0*v + b1*v1 + b2*v2;
    v2 = v1;
    v1 = v;
    return y;
}

/* function that calculates the filtered EMG signal from the raw EMG signal. 
So 2 chains of 3 biquads each are calculating the left and the right filtered EMG signal.
After this is calculated, the signals are sent to HIDscope (scope.send) to see what they look like.
The filtered left signal (llf_y) is shown in channel 1, the filtered right signal (rlf_y)is shown in channel 0 (scope.set)*/
void scopeSend(void){
    lno_y = biquad_lno(emgl.read(), lno_v1, lno_v2, lno_a1, lno_a2, lno_b0, lno_b1, lno_b2);
    lhf_y = biquad_lhf(lno_y, lhf_v1, lhf_v2, lhf_a1, lhf_a2, lhf_b0, lhf_b1, lhf_b2);
    lrect_y = fabs(lhf_y);
    llf_y = biquad_llf(lrect_y, llf_v1, llf_v2, llf_a1, llf_a2, llf_b0, llf_b1, llf_b2)/0.2;
    rno_y = biquad_rno(emgr.read(), rno_v1, rno_v2, rno_a1, rno_a2, rno_b0, rno_b1, rno_b2);
    rhf_y = biquad_rhf(rno_y, rhf_v1, rhf_v2, rhf_a1, rhf_a2, rhf_b0, rhf_b1, rhf_b2);
    rrect_y = fabs(rhf_y);
    rlf_y = biquad_rlf(rrect_y, rlf_v1, rlf_v2, rlf_a1, rlf_a2, rlf_b0, rlf_b1, rlf_b2)/0.2;  
    scope.set(1, llf_y);
    scope.set(0, rlf_y);
    scope.send();
    
    }
   
   //function that compares the filtered EMG signal to the set threshold and determines what colour the led should be
   //This led is for feedback purposes only and should obviously be replaced by the motors 
void threshold(){
  //If the right signal exceeds the threshold, the led should turn blue  
  if (rlf_y > threshold_value){
        ledB = 0;
        ledR = 1;
        ledG = 1;
        }
    //If the left signal exceeds the threshold, the led should turn red
    else if (llf_y > threshold_value){
            ledB = 1;
            ledR = 0;
            ledG = 1;
            }
    // If both signals exceed the threshold, the led should turn green         
    else if (rlf_y&&llf_y > threshold_value){
            ledB = 1;
            ledR = 1;
            ledG = 0;       
            }
    //If no signal exceeds the threshold, the led should be off
    else {
        ledB=1;
        ledG=1;
        ledR=1;
        }
    }


int main(){
    
    
   
  /*Attach the 'sample' function to the timer 'sample_timer'.
    this ensures that 'sample' is executed every... 0.002 seconds = 500 Hz
    emgSampleTicker.attach(&sample, 0.002);
    empty loop, sample() is executed periodically
    The same goes for the goTicker. It checks if the threshold is reached at the same rate new a new EMG signal comes in*/
    sampleTicker.attach(scopeSend,0.002);
    goTicker.attach(threshold,0.002);
    
    while(1) {
 
}
}