mbed motor control with emg

Dependencies:   Encoder HIDScope MODSERIAL QEI TextLCD biquadFilter mbed

Fork of 2MotorPID by Adam Bako

Revision:
2:69bfc537508f
Parent:
1:864a5f8bb886
Child:
3:c63c0a23ea21
--- a/main.cpp	Thu Nov 02 11:00:44 2017 +0000
+++ b/main.cpp	Thu Nov 02 18:37:18 2017 +0000
@@ -6,6 +6,8 @@
 #include "mbed.h"
 #include "QEI.h"
 #include "math.h"
+#include "iostream"
+#include "MODSERIAL.h"
 
 //intialize all pins
 PwmOut motor1(D5);
@@ -16,18 +18,21 @@
 QEI motor2Encoder (D12,D13, NC, 624,QEI::X4_ENCODING);
 DigitalIn button1(D8); //button to move cw
 DigitalIn button2(D9); //button to move ccw
+DigitalIn button3(D2);
+DigitalIn button4(D3);
+MODSERIAL pc(USBTX, USBRX);
 
 //initialize variables
 const float pi = 3.14159265358979323846; //value for pi
-double positionIncrement = 30; // increment of angle when button pressed (1 is a whole rotation (360 degrees))
+double positionIncrement = 20; // increment of angle when button pressed (1 is a whole rotation (360 degrees))
 
-const double motor1KP=1.3; //Proportional gain of motor1 PI control
-const double motor1KI=0.5; //Integral gain of motor1 PI control
-const double motor1KD=0.5; // Differential gain of motor1 PID control
+const double motor1KP=7.0; //Proportional gain of motor1 PI control
+const double motor1KI=3.0; //Integral gain of motor1 PI control
+const double motor1KD=3.0; // Differential gain of motor1 PID control
 
 const double motor2KP=1.3; //Proportional gain of motor1 PI control
 const double motor2KI=0.5; //Integral gain of motor1 PI control
-const double motor2KD=0.5; // Differential gain of motor1 PID control
+const double motor2KD=1.0; // Differential gain of motor1 PID control
 
 const double N=100; //LP filter coefficient
 const double encoderToMotor= 0.000119047619047619; //proportion of the rotation of the motor to the rotation of the encoder
@@ -45,12 +50,15 @@
 
 const float l1 = 460; //Length of the arm from base to joint 1 (arm1)   ENTER MANUALLY [mm]
 const float l2 = 450; //length of the arm from joint 1 to the end-effector.(arm2)   ENTER MANUALLY [mm]
-float x_des = 0; //(initial)desired x location of the end-effector (ee)
-float y_des = l1+l2; //(initial) desired y location of the end-effector (ee)
+float x_des = l1+l2; //(initial)desired x location of the end-effector (ee)
+float y_des = 0; //(initial) desired y location of the end-effector (ee)
 float xe, ye, D, phi, q2, beta, alpha, q1; //other variables used in calculating the angle for the motors
+float radDeg, rad2rot;
 //q1 is the angle for the base motor, q2 is the angle for the elbow motor, both in [rad]
 
-double PIDController(double error, const double Kp, const double Ki, const double Kd, double Ts, const double N,double &intError, double &DifError){
+
+double PIDController(double error, const double Kp, const double Ki, const double Kd, double Ts, const double N,double &intError, double &DifError)
+{
     const double a1 = -4/(N*Ts+2);
     const double a2 = -(N*Ts-2)/(N*Ts+2);
     const double b0 = (4*Kp + 4*Kd*N + 2*Ki*Ts + 2*Kp*N*Ts + Ki*N*pow(Ts,2))/(2*N*Ts + 4);
@@ -65,86 +73,133 @@
 }
 
 //Code for motor angles as a function of the length and positions of the arms, for a double revolutional joint arm in 2D plane
-void motorAngle(){
+void motorAngle()
+{
 //Function for making sure the arm does not exceed its maximum reach
 //if it tries to go beyond its max. reach
 //it will try to reach a point within reach in the same direction as desired.
+//Works for all 4 quadrants of the (unit) circle
     xe = x_des;
     ye = y_des;
-    while(pow(xe, 2)+pow(ye,2) > pow(l1+l2, 2)) {
-        if (y_des == 0) {   //make sure you do not divide by 0 if ye == 0
-            xe = x_des - 1;
-        } else {
-            xe = x_des - (x_des/y_des)/10;    //go to a smaller xe point on the same line
+
+    while(pow(xe, 2)+pow(ye, 2) > pow(l1+l2, 2)) {
+        if (xe > 0) {            //right hand plane
+            if (ye > 0) {        //positive x & y            QUADRANT 1
+                xe = x_des - (x_des/y_des);   //go to a smaller xe point on the same line
+                ye = y_des - (y_des/x_des);   //go to a smaller ye point on the same line
+            } else if (ye < 0) { //positive x, negative y    QUADRANT 2
+                xe = x_des - (x_des/y_des);   //smaller xe
+                ye = y_des + (y_des/x_des);   //greater ye
+            } else if (ye == 0) { //positive x, y == 0
+                xe = x_des - 1;                  //stay on the x-axis but at a smaller value (within reach)
+            }
+        } else if (xe < 0) {     //left hand plane
+            if (ye > 0) {        //negative x, positive y    QUADRANT 4
+                xe = x_des + (x_des/y_des);   //greater xe
+                ye = y_des - (y_des/x_des);   //smaller ye
+            } else if (ye < 0) { //negative x & y            QUADRANT 3
+                xe = x_des + (x_des/y_des);   //greater xe
+                ye = y_des + (y_des/x_des);   //greater ye
+            } else if (ye ==0) { //negative x, y == 0
+                xe = x_des + 1;                  //stay on the x-axis but at a greater value (within reach)
+            }
+
+        } else if (xe == 0) {    //on the y-axis
+            if (ye > 0) {        //x == 0, positive y
+                ye = y_des - 1;                  //stay on the y-axis but at a smaller value (within reach)
+            } else if (ye < 0) { //x == 0, negative y
+                ye = y_des + 1;                  //stay on the y-axis but at a greater value (within reach)
+                //x == 0 & y == 0 is a state that is unable to be reached, no need to cover that case
+            }
+            x_des = xe;
+            y_des = ye;
         }
-        if (x_des == 0) {   //make sure you do not divide by 0 if xe == 0
-            ye = y_des - 1;
-        } else {
-            ye = y_des - (y_des/x_des)/10;   //go to a smaller ye point on the same line
-        }
-        x_des = xe;
-        y_des = ye;
     }
 
+
 //from here on is the code for setting the angles for the motors
     D = ((pow(l1,2)+pow(l2,2))-pow(xe,2)-pow(ye,2))/(2*l1*l2); //D = cos(phi)
     phi = atan2(sqrt(1 - pow(D, 2)), D); //angle between arm1 and arm2, from arm1 to arm2 [rad]
     //Use atan2(sqrt(1 - pow(D, 2)),D) for "elbow down" position (like your right arm)
     q2 = pi - phi; //angle of arm2 with respect to the orientation of arm1, motor2 [rad]
     if (-pi/2 > q2) {       //Make sure the angle of motor2 doesn’t wreck our setup (max -90 or 90 degrees w.r.t. arm1)
-        q2 = -pi/2;
+        q2 = 0;
     } else if ( q2 > pi/2) {
         q2 = pi/2;
     }
     beta = atan2(ye, xe); //angle between "line from origin to ee" and x-axis [rad]
     alpha = atan2(l2*sin(q2), l1+l2*cos(q2)); //angle between "line from origin to ee" and arm1 [rad]
     q1 = beta - alpha; //angle of arm 1 with respect to the x-axis, motor1 [rad]
-    float 1radDeg = 180/pi; //amount of degrees in 1 radian
-    float rad2rot = 1radDeg/360;
+    radDeg = 180/pi;
+    rad2rot = radDeg/360;
     desiredAngle1 = q1 * rad2rot;
     desiredAngle2 = q2 * rad2rot;
+    pc.printf("\n New values \n\r");
+    pc.printf("xloc = %f, yloc = %f \n \r", xe, ye);
+    pc.printf("q1 = %f[rad], desA1 = %f [abs rot], q2 = %f[rad], desA2 = %f[abs rot]\n\r", q1, desiredAngle1, q2, desiredAngle2);
 }
 
-void motorButtonController(){
-    double position1= encoderToMotor*motor1Encoder.getPulses();
-    double posError1 = desiredAngle1 - position1;
+void motorButtonController()
+{
+    double angle1= encoderToMotor*motor1Encoder.getPulses();
+    double angleError1 = (desiredAngle1 - angle1)*1.25;
 
     //change direction based on error sign
-    if(PIDController( posError1, motor1KP, motor1KI,motor1KD, controllerTickerTime, N, motor1ErrorInt ,motor1ErrorDif)>0) {
+    if(PIDController( angleError1, motor1KP, motor1KI,motor1KD, controllerTickerTime, N, motor1ErrorInt ,motor1ErrorDif)>0) {
         motor1Dir=0;
     } else {
         motor1Dir =1;
     }
     //set motor speed based on PI controller error
-    motor1 = fabs(PIDController( posError1, motor1KP, motor1KI,motor1KD, controllerTickerTime, N, motor1ErrorInt ,motor1ErrorDif));
+    motor1 = fabs(PIDController( angleError1, motor1KP, motor1KI,motor1KD, controllerTickerTime, N, motor1ErrorInt ,motor1ErrorDif));
 
-    double position2= encoderToMotor*motor2Encoder.getPulses();
-    double posError2 = desiredAngle2 - position2;
+    double angle2= encoderToMotor*motor2Encoder.getPulses();
+    double angleError2 = desiredAngle2 - angle2;
 
     //change direction based on error sign
-    if(PIDController( posError2, motor2KP, motor2KI,motor2KD, controllerTickerTime, N, motor2ErrorInt ,motor2ErrorDif)>0) {
+    if(PIDController( angleError2, motor2KP, motor2KI,motor2KD, controllerTickerTime, N, motor2ErrorInt ,motor2ErrorDif)>0) {
         motor2Dir=0;
     } else {
         motor2Dir =1;
     }
     //set motor speed based on PI controller error
-    motor2 = fabs(PIDController( posError2, motor2KP, motor2KI,motor2KD, controllerTickerTime, N, motor2ErrorInt ,motor2ErrorDif));
+    motor2 = fabs(PIDController( angleError2, motor2KP, motor2KI,motor2KD, controllerTickerTime, N, motor2ErrorInt ,motor2ErrorDif));
 
 }
 
 int main()
 {
     wait(2);
+    xe = x_des;
+    ye = y_des;
+    pc.baud(115200);
+    pc.printf("\n Start up complete \n \r");
+    pc.printf("initial values: \n \r");
+    pc.printf("xloc = %f, yloc = %f \n \r", xe, ye);
+    pc.printf("q1 = %f[rad], desA1 = %f [abs rot], q2 = %f[rad], desA2 = %f[abs rot]\n \r", q1, desiredAngle1, q2, desiredAngle2);
     myControllerTicker.attach(&motorButtonController, controllerTickerTime);
     while(1) {
         if(!button1) {
-            y_des+=positionIncrement;
-            wait(0.5f);
+            y_des += positionIncrement;
+            motorAngle();
+            wait(0.3f);
         }
 
         if(!button2) {
-            y_des-=positionIncrement;
-            wait(0.5f);
+            y_des -= positionIncrement;
+            motorAngle();
+            wait(0.3f);
+        }
+
+        if(button3) {
+            x_des += positionIncrement;
+            motorAngle();
+            wait(0.3f);
+        }
+        if(button4) {
+            x_des -= positionIncrement;
+            motorAngle();
+            wait(0.3f);
         }
     }
 }
\ No newline at end of file