Jitse Giesen / Mbed 2 deprecated master

Dependencies:   biquadFilter mbed MODSERIAL

main.cpp

Committer:
Jitse_Giesen
Date:
2017-11-06
Revision:
15:3a09783b2406
Parent:
14:df5822cd0198
Child:
16:cd11083c754a

File content as of revision 15:3a09783b2406:

#include "mbed.h"
#include "math.h"
#include "QEI.h"
#include "BiQuad.h"
#include "MODSERIAL.h"

MODSERIAL       pc(USBTX, USBRX);

//Defining all in- and outputs
//EMG input
AnalogIn        emgBR( A0 );    //Right Biceps
AnalogIn        emgBL( A1 );    //Left Biceps

//Output motor 1 and reading Encoder motor 1
DigitalOut      motor1DirectionPin(D4);
PwmOut          motor1MagnitudePin(D5);
QEI             Encoder1(D12,D13,NC,32);

//Output motor 2 and reading Encoder motor 2
DigitalOut      motor2DirectionPin(D7);
PwmOut          motor2MagnitudePin(D6);
QEI             Encoder2(D10,D11,NC,32);

//Output motor 3 and reading Encoder motor 3
DigitalOut      motor3DirectionPin(D8);
PwmOut          motor3MagnitudePin(D9);
QEI             Encoder3(D2,D3,NC,32);

//LED output, needed for feedback
DigitalOut      led_R(LED_RED);
DigitalOut      led_G(LED_GREEN);
DigitalOut      led_B(LED_BLUE);

//Setting Tickers for sampling EMG and determing if the threshold is met
Ticker          sample_timer;
Ticker          threshold_timerR;
Ticker          threshold_timerL;

//Timer needed to determine the threshold for a pre-set time period
Timer           t_thresholdR;
Timer           t_thresholdL;

//Variables to store the current time in
float           currentTimeTR;
float           currentTimeTL;

//This is used when testing without EMG
InterruptIn     button(SW2); 
InterruptIn     button2(SW3);

//Timer needed for timing EMG input for the X and Y coördinates
Timer           t;

// Boolean needed to know if new input coordinates have to be given
bool            Move_done = false;
bool            Input_done = true;

/* Defining all the different BiQuad filters, which contain a Notch filter,
High-pass filter and Low-pass filter. The Notch filter cancels all frequencies
between 49 and 51 Hz, the High-pass filter cancels all frequencies below 20 Hz
and the Low-pass filter cancels out all frequencies below 4 Hz. The filters are
declared four times, so that they can be used for sampling of right and left
biceps, during measurements and calibration. */

/* Defining all the normalized values of b and a in the Notch filter for the
creation of the Notch BiQuad */

BiQuad          bqNotch1( 0.9876, -1.5981, 0.9876, -1.5981, 0.9752 );
BiQuad          bqNotch2( 0.9876, -1.5981, 0.9876, -1.5981, 0.9752 );

BiQuad          bqNotchTR( 0.9876, -1.5981, 0.9876, -1.5981, 0.9752 );
BiQuad          bqNotchTL( 0.9876, -1.5981, 0.9876, -1.5981, 0.9752 );

/* Defining all the normalized values of b and a in the High-pass filter for the
creation of the High-pass BiQuad */

BiQuad          bqHigh1( 0.8371, -1.6742, 0.8371, -1.6475, 0.7009 );
BiQuad          bqHigh2( 0.8371, -1.6742, 0.8371, -1.6475, 0.7009 );

BiQuad          bqHighTR( 0.8371, -1.6742, 0.8371, -1.6475, 0.7009 );
BiQuad          bqHighTL( 0.8371, -1.6742, 0.8371, -1.6475, 0.7009 );

/* Defining all the normalized values of b and a in the Low-pass filter for the
creation of the Low-pass BiQuad */

BiQuad          bqLow1( 6.0985e-4, 0.0012, 6.0985e-4, -1.9289, 0.9314 );
BiQuad          bqLow2( 6.0985e-4, 0.0012, 6.0985e-4, -1.9289, 0.9314 );

BiQuad          bqLowTR( 6.0985e-4, 0.0012, 6.0985e-4, -1.9289, 0.9314 );
BiQuad          bqLowTL( 6.0985e-4, 0.0012, 6.0985e-4, -1.9289, 0.9314 );

// Creating a variable needed for the creation of the BiQuadChain
BiQuadChain     bqChain1;
BiQuadChain     bqChain2;

BiQuadChain     bqChainTR;
BiQuadChain     bqChainTL;

//Declaring all floats needed in the filtering process
float          emgBRfiltered;   //Right biceps Notch+High pass filter
float          emgBRrectified;  //Right biceps rectified
float          emgBRcomplete;   //Right biceps low-pass filter, filtering complete

float          emgBLfiltered;   //Left biceps Notch+High pass filter
float          emgBLrectified;  //Left biceps rectified
float          emgBLcomplete;   //Left biceps low-pass filter, filtering complete

// Declaring all variables needed for getting the Threshold value
float          numsamples = 500;
float          emgBRsum = 0;
float          emgBRmeanMVC;
float          thresholdBR;

float          emgBLsum = 0;
float          emgBLmeanMVC;
float          thresholdBL;

/* Function to sample the EMG of the Right Biceps and get a Threshold value
from it, which can be used throughout the process */

void Threshold_samplingBR()
{
    t_thresholdR.start();
    currentTimeTR = t_thresholdR.read();


    if (currentTimeTR <= 1) {

        emgBRfiltered = bqChainTR.step( emgBR.read() );   //Notch+High-pass
        emgBRrectified = fabs(emgBRfiltered);            //Rectification
        emgBRcomplete = bqLowTR.step(emgBRrectified);     //Low-pass

        emgBRsum = emgBRsum + emgBRcomplete;
    }
    emgBRmeanMVC = emgBRsum/numsamples;
    thresholdBR = emgBRmeanMVC * 0.20;


    //pc.printf("ThresholdBR = %f \n", thresholdBR);
}
/* Function to sample the EMG of the Left Biceps and get a Threshold value
from it, which can be used throughout the process */

void Threshold_samplingBL()
{
    t_thresholdL.start();
    currentTimeTL = t_thresholdL.read();

    if (currentTimeTL <= 1) {

        emgBLfiltered = bqChain2.step( emgBL.read() );    //Notch+High-pass
        emgBLrectified = fabs( emgBLfiltered );           //Rectification
        emgBLcomplete = bqLow2.step( emgBLrectified );    //Low-pass

        emgBLsum = emgBLsum + emgBLcomplete;
    }

    emgBLmeanMVC = emgBLsum/numsamples;
    thresholdBL = emgBLmeanMVC * 0.20;
    
}

// EMG sampling and filtering

void EMG_sample()
{

    //Filtering steps for the Right Biceps EMG
    emgBRfiltered = bqChain1.step( emgBR.read() );   //Notch+High-pass
    emgBRrectified = fabs(emgBRfiltered);            //Rectification
    emgBRcomplete = bqLow1.step(emgBRrectified);     //Low-pass

    //Filtering steps for the Left Biceps EMG
    emgBLfiltered = bqChain2.step( emgBL.read() );    //Notch+High-pass
    emgBLrectified = fabs( emgBLfiltered );           //Rectification
    emgBLcomplete = bqLow2.step( emgBLrectified );    //Low-pass

}
// Function to make the BiQuadChain for the Notch and High pass filter for all three filters
void getbqChain()
{
    bqChain1.add(&bqNotch1).add(&bqHigh1);                 //Making the BiQuadChain
    bqChain2.add(&bqNotch2).add(&bqHigh2);

    bqChainTR.add(&bqNotchTR).add(&bqHighTR);
    bqChainTL.add(&bqNotchTR).add(&bqHighTL);
}

// Initial input value for couting the X-values
int Xin=0   ;
int Xin_new;
float huidigetijdX;

// Feedback system for counting values of X
void ledtX()
{
    t.reset();
    Xin++;
    pc.printf("Xin is %i\n",Xin);
    led_G=0;
    led_R=1;
    wait(0.2);
    led_G=1;
    led_R=0;
    wait(0.5);
}

// Couting system for values of X
int tellerX()
{
    if (Move_done == true) {
        t.reset();
        led_G=1;
        led_B=1;
        led_R=0;
        while(true) {
            //button.fall(ledtX);   // this can be used for testing without EMG
            if (emgBRcomplete > thresholdBR) {
                ledtX();
            }
            t.start();
            huidigetijdX=t.read();
            if (huidigetijdX>2) {
                led_R=1;                //Go to the next program (counting values for Y)
                Xin_new = Xin;
                Xin = 0;

                return Xin_new;
            }

        }

    }
    return 0;
}

// Initial values needed for Y (see comments at X function)
int Yin=0;
int Yin_new;
float huidigetijdY;

//Feedback system for couting values of Y
void ledtY()
{
    t.reset();
    Yin++;
    pc.printf("Yin is %i\n",Yin);
    led_G=0;
    led_B=1;
    wait(0.2);
    led_G=1;
    led_B=0;
    wait(0.5);
}

// Couting system for values of Y
int tellerY()
{
    if (Move_done == true) {
        t.reset();
        led_G=1;
        led_B=0;
        led_R=1;
        while(true) {
            //button.fall(ledtY);   // this can be used for testing without EMG
            if (emgBRcomplete > thresholdBR) {
                ledtY();
            }
            t.start();
            huidigetijdY=t.read();
            if (huidigetijdY>2) {
                led_B=1;
                Yin_new = Yin;
                Yin = 0;
                Input_done = true;
                Move_done = false;
                return Yin_new;

            }
        }
    }
    return 0;      // ga door naar het volgende programma
}

// Declaring all variables needed for calculating rope lengths,
/* The following six floats were found using our SOLIDWORKS model*/
float          Pox = 0;
float          Poy = 0;
float          Pbx = 0;
float          Pby = 887;
float          Prx = 768;
float          Pry = 443;
/* The end-effector is manually placed in this (see beneath) position*/
float          Pex=91;          //initial value choosen for calibration
float          Pey=278;         //initial value choosen for calibration
float          diamtrklosje=20;
float          pi=3.14159265359;    //M_PI didn't work for some reason
float          omtrekklosje=diamtrklosje*pi;
float          Lou;
float          Lbu;
float          Lru;
float          dLod;
float          dLbd;
float          dLrd;

// Declaring variables needed for calculating motor counts
float          roto;
float          rotb;
float          rotr;
float          rotzo;
float          rotzb;
float          rotzr;
float          counto;
float          countb;
float          countr;
float          countzo;
float          countzb;
float          countzr;
int reference_o;
int position_o;
int error_o;
int reference_b;
int position_b;
int error_b;
int reference_r;
int position_r;
int error_r;

// Declaring variables neeeded for calculating motor movements to get to a certain point        <- klopt dit?
float          hcounto;
float          hcountb;
float          hcountr;
float          Psx;
float          Psy;
float          Vex;
float          Vey;
float          Pstx;
float          Psty;
float          T=0.02;//seconds

float          kpo = 21;
float          kpb = 21;
float          kpr = 21;

float          motorValue1;
float          motorValue2;
float          motorValue3;

Ticker          controlmotor1; // één ticker van maken?
Ticker          controlmotor2; // één ticker van maken?
Ticker          controlmotor3; // één ticker van maken?

//Deel om motor(en) aan te sturen--------------------------------------------
// start Motor 1 ------------------------------------------------------------
float P1(int error_o, float kpo)
{
    return error_o*kpo;
}

void MotorController1()
{
    reference_o = (int) (counto-hcounto);
    position_o = Encoder1.getPulses();
    error_o = reference_o - position_o;

    if (-20<error_o && error_o<20) {
        motorValue1 = 0;
    } else {
        motorValue1 = P1(error_o, kpo)/4200;
    }
/*differs from the other to due to the motor being on the opposite side of the pillar*/
    if (motorValue1 >=0) motor1DirectionPin=0;       
    else motor1DirectionPin=1;
    if (fabs(motorValue1)>1) motor1MagnitudePin = 1;
    else motor1MagnitudePin = fabs(motorValue1);
}
// end Motor 1 --------------------------------------------------------------
// start Motor 2 ------------------------------------------------------------
float P2(int error_b, float kpb)
{
    return error_b*kpb;
}

void MotorController2()
{

    reference_b = (int) (-(countb-hcountb));
    position_b = Encoder2.getPulses();
    error_b = reference_b - position_b;
    
    if (-20<error_b && error_b<20) {
        motorValue2 = 0;
    } else {
        motorValue2 = P2(error_b, kpb)/4200;
    }

    if (motorValue2 <=0) motor2DirectionPin=0;
    else motor2DirectionPin=1;
    if (fabs(motorValue2)>1) motor2MagnitudePin = 1;
    else motor2MagnitudePin = fabs(motorValue2);
}
// end Motor 2 --------------------------------------------------------------
// start Motor 3 ------------------------------------------------------------


float P3(int error_r, float kpr)
{
    return error_r*kpr;
}

void MotorController3()
{
    reference_r = (int) (-(countr-hcountr));
    position_r = Encoder3.getPulses();
    error_r = reference_r - position_r;
    pc.printf("%i; %i; %i\n\r" ,position_b,reference_b,error_b);


    if (-20<error_r && error_r<20) {
        motorValue3 = 0;
    } else {
        motorValue3 = P3(error_r, kpr)/4200;
    }

    if (motorValue3 <=0) motor3DirectionPin=0;
    else motor3DirectionPin=1;
    if (fabs(motorValue3)>1) motor3MagnitudePin = 1;
    else motor3MagnitudePin = fabs(motorValue3);
}
// end Motor 3 --------------------------------------------------------------
// einde deel motor----------------------------------------------------------

Ticker loop;

/*Calculates ropelengths that are needed to get to new positions for each time 
step, based on the set coordinates and the position of the poles */
float touwlengtes()
{
    Lou=sqrt(pow((Pstx-Pox),2)+pow((Psty-Poy),2));
    Lbu=sqrt(pow((Pstx-Pbx),2)+pow((Psty-Pby),2));
    Lru=sqrt(pow((Pstx-Prx),2)+pow((Psty-Pry),2));
    return 0;
}

/* Calculates rotations (and associated counts) of the motor to get to the
desired new position for each time step*/
float turns()
{
    roto=Lou/omtrekklosje;
    rotb=Lbu/omtrekklosje;
    rotr=Lru/omtrekklosje;
    counto=roto*4200;
    countb=rotb*4200;
    countr=rotr*4200;
    return 0;
}

//calculate the setpoint for each time step
float Pst()
{
    Pstx=Pex+Vex*T;                               
    Psty=Pey+Vey*T;
    touwlengtes();
    Pex=Pstx;
    Pey=Psty;
    turns();
    return 0;
}

//Calculating desired end position based on the EMG input                       <- Waarom maar voor een paal?
float Ps()
{
    Psx=(Xin_new)*30+91;
    Psy=(Yin_new)*30+278;
    return 0;
}

// Rekent dit de snelheid uit waarmee de motoren bewegen?
void Ve()
{
    Vex=(Psx-Pex);
    Vey=(Psy-Pey);
    Pst();
    if((fabs(Vex)<0.01f)&&(fabs(Vey)<0.01f)) {
        Move_done=true;
        loop.detach();
    }
}

// Calculating the desired position, so that the motors can go here
int calculator()
{
    Ps();
    if (Move_done == false) {
        loop.attach(&Ve,0.02);
    }
    return 0;
}

// Function which makes it possible to lower the end-effector to pick up a piece
void zakker()
{
    dLod=sqrt(pow(Lou,2)+pow((277.85),2))-Lou;
    dLbd=sqrt(pow(Lbu,2)+pow((277.85),2))-Lbu;    
    dLrd=sqrt(pow(Lru,2)+pow((277.85),2))-Lru;
    rotzo=dLod/omtrekklosje;
    rotzb=dLbd/omtrekklosje;
    rotzr=dLrd/omtrekklosje;
    countzo=rotzo*4200;
    countzb=rotzb*4200;
    countzr=rotzr*4200;
    counto=countzo+hcounto+reference_o;             //differs from the other to due to the motor being on the opposite side of the pillar
    countb=-(reference_b-countzb-hcountb);
    countr=-(reference_r-countzr-hcountr);

    pc.printf("dLod=%.2f; dLbd=%.2f; dLrd=%.2f\n\r",dLod,dLbd,dLrd);
    pc.printf("o=%.2f  b=%.2f  countzr=%.2f",countzo,countzb,countzr);
    pc.printf("Position_r = %i; reference_r=%i; Error_r=%i\n\r" ,position_o,reference_o,error_o);
}


void zakken_threshold()
{
    if (Move_done == true) {
        if (emgBLcomplete > thresholdBL) {
            zakker();
        }
    }
}

void setcurrentposition()
{
    if(Input_done==true) {
        hcounto=4200*((sqrt(pow((Pex-Pox),2)+pow((Pey-Poy),2)))/omtrekklosje);
        hcountb=4200*((sqrt(pow((Pex-Pbx),2)+pow((Pey-Pby),2)))/omtrekklosje);
        hcountr=4200*((sqrt(pow((Pex-Prx),2)+pow((Pey-Pry),2)))/omtrekklosje);
        Input_done=false;
    }
}

int main()
{
    pc.baud(115200);
    wait(1.0f);
    getbqChain();
    threshold_timerR.attach(&Threshold_samplingBR, 0.002);
    threshold_timerL.attach(&Threshold_samplingBL, 0.002);
    setcurrentposition();
    while(true) {
        sample_timer.attach(&EMG_sample, 0.002);
        zakken_threshold();
        wait(2.5f); // om te zorgen dat je niet direct na de calibratie input moet geven en om te zorgen dat de zakker de tijd heeft voor nieuwe input vragen
        tellerX();
        tellerY();
        calculator();
        controlmotor1.attach(&MotorController1, 0.01);
        controlmotor2.attach(&MotorController2, 0.01);
        controlmotor3.attach(&MotorController3, 0.01);
        wait(4.0f); // om te zorgen dat je niet meteen tijdens t zakken nieuwe input moet geven
    }

}