Motor current controller

Fork of CURRENT_CONTROL by LDSC_Robotics_TAs

CURRENT_CONTROL.cpp

Committer:
benson516
Date:
2016-12-19
Revision:
7:6794cfba3564
Parent:
6:bae35ca64f10
Child:
8:fd6fb3cb12ec

File content as of revision 7:6794cfba3564:

#include "mbed.h"
#include "CURRENT_CONTROL.h"

//=====================LPF ====================//
LPF::LPF(float samplingTime, float cutOff_freq_Hz_in)
{
    Ts = samplingTime;
    cutOff_freq_Hz = cutOff_freq_Hz_in;
    alpha_Ts = (2*3.1415926)*cutOff_freq_Hz*Ts;
    output = 0.0;
    
    //
    Flag_Init = false;    
}

float LPF::filter(float input)
{
    // Initialization
    if (!Flag_Init){
        reset(input);
        Flag_Init = true;
        return output;
    }
    
    // output = (1.0 - alpha_Ts)*output + alpha_Ts*input;
    output += alpha_Ts*(input - output);
    return output;
}
void LPF::reset(float input)
{
    // output = (1.0 - alpha_Ts)*output + alpha_Ts*input;
    output = input;
    return;
}


//================== CURRENT_CONTROL =================//
CURRENT_CONTROL::CURRENT_CONTROL(PinName curChannel,
                                 PinName PwmChannel1,
                                 PinName PwmChannel2,
                                 PWMIndex pwmIndex,
                                 float Kp, float Ki, float Kd, float Ka,
                                 float samplingTime) : 
    currentAnalogIn(curChannel),
    MotorPlus(PwmChannel1),
    MotorMinus(PwmChannel2),
    pid(Kp,Ki,Kd,samplingTime),
    lpFilter(samplingTime, 100.0), // 1.5915 Hz = 10 rad/s
    curFeedBack(0.0),
    curFeedBack_filter(0.0),
    voltage_out(0.0)
    
{
    pwmIndex_ = pwmIndex;

    Ts = samplingTime;
    
    //setup motor PWM parameters
    MotorPlus.period_us(50); //set the pwm period = 50 us, where the frequency = 20kHz 
    MotorPlus.write(0.5);   //duty ratio = 0.5 in complementary output mode -> static
    if(pwmIndex_ == PWM1)TIM1->CCER |= 4;
    else if(pwmIndex_ == PWM2)TIM1->CCER |= 64; //enable complimentary output
    
    //
    Flag_Init = false;
    Init_count = 0;
    Accumulated_offset = 0.0;
    
    //
    currentOffset = 0.0;
    //
    delta_output = 0.0;
    
    // Set PID's parameters                        
    /////////////////////
    pid.Kp = Kp;
    pid.Ki = Ki;
    pid.Kd = Kd;
    pid.Ka = Ka; // Gain for anti-windup // Ka = 0.0017
}
void CURRENT_CONTROL::OffsetInit(void){
    if (Flag_Init) return;
    //
    Init_count++;
    Accumulated_offset += GetAnalogIn();
    
    if (Init_count >= 500){ // Fixed time
        currentOffset = Accumulated_offset/float(Init_count);
        Flag_Init = true;
    }
}
//
void CURRENT_CONTROL::SetParams(float Analog2Cur, float angSpeed2BackEmf, float voltage2DutyRatio)
{
    analog2Cur = Analog2Cur;//LTS25-NP current sensor working with STM32F446RE : 3.3*8/0.6
    Ke = angSpeed2BackEmf;
    voltage2Duty = voltage2DutyRatio;
    
}
//
float CURRENT_CONTROL::saturation(float input_value, float &delta, const float &limit_H, const float &limit_L){
    if( input_value > limit_H ){
        delta = limit_H - input_value;
        input_value = limit_H;
    }else if( input_value < limit_L ){  
        delta = limit_L - input_value;
        input_value = limit_L; 
    }else{
        delta = 0.0;
    }
    return input_value;
}
//
void CURRENT_CONTROL::Control(float curRef, float angularSpeed)
{
    // Init check
    OffsetInit();
    if (!Flag_Init) return;   
    //////////////////////////////////////
    
    // Get measurement
    GetCurrent();
     
    //--------------------------------//
    
    // PID
    pid.Compute_noWindUP(curRef, curFeedBack_filter);
    
    // Voltage output with back-emf compensation
    voltage_out = -pid.output + func_back_emf(angularSpeed); 
    
    // Output saturation and unit changing
    SetPWMDuty( 0.5 + saturation( voltage_out*voltage2Duty, delta_output, 0.5, -0.5) );
    
    
    //--------------------------------//
    
    // Anti-windup
    pid.Anti_windup(delta_output);
    

}
// Back emf as the function of rotational speed
float CURRENT_CONTROL::func_back_emf(const float &W_in){
    return (Ke*W_in);
}

//****************for test************************//
void CURRENT_CONTROL::SetPWMDuty(float ratio)
{
    MotorPlus = ratio;
    if(pwmIndex_ == PWM1){
        TIM1->CCER |= 4;
    }else if(pwmIndex_ == PWM2){
        TIM1->CCER |= 64;
    }
}

float CURRENT_CONTROL::GetAnalogIn(void)
{
    analogInValue = currentAnalogIn.read();
    return analogInValue;
}

float CURRENT_CONTROL::GetCurrent(void)
{
    // Init check
    if (!Flag_Init) return 0.0; 
    
    //-----------------------------------------//
    analogInValue = currentAnalogIn.read();
    
    // Unit transformation
    curFeedBack = (analogInValue - currentOffset)*analog2Cur;
    
    // Low-pass filter
    curFeedBack_filter = lpFilter.filter(curFeedBack);
    
    return  curFeedBack; //curFeedBack_filter;   
}