Astrid Schut / Mbed 2 deprecated Robot_Battle_met_ARVID

Dependencies:   biquadFilter MODSERIAL QEI Servo mbed

Fork of Robot_Battle_met_ARVID by Gaston Gabriël

Files at this revision

API Documentation at this revision

Comitter:
cmaas
Date:
Thu Nov 01 17:09:18 2018 +0000
Parent:
8:ec3ea0623620
Child:
10:2325e545ce11
Commit message:
KINEMATICS + CONTROL ADDED. COMPILING

Changed in this revision

QEI.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QEI.lib	Thu Nov 01 17:09:18 2018 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/aberk/code/QEI/#5c2ad81551aa
--- a/main.cpp	Thu Nov 01 16:40:11 2018 +0000
+++ b/main.cpp	Thu Nov 01 17:09:18 2018 +0000
@@ -1,15 +1,33 @@
-// EMG, RKI, PID, MOTOR
+// EMG + KINEMATICS + PID + MOTOR CONTROL
+
+//----------------~INITIATING-------------------------
 #include "mbed.h"
+
+// EMG                 --      DEPENDENCIES
 #include <iostream>
 #include "BiQuad.h"
 #include "BiQuadchains_zelfbeun.h"
 #include "MODSERIAL.h"
 
+// KINEMATICS          --       DEPENDENCIES
+#include "stdio.h"
+#define _USE_MATH_DEFINES
+#include <math.h>
+#define M_PI    3.14159265358979323846 /* pi */
+
+// PID CONTROLLER      --      DEPENDENCIES
+#include "BiQuad.h"
+#include "QEI.h"
+//#include "HIDScope.h"
+
+
+// GENERAL PIN DEFENITIONS
 MODSERIAL pc(USBTX, USBRX);
 
+// EMG     --      PIN DEFENITIONS 
 DigitalOut gpo(D0);
 
-DigitalIn button2(SW3);
+DigitalIn button2(SW3);  
 DigitalIn button1(SW2); //or SW2
 
 DigitalOut led1(LED_GREEN);
@@ -22,18 +40,126 @@
 Timer t; //timer try out for Astrid
 Timer timer_calibration; //timer for EMG calibration
 
-
-
 //Input system
 AnalogIn emg1(A0); //right biceps
 AnalogIn emg2(A1); //right triceps
 AnalogIn emg3(A2); //left biceps
 AnalogIn emg4(A3); //left triceps
 
+
+// PID  CONTROLLER     --        PIN DEFENITIONS 
+//AnalogIn button2(A4);
+//AnalogIn button1(A3);
+//DigitalIn button3(SW2);
+//DigitalIn button4(SW3);
+
+DigitalOut directionpin1(D7);   // motor 1
+DigitalOut directionpin2(D4);   // motor 2
+DigitalOut directionpin3(D13);  // motor 3
+PwmOut pwmpin1(D6);             // motor 1
+PwmOut pwmpin2(D5);             // motor 2
+PwmOut pwmpin3(D12);            // motor 3
+
+QEI encoder1 (D9, D8, NC, 8400, QEI::X4_ENCODING);
+QEI encoder2 (D11, D10, NC, 8400, QEI::X4_ENCODING); // motor 2
+QEI encoder3 (D3, D2, NC, 8400, QEI::X4_ENCODING);  // motor 3
+// HIDScope scope(2);
+
+//  PID - TICKERS
+Ticker ref_rot;
+Ticker show_counts;
+Ticker Scope_Data;
+
+//----------------GLOBALS--------------------------
+// GLOBALS EMG
+
 //Filtered EMG signals from the end of the chains
 volatile double emg1_filtered, emg2_filtered, emg3_filtered, emg4_filtered;
 int i = 0;
 
+//Define doubles for calibration and ticker
+double ts = 0.001; //tijdsstap
+double calibration_time = 55; //time EMG calibration should take
+
+volatile double temp_highest_emg1 = 0; //highest detected value right biceps
+volatile double temp_highest_emg2 = 0;
+volatile double temp_highest_emg3 = 0;
+volatile double temp_highest_emg4 = 0;
+
+//Doubles for calculation threshold
+double biceps_p_t = 0.4; //set threshold at percentage of highest value
+double triceps_p_t = 0.5; //set threshold at percentage of highest value
+volatile double threshold1;
+volatile double threshold2;
+volatile double threshold3;
+volatile double threshold4;
+
+// thresholdreads bools
+int bicepsR;
+int tricepsR;
+int bicepsL;
+int tricepsL;
+
+// VARIABLES ROBOT KINEMATICS
+// constants
+const float la = 0.256;         // lengte actieve arm
+const float lp = 0.21;          // lengte passieve arm
+const float rp = 0.052;         // straal van midden end effector tot hoekpunt
+const float rm = 0.23;          // straal van global midden tot motor
+const float a = 0.09;           // zijde van de driehoek
+const float xas = 0.40;         // afstand van motor 1 tot motor 3
+const float yas = 0.346;        // afstand van xas tot motor 2
+const float thetap = 0;         // rotatiehoek van de end effector
+
+
+// motor locatie
+const int a1x = 0;              //x locatie motor 1
+const int a1y = 0;              //y locatie motor 1
+const float a2x = (0.5)*xas;    // x locatie motor 2
+const float a2y = yas;          // y locatie motor 2
+const float a3x = xas;          // x locatie motor 3
+const int a3y = 0;              // y locatie motor 3
+
+// script voor het bepalen van de desired position aan de hand van emg (1/0)
+
+//  EMG OUTPUT
+int EMGxplus;
+int EMGxmin ;
+int EMGyplus;
+int EMGymin ;
+
+// Dit moet experimenteel geperfectioneerd worden
+float tijdstap = 0.005;      //nu wss heel langzaam, kan miss omhoog KEER V GEEFT VERANDERING IN POSITIE
+float v = 0.1;                // snelheid kan wss ook hoger
+
+float px = 0.2;     //starting x    // BOUNDARIES
+float py = 0.155;   // starting y   // BOUNDARIES
+
+// verschil horizontale as met de actieve arm
+float da1 = 1.619685; // verschil a1 hoek en motor
+float da2 = -0.609780;
+float da3 = 3.372859;
+
+// limits (since no forward kinematics)
+float upperxlim = 0.275; //36, 0.04, 0.315, -0.085niet helemaal naar requierments ff kijken of ie groter kan
+float lowerxlim = 0.10;
+float upperylim = 0.225;
+float lowerylim = 0.03; //0.03 is goed
+
+// VARIABLES PID CONTROLLER
+double PI = M_PI;// CHANGE THIS INTO M_PI
+double Kp = 14; //200 , 50
+double Ki = 0;   //1, 0.5
+double Kd = 3; //200, 10
+double Ts = 0.1; // Sample time in seconds
+double reference_rotation; //define as radians
+double motor_position;
+bool AlwaysTrue;
+
+
+//----------------FUNCTIONS--------------------------
+
+// ~~~~~~~~~~~~~~~~~~~EMG FUNCTIONS~~~~~~~~~~~~~~~~~~
 void emgsample()
 {
     //All EMG signal through Highpass
@@ -64,28 +190,8 @@
     emg2_filtered = lowp2.step(emg2_abs);
     emg3_filtered = lowp3.step(emg3_abs);
     emg4_filtered = lowp4.step(emg4_abs);
-
-
 }
 
-
-//Define doubles for calibration and ticker
-double ts = 0.001; //tijdsstap
-double calibration_time = 55; //time EMG calibration should take
-
-volatile double temp_highest_emg1 = 0; //highest detected value right biceps
-volatile double temp_highest_emg2 = 0;
-volatile double temp_highest_emg3 = 0;
-volatile double temp_highest_emg4 = 0;
-
-//Doubles for calculation threshold
-double biceps_p_t = 0.4; //set threshold at percentage of highest value
-double triceps_p_t = 0.5; //set threshold at percentage of highest value
-volatile double threshold1;
-volatile double threshold2;
-volatile double threshold3;
-volatile double threshold4;
-
 void CalibrationEMG()
 {
     //static float samples = calibration_time/ts;
@@ -137,15 +243,13 @@
         led1=1;
         led2=1;
         led3=1;
-
-
     }
-
+/*
     pc.printf("Highest value right biceps= %f \r\n", temp_highest_emg1);
     pc.printf("Highest value right triceps= %f \r\n", temp_highest_emg2);
     pc.printf("Highest value left biceps= %f \r\n", temp_highest_emg3);
     pc.printf("Highest value left triceps= %f \r\n", temp_highest_emg4);
-
+*/
 
     threshold1 = temp_highest_emg1*biceps_p_t;  //Right Biceps
     threshold2 = temp_highest_emg2*triceps_p_t; //Right Triceps
@@ -154,11 +258,6 @@
 }
 
 //Check if emg_filtered has reached their threshold
-int bicepsR;
-int tricepsR;
-int bicepsL;
-int tricepsL;
-
 void threshold_check()
 {
 
@@ -193,11 +292,8 @@
     pc.printf("Biceps Left = %i", bicepsL);
     pc.printf("Triceps Left = %i", tricepsL);
     */
-
-
 }
 
-
 //Activate ticker for Movement state, filtering and Threshold checking
 void movement_ticker_activator()
 {
@@ -210,6 +306,178 @@
     threshold_check_ticker.detach();
 }
 
+// ~~~~~~~~~~~~~~ROBOT KINEMATICS ~~~~~~~~~~~~~~~~~~
+
+// functie x positie
+float positionx(int EMGxplus,int EMGxmin)
+{
+    float EMGx = EMGxplus - EMGxmin;
+
+    float verplaatsingx = EMGx * tijdstap * v;
+    float pxnieuw = px + verplaatsingx;
+    // x limit
+    if (pxnieuw <= upperxlim && pxnieuw >= lowerxlim) {
+        px = pxnieuw;
+    } else {
+        if (pxnieuw >= lowerxlim) {
+            px = upperxlim;
+        } else {
+            px = lowerxlim;
+        }
+    }
+//printf("X eindpunt (%f) en verplaatsing: (%f)\n\r",px,verplaatsingx);
+    return px;
+}
+
+
+// functie y positie
+float positiony(int EMGyplus,int EMGymin)
+{
+    float EMGy = EMGyplus - EMGymin;
+
+    float verplaatsingy = EMGy * tijdstap * v;
+    float pynieuw = py + verplaatsingy;
+
+    // y limit
+    if (pynieuw <= upperylim && pynieuw >= lowerylim) {
+        py = pynieuw;
+    } else {
+        if (pynieuw >= lowerylim) {
+            py = upperylim;
+        } else {
+            py = lowerylim;
+        }
+    }
+//printf("Y eindpunt (%f) en verplaatsing: (%f) \n\r",py,verplaatsingy);
+    return (py);
+}
+
+
+//~~~~~~~~~~~~CALCULATIING MOTOR ANGLES ~~~~~~~~
+// arm 1 --> reference angle motor 1
+float hoek1(float px, float py) // input: ref x, ref y
+{
+    float c1x =  px - rp * cos(thetap +(M_PI/6));       // x locatie hoekpunt end-effector
+    float c1y = py - rp*sin(thetap+(M_PI/6));           // y locatie hoekpunt end-effector
+    float alpha1 = atan2((c1y-a1y),(c1x-a1x));          // hoek tussen horizontaal en lijn van motor naar bijbehorende end-effector punt
+    float psi1 = acos(( pow(la,2)-pow(lp,2)+pow((c1x-a1x),2)+pow((c1y-a1y),2))/(2*la*sqrt(pow ((c1x-a1x),2)+pow((c1y-a1y),2) ))); //Hoek tussen lijn van motor naar bijbehorende end=effector punt en actieve arm
+    float a1 = alpha1 + psi1 - da1;                          //hoek tussen horizontaal en actieve arm
+    //printf("arm 1 = %f \n\r",a1);
+    return a1;
+}
+
+// arm 2 --> reference angle motor 2
+float hoek2(float px, float py)
+{
+    float c2x =  px - rp * cos(thetap -(M_PI/2));
+    float c2y = py - rp*sin(thetap-(M_PI/2));
+    float alpha2 = atan2((c2y-a2y),(c2x-a2x));
+    float psi2 = acos(( pow(la,2)-pow(lp,2)+pow((c2x-a2x),2)+pow((c2y-a2y),2))/(2*la*sqrt(pow ((c2x-a2x),2)+pow((c2y-a2y),2) )));
+    float a2 = alpha2 + psi2 - da2;
+    //printf("arm 2 = %f \n\r",a2);
+    return a2;
+}
+
+//arm 3 --> reference angle motor 3
+float hoek3(float px, float py)
+{
+    float c3x =  px - rp * cos(thetap +(5*M_PI/6));
+    float c3y = py - rp*sin(thetap+(5*M_PI/6));
+    float alpha3 = atan2((c3y-a3y),(c3x-a3x));
+    float psi3 = acos(( pow(la,2)-pow(lp,2)+pow((c3x-a3x),2)+pow((c3y-a3y),2))/(2*la*sqrt(pow ((c3x-a3x),2)+pow((c3y-a3y),2) )));
+    float a3 = alpha3 + psi3 - da3;
+    //printf("arm 3 = %f \n\r",a3);
+    return a3;
+}
+
+// ~~~~~~~~~~~~~~PID CONTROLLER~~~~~~~~~~~~~~~~~~
+
+double PID_controller(double error)
+{
+    static double error_integral = 0;
+    static double error_prev = error; // initialization with this value only done once!
+    static BiQuad LowPassFilter(0.0640, 0.1279, 0.0640, -1.1683, 0.4241);
+
+    // Proportional part:
+    double u_k = Kp * error;
+
+    // Integral part
+    error_integral = error_integral + error * Ts;
+    double u_i = Ki * error_integral;
+
+    // Derivative part
+    double error_derivative = (error - error_prev)/Ts;
+    double filtered_error_derivative = LowPassFilter.step(error_derivative);
+    double u_d = Kd * filtered_error_derivative;
+    error_prev = error;
+
+    // Sum all parts and return it
+    return u_k + u_i + u_d;
+}
+
+
+// DIRECTON AND SPEED CONTROL
+void moter_control(double u)
+{
+
+    directionpin1= u > 0.0f; //eithertrueor false
+    if (fabs(u)> 0.7f) {
+        u = 0.7f;
+    } else {
+        u= u;
+    }
+    pwmpin1= fabs(u); //pwmduty cycle canonlybepositive, floatingpoint absolute value
+}
+
+void moter2_control(double u)
+{
+    directionpin2= u > 0.0f; //eithertrueor false
+    if (fabs(u)> 0.7f) {
+        u = 0.7f;
+    } else {
+        u= u;
+    }
+    pwmpin2= fabs(u); //pwmduty cycle canonlybepositive, floatingpoint absolute value
+}
+
+void moter3_control(double u)
+{
+    directionpin3= u > 0.0f; //eithertrueor false
+    if (fabs(u)> 0.7f) {
+        u = 0.7f;
+    } else {
+        u= u;
+    }
+    pwmpin3 = fabs(u); //pwmduty cycle canonlybepositive, floatingpoint absolute value
+}
+
+// CONTROLLING THE MOTOR
+void Motor_mover()
+{
+    double motor_position = encoder1.getPulses(); //output in counts
+    double reference_rotation = hoek1(px, py);
+    double error = reference_rotation - motor_position*(2*PI)/8400;
+    double u = PID_controller(error);
+    moter_control(u);
+
+    double motor_position2 = encoder2.getPulses(); //output in counts
+    double reference_rotation2 = hoek2(px, py);
+    double error_2 = reference_rotation2 - motor_position2*(2*PI)/8400;
+    double u_2 = PID_controller(error_2);
+    moter2_control(u_2);
+
+    double motor_position3 = encoder3.getPulses(); //output in counts
+    double reference_rotation3 = hoek3(px, py);
+    double error_3 = reference_rotation3 - motor_position3*(2*PI)/8400;
+    double u_3 = PID_controller(error_3);
+    moter3_control(u_3);
+
+
+}
+
+
+
+//-------------------- STATE MACHINE --------------------------
 enum states {MOTORS_OFF,CALIBRATION,HOMING,DEMO,MOVEMENT,CLICK};
 states currentState = MOTORS_OFF; //Chosen startingposition for states
 bool stateChanged = true; // Make sure the initialization of first state is executed
@@ -430,6 +698,9 @@
     }
 }
 
+// --------------------------MAIN--------------------
+
+
 int main()
 {
     //BiQuad Chain add
@@ -453,6 +724,9 @@
     led1 = 1;
     led2 = 1;
     led3 = 1;
+    
+    pwmpin1.period_us(60); // setup motor
+        ref_rot.attach(Motor_mover, 0.001);// HAS TO GO TO STATE MACHINE
 
     while (true) {
         ProcessStateMachine();