非线性观测器,就是磁链观测器,理论上这个比那些估算反电动势的要强得多,也稳定得多。 单出Matlab模型(2021b版本),图是直接闭环启动的效果,仿真里面可以做到。 在实际硬件中可以做到5%或者更低的转速闭环,目前在CortexM4的硬件中实现了。 vesc 里面用的就是这个观测器。

在电机控制圈子里混久了,总有几个玄学问题让人头秃——比如怎么在无感控制中稳定观测转速。老方法盯着反电动势搞事情,低速时就跟喝高似的飘忽不定。直到某天在实验室通宵肝代码,被师兄按头安利了磁链观测器,才明白什么叫降维打击。

先看这个非线性观测器的核心代码片段(Matlab 2021b验证过):

function [flux, omega] = FluxObserver(u_alpha, u_beta, i_alpha, i_beta, Ts)
    persistent flux_alpha flux_beta i_alpha_prev i_beta_prev;
    if isempty(flux_alpha)
        % 初始化磁链观测值
        flux_alpha = 0; flux_beta = 0;
        i_alpha_prev = 0; i_beta_prev = 0;
    end
    
    R = 0.2;   % 电机相电阻
    L = 0.001; % 电机电感
    
    % 电流微分近似计算
    di_alpha = (i_alpha - i_alpha_prev)/Ts;
    di_beta = (i_beta - i_beta_prev)/Ts;
    
    % 磁链观测器核心方程
    flux_alpha = flux_alpha + Ts*(u_alpha - R*i_alpha - L*di_alpha);
    flux_beta = flux_beta + Ts*(u_beta - R*i_beta - L*di_beta);
    
    % 转速解算(防除零处理)
    flux_sq = flux_alpha^2 + flux_beta^2;
    omega = (flux_alpha*i_beta - flux_beta*i_alpha) / max(flux_sq, 1e-6);
    
    % 更新历史值
    i_alpha_prev = i_alpha;
    i_beta_prev = i_beta;
end

这玩意儿妙就妙在直接跟磁链硬刚,不像反电动势观测器那样受制于电机转速。那个max函数防除零的操作,是实验室师弟烧了三个MOS管换来的血泪经验。

非线性观测器,就是磁链观测器,理论上这个比那些估算反电动势的要强得多,也稳定得多。 单出Matlab模型(2021b版本),图是直接闭环启动的效果,仿真里面可以做到。 在实际硬件中可以做到5%或者更低的转速闭环,目前在CortexM4的硬件中实现了。 vesc 里面用的就是这个观测器。

移植到Cortex-M4硬件时,得玩点骚操作:

// 在1kHz中断中执行的观测器
void Observer_ISR() {
    static struct { float a,b; } flux = {0}, i_prev = {0};
    
    float di_a = (adc_data.i_a - i_prev.a) * 1000.0f; // Ts=1ms
    float di_b = (adc_data.i_b - i_prev.b) * 1000.0f;
    
    // 带饱和保护的积分运算
    flux.a = clamp(flux.a + (pwm_volt.a - MOTOR_R*adc_data.i_a - MOTOR_L*di_a)*0.001, 
                  -FLUX_MAX, FLUX_MAX);
    flux.b = clamp(flux.b + (pwm_volt.b - MOTOR_R*adc_data.i_b - MOTOR_L*di_b)*0.001,
                  -FLUX_MAX, FLUX_MAX);
    
    // 滑动窗滤波处理转速
    static float omega_buf[8];
    float instant_omega = (flux.a*adc_data.i_b - flux.b*adc_data.i_a) / 
                         (flux.a*flux.a + flux.b*flux.b + 1e-6f);
    memmove(omega_buf, &omega_buf[1], 7*sizeof(float));
    omega_buf[7] = instant_omega;
    motor.omega = moving_average(omega_buf);
    
    i_prev = adc_data;
}

这里有几个骚操作:

  1. 用滑动窗滤波代替复杂滤波算法,M4跑起来毫无压力
  2. clamp函数防止积分饱和,实测能抗住电机堵转
  3. 在中断服务中直接处理,保证实时性

实测在电动滑板车上,从零速带载启动稳如老狗,5%转速精度轻松拿捏。后来翻VESC的开源代码,发现他们的观测器结构跟这个有异曲同工之妙,只不过加了个自适应参数调整的骚操作。

最后给个忠告:别在观测器里用float!我们最早用float类型在M4上跑,偶尔会出现蜜汁震荡。换成q15格式定点数之后,世界瞬间清净了——这事告诉我们,有时候硬件特性比算法本身更玄学。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐