Emg filter function script for a uni project. Made by Teun van der Molen

Dependencies:   HIDScope MODSERIAL mbed

Fork of frdm_EMG by Teun van der Molen

main.cpp

Committer:
teunman
Date:
2015-10-19
Revision:
11:d8dd024f9784
Parent:
10:b11eacb391ea

File content as of revision 11:d8dd024f9784:

#include "mbed.h"
#include "HIDScope.h"
#include "math.h" 
// Define the HIDScope and Ticker object
HIDScope    scope(4);

Ticker      scopeTimer;
Ticker      FilterTicker;


///////////////////////////////////////////////////MBED PORTS////////////////////////////////////////////////////////////////////

DigitalOut  light(LED2);
DigitalIn    knop(SW3);
AnalogIn    an_in(A0);  //The input from the emg board, make sure that the jumper pin on the EMG board corresponds with the value in the brackets here!!! (see bb pptx for details on jumper placement, default is A0)


/////////////////////////////////////////FILTER VALUES///////////////////////////////////////////////////////////////////////////////////

const float lag = 2500;                 //NO. of data points for moving average filter
      float values [2500] = { };          // The array that stores the values for Movavg !!!!! the value between "[]" MUST BE THE SAME AS LAG!!!!!!!!! (needs to be a numerical value so can't fill in lag here :(
      int n_avg = 0;                    // Counter for movavg
      float y_avg = 0;                  // value for movavg
      
      double ffy = 0;                   //movavg filterd output

double c = 5; //calibration value (in volts)
double n = 0; // counter for calibration
bool calib = false; //changes into false when calibration is done (reset program for new calibration); 
double v1=0, v2=0, u=0, y=0,     fy=0, fv1=0, fv2=0, fu=0,     ny=0, nv1=0, nv2=0, nu=0;;


//Notch filter  (n stand for notch filter (this is in fact the very first filter but is rarely changed) to alter this filter add "n" to all coefficents example: nb0,nb1 etc.)
const double nb0 = 0.8206743576788857,nb1 = -1.5610153912536877,nb2 = 0.8206743576788857,na1 = -1.5610153912536877,na2 = 0.6413487153577715; //Notch filter  Fc = 50 Hz  Fs 1000Hz


// 100 Hz filters (obsolete)

//const double b0 = 0.9999999999999999,b1 = 1.9999999999999998,b2 = 0.9999999999999999, a1 = 1.9999999999999998 ,a2 = 0.9999999999999998; //low-pass Fc = 50hz fs = 100hz
//const double fb0 = 0.02008333102602092 ,fb1 = 0.04016666205204184 ,fb2 = 0.02008333102602092, fa1 = -1.5610153912536877 ,fa2 = 0.6413487153577715; //low-pass Fc = 5hz fs = 100hz
//const double b0 = 0.8005910266528649,b1 = -1.6011820533057297,b2 = 0.8005910266528649,a1 = -1.5610153912536877,a2 = 0.6413487153577715; //high-pass Fc = 5hz fs = 100hz
//const double b0 = 0.007820199259120319,b1 = 0.015640398518240638,b2 = 0.007820199259120319,a1 = -1.7347238224240125,a2 = 0.7660046194604936; //low-pass Fc = 3hz fs = 100hz
//const double b0 = 0.0009446914586925257,b1 = 0.0018893829173850514,b2 = 0.0009446914586925257,a1 = -1.911196288237583,a2 = 0.914975054072353; //low-pass Fc = 1hz fs = 100hz
//const double b0 = 0.956542835577484, b1 = -1.913085671154968, b2 = 0.956542835577484, a1 = -1.911196288237583, a2 = 0.914975054072353; //high-pass Fc  =  1hz fs = 100hz



// 1000 Hz filters (f stands for the seccond filter, so make sure the first coefiecients are b0,b1 etc. and the seccond filter is  fb0,fb1,fb2 etc.)

//const double b0 = 0.00008765553769759188,b1 = 0.00017531107539518376,b2 = 0.00008765553769759188,a1 = -1.9733440008737442,a2 = 0.9736946230245347;//low-pass Fc = 3Hz fs = 1000hz
const double fb0 = 0.00034604125149151127,fb1 = 0.0006920825029830225, fb2 = 0.00034604125149151127 ,fa1 = -1.9466970561224466 ,fa2 = 0.9480812211284125; //low-pass Fc = 6Hz fs = 1000hz
//const double fb0 = 0.9149684297741606, fb1 = -1.8299368595483212, fb2 = 0.9149684297741606 ,fa1 = -1.8226935021735358, fa2 = 0.8371802169231065; // High-pass Fc = 20Hz fs = 1000hz
//const double fb0 = 0.8948577513857248 ,fb1 = -1.7897155027714495, fb2 = 0.8948577513857248,fa1 = -1.7786300789392977,fa2 = 0.8008009266036016; // High-pass Fc = 25Hz fs = 1000Hz
//const double b0 = 0.005542711916075981,b1 = 0.011085423832151962,b2 = 0.005542711916075981,a1 = -1.7786300789392977,a2 = 0.8008009266036016; //Low-pass Fc = 25Hz fs=1000Hz
//const double fb0 = 0.9780302754084559,fb1 = -1.9560605508169118,fb2 = 0.9780302754084559,fa1 = -1.9555778328194147,fa2 = 0.9565432688144089; //high-pass Fc = 6hz fs = 1000hz
const double b0 = 0.9911535113858849,b1 = -1.9823070227717698,b2 = 0.9911535113858849,a1 = -1.9822287623675816,a2 = 0.982385283175958; //High-pass Fc = 2Hz fs = 1000Hz
//const double fb0 = 0.0036216786873927774,fb1 = 0.007243357374785555,fb2 = 0.0036216786873927774,fa1 = -1.8226935021735358,fa2 = 0.8371802169231065; ///Low-pass Fc = 20 Hz Fs = 1000Hz


////////////////////////////////////////////////////////////////////HID SCOPE FUNCTION//////////////////////////////////////////////////////////////////////////////



// The data read and send function for HIDscope (can send any value to the HIDscope for read out)
void scopeSend()
{
    scope.set(0,an_in);
    scope.set(1,fy);
    scope.set(2,ffy);
    scope.set(3,c);
    scope.send();
    
 
        
        
}
 
 
 ///////////////////////////////////////////////////////////////////////FILTER CASCADE////////////////////////////////////////////////////////////////////////
 
 void computeBiquad(){  //The filter function (is called at the same frequency of the scope function (not sure if timing is fully correct here) and does the filter calculations)
   
   double nv = an_in - na1*nv1 - na2*nv2;   //notch filter at 50Hz for laptop adapter           ny is the filtered output
    ny= nb0*nv + nb1*nv1 +nb2*nv2;
    nv2=nv1;
    nv1=nv;
     
    double v = ny - a1*v1 - a2*v2;          //First filter (see filters to check values)        y is the filtered output
    y= b0*v + b1*v1 +b2*v2;
    v2=v1;
    v1=v;
     
       y = abs(y);                          //Rectifier                                         y is the rectified output
     
     
     double fv = y - fa1*fv1 - fa2*fv2;     //Second Filter (see filters to check values)       fy is the filtered output
    fy= fb0*fv + fb1*fv1 + fb2*fv2;
    fv2=fv1;
    fv1=fv;
    
    //fy = abs(fy);                         //Optional final rectifier (default should be off)           
    
    values [n_avg] = fy;                 //Moving Average filter (see filters to check lag etc.)
         n_avg = n_avg + 1;
     
     if (n_avg == lag){
          
         for (int n_divide = 0 ;n_divide <= lag; n_divide = n_divide + 1){
             y_avg = y_avg + values [n_divide];
            
             }
             
             n_avg = 0;
             ffy = y_avg/lag;
             y_avg = 0;
         }
    
    
    
}  //end compute biquad
 
 
 

 
 ////////////////////////////////////////////////////////////////////////MAIN FUNCTION/////////////////////////////////////////////////////////////
 
 
int main()
{
        light = 1; //Light is off by default
    
    
    /////////////////////////////////////////////////////////////////TICKERS///////////////////////////////////////////////////////////////////////
    
    // Attach the data read and send function at 1000 Hz
    scopeTimer.attach_us(&scopeSend, 1e5);   
    // Attach the filter calculation function at 1000 Hz
    FilterTicker.attach(&computeBiquad,0.0001f);
     
     
     
    while(1) {  //the everlasting while loop
    
    
    /////////////////////////////////////////////////////CALIBRATION AND TRIGGER ////////////////////////////////////////////
    
            if (ffy >=  c and calib == false){    //if there is no calibration going on and the filtered emg is above calibration the light goes on
                light = 0;
                }
        
      
            else if (knop == 0){     //pressing the button starts calibration
                
                c = 0;
                n = 0;
                light = 0;      //light is on during calibration
                calib = true;
                    
                       for(;calib == true and n <= 20.00; n = n + 1) {      //this loop ads the calibration value from the output of the filter, this also decides the time of calibration (see wait in combination with the n maximum)
        
                            c = (c + ffy);                 
                            wait(0.1);
        
                        }//end for 
        
          
          
          light = 1;        // light is off for a while after calibration
          calib = false;    // shuts of calibration
          c = (c/n) * 0.3;          //take the average of the emg output during calibration and set the calibration value
        
          
          wait(5);           // you can only calibrate every this amount of seconds
         } //end else if
             
      else{
            light = 1; //light stays off by default
            }
            
            
    } //END while
}//END main