MODSERIAL PID controller edit

Dependencies:   HIDScope MODSERIAL QEI biquadFilter mbed

Fork of PID_controller_Motor by BioBitches TN

Revision:
28:97b9e50c1180
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp.orig	Fri Oct 28 07:56:12 2016 +0000
@@ -0,0 +1,422 @@
+
+
+// HET DEFINIEREN VAN ALLES ==========================================================================================
+
+// Includen van alle libraries ---------------------------------------
+#include "mbed.h"
+#include "MODSERIAL.h"
+#include "QEI.h"
+#include "math.h"
+#include "HIDScope.h"
+
+// Definieren van de HIDscope ----------------------------------------
+HIDScope scope(3);               
+
+
+// Definieren van de Serial en Encoder -------------------------------
+MODSERIAL pc(USBTX, USBRX);
+#define SERIALBAUD 115200
+
+QEI encoder_motor1(D10,D11,NC,8400, QEI::X4_ENCODING);
+QEI encoder_motor2(D12,D13,NC,8400, QEI::X4_ENCODING);
+
+
+// Definieren van de Motorpins ---------------------------------------
+DigitalOut motor1_direction_pin(D7);
+PwmOut motor1_speed_pin(D6);
+
+DigitalOut motor2_direction_pin(D4);
+PwmOut motor2_speed_pin(D5);
+
+
+//Definieren van bord-elementen --------------------------------------
+InterruptIn motor_switch_button(D3);
+InterruptIn state_switch_button(D2);
+DigitalIn EMG_sim1(SW2);
+DigitalIn EMG_sim2(SW3);
+
+AnalogIn pot1(A1);                              // Dit is de gesimuleerde emg1
+AnalogIn pot2(A2);                              // Dit is de gesimuleerde emg2
+
+
+DigitalOut ledred(LED_RED, 1);
+DigitalOut ledgreen(LED_GREEN, 1);
+DigitalOut ledblue(LED_BLUE, 1);
+
+
+//Definieren van de tickers ------------------------------------------
+Ticker motor_ticker;                        // Deze ticker activeert het motor_runs programma, dit leest motor pos en ref pos uit, rekent de PID uit en stuurt met dit de motoren
+Ticker hidscope_ticker;
+
+
+
+// HET VASTSTELLEN VAN ALLE TE GEBRUIKEN VARIABELEN EN CONSTANTEN ======================================================
+
+enum states_enum{off, init, run};                   // De states waar de main loop doorheen loopt, off is uit, init is intialiseren en run is het aanturen vd motoren met emg.
+states_enum states = off;
+
+double ref_pos_prev_m1 = 0.0;                          // De initiele ref_pos_pref
+double ref_pos_prev_m2 = 0.0;
+
+int counts1;                                // Pulses van motoren
+int counts2;
+
+const double pi = 3.14159265358979323846264338327950288419716939937510;     // pi
+const double rad_per_count = (2.0*pi)/8400.0;       // Aantal rad per puls uit encoder
+
+const double radius_tandwiel = 0.008;
+const double meter_per_count = rad_per_count * radius_tandwiel;           // Het aantal meter dat het karretje aflegt per puls, DIT IS NOG ONBEKEND!!!
+
+const double v_max_karretje = 8.4*radius_tandwiel;                  // Maximale snelheid karretje, gelimiteerd door de v_max vd motor
+
+double error1_int = 0.00000;                 // Initiele error integral waardes
+double error2_int = 0.00000;
+
+const double T_motor_function = 0.1;           // Periode van de frequentie van het aanroepen van onder andere positiechecker (get_position) en de rest vd motor functie
+
+volatile bool flag1 = false, flag2 = false;   // De flags voor de functies aangeroepen door de tickers
+
+const double Kp_1 = 0.5;                    // De PID variablen voor motor 1
+const double Kd_1 = 0.1;
+const double Ki_1 = 0.1;
+
+const double Kp_2 = 1.0;                    // De PID variablen voor motor 2
+const double Kd_2 = 0.0;
+const double Ki_2 = 0.0;
+
+const double vrijheid_m1_rad = 0.5*pi;      // Dit is de uiterste postitie vd arm in radialen
+const double vrijheid_m2_meter = 0.5;         // Dit is de helft vd arm, dit is wat het karretje heen en weer kan bewegen
+
+const double initial_pos_m1 = vrijheid_m1_rad;                // Startin posities van de motoren
+const double initial_pos_m2 = 0; 
+
+double position_motor2; 
+double position_motor1;
+double position_motor2_prev = initial_pos_m2;    
+
+double PID_output_1 = 0.0;                      // De eerste PID_output, deze is nul anders gaan de motoren draaien
+double PID_output_2 = 0.0;
+double PID_output_2_1 = 0.0;
+
+double error_prev_1 = 0.0;                      // De initiele previous error
+double error_int_1 = 0.0;                       // De initiele intergral error
+
+double error_prev_2 = 0.0;
+double error_int_2 = 0.0;
+
+double reference_pos_m2;                      // De reference positie waar de motor heen wil afhankelijk van het EMG signaal
+double reference_pos_m1;
+
+enum which_motor{motor1, motor2};               // enum van de motoren
+which_motor motor_that_runs = motor1;
+
+
+
+
+
+
+// ALLE FUNCTIES BUITEN DE MAIN-LOOP ====================================================================================
+
+
+// De statechanger -----------------------------------------------------------
+void state_changer(){
+    if(states == off){
+        states = init;
+    }
+    else if(states == init){
+        states = run;
+    }
+    else{
+        states = off;
+    }
+}
+
+
+// Functie voor het switchen tussen de motors ------------------------------
+void motor_switch(){
+    if(motor_that_runs == motor1){
+        motor_that_runs = motor2;
+        }
+            else{
+                motor_that_runs = motor1;
+            }
+}
+
+
+
+// Functie voor het vinden van de positie van motor 1 ---------------------
+double get_position_m1(const double radpercount){          //returned de positie van de motor in radialen (positie vd arm in radialen)
+    counts1 = encoder_motor1.getPulses();           // Leest aantal pulses uit encoder af
+    return radpercount * counts1 + initial_pos_m1;      // rekent positie motor1 uit en geeft deze als output vd functie
+}
+
+
+// Functie voor vinden van de positie van motor 2 -----------------------------
+double get_position_m2(const double meterpercount, double mot_pos_prev){     // returned de positie van het karretje in meter
+    double mot_pos;
+    counts2 = encoder_motor2.getPulses();               // leest aantal pulses vd encoder af
+    mot_pos = meterpercount * counts2 + mot_pos_prev;
+    encoder_motor2.reset();
+    mot_pos_prev = mot_pos;
+    return mot_pos_prev;                     // rekent de positie van het karretje uit en geeft dit als output vd functie
+}
+
+
+// Functie voor het vinden van de reference position van motor 1 --------------------
+double get_reference_position_m1(double &ref_pos_prev, const double vrijheid_rad){
+    double ref_pos;
+    int final_signal = EMG_sim1.read() - EMG_sim2.read();     // Het uiteindelijke signaal uit de emg als output zit is -1, 0 of 1.
+    switch(final_signal){
+        case 0 :
+            ref_pos = ref_pos_prev;
+            break;
+        case 1 :
+            ref_pos = ref_pos_prev + T_motor_function*vrijheid_rad;         // Dit dwingt af dat de ref pos veranderd met ong 0.5 rad/s
+            break;
+        case -1 :
+            ref_pos = ref_pos_prev - T_motor_function*vrijheid_rad;
+            break;
+    }
+    if(ref_pos >= vrijheid_rad){
+        ref_pos = vrijheid_rad;
+    }
+    if(ref_pos <= -vrijheid_rad){
+        ref_pos = -vrijheid_rad;
+    }
+    ref_pos_prev = ref_pos;
+    return ref_pos_prev;            // vrijheid_rad is de uiterste positie vd arm in radialen                                                                    
+}
+
+
+// Functie voor het vinden van de reference position van motor 2 --------------------
+double get_reference_position_m2(double &ref_pos_prev, const double vrijheid_meter){
+    double ref_pos;
+    int final_signal = EMG_sim1.read() - EMG_sim2.read();     // Het uiteindelijke signaal uit de emg als output zit is -1, 0 of 1.
+    switch(final_signal){
+        case 0 :
+            ref_pos = ref_pos_prev;
+            break;
+        case 1 :
+            ref_pos = ref_pos_prev + T_motor_function*v_max_karretje;           // Hierdoor veranderd de ref_pos met de maximale snelheid vd motor (karretje)
+            break;
+        case -1 :
+            ref_pos = ref_pos_prev - T_motor_function*v_max_karretje;
+            break;
+    }
+    if(ref_pos >= vrijheid_meter){
+        ref_pos = vrijheid_meter;
+    }
+    if(ref_pos <= 0){
+        ref_pos = 0;
+    }
+    ref_pos_prev = ref_pos;
+    return ref_pos_prev;                                                                                
+}
+
+
+// HIDScope functie ----------------------------------------------------------------------
+void set_scope(double input1, double input2, double input3){
+    scope.set(0, input1); 
+    scope.set(1, input2);
+    scope.set(2, input3);
+    scope.send();
+}
+
+
+// De PID-controller voor de motors -------------------------------------------------
+double PID_controller(double ref_pos, double mot_pos, double &e_prev, double &e_int, const double Kp, const double Kd, const double Ki){
+    double error = ref_pos - mot_pos;       // error uitrekenen
+    double error_dif = (error-e_prev)/T_motor_function;      // De error differentieren
+    //error_dif = .....       // Filter biquad poep
+    e_prev = error;                                 // Hier wordt de error opgeslagen voor de volgende keer
+    e_int = e_int + T_motor_function*error;             // De error integreren
+    return Kp*error + Ki*e_int + Kd*error_dif;       // De uiteindelijke PID output
+}
+       
+
+// Motor 1 besturen ---------------------------------------------------------------------
+void set_motor1(double motor_input){        // functie die de motor aanstuurt mt als input de PID-output
+    if (motor_input >= 0){                  // Dit checkt welke kant de motor op moet draaien
+        motor1_direction_pin = 1;           // Clockwise
+    }
+        else {
+            motor1_direction_pin = 0;       // CounterClockwise
+        }
+    if (fabs(motor_input)>1){               // Dit fixed de PwmOutput op maximaal 1
+        motor_input = 1;
+    }
+    motor1_speed_pin = fabs(motor_input);   // Dit geeft de uiteindelijke input door aan de motor
+}
+ 
+ 
+// Motor 2 besturen ---------------------------------------------------------------------
+void set_motor2(double motor_input){        // functie die de motor aanstuurt mt als input de PID-output
+    if (motor_input >= 0){                  // Dit checkt welke kant de motor op moet draaien
+        motor2_direction_pin = 1;           // Clockwise
+    }
+        else {
+            motor2_direction_pin = 0;       // CounterClockwise
+        }
+    if (fabs(motor_input)>1){               // Dit fixed de PwmOutput op maximaal 1
+        motor_input = 1;
+    }
+    motor2_speed_pin = fabs(motor_input);   // Dit geeft de uiteindelijke input door aan de motor
+}
+
+
+// De go-flag functies -----------------------------------------------------------------
+void flag1_activate(){flag1=true;}           // Activeert de flag
+void flag2_activate(){flag2=true;}   
+
+
+// Dit doet de robot als hij niets doet ------------------------------------------------------
+void robot_is_off(){
+    ledgreen.write(1);              
+    ledred.write(0);               // Indicator ik ben uit
+    motor1_speed_pin = 0;           // Uitzetten vd motoren
+    motor2_speed_pin = 0;
+}
+
+
+// De initialiseren functie ------------------------------------------------------------
+void initialise(){       // Deze functie laat de motor van een vaste uiterste positie (fysisch limiet) naar het middelpunt draaien.
+    ref_pos_prev_m1 = initial_pos_m1;
+    ref_pos_prev_m2 = initial_pos_m2;
+    ledgreen.write(0);
+    encoder_motor1.reset();
+    encoder_motor2.reset();             
+    motor1_speed_pin = 0;
+}  
+
+
+// De functie die de motoren aanstuurt -------------------------------------------------
+void running_motors(){              // Deze functie kijkt welke motor moet draaien en rekent dan de PID uit en geeft dit door aan de motor input functie
+    if (flag1){
+            flag1 = false;
+            ledred.write(1);
+            switch (motor_that_runs){
+                case motor1 :      // In deze case draait alleen motor 1
+                    reference_pos_m1 = get_reference_position_m1(ref_pos_prev_m1, vrijheid_m1_rad);
+                    position_motor1 = get_position_m1(rad_per_count);
+                    PID_output_1 = PID_controller(reference_pos_m1, position_motor1, error_prev_1, error_int_1, Kp_1, Kd_1, Ki_1);
+                    //PID_output_2_1 = PID_controller(-reference_pos_m1, get_position_m1(rad_per_count), error_prev_1, error_int_1, Kp_1, Kd_1, Ki_1); // Zorgt er voor dat motor2 meedraait met motor1 
+                    set_motor1(PID_output_1);
+                    set_motor2(PID_output_1);
+                    encoder_motor2.reset();
+                    break;
+                case motor2 :
+                    reference_pos_m2 = get_reference_position_m2(ref_pos_prev_m2, vrijheid_m2_meter);
+                    position_motor2 = get_position_m2(meter_per_count, position_motor2_prev);
+                    PID_output_2 = PID_controller(reference_pos_m2, position_motor2, error_prev_2, error_int_2, Kp_2, Kd_2, Ki_2);
+                    PID_output_1 = PID_controller(reference_pos_m1, get_position_m1(rad_per_count), error_prev_1, error_int_1, Kp_1, Kd_1, Ki_1);   // Zorgt ervoor dat motor1 op de dezelfde positie blijft als motor 2 draait.
+                    set_motor2(PID_output_2);
+                    set_motor1(PID_output_1);
+                    position_motor2_prev = position_motor2;
+                    break;
+            }
+    }
+}
+
+
+// De HIDscope debug functie ----------------------------------------------------------------
+void call_HIDscope(double input_1, double input_2, double input_3){             // Deze functie roept de HIDscope aan
+        if (flag2){
+            flag2 = false;
+            set_scope(input_1, input_2, input_3);
+        }
+}
+
+
+
+
+// DE MAIN =================================================================================================================
+int main()
+{
+    pc.baud(SERIALBAUD);
+    
+    state_switch_button.fall(&state_changer);        // Switcht states
+    motor_switch_button.fall(&motor_switch);        // Switcht motors
+    
+
+    
+    motor_ticker.attach(&flag1_activate, T_motor_function);                  // Activeert de go-flag van motor positie 
+    hidscope_ticker.attach(&flag2_activate,0.01);   // Leest ref pos en mot pos uit, rekent PID uit en stuurt motoren aan.
+    
+    while(1){
+        switch(states){
+            case off :                    // Dan staat het programma stil en gebeurt er niks
+                robot_is_off();
+                break;
+            case init :          // Hier voert hij alleen het initialiseren van motor 1 uit
+                initialise();      
+                break;
+            case run :
+                running_motors();       // Hier voert hij het programma voor het aansturen vd motors uit
+                break;
+            
+        }
+        call_HIDscope(PID_output_1, reference_pos_m1, position_motor1);
+    }  
+}
+        
+        
+        
+        
+        
+        
+        
+        
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+