MODSERIAL PID controller edit
Dependencies: HIDScope MODSERIAL QEI biquadFilter mbed
Fork of PID_controller_Motor by
Diff: main.cpp.orig
- 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); + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +