Robot control

Dependencies:   HIDScope MODSERIAL QEI biquadFilter mbed

Files at this revision

API Documentation at this revision

Comitter:
Luuk
Date:
Tue Oct 31 11:21:16 2017 +0000
Parent:
6:acc2669ab20c
Commit message:
with calibration

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Mon Oct 30 15:32:52 2017 +0000
+++ b/main.cpp	Tue Oct 31 11:21:16 2017 +0000
@@ -7,10 +7,10 @@
 Serial pc (USBTX,USBRX);
 //HIDScope scope(2);
 
-PwmOut Motor1Vel(D6);            //motor 1 velocity control
+PwmOut Motor1pwm(D6);            //motor 1 velocity control
 DigitalOut Motor1Dir(D7);        //motor 1 direction
 PwmOut Motor2Vel(D5);            //motor 2 velocity control
-DigitalOut Motor2Dir(D4);        //motor 2 direction
+DigitalOut Motor2pwm(D4);        //motor 2 direction
 DigitalOut led1(D2);
 AnalogIn emg1(A0);
 AnalogIn emg2(A1);
@@ -18,6 +18,7 @@
 DigitalOut Button(D3);
 DigitalOut ledb(LED_BLUE);
 DigitalOut ledg(LED_GREEN);
+DigitalOut ledr(LED_RED);
 
 QEI encoder1(D10,D11,NC,16);      //define encoder pins
 QEI encoder2(D8,D9,NC,16);
@@ -30,14 +31,14 @@
 
 float Angle1,Angle2;              //real angles of the motor
 float XPos, YPos;                 //position of the end-effector
-float XSet, YSet;                 //desired position of the end-effector
+float XSet = 42, YSet = 0;                 //desired position of the end-effector
 float L = 30.0;                  //length of the arms of the robot
 const float Ts = 0.01;            //to control the tickers
 const float KV = 1;               //velocity constant, to scale the desired velocity of the end-effector
 const float P = 0.1;
 
-const float pi = 3.14159265359,PulsesPerRev = 16.0,GearRatio = 131.15*3;   //to convert pulses to radians 
-const float Angle1_0 = pi/4 ,Angle2_0 = pi/4;    //initial angle of the motors
+const float pi = 3.14159265359,PulsesPerRev = 16.0,GearRatio = 131.25*3;   //to convert pulses to radians 
+const float Angle1_0 = pi/2 ,Angle2_0 = 0;    //initial angle of the motors
 
 //variables and constants for the PID
 const float KP = 200, KI = 0.1, KD = 6, N = 100;
@@ -47,7 +48,8 @@
 double Y1, Y2;                // Y1 and Y2 are taken to conform Y to be used to change the set position X is also used to change the set position
 volatile double Y, X;          
 
-volatile bool ReturnIP = false;
+volatile bool ReturnHP = false;       //to keep calling HomePosition until getting to the setpoint
+volatile bool calibration = true;     //to call FirstMovement the first loop, when the program is run
 int counter = 0;                      //to count the time of inactivity
 
 double emg1filt()
@@ -98,7 +100,7 @@
     const float a2 = -(N*Ts-2)/(N*Ts+2);
     const float b0 = (4*KP+4*KD*N+2*KI*Ts+2*KP*N*Ts+KI*N*pow(Ts,2))/(2*N*Ts+4);
     const float b1 = (KI*N*pow(Ts,2)-4*KP-4*KD*N)/(N*Ts+2);
-    const float b2 = (4*KP+4*KD*N-2*KI*Ts-2*KP*N*Ts+2*KP*N*pow(Ts,2))/(2*N*Ts+4);
+    const float b2 = (4*KP+4*KD*N-2*KI*Ts-2*KP*N*Ts+2*KI*N*pow(Ts,2))/(2*N*Ts+4);
     
     float v = err-a1*v1-a2*v2;
     float u = abs(b0*v+b1*v1+b2*v2);
@@ -109,7 +111,7 @@
 void positionxy(float &Angle1,float &Angle2,float &XPos,float &YPos)
 { 
     Angle1 = -(encoder1.getPulses()/(2*PulsesPerRev*GearRatio))*2*pi + Angle1_0;   //angles of the arms driven by the motors in radians
-    Angle2 = -((encoder2.getPulses()/(2*PulsesPerRev*GearRatio))*2*pi + Angle2_0);
+    Angle2 = -(encoder2.getPulses()/(2*PulsesPerRev*GearRatio))*2*pi + Angle2_0;
     
     XPos = L*cos(Angle1)+L*cos(Angle2);    // calculate the position of the end-effector
     YPos = L*sin(Angle1)+L*sin(Angle2); 
@@ -137,31 +139,43 @@
     float Angle1Set = Angle1 + W1*Ts;   //calculate the set angle, angle at which the motor should be after 1 period with the calculated angular velocity
     float Angle2Set = Angle2 + W2*Ts;
     
-    float VELOCITY1 = PID(Angle1Set-Angle1,KP,KI,KD,Ts,N,M1_v1,M1_v2)*P;   //PID controller to choose the velocity of the motors
-    float DIRECTION1 = Direction(Angle1Set-Angle1);
-    float VELOCITY2 = PID(Angle2Set-Angle2,KP,KI,KD,Ts,N,M2_v1,M2_v2)*P;
-    float DIRECTION2 = !Direction(Angle2Set-Angle2);
-    Motor1Vel = VELOCITY1;
-    Motor1Dir = DIRECTION1;
-    Motor2Vel = VELOCITY2;
-    Motor2Dir = DIRECTION2;
-    pc.printf("Angle1: %f Angle2: %f XPos: %f YPos: %f \r\n", Angle1 ,Angle2, XPos, YPos );
+    Motor1pwm = PID(Angle1Set-Angle1,KP,KI,KD,Ts,N,M1_v1,M1_v2)*P;;
+    Motor1Dir = Direction(Angle1Set-Angle1);;
+    Motor2Vel = PID(Angle2Set-Angle2,KP,KI,KD,Ts,N,M2_v1,M2_v2)*P;;
+    Motor2pwm = !Direction(Angle2Set-Angle2);
+    pc.printf("Angle1: %f Angle2: %f XPos: %f YPos: %f \r\n", Angle1, Angle2, XPos, YPos );
     
 }
 
+void FirstMovement()//function to get the end-effector to the workspace (with safety margin) to go from there to the home position
+{
+    ledr = 0;
+    XSet = 30;
+    YSet = 0;
+    positionxy(Angle1,Angle2,XPos,YPos); 
+    MoveMotors(XSet,YSet);
+    
+    if(pow(XSet-XPos,2)+pow(YSet-YPos,2) < pow(0.2,2))
+    {//when the motor is close to the set angle(inside the safe workspace) go to the home position
+        ledr = 1;
+        calibration = false;
+        ReturnHP = true;
+    }
+}
+
 void GoToSet()
 {   
     ledg = 0;
     ledb = 1;
-    /*XSet += X;  // keep increasing the set point, depending on the input
-    YSet += Y;*/
-    XSet = 46;
+    XSet = 42+X*10;  // keep increasing the set point, depending on the input
+    //YSet += Y*0.1;
+    //XSet = 46;
     YSet = 0;
     MoveMotors(XSet,YSet);  
       
 }
 
-void InitialPosition()  //Go back to the initial position
+void HomePosition()  //Go back to the initial position
 {  
     ledb = 0;
     ledg = 1;
@@ -171,11 +185,11 @@
     positionxy(Angle1,Angle2,XPos,YPos);
     if(sqrt(pow(XPos-XSet,2)+pow(YPos-YSet,2))<AllowedError)  //to call the function until the end effector is at the initial position
     {
-        ReturnIP = false;
+        ReturnHP = false;
     }
     else
     {
-        ReturnIP = true; 
+        ReturnHP = true; 
     }
     //The following if-else statement is to choose a set point so that the end-effector does not go out of the work space while returning 
     if(XPos<X1)
@@ -203,27 +217,32 @@
 
 void CallFuncMovement()   //decide which function has to be used
 {   
+
     X = emg1.read(); 
     Y = emg2.read();                   
     positionxy(Angle1,Angle2,XPos,YPos);     //calculate the position of the end point
     if (Button == 1)
     {  //stop motors
-        Motor1Vel = 0;
-        Motor2Vel = 0;
+        Motor1pwm = 0;
+        Motor2pwm = 0;
     }
-    else if (ReturnIP)
+    else if(calibration)
+    {
+        FirstMovement();  
+    }
+    else if(ReturnHP)
     {   //when InitialPosition is called, keep calling until the end-effector gets there;
-        InitialPosition();
+        HomePosition();
         counter = 0;
     }
     else if (sqrt(pow(XPos-300,2) + pow(YPos,2)) > 280 || sqrt(pow(XPos,2) + pow(YPos,2)) > 570 || sqrt(pow(XPos,2) + pow(YPos-300,2)) > 320 || sqrt(pow(XPos,2) + pow(YPos+300,2)) > 320 ) 
     { // limit so that the robot does not break. 
-        InitialPosition();
+        HomePosition();
         counter = 0;    
     }
     else if (counter >= 200)
     {  //after 2 seconds of inactivity the robot goes back to the initial position
-        InitialPosition();
+        HomePosition();
         counter = 0;
     }
     else if (X > 0 || Y != 0)