Dit is het actieve stuurprogramma, behorend bij de bacheloropdracht van Menno Sytsma over de integratie van een Twisted string actuator in een handorthese

Dependencies:   EMG FastPWM HIDScope mbed-src

Revision:
0:c727f4699e80
Child:
1:57926254e65b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jun 08 11:43:46 2016 +0000
@@ -0,0 +1,337 @@
+#include "mbed.h"
+#include "HIDScope.h"
+#include "biquadFilter.h"
+#include "FastPWM.h"
+
+// Define the HIDScope and Ticker object
+HIDScope    scope(5);
+Ticker      scopeTimer;
+volatile bool LoopTimerFlag;
+Ticker      ForceTimer;
+volatile bool LoopTimerFlag2;
+//Serial pc(USBTX, USBRX);
+
+// Read the analog input
+//AnalogIn    a_in(A0); // Potmeter
+AnalogIn    a_in2(A3); //OUT-
+AnalogIn    a_in3(A4); //OUT+
+
+Ticker Loopticker;                  // Deze ticker wordt gebruikt om de looptimerflag aan te roepen.
+AnalogIn Referentie(A0);            // De schuifpotmeter naast de geleiding van de draad is de referentie.
+AnalogIn Boardpotmeter(A1);        // POT1 op het board wordt gebruikt als input van de controlloop.
+AnalogIn Boardpotmeter2(A2);
+DigitalOut motor1direction(D7);     //D6 en D7 voor motor 1 (op het motorshield)
+FastPWM motor1speed(D6);
+DigitalOut Led(LED_RED);
+DigitalOut Roodisplus(D5);
+DigitalOut Versterker(D4);
+float potmeter;
+float Error;
+float Referentie2;//=1.0;
+float Output;
+float Input;
+double Error_prev = 0;
+double Error_int = 0;
+double Error_der;
+double Ref_der = 0;
+double Ref_prev = 0;
+double Ref_prev2 = 0;
+double Ref2;
+double Input3;
+double Input_der=0;
+double Input_prev=0;
+double Input_prev2=4;
+double Plaats_der;
+double Force_nieuw=0;
+double Plaats_acc;
+double Ref_der_prev;
+double Plaats_der1;
+
+//LowPass filter 2 Hz
+//double low1_v1 = 0, low1_v2 = 0;
+//double low2_v1 = 0, low2_v2 = 0;
+const double a1_LP =  -1.940778135263835, a2_LP = 0.942482022027066;
+const double b0_LP = 0.000425971690807714, b1_LP = 0.000851943381615428, b2_LP = 0.000425971690807714;
+const double a1_HP = -1.982228929792529, a2_HP = 0.982385450614125;
+const double b0_HP =  0.991153595101663, b1_HP = -1.982307190203327, b2_HP = 0.991153595101663;
+const double a1_LP5 = -1.822694925196308, a2_LP5 = 0.837181651256023 ;    //-1.911197067426073, a2_LP5 =  0.914975834801434;
+const double b0_LP5 =  0.003621681514929 , b1_LP5 =  0.007243363029857, b2_LP5 = 0.003621681514929;  // 0.000944691843840, b1_LP5 =  0.001889383687680 , b2_LP5 = 0.000944691843840;
+
+const double a1_LP3 =  -1.561018075800718, a2_LP3 = 0.641351538057563;
+const double b0_LP3 = 0.020083365564211, b1_LP3 = 0.040166731128423, b2_LP3 = 0.020083365564211;
+const double a1_LP2 =  -1.561018075800718, a2_LP2 = 0.641351538057563;
+const double b0_LP2 = 0.020083365564211, b1_LP2 = 0.040166731128423, b2_LP2 = 0.020083365564211;
+const double a1_LP4 =  -1.561018075800718, a2_LP4 = 0.641351538057563;
+const double b0_LP4 = 0.020083365564211, b1_LP4 = 0.040166731128423, b2_LP4 = 0.020083365564211;
+
+/*
+const double a1_LP =  -1.911197067426073, a2_LP = 0.914975834801434;
+const double b0_LP = 0.067455273889072, b1_LP = 0.134910547778144, b2_LP = 0.067455273889072;
+const double a1_HP = -1.982228929792529, a2_HP = 0.982385450614125;
+const double b0_HP =  0.991153595101663, b1_HP = -1.982307190203327, b2_HP = 0.991153595101663;
+*/
+biquadFilter Filter1(a1_LP, a2_LP, b0_LP, b1_LP, b2_LP);
+biquadFilter Filter2(a1_HP, a2_HP, b0_HP, b1_HP, b2_HP);
+biquadFilter Filter3(a1_LP3, a2_LP3, b0_LP3, b1_LP3, b2_LP3);
+biquadFilter Filter4(a1_LP2, a2_LP2, b0_LP2, b1_LP2, b2_LP2);
+biquadFilter Filter5(a1_LP4, a2_LP4, b0_LP4, b1_LP4, b2_LP4);
+biquadFilter Filter6(a1_LP5, a2_LP5, b0_LP5, b1_LP5, b2_LP5); // fk is 2 Hz
+biquadFilter Filter7(a1_LP, a2_LP, b0_LP, b1_LP, b2_LP);
+
+double Y_filt;
+double Y_filt2;
+double Y_filtprev;
+double Y_filtprev2;
+double Y_filtprev3;
+double Y_filtprev4;
+double Y_filtprev5;
+double Y_filtder;
+int A;
+float time_;
+const float time_increment = 0.005;
+
+// The data read and send function
+void scopeSend()
+{
+    scope.set(0,Force_nieuw);
+    //scope.set(1,Input);
+    scope.set(3,Input);//Boardpotmeter2.read());
+    scope.set(1,Y_filtder);
+    scope.set(2,Plaats_der);
+    scope.set(4,A);
+    scope.send();
+
+}
+
+void tickerfunctie()                //Deze functie wordt elke honderdste seconde aangeroepen en zorgt ervoor dat de while-loop helemaal uitgevoerd kan worden.
+{
+    LoopTimerFlag = 1;
+}
+
+void tickerfunctie2()                //Deze functie wordt elke honderdste seconde aangeroepen en zorgt ervoor dat de while-loop helemaal uitgevoerd kan worden.
+{
+    LoopTimerFlag2 = 1;
+}
+
+
+double Referentieschaling(double A, double B)
+{
+    double Y= 787.3008916207206*pow(A,4) -565.1143141517078*pow(A,3) + 122.8516837382677*pow(A,2) + 0.0556616744031*A + 0.0912411880277;
+    Referentie2 = Filter4.step(Y);
+    if (Referentie2<=2.5 or Referentie2>=9.2) {
+        Led = 0;
+        Referentie2 = B;
+    }
+    return Referentie2;
+}
+
+double Inputberekening(double B)
+{
+    double Inp = 10*B;            // De potmeter geeft ook waardes tussen 0 en 1, dit wordt met een factor 10 geschaald zodat deze als een positie in cm opgelegd kunnen worden.
+    Input = Filter3.step(Inp);
+    //Input = 6+(2.5*sin(time_));
+    if (Input>=9) {                             // De Input moet binnnen een aantal grenzen blijven. Groter dan 7 is mechanisch niet mogelijk.
+        Input=9;                                // Bij een waarde kleiner dan 1,5 zijn de strings niet meer gewikkeld en werkt de controller averechts en is deze uiterst instabiel.
+    } else if (Input<=3.0) {
+        Input = 3.0;
+    }
+    return Input;
+}
+
+/*double Input2(double B)
+{
+    // if (Y_filtder
+    if (Y_filtder>=1) {
+        Input3 = Input_prev2+0.01;
+        wait(0);
+    }
+    if (Y_filtder<= -1) {
+        Input3 = Input_prev2-0.01;
+        wait(0);
+    }
+    if (Input3 >= 9) {
+        Input3 =9;
+    }
+    if (Input3 <= 2.5) {
+        Input3 =2.5;
+    }
+
+    Input_prev2 = Input3;
+    return Input3;
+}*/
+
+
+double Force_prev;
+double Input_prev3;
+
+double Inputberekening3(double B){
+    if (Force_nieuw>=2.5) {
+        if (A == 1) {
+            Input3 = Input_prev3-0.01;
+        }
+        if (A == 0 && Force_prev>2.5) {
+            A = 0;
+            //pc.printf("A = 0 en Forceprev>1.5 \n");
+        }
+        if (A <= 0 && Force_prev<=2.5) {
+            A++;
+            Input3 = Input_prev3+0.01;
+           // pc.printf("A = 0 en Forceprev<1.5 \n");
+        }
+    }
+    else if (Force_nieuw<=-2.5) {
+        if (A == -1)
+            { Input3 = Input_prev3+0.01;
+            }
+            if (A == 0 && Force_prev<-2.5) {
+                A = 0;
+               // pc.printf("A = 0 en Forceprev<1.5 Force<-1.5 \n");
+            }
+        if (A >= 0 && Force_prev>=-2.5) {
+            A--;
+            Input3 = Input_prev3-0.01;
+           // pc.printf("A = 0 en Forceprev<1.5 Force<-1.5 \n");
+        }
+    } 
+    else {
+        Input3 = Input_prev3 - A*0.01;
+       // pc.printf("Else A = %i \n", A);
+    }
+    Force_prev= Force_nieuw;
+    if (Input3 >= 9) {
+        Input3 =9;
+    }
+    if (Input3 <= 3.5) {
+        Input3 =3.5;
+    }
+    Input_prev3 = Input3;
+    return Input3;
+
+}
+
+double Errorberekening(double Ref,double Input)
+{
+    Error = Input-Ref;                  // Het Error-signaal wordt ook gebruikt voor de PWMOut, dus mag deze niet hoger worden dan 1, 1 is immers al full speed voor de motor.
+    /* if (Error>=1) {
+        Error=1;
+    } else if (Error<=-1) {
+        Error = -1;
+    }
+    else if (fabs(Error)<0.01)
+    { Error = 0; }*/
+    return Error;
+}
+double PID_controller(double Error, double KP, double KI, double KD, double Ts, double &Error_int, double &e_prev)
+{
+    Error_der = (Error-Error_prev)/Ts;
+    Error_prev = Error;
+    Error_int = Error_int + Ts*Error;
+
+    return KP*Error+KI*Ts*Error_int+KD*Ts*Error_der;
+}
+
+void Afgeleide_Force()
+{
+    //while(LoopTimerFlag2 !=1);                  // Als LTF 0 is, blijft hij 0 en stopt de loop.
+    //LoopTimerFlag2 = 0;
+    Y_filtder = (Y_filt-Y_filtprev)/0.01;
+    //Y_filtder = 3*Filter7.step(Y_filtder);
+    Y_filtprev = Y_filt;
+}
+
+void Afgeleide_Plaats()
+{
+    //while(LoopTimerFlag2 !=1);                  // Als LTF 0 is, blijft hij 0 en stopt de loop.
+    LoopTimerFlag2 = 0;
+    Plaats_der = Ref_der/0.01; //(Referentie2-Ref_prev2)/0.1;
+    Plaats_der1 = Filter6.step(Plaats_der);
+    Plaats_der = (Plaats_der1-Ref_der_prev)/0.1;
+    //Plaats_der = Filter5.step(Plaats_acc);
+    if (Plaats_der>=0) {
+        Plaats_der = Plaats_der;
+    } else if (Plaats_der<0) {
+        Plaats_der = 0.5*Plaats_der;
+    }
+    Ref_der_prev= Plaats_der1;
+}
+
+void Motor_controller()
+{
+    if(Output>=0) {
+        motor1direction.write(1);
+        motor1speed = 0.2+fabs(Output);
+    } else if (Output<0) {
+        motor1direction.write(0);
+        motor1speed = 0.05*fabs(Output);
+    }
+    /* if(Input_der < 0)
+     {
+            // motor1direction.write(0);
+            // motor1speed = 0.05*fabs(Output);
+         if(Output>=0)
+             {
+             motor1direction.write(1);
+             motor1speed = 0.3*fabs(Output);
+             }
+         else if (Output<0)
+             {
+             motor1direction.write(0);
+             motor1speed = 0.09*fabs(Output);
+             }
+     }
+     if(Input_der >= 0)
+     {
+    // motor1direction.write(1);
+     //motor1speed = 1;
+         if(Output>=-0.50)
+             {
+             motor1direction.write(1);
+             motor1speed = (fabs(Output)+0.3);
+             }
+         else if (Output<-0.5)
+             {
+             motor1direction.write(0);
+             motor1speed = 0.01*fabs(Output);
+             }
+     }*/
+
+
+    //if (fabs(Output)>=0.01)
+    // motor1speed = fabs(Output);
+    //else if (fabs(Output)<0.01)
+    //{motor1speed= 0;}
+}
+
+int main()
+{
+    Roodisplus.write(1);
+    Versterker.write(1);
+    // Attach the data read and send function at 100 Hz
+    scopeTimer.attach_us(&tickerfunctie, 1/0.0003);// 1e4);
+    ForceTimer.attach_us(&tickerfunctie2, 1e4);
+    while(1)    {
+        while(LoopTimerFlag !=1);                  // Als LTF 0 is, blijft hij 0 en stopt de loop.
+        LoopTimerFlag = 0;    // Als voorgaand statement niet waar is, maken we de LTF weer 0 en gaan we verder met het programma
+        Led = 1;
+        Y_filt = 3*Filter1.step(a_in3.read());
+        Y_filt2 = Filter2.step(Y_filt);
+        Input = Inputberekening3(Force_nieuw); //Inputberekening(Boardpotmeter.read()); //Input2(Y_filtder); //Inputberekening(Boardpotmeter.read()); Input3(Force_nieuw);
+        time_ += time_increment;
+        Ref2 =  Referentieschaling(Referentie.read()/2,Input);       // De referentiewaarde is via deze functie (gevonden met metingen en polyfit) verbonden aan de afstand in centimeters voor waarden tussen 0 en 0.5.
+        Error = Errorberekening(Ref2, Input);
+        Ref_der = Referentie2-Ref_prev;
+        Input_der = Input-Input_prev;
+        Ref_prev = Referentie2;
+        Input_prev = Input;
+        Output = PID_controller(Error,3,2,1,0.01, Error_prev, Error_int);
+        Motor_controller();
+        if (LoopTimerFlag2==1) {
+            Afgeleide_Force();
+            Afgeleide_Plaats();
+            Force_nieuw = Y_filtder-Boardpotmeter2.read()*Plaats_der;
+        }
+        scopeSend();
+    }
+
+
+}
\ No newline at end of file