一种用于FOC控制的无感非线性观察器论文及源码(本杰明VESC使用),棒子兄的论文observer

最近在浏览VESC代码,看到它使用了一种观测器是基于此论文的,特下载跟大家分享:

LYJ博客


一种无传感器非线性观察器(本杰明电调)2010-IEEE_TPEL-Lee-Hong-Nam-Ortega-Praly-Astolfi.pdf


最近看了下源码,做了一部分注解,有兴趣的可以留言一起学习:

// dt:就是调用此函数的时间,例如pwm10k,dt=1/10k=100us = 0.0000001s
void observer_update(float v_alpha, float v_beta, float i_alpha, float i_beta,
        float dt, volatile float *x1, volatile float *x2, volatile float *phase) {

    const float L = (3.0 / 2.0) * m_conf->foc_motor_l;
    const float lambda = m_conf->foc_motor_flux_linkage;
    float R = (3.0 / 2.0) * m_conf->foc_motor_r;

    // Saturation compensation 饱和补偿电阻?
    const float sign = (m_motor_state.iq * m_motor_state.vq) >= 0.0 ? 1.0 : -1.0;
    R -= R * sign * m_conf->foc_sat_comp * (m_motor_state.i_abs_filter / m_conf->l_current_max);

    // Temperature compensation 温度补偿电阻
    const float t = mc_interface_temp_motor_filtered();
    if (m_conf->foc_temp_comp && t > -5.0) {
        R += R * 0.00386 * (t - m_conf->foc_temp_comp_base_temp);
    }

    const float L_ia = L * i_alpha;
    const float L_ib = L * i_beta;
    const float R_ia = R * i_alpha;
    const float R_ib = R * i_beta;
    const float lambda_2 = SQ(lambda); // 磁链的平方
    const float gamma_half = m_gamma_now * 0.5; // 观测器增益的一半,公式8

    // Original
//    float err = lambda_2 - (SQ(*x1 - L_ia) + SQ(*x2 - L_ib));
//    float x1_dot = -R_ia + v_alpha + gamma_half * (*x1 - L_ia) * err;
//    float x2_dot = -R_ib + v_beta + gamma_half * (*x2 - L_ib) * err;
//    *x1 += x1_dot * dt;
//    *x2 += x2_dot * dt;

    // Iterative with some trial and error 迭代6次?
    const int iterations = 6;
    const float dt_iteration = dt / (float)iterations;

    for (int i = 0;i < iterations;i++) {
        float err = lambda_2 - (SQ(*x1 - L_ia) + SQ(*x2 - L_ib)); // 公式8的减法
        float gamma_tmp = gamma_half;

        if (utils_truncate_number_abs(&err, lambda_2 * 0.2)) { // 把err限定在 lambda_2*0.2内
            gamma_tmp *= 10.0; // 超过范围后放大?相当于 m_gamma_now 放大5倍
        }

        // 公式4:y=-RsIab + Vab ,则向量     -Ria + va
        //                            - Rib +vb
        // 公式8:dx/dt = y + gamma/2*n(x)*err
        float x1_dot = -R_ia + v_alpha + gamma_tmp * (*x1 - L_ia) * err;
        float x2_dot = -R_ib + v_beta + gamma_tmp * (*x2 - L_ib) * err;

        *x1 += x1_dot * dt_iteration;
        *x2 += x2_dot * dt_iteration;
    }

    // Same as above, but without iterations.
//    float err = lambda_2 - (SQ(*x1 - L_ia) + SQ(*x2 - L_ib));
//    float gamma_tmp = gamma_half;
//    if (utils_truncate_number_abs(&err, lambda_2 * 0.2)) {
//        gamma_tmp *= 10.0;
//    }
//    float x1_dot = -R_ia + v_alpha + gamma_tmp * (*x1 - L_ia) * err;
//    float x2_dot = -R_ib + v_beta + gamma_tmp * (*x2 - L_ib) * err;
//    *x1 += x1_dot * dt;
//    *x2 += x2_dot * dt;

    // 确保x1 x2不是nan,也可以用 isnan()函数
    UTILS_NAN_ZERO(*x1);
    UTILS_NAN_ZERO(*x2);

    // 最后得到估算角度theta 三角,公式9
    // atan2(y, x)是4象限反正切,它的取值不仅取决于正切值y/x,还取决于点 (x, y) 落入哪个象限
    *phase = utils_fast_atan2(*x2 - L_ib, *x1 - L_ia);
}



本文为3YL原创,转载无需联系,但请注明来自labisart.com。

原创文章不容易,如果觉得对你有帮助,就打赏一下吧:

查看打赏记录

发表评论请遵守党国法律!后台审核后方可显示!
  • 最新评论
  • 总共3条评论

易缘天地:老兄,本明杰的高频注入研究过吗,他怎么做的,最近我做了个方波注入的。性看看本明杰怎么做的

2020-07-10 11:00:38 回复

  • 3YL 回复 易缘天地:高频注入那块没看,好像没有吧
  • 2020-07-15 08:54:58 回复

易缘天地:我用simulink仿真了一下,和实际角度一直差45度,关键电机的温度如何获取。

2020-06-30 09:52:50 回复

易缘天地:试了吗这个观测器效果如何

2020-06-30 08:59:23 回复

  • 3YL 回复 易缘天地:打算用小米的,他这个要反向电动势,不爽
  • 2020-07-03 18:31:50 回复
  • Blog v1.1© 2020 labisart.com 版权所有 | 联系:labartwork@163.com