4. 有效值电流保护原理
各位工程师朋友,咱们今天聊点实在的。过流保护不能只看峰值,那玩意儿容易误触发。真正决定电机能不能扛得住的,是电流的有效值,也就是 RMS。说白了,就是电流做功发热的那个“等效直流值”。
我刚开始做驱动的时候,也踩过这个坑。峰值保护设得死死的,结果电机没烧,IGBT 先炸了。后来才明白,热积累看的是 RMS,不是瞬时尖峰。这一章,我就把 RMS 计算、软件滤波和热积累模型掰开揉碎了讲。
核心观点:有效值保护的本质是“热量管理”。电机和功率器件的热时间常数远大于电流周期,所以 RMS 比峰值更能反映真实温升。
4.1 RMS 计算算法
RMS 的数学定义大家都知道:I_rms = sqrt( (1/T) * ∫ i²(t) dt )。但在 DSP 或 MCU 里,我们得用离散采样点来算。这里我介绍三种工程上最常用的方法。
4.1.1 滑动窗口 RMS
这是最直观的方法。维护一个长度为 N 的采样值平方缓冲区,每次新采样进来,就替换掉最老的那个。然后对缓冲区求和,除以 N,再开方。
// 滑动窗口 RMS 实现(C 语言伪代码)
#define WINDOW_SIZE 200 // 10kHz 采样率,对应 20ms 工频周期
float buffer[WINDOW_SIZE];
uint16_t index = 0;
float sum_sq = 0.0f;
float calc_sliding_rms(float new_sample) {
// 减去最老的值
sum_sq -= buffer[index];
// 存入新值
buffer[index] = new_sample * new_sample;
// 加上新值
sum_sq += buffer[index];
// 更新索引
index = (index + 1) % WINDOW_SIZE;
// 返回 RMS
return sqrtf(sum_sq / WINDOW_SIZE);
}
我的经验:窗口长度 N 要覆盖至少一个完整基波周期。对于 50Hz 系统,采样率 10kHz 时 N=200 刚刚好。N 太小 RMS 会跟着瞬时值抖,N 太大响应又太慢。我曾经在一个项目里把 N 设成 400,结果保护动作慢了半拍,MOSFET 直接冒烟了。
4.1.2 单周期 RMS
这个方法更省内存。它只存一个周期内的采样点,每个周期结束时计算一次 RMS。适合对实时性要求不那么苛刻的场景。
// 单周期 RMS
float samples_per_cycle[200];
uint16_t count = 0;
float sum_sq = 0.0f;
float calc_cycle_rms(float new_sample) {
sum_sq += new_sample * new_sample;
samples_per_cycle[count++] = new_sample;
if (count >= 200) { // 一个周期结束
float rms = sqrtf(sum_sq / 200);
// 复位
count = 0;
sum_sq = 0.0f;
return rms;
}
return -1.0f; // 周期未结束,返回无效值
}
4.1.3 递推 RMS(省算力方案)
如果 MCU 算力有限,不想每次开方,可以用递推近似。说白了就是用一阶低通滤波来平滑 I² 值,需要输出时再开方。
// 递推 RMS(一阶滤波 + 平方)
float i_sq_filtered = 0.0f;
float alpha = 0.01f; // 滤波系数
float calc_recursive_rms(float new_sample) {
float i_sq = new_sample * new_sample;
i_sq_filtered = (1 - alpha) * i_sq_filtered + alpha * i_sq;
return sqrtf(i_sq_filtered);
}
注意:递推法的 alpha 系数决定了响应速度。alpha 越大响应越快,但纹波也大。我一般取 alpha = Ts / τ,其中 Ts 是采样周期,τ 是期望的滤波时间常数。比如 Ts=100μs,τ=20ms,alpha=0.005。
4.2 软件滤波实现
算出来的 RMS 值,直接拿去跟阈值比较?别急。采样噪声、PWM 开关毛刺都会让 RMS 值抖动。这时候就需要软件滤波了。
4.2.1 一阶低通滤波
这是我最常用的方法。简单、可靠、算力开销小。
// 一阶低通滤波
float rms_filtered = 0.0f;
float k_filter = 0.1f; // 滤波系数,0~1
float lowpass_rms(float rms_raw) {
rms_filtered = (1 - k_filter) * rms_filtered + k_filter * rms_raw;
return rms_filtered;
}
k_filter 怎么选?我有个经验公式:k_filter = 1 - exp(-Ts / Tf)。Ts 是 RMS 更新周期,Tf 是期望的滤波时间常数。举个例子,RMS 每 1ms 更新一次,想要 10ms 的滤波时间,k_filter ≈ 0.095。
4.2.2 截止频率选择
滤波器的截止频率要避开两个东西:一是电网频率的 2 倍频(100Hz/120Hz),二是机械谐振频率。我一般把截止频率设在 5~20Hz 之间。
| 应用场景 | 推荐截止频率 | 说明 |
|---|---|---|
| 通用工业伺服 | 10 Hz | 兼顾响应与平滑 |
| 高速主轴 | 20 Hz | 需要快速响应过流 |
| 电梯/起重 | 5 Hz | 安全优先,允许慢响应 |
| 电动汽车牵引 | 15 Hz | 动态工况多 |
避坑指南:我曾经在一个风机项目里把截止频率设到 2Hz,结果电机堵转时保护动作慢了 300ms,绕组都烧变色了。后来改成 8Hz,问题解决。记住,滤波不是越平滑越好。
4.2.3 定点数实现技巧
如果 MCU 没有 FPU,浮点运算太慢。可以用 Q15 或 Q31 定点数来实现滤波。说白了就是把小数放大成整数来算。
// Q15 定点数一阶滤波
// k_filter = 0.1 → Q15 表示为 0.1 * 32768 = 3277
#define K_FILTER_Q15 3277
#define ONE_MINUS_K_Q15 (32768 - 3277) // 29491
int16_t rms_filtered_q15 = 0;
int16_t lowpass_rms_q15(int16_t rms_raw_q15) {
int32_t temp;
temp = (int32_t)ONE_MINUS_K_Q15 * rms_filtered_q15;
temp += (int32_t)K_FILTER_Q15 * rms_raw_q15;
rms_filtered_q15 = (int16_t)(temp >> 15);
return rms_filtered_q15;
}
4.3 热积累模型
RMS 保护还不够。为什么?因为电机和功率器件有热惯性。短时间过流可能没事,但长时间小过流反而会烧。这就需要热积累模型了。
4.3.1 一阶热模型
热模型可以类比 RC 电路。电流的平方相当于热功率(I²R),热容相当于电容,热阻相当于电阻。温升就是电容上的电压。
// 一阶热积累模型
float thermal_state = 0.0f; // 0~1,表示温升百分比
float tau_thermal = 60.0f; // 热时间常数,单位秒
float ts_thermal = 0.001f; // 热模型更新周期,1ms
void update_thermal_model(float i_rms, float i_rated) {
float i_pu = i_rms / i_rated; // 标幺化
float i_sq = i_pu * i_pu;
// 离散化一阶热模型
float alpha_thermal = ts_thermal / tau_thermal;
thermal_state += alpha_thermal * (i_sq - thermal_state);
// 限幅
if (thermal_state > 1.0f) thermal_state = 1.0f;
if (thermal_state < 0.0f) thermal_state = 0.0f;
}
// 判断是否过温
bool is_thermal_trip(float threshold) {
return thermal_state >= threshold;
}
关键参数:热时间常数 τ 可以从电机 datasheet 里查,一般电机绕组 τ 在 30~300 秒之间。IGBT 模块的 τ 短一些,约 1~10 秒。如果 datasheet 没给,可以用堵转实验来标定。
4.3.2 I²t 累积
有些场合需要更精确的 I²t 保护。说白了就是积分电流平方,超过阈值就跳闸。这在伺服驱动里很常见。
// I²t 累积保护
float i2t_integral = 0.0f;
float i2t_limit = 100.0f; // 阈值,单位 A²·s
void update_i2t(float i_rms, float dt) {
float i_sq = i_rms * i_rms;
i2t_integral += i_sq * dt;
// 散热衰减(可选)
float decay = 1.0f - (dt / tau_thermal);
if (decay > 0.0f) {
i2t_integral *= decay;
}
// 限幅
if (i2t_integral > i2t_limit) {
// 触发保护
trigger_overcurrent_protection();
}
}
注意:I²t 模型里一定要加散热衰减项。否则电流一停,积分值还卡在那里,下次启动容易误触发。我见过有人忘了加衰减,电机空转都报过流,查了半天才发现是积分没清零。
4.4 参数整定流程
讲了这么多理论,来点实际的。参数整定我一般按这个步骤来:
- 确定 RMS 计算方式:算力够用选滑动窗口,内存紧张选递推法。
- 选择滤波截止频率:根据应用场景查上表,先取中间值 10Hz。
- 标定热时间常数:查 datasheet 或做堵转实验。
- 设置保护阈值:一般取额定电流的 1.2~1.5 倍作为 RMS 阈值。
- 联调验证:带载运行,用示波器抓 RMS 波形,看保护动作点是否准确。
| 步骤 | 参数 | 推荐初始值 | 调整方向 |
|---|---|---|---|
| 1 | 窗口长度 N | 200 (10kHz/50Hz) | 响应慢则减小 |
| 2 | 滤波系数 k_filter | 0.1 | 纹波大则减小 |
| 3 | 热时间常数 τ | 60s (电机) | 查 datasheet |
| 4 | RMS 阈值 | 1.3 × I_rated | 误动则增大 |
| 5 | I²t 阈值 | 100 A²·s | 根据线径计算 |
最后说一句:参数整定没有万能公式。每个项目都要根据实际工况微调。我习惯在调试阶段把 RMS 值和热积累状态通过 DAC 输出到示波器,肉眼看着调,比光看寄存器快多了。