4、电流采样与重构:单电阻、双电阻、三电阻采样原理,相电流重构算法,采样时序与死区补偿

做FOC控制,说白了就是在跟电流打交道。你算得再准,PWM给得再漂亮,要是电流采回来就是错的,那整个系统就是空中楼阁。我刚开始做电机驱动那会儿,就吃过这个亏——算法调了半个月,波形怎么看怎么不对劲,最后发现是采样时序没搞对,白白浪费了时间。

这一章,咱们就把电流采样这件事彻底讲透。单电阻、双电阻、三电阻,这三种方案我都实际用过,各有各的脾气。我会把原理、算法、时序、补偿这些关键点,结合我踩过的坑,一次性说清楚。

4.1 三种采样方案的核心差异

先看一张总览图,把三种方案的结构和适用场景理清楚。

电流采样方案对比 三电阻采样 • 三个下桥臂各一个采样电阻 • 直接测量三相电流 • 精度最高 • 成本最高 优点: ✓ 采样窗口宽 ✓ 算法简单 ✓ 适合大功率 缺点: ✗ 成本高 ✗ 布线复杂 双电阻采样 • 两个下桥臂各一个采样电阻 • 第三相电流通过计算得到 • 性价比之选 • 应用最广泛 优点: ✓ 成本适中 ✓ 精度较好 ✓ 布线简单 缺点: ✗ 需重构第三相 ✗ 低占空比有盲区 单电阻采样 • 直流母线一个采样电阻 • 通过时序重构三相电流 • 成本最低 • 算法最复杂 优点: ✓ 成本最低 ✓ PCB面积小 ✓ 适合小功率 缺点: ✗ 采样窗口窄 ✗ 重构算法复杂 成本↓ 成本↓ 复杂度↑ 复杂度↑

从上图可以看得很清楚:三电阻最贵但最省心,单电阻最便宜但最折腾,双电阻是中间路线。我个人习惯,如果项目对成本不敏感,优先选三电阻;如果是消费级产品,双电阻是主流;只有在小功率、极致成本要求的场景下,我才会考虑单电阻。

4.2 三电阻采样:最直接,也最可靠

三电阻采样的原理很简单:在三个下桥臂的MOSFET源极和GND之间,各串联一个精密采样电阻。当某一相的下管导通时,该相的电流就会流过对应的采样电阻,产生一个压降。ADC测量这个压降,除以电阻值,就得到了电流。

这里有个关键点——采样时机。你想想看,下管导通的时候才能采到电流,那如果某一相的上管一直开着、下管一直关着,这相电流就采不到。所以采样必须发生在PWM周期的特定时刻。

采样窗口的计算:

假设PWM周期为Tpwm,死区时间为Tdead,下管最小导通时间为Ton_min,那么有效采样窗口为:

T_sample = Tpwm - Tdead - Ton_min

这个窗口必须大于ADC的采样转换时间,否则数据就是错的。

我在做一款伺服驱动器时,遇到过一个问题:PWM频率设到了20kHz,周期只有50μs,死区占了2μs,ADC采样需要1μs,算下来采样窗口只有47μs,看起来够用。但实际调试时发现,在低占空比区域,下管导通时间太短,采样窗口被压缩到只有几百纳秒,ADC根本来不及转换。后来我加了一个采样保持电路,才把这个问题解决掉。

4.3 双电阻采样:性价比之王

双电阻采样只用了两个采样电阻,通常放在V相和W相的下桥臂。U相的电流通过基尔霍夫电流定律计算得到:

Iu = -(Iv + Iw)

这个公式看起来简单,但实际用起来有几个坑。我一个个说。

第一个坑:当某一相的占空比接近0%或100%时,该相下管的导通时间太短,采样窗口不够。这时候你只能采到两相电流,第三相靠算。但如果两相都采不到呢?那就麻烦了。

第二个坑:计算出来的第三相电流,精度取决于前两相的测量精度。如果前两相有噪声,第三相就是噪声的叠加。我曾经在一个项目中,发现U相电流的噪声比V相和W相大了将近一倍,就是因为这个原因。

我的建议:双电阻采样时,尽量让采样时刻对齐在PWM周期的中间点。这时候三相电流都比较稳定,噪声最小。具体做法是在PWM定时器的中间点触发ADC采样,而不是在边沿触发。

4.4 单电阻采样:最省钱,也最烧脑

单电阻采样只在直流母线上放一个采样电阻。它的原理是利用PWM开关状态的变化,在不同时间段内,母线电流等于不同相的相电流。通过在一个PWM周期内多次采样,可以重构出三相电流。

举个例子:当U相上管和V相下管导通时,母线电流等于U相电流;当U相上管和W相下管导通时,母线电流等于U相电流的负值。通过在不同开关状态下采样,再结合PWM占空比信息,就能算出三相电流。

这个算法的核心是:在一个PWM周期内,至少需要两次有效的采样。而且这两次采样必须对应不同的相电流。

注意:单电阻采样有一个著名的「不可观测区域」问题。当三相占空比非常接近时(比如都在50%附近),所有开关状态变化都很短,你根本找不到两个足够宽的采样窗口。这时候重构算法会失效。

解决办法有两种:一是修改PWM模式,插入额外的开关状态;二是采用预测算法,用上一周期的数据推算本周期的电流。我一般两种方法结合用,效果最好。

4.5 相电流重构算法详解

这里我以双电阻采样为例,给出一个完整的相电流重构流程。单电阻的算法更复杂,但思路是一样的。

// 双电阻采样相电流重构
// 假设采样电阻在 V相 和 W相

typedef struct {
    float Iu;   // U相电流
    float Iv;   // V相电流  
    float Iw;   // W相电流
} PhaseCurrent_t;

PhaseCurrent_t ReconstructCurrent(float adc_v, float adc_w) {
    PhaseCurrent_t current;
    
    // 1. 直接读取V相和W相电流
    current.Iv = adc_v / R_SHUNT / GAIN_AMP;
    current.Iw = adc_w / R_SHUNT / GAIN_AMP;
    
    // 2. 计算U相电流
    current.Iu = -(current.Iv + current.Iw);
    
    // 3. 检查是否在不可观测区域
    // 如果某相占空比接近0或100%,该相采样可能无效
    if (IsInDeadZone(duty_v) || IsInDeadZone(duty_w)) {
        // 进入补偿模式
        current = CompensateWithPrediction(current);
    }
    
    return current;
}

这段代码看起来简单,但实际工程中要考虑的事情很多。比如ADC的偏移校准、增益校准、滤波处理等等。我习惯在初始化时做一次自动校准,把ADC的零漂和增益误差存下来,后续每次采样都做补偿。

4.6 采样时序与死区补偿

采样时序是电流采样中最容易被忽视、但影响最大的环节。我见过太多工程师,算法写得漂亮,硬件设计也没问题,就是采样时序没搞对,导致整个系统性能上不去。

先看一个典型的采样时序图:

PWM周期内采样时序 0 Tpwm/2 Tpwm U相 V相 W相 采样点1 采样点2 死区 采样窗口

从图中可以看到,采样点通常选在PWM周期的中间位置。为什么?因为这时候三相电流已经稳定,开关噪声最小。如果你在边沿采样,正好赶上开关管的上升沿或下降沿,那噪声会直接灌进ADC,采出来的数据根本不能用。

死区补偿是另一个关键点。死区是为了防止上下管直通而插入的延迟时间,但它会导致输出电压的畸变。这种畸变会反映在电流波形上,表现为电流的过零失真。

我常用的死区补偿方法有两种:

  1. 电压前馈补偿:根据电流方向,在PWM占空比中叠加一个补偿量。电流为正时加一个正补偿,为负时加一个负补偿。
  2. 电流反馈补偿:实时检测电流过零点,在过零点附近调整补偿量的大小。

死区补偿的工程经验:

我曾经在一个项目中,死区时间设了3μs,结果电机在低速运行时噪音特别大。后来我用示波器抓了电流波形,发现过零点附近有明显的「台阶」。通过引入自适应死区补偿算法,根据当前转速和负载动态调整补偿量,噪音问题才彻底解决。

具体的补偿量计算公式:

V_comp = sign(I) * T_dead * V_dc / T_pwm

其中sign(I)是电流方向,T_dead是死区时间,V_dc是母线电压,T_pwm是PWM周期。

4.7 采样电路的硬件设计要点

最后聊几句硬件。采样电路设计不好,软件再怎么补偿也白搭。

  • 采样电阻的选择:阻值不能太大,否则功耗高、发热严重;也不能太小,否则信噪比不够。一般取几毫欧到几十毫欧,具体看电流范围。
  • 运放的选择:要选低失调电压、低温漂的运放。我常用的有AD8418、INA240这些。
  • PCB布局:采样电阻到运放的走线要短,要远离功率走线。差分走线最好,能抑制共模噪声。
  • 滤波电容:在运放输入端加RC滤波,截止频率一般设在几MHz,滤掉开关噪声。

一个小技巧:在采样电阻两端并联一个小电容(几十pF),可以滤掉高频噪声。但电容不能太大,否则会影响采样信号的建立时间。我一般取47pF到100pF之间,具体值要根据实际波形调整。

好了,电流采样这部分就讲到这里。三种方案各有优劣,选哪种取决于你的项目需求。但不管选哪种,采样时序和死区补偿都是绕不开的坎。把这些搞明白了,你的FOC控制就成功了一半。