DemoState with IK and MotorControl and input vx_des and vy_des with potmeter1 and button2
Dependencies: FastPWM MODSERIAL Matrix MatrixMath mbed QEI
main.cpp
- Committer:
- 1856413
- Date:
- 2018-11-01
- Revision:
- 0:550f6e86da32
- Child:
- 1:2219a519e2bf
File content as of revision 0:550f6e86da32:
#include "mbed.h" #include "FastPWM.h" #include "MODSERIAL.h" #include "Matrix.h" #include "QEI.h" #include <math.h> MODSERIAL pc(USBTX, USBRX); DigitalOut motor1DirectionPin(D7); DigitalOut motor2DirectionPin(D4); DigitalOut Led(LED_GREEN); DigitalIn button2(SW3); FastPWM motor1MagnitudePin(D6); FastPWM motor2MagnitudePin(D5); AnalogIn potMeter1(A4); AnalogIn potMeter2(A5); InterruptIn button2(D3); QEI Encoder1 (D12, D13, NC, 64, QEI::X4_ENCODING); QEI Encoder2 (D10, D11, NC, 64, QEI::X4_ENCODING); // Tickers Ticker startMotor; Ticker printTicker; //------------------------------------------------------------------------------ //Inverse Kinematics const double L0 = 0.1; // Horizontal length from base to first joint [m] NAMETEN!! const double L1 = 0.3; // Length link 1 [m] NAMETEN!! const double L2 = 0.3; // Length link 2 [m] NAMETEN!! const double L3 = 0.1; // Vertical length from base to first joint [m] NAMETEN! volatile double q1 = 0.0; // Starting reference angle of first link [rad] volatile double q2 = -(0.5*3.14); // Starting reference angle of second link wrt first link [rad] double t = 2.0; // Time interval [s] SHOULD BE REPLACED SAMPLING TIJD!! Matrix Q_set(2,1); // Setting a matrix for storing the angular velocities [rad/sec] Matrix J(2,2); // Setting a matrix for the Jacobian Matrix V(2,1); // Setting a matrix for storing the EMG-measured velocities // Motor Control volatile double potMeterPosition1 = 0.0; volatile double potMeterPosition2 = 0.0; volatile double motorValue1 = 0.01; volatile double motorValue2 = 0.01; volatile double Kp = 0.34; //dit maken we variabel, dit zorgt voor een grote of kleine overshoot volatile double Ki = 0.0; //dit moeten we bepalen met een plot bijvoorbeeld volatile double Kd = 0.0; volatile double Ts = 0.01; // SAMPLING TIJD!! //------------------------------------------------------------------------------ // Potmeter values TO DETERMINE VX_DES, VY_DES double GetPotMeterPosition1() // Measure the current Potmeter1 value { double potMeter1In = potMeter1.read(); potMeterPosition1 = 8.0*3.14*potMeter1In - 4.0*3.14 ; // Reference value y, scaled to -4 to 4 revolutions return potMeterPosition1; } double GetPotMeterPosition2() // Measure the current Potmeter2 value { double potMeter2In = potMeter2.read(); potMeterPosition2 = 8.0*3.14*potMeter2In - 4.0*3.14 ; return potMeterPosition2; } // Drive the motor double FeedbackControl1(double Error1) // Dit moet zo geschreven worden dat het zowel met EMG als met potmeters gebruikt kan worden { static double Error_integral1 = 0; static double Error_prev1 = Error1; //static BiQuad LowPassFilter(..., ..., ..., ..., ...) // Proportional part: //van 0 tot 20, waardes rond de 5 zijn het beste (minder overshoot + minder trilling motor beste combinatie hiervan) double u_k1 = Kp * Error1; // Integral part: Error_integral1 = Error_integral1 + Error1 * Ts; double u_i1 = Ki * Error_integral1; // Derivative part double Error_derivative1 = (Error1 - Error_prev1)/Ts; double u_d1 = Kd * Error_derivative1; Error_prev1 = Error1; // Sum all parts and return it return u_k1 + u_i1 + u_d1; //motorValue } double FeedbackControl2(double Error2) { static double Error_integral2 = 0; static double Error_prev2 = Error2; //static BiQuad LowPassFilter(..., ..., ..., ..., ...) // Proportional part: //van 0 tot 20, waardes rond de 5 zijn het beste (minder overshoot + minder trilling motor beste combinatie hiervan) double u_k2 = Kp * Error2; // Integral part: Error_integral2 = Error_integral2 + Error2 * Ts; double u_i2 = Ki * Error_integral2; // Derivative part double Error_derivative2 = (Error2 - Error_prev2)/Ts; double u_d2 = Kd * Error_derivative2; Error_prev2 = Error2; // Sum all parts and return it return u_k2 + u_i2 + u_d2; //motorValue } void SetMotor1(double motorValue1) { // Given -1<=motorValue<=1, this sets the PWM and direction // bits for motor 1. Positive value makes motor rotating // clockwise. motorValues outside range are truncated to // within range // 0 = clockwise motor direction // 1 = counterclockwise motor direction if (motorValue1 >=0) { motor1Direction=0; } else { motor1Direction=1; } if (fabs(motorValue1)>1) { motor1PWM = 1; } else { motor1PWM = fabs(motorValue1); } } void SetMotor2(double motorValue2) { // Given -1<=motorValue<=1, this sets the PWM and direction // bits for motor 1. Positive value makes motor rotating // clockwise. motorValues outside range are truncated to // within range // 0 = counterclockwise motor direction // 1 = clockwise motor direction if (motorValue2 >=0) { motor2Direction=1; } else { motor2Direction=0; } if (fabs(motorValue2)>1) { motor2PWM = 1; } else { motor2PWM = fabs(motorValue2); } } void MeasureAndControl1(void) { // This function determines the desired velocity, measures the // actual velocity, and controls the motor with // a simple Feedback controller. Call this from a Ticker. potMeterPosition1 = q1; currentPosition1 = MeasureEncoderPosition1(); motorValue1 = FeedbackControl1(potMeterPosition1 - currentPosition1); SetMotor1(motorValue1); } void MeasureAndControl2(void) { // This function determines the desired velocity, measures the // actual velocity, and controls the motor with // a simple Feedback controller. Call this from a Ticker. potMeterPosition2 = q2; currentPosition2 = MeasureEncoderPosition2(); motorValue2 = FeedbackControl2(potMeterPosition2 - currentPosition2); SetMotor2(motorValue2); //------------------------------------------------------------------------------ // Kinematic functions Matrix ComputeJ(void){ double a = -sin(q2)/(L1*cos(q1)*sin(q2)-L1*cos(q2)*sin(q1)); double b = cos(q2)/(L1*cos(q1)*sin(q2)-L1*cos(q2)*sin(q1)); double c = (L1*sin(q1)+L2*sin(q2))/(L1*L2*cos(q1)*sin(q2)-L1*L2*cos(q2)*sin(q1)); double d = -(L1*cos(q1)+L2*cos(q2))/(L1*L2*cos(q1)*sin(q2)-L1*L2*cos(q2)*sin(q1)); J << a << b << c << d; return J; } Matrix ComputeV(void){ V.add(1,1,vx_des); // Add desired x-velocity in V V.add(2,1,vy_des); // Add desired y-velocity in V return V; } double IntegrateQ1(){ q1 = q1 + (Q_set(1,1))*t; // new value for q1 return q1; } double IntegrateQ2(){ q2 = q2 + (Q_set(2,1))*t; // new value for q2 return q2; } Matrix ComputeQ_set(void){ float a = J(1,1); float b = J(1,2); float c = J(2,1); float d = J(2,2); float e = V(1,1); float f = V(2,1); float first_row = a*e + b*f; float second_row = c*e + d*f; Q_set.add(1,1,first_row); Q_set.add(2,1,second_row); return Q_set; } int main(){ //led = 0; pc.baud(115200); pc.printf("\r\nDoet het script het?\r\n"); // Compute Jacobian J = ComputeJ(); J.print(); pc.printf("\r\n"); // Compute velocities V = ComputeV(); V.print(); pc.printf("\r\n"); // Multiplying matrix J and V and storing in array Q_set Q_set = ComputeQ_set(); // velocity to position q1 = IntegrateQ1(); q2 = IntegrateQ2(); /*if (q1 > ... && < ...) { TurnMotorsOff; /go to failure mode } if (q2 > ... && < ...) { TurnMotorsOff/go to failure mode }*/ pc.printf("New position q1: %f, New Position q2: %f", q1, q2); } int main() { currentPosition1 = MeasureEncoderPosition1(); // You want to know the current angle of the motors to get the right Jacobian currentPosition2 = MeasureEncoderPosition2(); // You want to know the current angle of the motors to get the right Jacobian J = ComputeJ(); // Compute matrix J (inverse Jacobian, and Twist is already left out) V = ComputeV(); // Compute matrix V (stores the desired velocities obtained from the EMG signal) Q_set = ComputeQ_set(); // Compute Q_set (stores Q1 and Q2) IntegrateQ1(); // Compute required angle to go to desired position of end-effector IntegrateQ2(); // Compute required angle to go to desired position of end-effector if (q1 < 1.047) { // q1 can only be smaller than 1.047 rad q1 = q1; } else { // If value of q1 is greater than 1.047 rad, then stay at maximum angle q1 = 1.047; } if (q2 < 0.61) { // q2 cannot be smaller than 0.61 rad q2 = 0.61; // Stay at mimimum angle } else if (q2 > 1.57) { // q2 cannot be greater than 1.57 rad q2 = 1.57; // Stay at maximum angle } else { // If q2 is in the right range, let calculated q2 be q2 q2 = q2; } // Determine error and add PID control double errorIK1 = ErrorInverseKinematics1(); // Determine difference between current angle motor 1 and desired angle double errorIK2 = ErrorInverseKinematics2(); // Determine difference between current angle motor 2 and desired angle // Determine motorValues motorValue1 = FeedbackControl1(errorIK1); // Calculate motorValue1 motorValue2 = FeedbackControl2(errorIK2); // Calculate motorValue2 // Make Motor move SetMotor1(motorValue1); SetMotor2(motorValue2); while (true){} }