4. 基于电流极性的死区补偿:三相电流极性判断、补偿电压计算、实现流程
死区补偿这个话题,说实话,很多做FOC的工程师都绕不过去。我记得刚入行那会儿,调一个电机驱动板,空载波形看着挺漂亮,一带负载就出现明显的电流畸变,转矩脉动大得吓人。折腾了两天,最后发现是死区效应在作祟。从那以后,我对死区补偿这块就特别上心。
今天咱们聊的这种方法——基于电流极性的死区补偿,是工程中最常用、也最直观的一种。说白了,就是根据三相电流的方向,判断当前该补多少电压,然后把这个电压加回去。
4.1 死区效应是怎么产生的?
先简单回顾一下。死区时间,是上下桥臂开关管切换时,为了防止直通而插入的一段“同时关断”的时间。在这段时间里,电流通过续流二极管续流。
问题出在哪呢?
- 死区时间内,输出电压不受PWM控制,而是由电流方向决定。
- 电流从负载流向母线(正电流)时,下管续流二极管导通,输出被拉到负母线。
- 电流从母线流向负载(负电流)时,上管续流二极管导通,输出被拉到正母线。
结果就是:实际输出电压和理想PWM指令之间,产生了一个偏差。这个偏差和电流方向有关,和死区时间有关,也和开关频率有关。
核心结论:死区效应导致的电压误差,方向与电流极性相反,大小等于 Vdc * Tdead * fsw(母线电压 × 死区时间 × 开关频率)。
嗯,这里要注意:这个公式是理想情况,实际中还要考虑管压降、导通电阻等因素。但作为补偿的基准,完全够用。
4.2 三相电流极性判断
补偿的第一步,就是判断电流极性。听起来简单,做起来有不少坑。
直接采样法:
最直接的办法,就是用ADC采样三相电流,然后判断正负。但实际中,电流信号往往有噪声,尤其是在过零点附近,一个抖动就会导致极性误判。
我个人的习惯做法:
- 加滞回比较:设置一个阈值(比如额定电流的1%~2%),电流绝对值小于这个阈值时,保持上一次的极性判断结果。
- 软件滤波:对采样值做一阶低通滤波,截止频率设到几百赫兹就行,不影响动态响应。
- 结合PWM同步:在PWM的特定时刻(比如下管导通中点)采样,这时候电流纹波最小,信噪比最高。
避坑指南:我曾经在一个项目里,直接用原始ADC值判断极性,结果在电流过零时,补偿电压来回跳变,导致电机在低速时发出“嗡嗡”的噪声。后来加了滞回,问题立刻解决。
代码示例:电流极性判断(带滞回)
// 电流极性判断,带滞回
typedef enum {
POLARITY_POSITIVE = 1,
POLARITY_NEGATIVE = -1,
POLARITY_ZERO = 0
} Polarity_t;
Polarity_t Current_Polarity_Detect(float current, float threshold) {
static Polarity_t last_polarity = POLARITY_ZERO;
if (current > threshold) {
last_polarity = POLARITY_POSITIVE;
} else if (current < -threshold) {
last_polarity = POLARITY_NEGATIVE;
}
// 在阈值范围内,保持上一次结果
return last_polarity;
}
4.3 补偿电压计算
知道了电流极性,补偿电压就好算了。基本公式如下:
补偿电压 = 极性符号 × 死区补偿幅值
其中:
- 极性符号:电流为正时取+1,为负时取-1。
- 死区补偿幅值:
Vcomp = Vdc * Tdead * fsw
但实际工程中,我建议你考虑两个修正因素:
| 修正因素 | 说明 | 典型值 |
|---|---|---|
| 管压降 | IGBT或MOSFET导通时的饱和压降,以及续流二极管的压降 | 0.7V~2V(视器件而定) |
| 导通电阻 | 开关管导通电阻引起的压降,与电流大小成正比 | 几毫欧到几十毫欧 |
修正后的补偿电压:
Vcomp = Vdc * Tdead * fsw + Vf + I * Rds_on
其中Vf是续流二极管压降,Rds_on是导通电阻,I是当前相电流。
注意:管压降和导通电阻的修正,在低压大电流场合(比如48V系统)特别重要。母线电压越低,死区补偿的占比越大,忽略这些因素会导致补偿不足或过补。
4.4 实现流程
整个实现流程,我画了一张图,方便你理解:
流程看起来不复杂,但每一步都有细节。我展开说一下:
4.5 实现中的关键细节
1. 补偿时机
补偿电压应该在SVPWM计算之后、占空比更新之前叠加。具体来说:
- 先算出三相的占空比(Ta, Tb, Tc)
- 根据电流极性,算出每相需要补偿的占空比增量
- 叠加后,再写入PWM比较寄存器
2. 补偿限幅
叠加后的占空比不能超过0~1的范围。我曾经遇到过,补偿量太大导致占空比溢出,电机反而失控。所以一定要做限幅处理:
// 补偿后限幅
Ta_comp = Ta + delta_Ta;
if (Ta_comp > 1.0f) Ta_comp = 1.0f;
if (Ta_comp < 0.0f) Ta_comp = 0.0f;
3. 低速时的特殊处理
电机转速很低时,反电动势很小,死区效应的影响相对更大。这时候补偿要更精确。我的做法是:
- 在低速段(比如低于额定转速的5%),适当增大滞回阈值,防止极性频繁跳变
- 同时,补偿幅值可以稍微降低一点(比如乘以0.9),避免过补导致电流振荡
经验之谈:死区补偿不是越精确越好。有时候,稍微欠补一点,系统的稳定性反而更好。我见过有人把补偿算得特别准,结果电流波形上出现了高频振荡。后来把补偿系数从1.0降到0.85,问题就消失了。
4.6 完整代码框架
最后,给出一段完整的死区补偿实现框架,你可以直接参考:
// 死区补偿主函数
void DeadTime_Compensation(float Ia, float Ib, float Ic,
float *Ta, float *Tb, float *Tc) {
// 1. 电流极性判断(带滞回)
Polarity_t Pa = Current_Polarity_Detect(Ia, 0.02f);
Polarity_t Pb = Current_Polarity_Detect(Ib, 0.02f);
Polarity_t Pc = Current_Polarity_Detect(Ic, 0.02f);
// 2. 计算补偿占空比增量
float Vdc = Get_Bus_Voltage();
float Tdead = 2e-6f; // 2us死区
float fsw = 10e3f; // 10kHz开关频率
float Vcomp = Vdc * Tdead * fsw;
float delta_D = Vcomp / Vdc; // 转换为占空比增量
// 3. 叠加补偿(注意极性)
*Ta += (float)Pa * delta_D;
*Tb += (float)Pb * delta_D;
*Tc += (float)Pc * delta_D;
// 4. 限幅
*Ta = CLAMP(*Ta, 0.0f, 1.0f);
*Tb = CLAMP(*Tb, 0.0f, 1.0f);
*Tc = CLAMP(*Tc, 0.0f, 1.0f);
}
好了,基于电流极性的死区补偿,核心内容就这些。说白了就是三步:判断极性、算补偿量、叠加上去。但每一步都有工程上的坑,希望我今天分享的这些经验,能帮你少走一些弯路。
最后提醒一句:调试死区补偿时,最好先用电流探头观察相电流波形。补偿到位的话,电流过零点附近的畸变会明显改善,转矩脉动也会减小。如果发现补偿后波形反而变差了,先检查极性判断是否正确,再检查补偿幅值是否合适。
公众号:蓝海资料掘金营,微信deep3321