MODSERIAL PID controller edit
Dependencies: HIDScope MODSERIAL QEI biquadFilter mbed
Fork of PID_controller_Motor by
main.cpp.orig
- Committer:
- MBroek
- Date:
- 2016-10-28
- Revision:
- 30:457e42514c47
- Parent:
- 28:97b9e50c1180
File content as of revision 30:457e42514c47:
// 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); } }