Volledig besturingssysteem voor de myoelectrische prothese arm van mijn bachelor opdracht

Dependencies:   mbed QEI MODSERIAL FastPWM biquadFilter

Revision:
2:7c9974f0947a
Parent:
1:070092564648
Child:
3:2aaf54ce090b
diff -r 070092564648 -r 7c9974f0947a main.cpp
--- a/main.cpp	Wed Oct 31 19:09:22 2018 +0000
+++ b/main.cpp	Wed Mar 27 17:33:56 2019 +0000
@@ -1,18 +1,279 @@
 //Voor het toevoegen van een button:
 #include "mbed.h"
-#include <iostream>
-DigitalOut gpo(D0);
+#include "MODSERIAL.h"
+#include "QEI.h"
+#include "BiQuad.h"
 
-DigitalIn button2(SW3);  
-DigitalIn button1(SW2); //or SW2
+// Algemeen
+DigitalIn button3(SW3);  
+DigitalIn button2(SW2); 
+AnalogIn But2(A5);
+AnalogIn But1(A3);
 
 DigitalOut led1(LED_GREEN);
 DigitalOut led2(LED_RED);
 DigitalOut led3(LED_BLUE);
 
+MODSERIAL pc(USBTX, USBRX);
 Timer t;
+Timer t2;
+//Motoren
+DigitalOut direction1(D4);
+PwmOut pwmpin1(D5);
+PwmOut pwmpin2(D6);
+DigitalOut direction2(D7);
+volatile float pwm1;
+volatile float pwm2;
+
+//Encoder
+QEI encoder1 (D10, D9, NC, 1200, QEI::X4_ENCODING);
+QEI encoder2 (D13, D12, NC, 4800, QEI::X4_ENCODING);
+double Pulses1;
+double motor_position1;
+double Pulses2;
+double motor_position2;
+double error1;
+
+//Pot meter
+AnalogIn pot(A1);
+AnalogIn pot0(A0);
+float Pot2;
+float Pot1;
+
+//Ticker
+Ticker Pwm;
+Ticker PotRead;
+Ticker Kdc;
+
+//Kinematica
+double stap1;
+double stap2;
+double KPot;
+
+float ElbowReference;
+float Ellebooghoek1;
+float Ellebooghoek2;
+float Ellebooghoek3;
+float Ellebooghoek4;
+
+float PolsReference;
+float Polshoek1;
+float Polshoek2;
+float Polshoek3;
+float Polshoek4;
+
+float Hoeknieuw1;
+float Hoeknieuw2;
+
+//Limiet in graden
+float lowerlim1 = 0;
+float upperlim1 = 748.8;
+float lowerlim2 = 0;
+float upperlim2 = 1300;   
+
+// VARIABLES PID CONTROLLER
+double Kp1 = 5;          
+double Ki1 = 0;          
+double Kd1 = 1;
+double Kp2 = 6;          // Zonder arm: 6,0,1
+double Ki2 = 0;          
+double Kd2 = 1;          
+double Ts = 0.0005;      // Sample time in seconds
+
+// Functies Kinematica
+float Kinematics1(float KPot)
+{
+
+    if (KPot > 0.45f) {
+        stap1 = KPot*150*Ts;
+        Hoeknieuw1 = PolsReference + stap1;
+        return Hoeknieuw1;
+    }
+
+    else if (KPot < -0.45f) {
+        stap1 = KPot*150*Ts;
+        Hoeknieuw1 = PolsReference + stap1;
+        return Hoeknieuw1;
+    }
+
+    else {
+        return PolsReference;
+    }
+}
+float Kinematics2(float KPot)
+{
+
+    if (KPot > 0.45f) {
+        stap2 = KPot*300*Ts;         
+        Hoeknieuw2 = ElbowReference + stap2;
+        return Hoeknieuw2;
+    }
+
+    else if (KPot < -0.45f) {
+        stap2 = KPot*300*Ts;
+        Hoeknieuw2 = ElbowReference + stap2;
+        return Hoeknieuw2;
+    }
+
+    else {
+        return ElbowReference;
+    }
+}
+
+float Limits1(float Polshoek2)
+{
+
+    if (Polshoek2 <= upperlim1 && Polshoek2 >= lowerlim1) {       //Binnen de limieten
+        Polshoek3 = Polshoek2;
+    }
+
+    else {
+        if (Polshoek2 >= upperlim1) {                            //Boven de limiet
+            Polshoek3 = upperlim1;
+        } else {                                                    //Onder de limiet
+            Polshoek3 = lowerlim1;
+        }
+    }
+
+    return Polshoek3;
+}
+
+
+float Limits2(float Ellebooghoek2)
+{
 
-enum states {MOTORS_OFF,CALIBRATION,HOMING,DEMO,MOVEMENT,CLICK}; 
+    if (Ellebooghoek2 <= upperlim2 && Ellebooghoek2 >= lowerlim2) {       //Binnen de limieten
+        Ellebooghoek3 = Ellebooghoek2;
+    }
+
+    else {
+        if (Ellebooghoek2 >= upperlim2) {                            //Boven de limiet
+            Ellebooghoek3 = upperlim2;
+        } else {                                                    //Onder de limiet
+            Ellebooghoek3 = lowerlim2;
+        }
+    }
+
+    return Ellebooghoek3;
+}
+
+
+// PID Controller
+double PID_controller1(double error1)
+{
+    static double error1_integral = 0;
+    static double error1_prev = error1; // initialization with this value only done once!
+    static BiQuad LowPassFilter(0.0640, 0.1279, 0.0640, -1.1683, 0.4241); //(BIQUAD_FILTER_TYPE type, T dbGain, T freq, T srate, T bandwidth);
+      
+    // Proportional part:
+    double u_k1 = Kp1 * error1;
+
+    // Integral part
+    error1_integral = error1_integral + error1 * Ts;
+    double u_i1 = Ki1* error1_integral;
+
+    // Derivative part
+    double error1_derivative = (error1 - error1_prev)/Ts;
+    double filtered_error1_derivative = LowPassFilter.step(error1_derivative);
+    double u_d1 = Kd1 * filtered_error1_derivative;
+    error1_prev = error1;
+
+    // Sum all parts and return it
+    return u_k1 + u_i1 + u_d1;
+}
+double PID_controller2(double error2)
+{
+    static double error2_integral = 0;
+    static double error2_prev = error2; // initialization with this value only done once!
+    static BiQuad LowPassFilter(0.0640, 0.1279, 0.0640, -1.1683, 0.4241); //(BIQUAD_FILTER_TYPE type, T dbGain, T freq, T srate, T bandwidth);
+       
+    // Proportional part:
+    double u_k2 = Kp2 * error2;
+
+    // Integral part
+    error2_integral = error2_integral + error2 * Ts;
+    double u_i2 = Ki2 * error2_integral;
+
+    // Derivative part
+    double error2_derivative = (error2 - error2_prev)/Ts;
+    double filtered_error2_derivative = LowPassFilter.step(error2_derivative);
+    double u_d2 = Kd2 * filtered_error2_derivative;
+    error2_prev = error2;
+
+    // Sum all parts and return it
+    return u_k2 + u_i2 + u_d2;
+}
+
+// Functies Motor
+void moter1_control(double u1)
+{
+    direction1= u1 > 0.0f; //positief = CW
+    if (fabs(u1)> 0.5f) {
+        u1 = 0.5f;
+    } else {
+        u1= u1;
+    }
+    pwmpin1= fabs(u1); //pwmduty cycle canonlybepositive, floatingpoint absolute value
+}
+
+void moter2_control(double u2)
+{
+    direction2= u2 < 0.0f; //positief = CW
+    if (fabs(u2)> 0.99f) {
+        u2 = 0.99f;
+    } else {
+        u2= u2;
+    }
+    pwmpin2= fabs(u2); //pwmduty cycle canonlybepositive, floatingpoint absolute value
+}
+
+void PwmMotor(void)
+{
+    // Reference hoek berekenen, in graden
+    float Ellebooghoek1 = Kinematics2(pwm2);
+    float Ellebooghoek4 = Limits2(Ellebooghoek1);
+    ElbowReference = Ellebooghoek4;
+    
+    float Polshoek1 = Kinematics1(pwm2);
+    float Polshoek4 = Limits1(Polshoek1);
+    PolsReference = Polshoek4;
+
+    // Positie motor berekenen, in graden
+    Pulses1 = encoder1.getPulses();
+    motor_position1 = -(Pulses1/1200)*360;
+    Pulses2 = encoder2.getPulses();
+    motor_position2 = -(Pulses2/4800)*360;
+
+    double error1 = PolsReference - motor_position1;
+    double u1 = PID_controller1(error1);
+    moter1_control(u1);
+    
+    double error2 = ElbowReference - motor_position2;
+    double u2 = PID_controller2(error2);
+    moter2_control(u2);
+
+}
+
+void MotorOn(void)
+{
+    pwmpin1 = 0;
+    pwmpin2 = 0;
+    Pwm.attach (PwmMotor, Ts);
+
+}
+
+
+void ContinuousReader(void)
+{
+    Pot2 = pot.read();
+    Pot1 = pot0.read();
+    pwm2 =(Pot2*2)-1;            //scaling naar -1 tot 1
+    pwm1 =(Pot1*2)-1;
+}
+
+// StateMachine
+
+enum states {MOTORS_OFF,CALIBRATION,HOMING1,HOMING2,DEMO,MOVEMENT,FREEZE}; 
 int f = 1;
 states currentState = MOTORS_OFF; 
 bool stateChanged = true; // Make sure the initialization of first state is executed
@@ -26,6 +287,7 @@
       if (stateChanged)
       {
         // state initialization: rood
+
         led1 = 1;
         led2 = 0; 
         led3 = 1;
@@ -34,14 +296,9 @@
       }
     
       // State transition logic: Als button 1 word ingedrukt --> calibratie, anders motor uithouden
-        if (!button1)
+        if (!button3)
         {        
-        currentState = CALIBRATION;
-        stateChanged = true;
-        }
-        else if (!button2)
-        {        
-        currentState = HOMING  ;
+        currentState = CALIBRATION  ;
         stateChanged = true;
         }
         else
@@ -67,11 +324,11 @@
       
       // State transition logic: automatisch terug naar motors off.
 
-        currentState = MOTORS_OFF;
-        stateChanged = true; 
+        currentState = HOMING1;
+        stateChanged = true;
         break; 
-      
-    case HOMING:
+
+case HOMING1:
     // Actions
       if (stateChanged)
       {
@@ -80,21 +337,36 @@
         led1 = 0;
         led2 = 1;
         led3 = 1;
-        wait (1);
+        
+        if (!But1)
+        {
+        led1 = 1;
+        float H1 = 0.98f;
+        moter1_control(H1);
+        wait(0.001f);
+        }
+        else if (!But2)
+        {
+        led1 = 1;
+        float H1 = -0.98f;
+        moter1_control(H1);
+        wait(0.001f);
+        }
+        Pulses1 = 0;
+        pwmpin1 = 0;
+        pwmpin2 = 0;
+        ;
         
         stateChanged = false;
       }
           
-      // State transition logic: naar DEMO (button1), naar MOVEMENT(button2)
-        if (!button1)
+      // State transition logic: naar DEMO (button2), naar MOVEMENT(button3)
+
+        if (!button3)
         {        
-        currentState = DEMO;
+        currentState = HOMING2  ;
         stateChanged = true;
-        }
-        else if (!button2)
-        {        
-        currentState = MOVEMENT  ;
-        stateChanged = true;
+        wait(1);
         }
         else if (t>300) 
         {        
@@ -105,7 +377,68 @@
         }
         else
         {        
-        currentState = HOMING  ;
+        currentState = HOMING1  ;
+        stateChanged = true;
+        }
+        break;      
+    
+    case HOMING2:
+    // Actions
+      if (stateChanged)
+      {
+        // state initialization: green
+        t.start();
+        led1 = 0;
+        led2 = 1;
+        led3 = 1;
+        
+        if (!But1)
+        {
+        led1 = 1;
+        float H2 = 0.98f;
+        moter2_control(H2);
+        wait(0.001f);
+        }
+        else if (!But2)
+        {
+        led1 = 1;
+        float H2 = -0.98f;
+        moter2_control(H2);
+        wait(0.001f);
+        }
+        Pulses2 = 0;
+        pwmpin1 = 0;
+        pwmpin2 = 0;
+        ;
+        
+        stateChanged = false;
+      }
+          
+      // State transition logic: naar DEMO (button2), naar MOVEMENT(button3)
+        if (!button2)
+        {        
+        currentState = DEMO;
+        stateChanged = true;
+        }
+        else if (!button3)
+        {        
+        currentState = MOVEMENT  ;
+        stateChanged = true;
+        led1 = 1;
+        led2 = 0;
+        led3 = 0;
+        wait(1);
+        }
+        else if (t>300) 
+        {        
+        t.stop();
+        t.reset();
+        currentState = MOTORS_OFF  ;
+        stateChanged = true;
+        }
+        else
+        {        
+        currentState = HOMING2  ;
         stateChanged = true;
         }
         break;
@@ -124,7 +457,7 @@
       }
           
       // State transition logic: automatisch terug naar HOMING
-        currentState = HOMING;
+        currentState = HOMING1;
         stateChanged = true;
         break;
               
@@ -134,22 +467,27 @@
       {
         // state initialization: purple
         t.start();
+        pwmpin1 = 0;
+        pwmpin2 = 0;
+        Pwm.attach (PwmMotor, Ts);
         led1 = 1;
         led2 = 0;
         led3 = 0;
-        wait (1);
-        
+              
         stateChanged = false;
       }
           
-      // State transition logic: naar CLICK (button1), naar MOTORS_OFF(button2) anders naar MOVEMENT
-        if (!button1)
+      // State transition logic: naar FREEZE (button2), naar MOTORS_OFF(button3) anders naar MOVEMENT
+        if (!button2)
         {        
-        currentState = CLICK;
+        currentState = FREEZE;
         stateChanged = true; 
         }
-        else if (!button2)
+        else if (!button3)
         {        
+        Pwm.detach ();
+        pwmpin2 = 0;
+        pwmpin1 = 0;
         currentState = MOTORS_OFF  ;
         stateChanged = true;
         }
@@ -157,7 +495,7 @@
         {        
         t.stop();
         t.reset();
-        currentState = HOMING  ;
+        currentState = HOMING1  ;
         stateChanged = true;
         }
         else
@@ -167,7 +505,7 @@
         }
         break;
         
-        case CLICK:
+        case FREEZE:
     // Actions
       if (stateChanged)
       {
@@ -191,19 +529,42 @@
  
 int main()
 {
-    while (true)
+    
+    t2.start();
+    int counter = 0;
+    pwmpin2.period_us(60);
+    PotRead.attach(ContinuousReader,Ts);
+    pc.baud(115200);
+    
+    while(true)
     {
     led1 = 1;
-    led2 = 1;
-    led3 = 1;
+    led2 =1;
+    led3 =1;
+    if(counter==10) 
+        {
+        float tmp = t2.read();
+        printf("%f,%f,%f,%f\n\r",tmp,motor_position2,ElbowReference,Pulses2);
+        counter = 0;
+        }
+    counter++;
+    
     ProcessStateMachine();
+
     
+    wait(0.001);
+    }
     }
     
-}
+
+    
+    
+    
+    
 
 
 
 
 
 
+