![](/media/cache/group/Diana_su_nero.jpg.50x50_q85.jpg)
Controller of the linear speed of the arm
Dependencies: QEI X_NUCLEO_IHM04A1
main.cpp
- Committer:
- LuCordeschi
- Date:
- 2019-05-27
- Revision:
- 4:0b8f77ae7af0
- Parent:
- 3:bbd927c5bfa9
- Child:
- 5:ef270034f9a5
File content as of revision 4:0b8f77ae7af0:
#include "mbed.h" #include "L6206.h" #include "BDCMotor.h" #include <math.h> #include "QEI.h" #define pulsesPerRev 45 Thread thread; QEI encoder(PB_4, PB_5,NC, pulsesPerRev, QEI::X4_ENCODING); //Check the datasheet to know what is the pulses for revolution value //From the library it requires to pass NC in the index space in the case it is not present InterruptIn endstop (PC_1); DigitalOut led1(LED1); InterruptIn button(USER_BUTTON); L6206 *motor; L6206 L6206(PinName EN_A, PinName EN_B, PinName IN_1A, PinName IN_2A, PinName IN_1B, PinName IN_2B) ; void go_to_zero(float maxAcceleration,float maxVelocity, float EncoderResolution, int pos_encoder, int k, int k1, int t) { motor->run(1, BDCMotor::BWD); k=0; while (t != 3) { k1 = k; k = k+maxAcceleration/EncoderResolution*100/maxVelocity; motor->set_speed(k1,k); pos_encoder = encoder.getPulses(); if (pos_encoder==0) { t++; } else { t=0; } } } //Pin can: CANRX PB8 and CANTX PB9 const PinName can1rxPins[] = {PB_8}; const PinName can1txPins[] = {PB_9}; CAN can1(can1rxPins[0], can1txPins[0]); CANMessage messageIn; CANMessage messageOut; void canRxIsr() { while(1) { if(can1.read(messageIn)) { led1 = !led1; printf("received\n\r"); } } } void command() { canRxIsr(); wait(0.5); } void sendMessage() { int status = can1.write(messageOut); printf("Send status: %d\r\n", status); } void controller(float v_normalized, float v_max,float v_actual, float a_max, float resolution, int pos_encoder, float position, float prev_position) { float v_request = abs(v_normalized*v_max); //*(100/v_max); //Command is think to be a normalized velocity float delta_v = v_request-v_actual; float k=0; prev_position=0; while (delta_v != 0) { /*Choosing a maximum acceleration, preferebly linked to the condition of the syste (motor, structure, Pwm and so on). Imposing an acceleration of 7.5 mm/s^2 to reach the v_max 2 secs are needed.*/ //Measure the new position if (v_normalized > 0){ motor->run(1, BDCMotor::FWD); float k1 = k; k = k+ a_max/( resolution)*100/(v_max); motor->set_speed(k1,k); } else if (v_normalized<0){ motor->run(1, BDCMotor::BWD); float k1 = k; k = k+a_max/resolution*100/v_max; motor->set_speed(k1,k); } else{ float k1 = k; k = k-a_max/resolution*100/v_max; motor->set_speed(k1,k); } pos_encoder = encoder.getPulses(); v_actual = (pos_encoder)*resolution; delta_v = v_request-v_actual; position = prev_position + pos_encoder /* to multiply for Rad angle made (in average) by the encoder for each pulse*/; prev_position = position; wait(0.1); } } int main (int argc,char **argv) { //Prendo il comando -> fisso un punto da raggiungere (Automatico) -> In tot step voglio tale duty cicle //Common variables float k = 0; float v_max = 15; //mm/s float pos_encoder = 0; //Posizione misurata dall'encoder float k1 = 0; float resolution; //sampling = resolution of the encoder int Auto = 0; int t=0; //Auto variables float finalDestination; //posizione da raggiungere RICEVUTA COME PARAMETRO float acceleration_range = 15; //n° step in accelerazione/decelerazione. Deciso da me float track_error = 1; float sens_error; //Error given by the amplitude of a step of the encoder float PWM_dutyReduct = 0; //Variables used in case of triangular control float acc_rangeReduct = 0; float Contr_reference = 0; //Is the starting tracking error, needed to impose the right form of controller //Manual variables float v_normalized = 0; //Manual command that indicates the direction and the magnitude of the velocity float v_actual = 0; //real velocity of the arm, computed through as incremental ratio float a_max = 7.5; //maximum accelerazion mm/s^2 float position=0; float prev_position=0; //Initialization: to write the right pins //L6206(PinName EN_flag_A, PinName EN_flag_B, PinName pwm_1A, PinName pwm_2A, PinName pwm_1B, PinName pwm_2B) : BDCMotor(), flag_A_irq(EN_flag_A), flag_B_irq(EN_flag_B), EN_flag_A(EN_flag_A), EN_flag_B(EN_flag_B), pwm_1A(pwm_1A), pwm_2A(pwm_2A), pwm_1B(pwm_1B), pwm_2B(pwm_2B) go_to_zero(a_max, v_max, resolution ,pos_encoder , k, k1, t); //Absolute position of the actuator (from can?) switch (Auto) { case 1: {/*The rover is in its automatic mode*/ //OTTENGO LA posizione iniziale dell'encoder startPos_encoder //Ottengo il comando Contr_reference = finalDestination-position; track_error = Contr_reference; while (track_error>sens_error) { if (Contr_reference>2*acceleration_range) { //Controllo trapezoidale if (track_error>(finalDestination-acceleration_range)) { k1 = k; k = (track_error/(finalDestination-acceleration_range))*100; //V da imporre motor->set_speed(k1,k); } else if (track_error<acceleration_range) { k1 = k; k = ((track_error)/acceleration_range)*100; //PWM_duty = 90*(1-k) motor->set_speed(k1,k); } //Leggo la pos_encoder attuale } else { //Controllo triangolare /*Si agisce in maniera analoga al caso non saturato ma si impone un duty cicle massimo minore In particolare la v_max è proporzionale alla dimensione dello spostamento con 90 che corrisponde a un intervallo pari a 40 e poi si defininisce il nuovo PWM_dutyReduct = interval*90/40 */ PWM_dutyReduct = (Contr_reference/(2*acceleration_range))*100; //A new variable is needed to indicate the range of acceleration (in this case is less than the acceleration_range) acc_rangeReduct = Contr_reference/2; if (track_error>acc_rangeReduct) { k1 = k; k = (track_error/(finalDestination-acc_rangeReduct))*PWM_dutyReduct; //costante di proporzionalità //PWM_duty = k1*PWM_dutyReduct motor->set_speed(k1,k); } else { k1 = k; k = (track_error/acc_rangeReduct)*PWM_dutyReduct; //PWM_duty = PWM_dutyReduct*(1-k) motor->set_speed(k1,k); } //Leggo la pos_encoder attuale } track_error = finalDestination-pos_encoder; //It is used as counter } } break; default: { //Manual control based on a velocity control with a position feedback. The following velocities are gotten through a [-1,1] command, //normalized velocity controller(v_normalized, v_max, v_actual, a_max, resolution, pos_encoder, position, prev_position); thread.start(command); while(1){ sendMessage(); //position } break; } } }