![](/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@1:97a0f449f19d, 2019-05-03 (annotated)
- Committer:
- LuCordeschi
- Date:
- Fri May 03 15:07:35 2019 +0000
- Revision:
- 1:97a0f449f19d
- Parent:
- 0:839902368a34
- Child:
- 2:fc8d58f9f5ce
Speed arm controller;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
LuCordeschi | 0:839902368a34 | 1 | #include "mbed.h" |
LuCordeschi | 1:97a0f449f19d | 2 | #include "L6206.h" |
LuCordeschi | 0:839902368a34 | 3 | #include "BDCMotor.h" |
LuCordeschi | 0:839902368a34 | 4 | #include <math.h> |
LuCordeschi | 0:839902368a34 | 5 | |
LuCordeschi | 1:97a0f449f19d | 6 | Thread thread; |
LuCordeschi | 1:97a0f449f19d | 7 | |
LuCordeschi | 1:97a0f449f19d | 8 | |
LuCordeschi | 1:97a0f449f19d | 9 | void encoder() { |
LuCordeschi | 1:97a0f449f19d | 10 | //Read the position by the encoder and save it in pos_encoder |
LuCordeschi | 1:97a0f449f19d | 11 | wait(0.1); |
LuCordeschi | 1:97a0f449f19d | 12 | } |
LuCordeschi | 1:97a0f449f19d | 13 | void command() { |
LuCordeschi | 1:97a0f449f19d | 14 | //Read the command (at the moment considered by me a normalized velocity) |
LuCordeschi | 1:97a0f449f19d | 15 | wait(0.2); |
LuCordeschi | 1:97a0f449f19d | 16 | } |
LuCordeschi | 0:839902368a34 | 17 | int main (int argc,char **argv) { |
LuCordeschi | 0:839902368a34 | 18 | |
LuCordeschi | 1:97a0f449f19d | 19 | //Prendo il comando -> fisso un punto da raggiungere (Automatico) -> In tot step voglio tale duty cicle |
LuCordeschi | 1:97a0f449f19d | 20 | //Common variables |
LuCordeschi | 1:97a0f449f19d | 21 | float k = 0; |
LuCordeschi | 1:97a0f449f19d | 22 | float v_max = 15; //mm/s |
LuCordeschi | 1:97a0f449f19d | 23 | float pos_encoder = 0; //Posizione misurata dall'encoder |
LuCordeschi | 1:97a0f449f19d | 24 | float k1 = 0; |
LuCordeschi | 1:97a0f449f19d | 25 | float startPos_encoder = 0; |
LuCordeschi | 1:97a0f449f19d | 26 | float frequency; //sampling frequency of the encoder |
LuCordeschi | 1:97a0f449f19d | 27 | int Auto = 0; |
LuCordeschi | 1:97a0f449f19d | 28 | |
LuCordeschi | 1:97a0f449f19d | 29 | //Auto variables |
LuCordeschi | 0:839902368a34 | 30 | float finalDestination; //posizione da raggiungere RICEVUTA COME PARAMETRO |
LuCordeschi | 1:97a0f449f19d | 31 | float acceleration_range = 15; //n° step in accelerazione/decelerazione. Deciso da me |
LuCordeschi | 1:97a0f449f19d | 32 | float track_error = 1; |
LuCordeschi | 0:839902368a34 | 33 | float sens_error; //Error given by the amplitude of a step of the encoder |
LuCordeschi | 1:97a0f449f19d | 34 | float v_request = 0; |
LuCordeschi | 1:97a0f449f19d | 35 | float PWM_dutyReduct = 0; //Variables used in case of triangular control |
LuCordeschi | 1:97a0f449f19d | 36 | float acc_rangeReduct = 0; |
LuCordeschi | 1:97a0f449f19d | 37 | float Contr_reference = 0; //Is the starting tracking error, needed to impose the right form of controller |
LuCordeschi | 1:97a0f449f19d | 38 | |
LuCordeschi | 1:97a0f449f19d | 39 | //Manual variables |
LuCordeschi | 1:97a0f449f19d | 40 | float v_normalized = 0; //Manual command that indicates the direction and the magnitude of the velocity |
LuCordeschi | 1:97a0f449f19d | 41 | float v_actual = 0; //real velocity of the arm, computed through as incremental ratio |
LuCordeschi | 1:97a0f449f19d | 42 | float delta_v=0; //Difference of velocities used as input for control |
LuCordeschi | 1:97a0f449f19d | 43 | float a_max = 7.5; //maximum accelerazion mm/s^2 |
LuCordeschi | 1:97a0f449f19d | 44 | float time = 0; |
LuCordeschi | 1:97a0f449f19d | 45 | float prev_pos = 0; //Previous potition to compute the velocity as an incremental ratio |
LuCordeschi | 1:97a0f449f19d | 46 | |
LuCordeschi | 1:97a0f449f19d | 47 | //Initialization: to write the right pins |
LuCordeschi | 1:97a0f449f19d | 48 | //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) |
LuCordeschi | 1:97a0f449f19d | 49 | |
LuCordeschi | 0:839902368a34 | 50 | L6206 *motor; |
LuCordeschi | 0:839902368a34 | 51 | |
LuCordeschi | 1:97a0f449f19d | 52 | /*Take initial pos encoder -> saved in starPos_encoder*/ |
LuCordeschi | 1:97a0f449f19d | 53 | |
LuCordeschi | 1:97a0f449f19d | 54 | pos_encoder = startPos_encoder; |
LuCordeschi | 1:97a0f449f19d | 55 | switch (Auto) { |
LuCordeschi | 0:839902368a34 | 56 | |
LuCordeschi | 1:97a0f449f19d | 57 | case 1: {/*The rover is in its automatic mode*/ |
LuCordeschi | 1:97a0f449f19d | 58 | |
LuCordeschi | 1:97a0f449f19d | 59 | //OTTENGO LA posizione iniziale dell'encoder startPos_encoder |
LuCordeschi | 0:839902368a34 | 60 | //Ottengo il comando |
LuCordeschi | 1:97a0f449f19d | 61 | Contr_reference = finalDestination-startPos_encoder; |
LuCordeschi | 1:97a0f449f19d | 62 | track_error = Contr_reference; |
LuCordeschi | 0:839902368a34 | 63 | while (track_error>sens_error) { |
LuCordeschi | 0:839902368a34 | 64 | |
LuCordeschi | 0:839902368a34 | 65 | if (Contr_reference>2*acceleration_range) { //Controllo trapezoidale |
LuCordeschi | 0:839902368a34 | 66 | |
LuCordeschi | 0:839902368a34 | 67 | if (track_error>(finalDestination-acceleration_range)) { |
LuCordeschi | 1:97a0f449f19d | 68 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 69 | k = (track_error/(finalDestination-acceleration_range))*100; //V da imporre |
LuCordeschi | 0:839902368a34 | 70 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 71 | |
LuCordeschi | 0:839902368a34 | 72 | |
LuCordeschi | 0:839902368a34 | 73 | } else if (track_error<acceleration_range) { |
LuCordeschi | 0:839902368a34 | 74 | |
LuCordeschi | 1:97a0f449f19d | 75 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 76 | k = ((track_error)/acceleration_range)*100; //PWM_duty = 90*(1-k) |
LuCordeschi | 0:839902368a34 | 77 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 78 | |
LuCordeschi | 0:839902368a34 | 79 | } else { //Can it be eliminated? (no command, no velocity variations) |
LuCordeschi | 0:839902368a34 | 80 | /*v stays constant*/ |
LuCordeschi | 0:839902368a34 | 81 | } |
LuCordeschi | 0:839902368a34 | 82 | //Leggo la pos_encoder attuale |
LuCordeschi | 0:839902368a34 | 83 | |
LuCordeschi | 0:839902368a34 | 84 | } else { //Controllo triangolare |
LuCordeschi | 0:839902368a34 | 85 | /*Si agisce in maniera analoga al caso non saturato ma si impone un duty cicle massimo minore |
LuCordeschi | 0:839902368a34 | 86 | In particolare la v_max è proporzionale alla dimensione dello spostamento con 90 che corrisponde |
LuCordeschi | 1:97a0f449f19d | 87 | a un intervallo pari a 40 e poi si defininisce il nuovo PWM_dutyReduct = interval*90/40 |
LuCordeschi | 0:839902368a34 | 88 | */ |
LuCordeschi | 0:839902368a34 | 89 | |
LuCordeschi | 1:97a0f449f19d | 90 | PWM_dutyReduct = (Contr_reference/(2*acceleration_range))*100; |
LuCordeschi | 0:839902368a34 | 91 | |
LuCordeschi | 0:839902368a34 | 92 | //A new variable is needed to indicate the range of acceleration (in this case is less than the acceleration_range) |
LuCordeschi | 1:97a0f449f19d | 93 | acc_rangeReduct = Contr_reference/2; |
LuCordeschi | 1:97a0f449f19d | 94 | if (track_error>acc_rangeReduct) { |
LuCordeschi | 1:97a0f449f19d | 95 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 96 | k = (track_error/(finalDestination-acc_rangeReduct))*PWM_dutyReduct; //costante di proporzionalità |
LuCordeschi | 1:97a0f449f19d | 97 | //PWM_duty = k1*PWM_dutyReduct |
LuCordeschi | 1:97a0f449f19d | 98 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 99 | |
LuCordeschi | 0:839902368a34 | 100 | } else { |
LuCordeschi | 1:97a0f449f19d | 101 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 102 | k = (track_error/acc_rangeReduct)*PWM_dutyReduct; |
LuCordeschi | 1:97a0f449f19d | 103 | //PWM_duty = PWM_dutyReduct*(1-k) |
LuCordeschi | 0:839902368a34 | 104 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 105 | |
LuCordeschi | 0:839902368a34 | 106 | } |
LuCordeschi | 0:839902368a34 | 107 | //Leggo la pos_encoder attuale |
LuCordeschi | 0:839902368a34 | 108 | } |
LuCordeschi | 1:97a0f449f19d | 109 | track_error = finalDestination-pos_encoder; //It is used as counter |
LuCordeschi | 0:839902368a34 | 110 | } |
LuCordeschi | 0:839902368a34 | 111 | } |
LuCordeschi | 0:839902368a34 | 112 | break; |
LuCordeschi | 0:839902368a34 | 113 | |
LuCordeschi | 1:97a0f449f19d | 114 | default: { //Manual control based on a velocity control with a position feedback. The following velocities are gotten through a [-1,1] command, |
LuCordeschi | 1:97a0f449f19d | 115 | //normalized velocity |
LuCordeschi | 1:97a0f449f19d | 116 | while(1) { |
LuCordeschi | 1:97a0f449f19d | 117 | |
LuCordeschi | 1:97a0f449f19d | 118 | v_request = abs(v_normalized*v_max); //*(100/v_max); //Command is think to be a normalized velocity |
LuCordeschi | 1:97a0f449f19d | 119 | delta_v = v_request-v_actual; |
LuCordeschi | 1:97a0f449f19d | 120 | while (delta_v != 0) { //MUST add a condition about the maximum acceleration. |
LuCordeschi | 1:97a0f449f19d | 121 | /*Choosing a maximum acceleration, preferebly linked to the condition of the syste (motor, structure, Pwm and so on). |
LuCordeschi | 1:97a0f449f19d | 122 | Imposing an acceleration of 7.5 mm/s^2 to reach the v_max 2 secs are needed.*/ |
LuCordeschi | 1:97a0f449f19d | 123 | //Measure the new position |
LuCordeschi | 1:97a0f449f19d | 124 | time = time+(1/frequency); |
LuCordeschi | 1:97a0f449f19d | 125 | |
LuCordeschi | 1:97a0f449f19d | 126 | if (v_normalized > 0){ |
LuCordeschi | 1:97a0f449f19d | 127 | motor->run(1, BDCMotor::FWD); |
LuCordeschi | 1:97a0f449f19d | 128 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 129 | k = k+a_max/frequency*100/v_max; |
LuCordeschi | 1:97a0f449f19d | 130 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 131 | |
LuCordeschi | 1:97a0f449f19d | 132 | } else if (v_normalized<0){ |
LuCordeschi | 1:97a0f449f19d | 133 | motor->run(1, BDCMotor::BWD); |
LuCordeschi | 1:97a0f449f19d | 134 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 135 | k = k+a_max/frequency*100/v_max; |
LuCordeschi | 1:97a0f449f19d | 136 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 137 | |
LuCordeschi | 1:97a0f449f19d | 138 | } else{ |
LuCordeschi | 1:97a0f449f19d | 139 | k1 = k; |
LuCordeschi | 1:97a0f449f19d | 140 | k = k-a_max/frequency*100/v_max; |
LuCordeschi | 1:97a0f449f19d | 141 | motor->set_speed(k1,k); |
LuCordeschi | 1:97a0f449f19d | 142 | |
LuCordeschi | 1:97a0f449f19d | 143 | } |
LuCordeschi | 1:97a0f449f19d | 144 | |
LuCordeschi | 1:97a0f449f19d | 145 | prev_pos = pos_encoder; |
LuCordeschi | 1:97a0f449f19d | 146 | |
LuCordeschi | 1:97a0f449f19d | 147 | v_actual = (pos_encoder-prev_pos)*frequency; |
LuCordeschi | 1:97a0f449f19d | 148 | //In this computation is better to consider the velocity in the single period or the overall one? |
LuCordeschi | 1:97a0f449f19d | 149 | |
LuCordeschi | 1:97a0f449f19d | 150 | delta_v = v_request-v_actual; |
LuCordeschi | 1:97a0f449f19d | 151 | wait(0.1); |
LuCordeschi | 1:97a0f449f19d | 152 | } |
LuCordeschi | 1:97a0f449f19d | 153 | |
LuCordeschi | 1:97a0f449f19d | 154 | } |
LuCordeschi | 1:97a0f449f19d | 155 | } |
LuCordeschi | 1:97a0f449f19d | 156 | break; |
LuCordeschi | 1:97a0f449f19d | 157 | |
LuCordeschi | 1:97a0f449f19d | 158 | |
LuCordeschi | 1:97a0f449f19d | 159 | } |
LuCordeschi | 0:839902368a34 | 160 | } |