Final version used at presentation. Working parts: idle, enccali, emgcali, brushingmode, demomode(potmeter).

Dependencies:   mbed QEI HIDScope biquadFilter MODSERIAL Encoder FastPWM

main.cpp

Committer:
dguru
Date:
2019-11-04
Revision:
3:8eb1b9e0d676
Parent:
2:6ca30ccec353

File content as of revision 3:8eb1b9e0d676:

#include <math.h>
#include "mbed.h"
#include "MODSERIAL.h"
#include "QEI.h"
#include "FastPWM.h"
#include "HIDScope.h"
#include <stdio.h>      /* printf */
#include <stdlib.h>     /* abs */
#include <complex>
#include "BiQuad.h"
 
 
const double PI = 3.1415926535897;
 
InterruptIn but1(D1); 
InterruptIn but2(D0); 
DigitalIn butsw2(SW3); 
DigitalIn butsw3(SW2); 
AnalogIn potMeter1(A5);
AnalogIn potMeter2(A4);
 
DigitalOut motor1_direction(D4);                                                //richting van motor1
FastPWM motor1_pwm(D5);                                                         //Motor 1 PWM controle van de snelheid
DigitalOut motor2_direction(D7);                                                //richting van motor2
FastPWM motor2_pwm(D6);                                                         //Motor 2 PWM controle van de snelheid
 
Ticker loop_ticker;
// SERIAL COMMUNICATION WITH PC.................................................
Serial pc(USBTX, USBRX);
 
enum States {s_idle, s_calibratie_encoder, s_demonstratie, s_EMGcalibratie, s_EMG};
States state;
 
// ENCODER .....................................................................
QEI enc1 (D13, D12, NC, 4200); //encoder 1 gebruiken
QEI enc2 (D9,  D8,  NC, 4200); //encoder 2 gebruiken
 
const float dt = 0.001;
double e_int = 0;
double e_int2 = 0;
double theta1;
double theta2;
int enc1_zero = 0;
int enc2_zero = 0;
int enc1_value;
int enc2_value;
const int maxwaarde = 400;
 
volatile double Huidigepositie1=0;
volatile double Huidigepositie2=0;
volatile double motorValue1;
volatile double motorValue2;
volatile double refP;
volatile double refP2;
volatile double error1;
volatile double error2;
 
bool state_changed = false;
volatile bool A=true;
volatile bool B=true;
volatile bool but1_pressed = false;
volatile bool but2_pressed = false;
volatile bool butsw2_pressed = false;
volatile bool butsw3_pressed = false;
volatile bool failure_occurred = false;
 
const bool clockwise1 = true;
const bool clockwise2 = true;
volatile bool direction1 = clockwise1;
volatile bool direction2 = clockwise2;
 
// RKI VARIABELEN...............................................................
// Lengtes zijn in meters
// Vaste variabelen:
const double L0 = 0.25;                                                         // lengte arm 1 --> moet nog goed worden opgemeten!
const double L2 = 0.375;                                                         // Lengte arm 2 --> moet ook nog goed opgemeten worden!
const double r_trans = 0.035;                                                   // gebruiken voor translation naar shaft rotation
//const double gear1=1.0;
const double gear2=1.25;


// Variërende variabelen:
double q1 = 0;                                                                  // Motorhoek van joint 1 op beginpositie
double q2 = PI/2;                                                               // Motorhoek van joint 2 op beginpositie
double v_x;                                                                     // Snelheid van end effector in x richting --> Door EMG signals
double v_y;                                                                     // Snelheid van end effector in y richting --> Door EMG signals
 
double Lq1;                                                                     // Translatieafstand als gevolg van motor rotation joint 1
double Cq2;                                                                     // Joint angle van het systeem (gecorrigeerd voor gear ratio 1:1.1)
 
double q1_dot;                                                                  // Benodigde hoeksnelheid van motor 1
double q2_dot;                                                                  // Benodigde hoeksnelheid van motor 2
 
double q1_ii;                                                                   // Referentie signaal voor motorhoek q1
double q2_ii;                                                                   // Referentie signaal voor motorhoek q2
 
//PI VARIABELEN................................................................
const double kp=0.01;                                                          // Soort van geschaald --> meer onderzoek nodig
const double ki=0.0001;
const double kp2=0.01;
const double ki2=0.0001;


double maxPWM1 = 0.2;
double maxPWM2 = 0.2;
 
//FILTERS EMG...................................................................
 
//Filters EMG
//Filters Linker Biceps
//In de volgorde High pass, notch, low pass
//BiQuad LBHP1(1, 2.000000023182220, 0.999999981993818, 1.893415601022358, 0.896255659548714);
//BiQuad LBHP2(1, 1.999999976817780, 0.999999976817780, 1.778313488139574, 0.790599715524785);
BiQuad LBHP1(0.995566972017647,  -1.991133944035294,   0.995566972017647, 1.000000000000000,  -1.991114292201654,   0.991153595868935);
//BiQuad LBHP2([3.913020539916823e-05,7.826041079833645e-05,3.913020539916823e-05, -1.982228929792529,0.982385450614126]);
BiQuad LBN1( 0.5, 0, 0.5, 0, 0);
BiQuad LBLP1(0000.087655548754006,   0000.175311097508013,   0000.087655548754006,    1.000000000000000,  -1.973344249781299,   0.973694871976315);
//BiQuad LBLP2( 0.000155148423475721, 0.000310296846951441, 0.000155148423475721,-1.96446058020523, 0.965081173899135);
BiQuadChain LeftBicepHP;
BiQuadChain LeftBicepN;
BiQuadChain LeftBicepLP;

//Filters Rechter Biceps
//In de volgorde High pass, notch, low pass
//BiQuad RBHP1(1, 2.000000023182220, 0.999999981993818, 1.893415601022358, 0.896255659548714);
//BiQuad RBHP2(1, 1.999999976817780, 0.999999976817780, 1.778313488139574, 0.790599715524785);
BiQuad RBHP1(0.995566972017647,  -1.991133944035294,   0.995566972017647, 1.000000000000000,  -1.991114292201654,   0.991153595868935);
//BiQuad RBHP2([3.913020539916823e-05,7.826041079833645e-05,3.913020539916823e-05, -1.982228929792529,0.982385450614126]);
BiQuad RBN1( 0.5, 0, 0.5, 0, 0);
BiQuad RBLP1(0000.087655548754006,   0000.175311097508013,   0000.087655548754006,  1.000000000000000,  -1.973344249781299,   0.973694871976315);
//BiQuad RBLP2( 0.000155148423475721, 0.000310296846951441, 0.000155148423475721,-1.96446058020523, 0.965081173899135);
BiQuadChain RightBicepHP;
BiQuadChain RightBicepN;
BiQuadChain RightBicepLP;


//Filters Rechter Quadriceps
//In de volgorde High pass, notch, low pass
//BiQuad RTHP1(1, 2.000000023182220, 0.999999981993818, 1.893415601022358, 0.896255659548714);
//BiQuad RTHP2(1, 1.999999976817780, 0.999999976817780, 1.778313488139574, 0.790599715524785);
BiQuad RTHP1(0.995566972017647,  -1.991133944035294 ,  0.995566972017647 ,1.000000000000000,  -1.991114292201654 ,  0.991153595868935);
//BiQuad RTHP2(1, 1.999999966458334, 0.999999966458334, -1.988418014198592, 0.988451549797368);
BiQuad RTN1( 0.5, 0, 0.5, 0, 0);
BiQuad RTLP1(0000.087655548754006  , 0.175311097508013 ,  0.087655548754006,  1.000000000000000 , -1.973344249781299  , 0.973694871976315);
//BiQuad RTLP2( 0.000155148423475721, 0.000310296846951441, 0.000155148423475721,-1.96446058020523, 0.965081173899135);
BiQuadChain RightLegHP;
BiQuadChain RightLegN;
BiQuadChain RightLegLP;
 
double emgLBHP;
double emgLBN;
double emgLBA;
//double emgLBLP;
//double emgAbsLBNotch;

double emgRBHP;
double emgRBN;
double emgRBA;
double emgRBLP;
double emgAbsRBNotch;

double emgRTN;
double emgRTHP;
double emgRTA;
//double emgRTLP;
//double emgAbsRTNotch;

double emgLBfiltered;
double emgRBfiltered;
double emgRTfiltered;
double emgLBraw;
double emgRBraw;
double emgRTraw;


double threshold_emgLB;
double threshold_emgRB;
double threshold_emgRT;
double threshold = 0.5;
double emgLB_max = 0.000;
double emgRB_max = 0.000;
double emgRT_max = 0.000;
double emgLB_maxrust = 0.000;
double emgRB_maxrust = 0.000;
double emgRT_maxrust = 0.000;
volatile int tijd = 0;
double timecalibration;

double emgsumLB;
double emgsumRB;
double emgsumRT;
double restmeanLB = 0.000;
double restmeanRB = 0.000;
double restmeanRT = 0.000;
//double emgmeansubLB;
//double emgmeansubRB;
//double emgmeansubRT;
double LBvalue;
double RBvalue;
double RTvalue;
double emgLBrust;
double emgRBrust;
double emgRTrust;
double RestmeanLB;
double RestmeanRB;
double RestmeanRT;

 
DigitalOut ledr(LED_RED);
DigitalOut ledg(LED_GREEN);
DigitalOut ledb(LED_BLUE);


AnalogIn emgLB(A0);     //read EMG left bicep
AnalogIn emgRB(A1);     //read EMG right bicep
AnalogIn emgRT(A2);     //read EMG right quadriceps

//HIDScope scope(6);      //aantal kanalen HIDScope (voor test 5, voor echt 6)
 
void rest()
// Rust. Hier wordt niets uitgevoerd. Wanneer button1
{
    // wordt ingedrukt gaan we naar de volgende state waar
    if (but1_pressed) {                                                         // de encoders worden gekalibreerd.
        state_changed = true;
        state = s_calibratie_encoder;
        but1_pressed = false;
    }
}
 
void calibratie_encoder()                                                       // calibratie encoder. Hier worden de encoders gekalibreerd en op
{
    // 0 gezet. Wanneer op button 1 wordt gedrukt gaan we naar de
    if (state_changed) {                                                        // demo modus, wanneer op button 2 wordt gedruk gaan we naar
        pc.printf("Started encoder calibration\r\n");                           // de EMG calibratie
        state_changed = false;
    }
    else if (but1_pressed) {
        pc.printf("Encoder has been calibrated \r\n");
        enc1_value = enc1.getPulses();
        enc2_value = enc2.getPulses();
        //enc1_value -= enc1_zero;
        //enc2_value -= enc2_zero;
        theta1 = (float)(enc1_value)/(float)(4200)*2*PI;                        // First arm rotated fully ccw
        theta2 = (float)(enc2_value)/(float)(4200)*2*PI;                        // second arm fully clockwise --> looks like a Z
        enc1_zero = enc1_value;
        enc2_zero = enc2_value;
        

        pc.printf("enc01: %i\r\n", enc1_zero);
        pc.printf("enc1value: %i\r\n", enc1_value);
        pc.printf("enc02: %i\r\n",enc2_zero);
        pc.printf("enc2value: %i\r\n", enc2_value);
        pc.printf("hoek 1: %f\r\n",theta1);
        pc.printf("hoek 2: %f\r\n",theta2);
        but1_pressed = false;
        state_changed = true;
        state = s_demonstratie;
    }
 
    else if (but2_pressed) {
        pc.printf("Encoder has been calibrated \r\n");
        enc1_value = enc1.getPulses();
        enc2_value = enc2.getPulses();
        //enc1_value -= enc1_zero;
        //enc2_value -= enc2_zero;
        theta1 = (float)(enc1_value)/(float)(4200)*2*PI;
        theta2 = (float)(enc2_value)/(float)(4200)*2*PI;
        enc1_zero = enc1_value;
        enc2_zero = enc2_value;
        

        pc.printf("enc01: %i\r\n", enc1_zero);
        pc.printf("enc1value: %i\r\n", enc1_value);
        pc.printf("enc02: %i\r\n",enc2_zero);
        pc.printf("enc2value: %i\r\n", enc2_value);
        pc.printf("hoek 1: %f\r\n",theta1);
        pc.printf("hoek 2: %f\r\n",theta2);
        
        but2_pressed = false;
        state_changed = true;
        state = s_EMGcalibratie;
        
    }
}
 
void filteren()
{
     //linkerbicep
    emgLBraw= emgLB.read(); //dit wordt: emgLBoffset
    emgLBHP=LeftBicepHP.step(emgLBraw);
    emgLBN=LeftBicepN.step(emgLBHP);
    //emgmeansubLB = emgLBN - RestmeanLB;
    emgLBA= fabs(emgLBN);
    emgLBfiltered=LeftBicepLP.step(emgLBA);
    //LBvalue = emgLBfiltered/emgLB_max;

   /* //to show if filter is working
    scope.set(0, emgLBraw);
    scope.set(1, emgLBfiltered);
    scope.set(2, emgRBraw);
    scope.set(3, emgRBfiltered);
    scope.set(4, emgRTraw);
    scope.set(5, emgRTfiltered); 
    scope.send();
*/
    //rechterbicep
    emgRBraw= emgRB.read();
    emgRBHP= RightBicepHP.step(emgRBraw);
    emgRBN=RightBicepN.step(emgRBHP);
    //emgmeansubRB = emgRBN - RestmeanRB;
    emgRBA= fabs(emgRBN);
    emgRBfiltered=RightBicepLP.step(emgRBA);
    //RBvalue = emgRBfiltered/emgRB_max;

    //Right Quadriceps
    emgRTraw= emgRT.read();
    emgRTHP= RightLegHP.step(emgRTraw);
    emgRTN= RightLegN.step(emgRTHP);
   // emgmeansubRT = emgRTHP - RestmeanRT;
    emgRTA= fabs(emgRTN);
    emgRTfiltered=RightLegLP.step(emgRTA);
    //RTvalue = emgRTfiltered/emgRT_max;
   
 
}
 
void EMGcalibration()
    {
        
            emgLBraw= emgLB.read(); //dit wordt: emgLBoffset
            emgLBHP=LeftBicepHP.step(emgLBraw);
            emgLBN=LeftBicepN.step(emgLBHP);
            emgLBA= fabs(emgLBN);
            emgLBfiltered=LeftBicepLP.step(emgLBA);
    
            emgRBraw= emgRB.read();
            emgRBHP= RightBicepHP.step(emgRBraw);
            emgRBN=RightBicepN.step(emgRBHP);
            emgRBA= fabs(emgRBN);
            emgRBfiltered=RightBicepLP.step(emgRBA);
        
    
            emgRTraw= emgRT.read();
            emgRTHP= RightLegHP.step(emgRTraw);
            emgRTN= RightLegN.step(emgRTHP);
            emgRTA= fabs(emgRTN);
            emgRTfiltered=RightLegLP.step(emgRTA);
    
        if (tijd > 1000 && tijd < 6000) {
            emgLBraw= emgLB.read();
            emgLBHP=LeftBicepHP.step(emgLBraw);
            emgLBN=LeftBicepN.step(emgLBHP);
            //emgmeansubLB = emgLBN - restmeanLB;
            emgLBA= fabs(emgLBN);
            emgLBfiltered=LeftBicepLP.step(emgLBA);
            if (emgLBfiltered > emgLB_max) {
                emgLB_max = emgLBfiltered;
            }
            //pc.baud(115200);
            //pc.printf("emgLB_max = %f \r\n", emgLB_max);// geen tekst printen in ticker want dat gaat mis xjes
            ledr=0; //led gaat aan zodra je linkerbicep moet aanspannen
        }
    
        else if (tijd > 7000 && tijd < 12000) {
            emgRBraw= emgRB.read();
            emgRBHP= RightBicepHP.step(emgRBraw);
            emgRBN=RightBicepN.step(emgRBHP);
            //emgmeansubRB = emgRBN - RestmeanRB;
            emgRBA= fabs(emgRBN);
            emgRBfiltered=RightBicepLP.step(emgRBA);
            if (emgRBfiltered > emgRB_max) {
                emgRB_max = emgRBfiltered;
            }
            //pc.printf("emgRB_max = %f \r\n", emgRB_max);
            ledr=0; //led gaat uit zodra je rechterbicep moet aanspannen
        }
    
    
        else if (tijd > 13000 && tijd < 18000) {
            emgRTraw= emgRT.read();
            emgRTHP= RightLegHP.step(emgRTraw);
            emgRTN= RightLegN.step(emgRTHP);
            //emgmeansubRT = emgRTHP - RestmeanRT;
            emgRTA= fabs(emgRTN);
            emgRTfiltered=RightLegLP.step(emgRTA);
            if (emgRTfiltered > emgRT_max) {
                emgRT_max = emgRTfiltered;
            }
            //pc.printf("emgRT_max = %f \r\n", emgRT_max);
            ledr=0; //led gaat aan zodra je rechterbeenspier moet aanspannen
        } else if (tijd > 18000) {
            ledr=1; //led gaat uit zodra kalibratie voltooid
            state=s_EMG;
            state_changed=true;
            
            //pc.printf("Calibration finished!");
        } else {
            ledr=1;
            }
     
        pc.printf("%i", tijd);
        tijd++;
        threshold_emgLB = threshold*emgLB_max;   //bepaal threshold, nu op 0.15*maximale waarde. 
        threshold_emgRB = threshold*emgRB_max; 
        threshold_emgRT = threshold*emgRT_max;
    
    
    // if threshold_emgx is reached, brushingmodes activated
}
 
 
 
void SetMotor1(float motorValue1)
{
    // gegeven motorValue1 <=1, schrijft snelheid naar pwm.
    // MotorValues buiten range worden afgekapt dat ze binnen de range vallen.
    motor1_pwm.write(fabs(motorValue1) > 1 ? 1 : fabs(motorValue1));
}
 
void SetMotor2(float motorValue2)
{
    motor2_pwm.write(fabs(motorValue2) > 1 ? 1 : fabs(motorValue2));
}
 
void brushingmode()
{
    
        //boven draait arm 1 aan, dus motor 1 
        //onder draait arm 2 aan, dus motor 2 
        if (emgLBfiltered > threshold_emgLB){      //tandenborstel naar links (cw/ccw) //direction1/2 = cw/ccw
        
        motor2_direction.write(direction1);   //motor 2 gaat cw
        //motor2_direction.write(direction1 = !direction1); //is counterclockwise
        motor2_pwm.write(maxPWM2);
        ledr=0;
        
        
        }else if (emgRBfiltered > threshold_emgRB){
            motor2_pwm.write(maxPWM2);
            motor2_direction.write(direction1 = !direction1); //is counterclockwise
        //tandenborstel naar rechts
        ledg=0;
        
        
        }else if (emgRTfiltered > threshold_emgRT){
        motor1_direction.write(direction1 = !direction1);
        motor1_pwm.write(maxPWM1);
        //tandenborstel naar achter
        ledb=0;
        
        }else if (emgRBfiltered > threshold_emgRB && emgLBfiltered > threshold_emgLB){
        motor1_direction.write(direction1); //motor 1 gaat cw
        motor1_pwm.write(maxPWM1);
        //tandenborstel naar voren
        ledg=0;
        ledr=0;
}
}
 
void demonstratie()
{
    if (state_changed) {                                                        //
        pc.printf("Demonstratie gestart\r\n")   ;                                //
        state_changed = false;
    }
}
 
 
void RKI()
{
    Lq1 = q1*r_trans;
    Cq2 = q2/gear2;                               //1.25 is gear ratio voor q2
 
    q1_dot = (v_x + (v_y*(L2*sin(q2/gear2)))/(L0 + q1*r_trans + L2*cos(q2/gear2)))/r_trans;
    q2_dot = (gear2*v_y)/(L0 + q1*r_trans + L2*cos(q2/gear2));
 
    q1_ii = q1 + q1_dot*dt;
    q2_ii = q2 + q2_dot*dt;
 
    q1 = q1_ii;
    q2 = q2_ii;
 
}
 
double GetReferencePosition()
{
    double Potmeterwaarde = potMeter2.read();
 
    double refP = Potmeterwaarde*maxwaarde;
    return refP;
}
 
double GetReferencePosition2()
{
    double potmeterwaarde2 = potMeter1.read();
    double refP2 = potmeterwaarde2*maxwaarde;
    return refP2;
}
 
double FeedBackControl(double error, double &e_int)
{
    //double Proportional= kp*error1;
    double motorValue1= kp*error1;
    //e_int = e_int+dt*error1;
    //double Integrator = ki*e_int;
 
   // motorValue1 = Proportional + Integrator ;
    return motorValue1;
}
 
double FeedBackControl2(double error2, double &e_int2)
{
    //double Proportional2= kp2*error2;
    double motorValue2= kp2*error2;
    //e_int2 = e_int2+dt*error2;
    //double Integrator2 = ki2*e_int2;
 
    //double motorValue2 = Proportional2 + Integrator2 ;
    return motorValue2;
}
 
void MeasureAndControl()
{
    // RKI aanroepen
    //RKI();
    // hier the control of the 1st control system
    refP = GetReferencePosition();                    //moet eigenlijk nog met RKI
    Huidigepositie1 = enc1.getPulses()*4200;
    //error1 = (refP - Huidigepositie1);// make an error
    error1 = refP ;// ffwd
    motorValue1 = FeedBackControl(error1, e_int);
    SetMotor1(motorValue1);
    // hier the control of the 2nd control system
    refP2 = GetReferencePosition2();
    Huidigepositie2 = enc2.getPulses();
    //error2 = (refP2 - Huidigepositie2);// make an error
    error2 = refP2;// ffwd
    motorValue2 = FeedBackControl2(error2, e_int2);
    SetMotor2(motorValue2);
    //pc.printf("refP = %d, huidigepos = %d, motorvalue = %d, refP2 = %d, huidigepos2 = %d, motorvalue2 = %d \r\n", refP, Huidigepositie1, motorValue1, refP2, Huidigepositie2, Huidigepositie2);
 
}
 
void direction()
{
    if (butsw2==0) {
        if (A==true) { // zodat het knopje 1 x wordt afgelezen
            // richting veranderen
            motor1_direction.write(direction1 = !direction1);
            pc.printf("direction: %s\r\n\n", direction1 ? "clockwise" : "counter clockwise");
            A=false;
        }
    } else {
        A=true;
    }
 
    if (butsw3==0) {
        if (B==true) {
            motor2_direction.write(direction2 = !direction2);
            pc.printf("direction: %s\r\n\n", direction2 ? "clockwise" : "counter clockwise");
            B=false;
        }
    } else {
        B=true;
    }
 
}
 
void but1_interrupt()
{
    /*if(but2.read()) {//both buttons are pressed
     failure_occurred = true;
    }*/
    but1_pressed = true;
    pc.printf("Button 1 interrupt active \n\r");
}
 
void but2_interrupt()
{
    /*if(but1.read()) {//both buttons are pressed
      failure_occurred = true;
    }*/
    but2_pressed = true;
    pc.printf("Button 2 interrupt active \n\r");
}

 void state_machine()
{
    //run current state
    switch (state) {
        case s_idle:                                                            // in deze state gebeurd niets. Als op knop 1 wordt gedrukt
            rest();                                                             // gaan we over naar s_calibratie_encoder
            break;
        case s_calibratie_encoder:                                              // in deze state worden de encoders gekalibreerd. knop 1 -> s_demonstratie
            calibratie_encoder();                                               // knop 2 -> s_EMGcalibratie
            break;
        case s_demonstratie:                                                    // in deze state kunnen de motors worden bestuurd met de potmeters
            demonstratie();
            MeasureAndControl();                                                // en switch 2 en 3( pot1,sw2->motor1 / pot2,sw3->motor2
            direction();                                                        // als op knop 2 wordt gedrukt komen we in de s_idle state
            if (but2_pressed) {
                pc.printf("fail. \r\n");
                but2_pressed = false;
                state_changed = true;
                state = s_idle;
            }
            break;
            
        case s_EMGcalibratie:
            EMGcalibration();
            break;
            
        case s_EMG:
            ledg=1;
            ledr=1;
            ledb=1;
            state_changed=false;
            filteren();
            brushingmode();
               if (but2_pressed) {
                pc.printf("fail. \r\n");
                but2_pressed = false;
                state_changed = true;
                state = s_idle;
                }
            break;
 
        }
}

int main()
{
    pc.baud(115200);
    pc.printf("Executing main()... \r\n");
    state = s_idle;
    ledg=1;
    ledr=1;
    ledb=1;
 
    LeftBicepHP.add( &LBHP1 );  //BiQuadChain bqc;   //bqc.add( &bq1 ).add( &bq2 );
    LeftBicepN.add( &LBN1 );
    LeftBicepLP.add( &LBLP1 );


    RightBicepHP.add( &RBHP1 );
    RightBicepN.add( &RBN1 );
    RightBicepLP.add( &RBLP1 );

    RightLegHP.add( &RTHP1 );
    RightLegN.add( &RTN1 );
    RightLegLP.add( &RTLP1 );
 
    but1.fall(&but1_interrupt);
    but2.fall(&but2_interrupt);
    loop_ticker.attach(&state_machine, dt); 
    pc.printf("state_machine active!\n\r");
 
}