Controller of the linear speed of the arm

Dependencies:   QEI X_NUCLEO_IHM04A1

main.cpp

Committer:
LuCordeschi
Date:
2019-05-23
Revision:
3:bbd927c5bfa9
Parent:
2:fc8d58f9f5ce
Child:
4:0b8f77ae7af0

File content as of revision 3:bbd927c5bfa9:

#include "mbed.h"
#include "L6206.h"
#include "BDCMotor.h"
#include <math.h>
#include "QEI.h"

Thread thread;

QEI encoder(PinName PB4, PinName PB5,PinName NC, int pulsesPerRev,QEI::Encoding 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 (PinName PC1);
DigitalOut led(LED1);
InterruptIn button(PinName 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 PulseperPeriod, 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);
        PulseperPeriod = encoder.getPulses();

        if (pos_encoder==0) {
            t++;
        } else {
            t=0;
        }
    }
}

//Pin can: CANRX PB8 and CANTX PB9
void canRxIsr() {
    while(1) {

    if(can1.read(messageIn))
     
        {
            led1 = !led1;
            printf("received\n\r");
        }
    }
}
void command() {
    
    canRxIsr();
    wait(0.5);
}
void sendMessage()
{
    int status = can.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 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;
    
    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 = position + pos_encoder*/*Rad angle made (in average) by the encoder for each pulse*/;

            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 v_request = 0;
    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 delta_v=0; //Difference of velocities used as input for control
    float a_max = 7.5; //maximum accelerazion mm/s^2
    float time = 0;
    float 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)
    
    gotozero(a_max,v_max,resolution, 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-startPos_encoder;
                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
      
        
                thread.start(controller);

                thread.start(command);

                while(1){

                    sendMessage(); //position
                            
                }
                    
            break;
            
        }
    }