K60电机闭环控制

仅用于备份本人所写笔记,如有错误还请包含。转载请注明出处!

程序使用逐飞科技K60库 V2.0.3

首先需要获取编码器的值,每 2ms 取一次值,为了减小误差,再每 4ms 计算一次平均值,所以需要用到定时器,这里不多赘述。取到的值再经过计算,即可算出电机当前速度。

代码示例:

#define unitPulse 1783          // 编码器测得的车轮转一圈的单位脉冲
#define motorRadius 0.063       // 车轮轮胎半径(米)

// 编码器初始化
void EncoderInit(void) {

    ftm_quad_init(ftm2);            // 初始化 ftm2 为正交解码
    port_init_NoAlt(B18, PULLUP);   // 上拉
    port_init_NoAlt(B19, PULLUP);
}

// 获取编码器脉冲值
float EncoderRead(void) {

    float _data = 0;
    _data = ftm_quad_get(ftm2);    // 获取编码器的脉冲值
    ftm_quad_clean(ftm2);          // 清除正交解码的脉冲值

    return ABS(_data);
}

// 计算电机速度
void GetMotorSpeed(void) {

    encoder.finalValue += 0.25f * (encoder.averValue - encoder.finalValue);  // 一阶低通滤波
    encoder.motorRounds = (encoder.finalValue * 250) / unitPulse;           // 电机每 1s 转的圈数
    encoder.motorDistance = encoder.motorRounds * (2*PI*motorRadius);       // 电机运行长度 m
    encoder.motorSpeed = encoder.motorDistance / 1;                         // 电机速度 m/s

}

需要放到定时器里的程序:

// 放到 2ms 里
encoder.value += EncoderRead();         // 每 2ms 读取编码器的值

// 放到 4ms 里
encoder.averValue = encoder.value / 2;    // 将编码器的值求平均,减少误差
encoder.value = 0;                        // 将编码器值归零,重新记值

最后得出的变量 encoder.motorSpeed 就是电机当前速度。

计算出速度后,把该变量赋值给 PID 计算,算出电机需要的占空比,这样就能对电机速度闭环了。

代码示例:

uint16 motorPid_10Kp = 1, motorPid_10Ki = 2;       // 10 倍的 KP、KI 值(之所以用10倍,是因为需要在 OLED 上调参,而 OLED 上改一次值变化范围为 1,而我们需要的参数变化范围为 0.1)

// 电机 pid 计算
static void MotorPid(void) {

    static float _err, _expectPwm, _lastErr;

    motorPid.kp = (float)(motorPid_10Kp) / 10;      // 动态调整 PID 参数,因为在不同路段需要不同的效果
    motorPid.ki = (float)(motorPid_10Ki) / 10;      // Ki 越大,速度变化越快  0.1-1.0

    _err = motor.expectSpeed - encoder.motorSpeed;   // 期望速度可以自己设定,或者通过计算得到
    _expectPwm += motorPid.kp * (_err - _lastErr) + motorPid.ki * _err;
    _lastErr = _err;

    // 电机占空比限幅
    if(_expectPwm > 260) _expectPwm = 260;          // 限制最高占空比
    if(_expectPwm <= 0)  _expectPwm = 0;            // 限制最低占空比

    motor.expectDutyRatio = (int16)(_expectPwm);

}

把期望占空比赋值给电机控制函数即可:

// 电机初始化
void MotorInit(void) {

    ftm_pwm_init(ftm1, ftm_ch0, 10*1000, 0);    // A12 端口,初始化 ftm_pwm,频率为 10k,占空比为 0
    ftm_pwm_init(ftm1, ftm_ch1, 10*1000, 0);    // A13 端口,初始化 ftm_pwm,频率为 10k,占空比为 0
}

// 电机占空比赋值
void Motor(uint16 _speed1, uint16 _speed2) {

    ftm_pwm_duty(ftm1, ftm_ch0, _speed1);       // A12 端口
    ftm_pwm_duty(ftm1, ftm_ch1, _speed2);       // A13 端口
}

// 电机控制
void MotorControl(void) {

    MotorPid();                             // PID 计算
    Motor(0, motor.expectDutyRatio);          // 赋值占空比
}

转载于:https://www.cnblogs.com/zhangxiaochn/p/K60_Motor_Control.html

你可能感兴趣的:(K60电机闭环控制)