4. 有效值电流保护原理

各位工程师朋友,咱们今天聊点实在的。过流保护不能只看峰值,那玩意儿容易误触发。真正决定电机能不能扛得住的,是电流的有效值,也就是 RMS。说白了,就是电流做功发热的那个“等效直流值”。

我刚开始做驱动的时候,也踩过这个坑。峰值保护设得死死的,结果电机没烧,IGBT 先炸了。后来才明白,热积累看的是 RMS,不是瞬时尖峰。这一章,我就把 RMS 计算、软件滤波和热积累模型掰开揉碎了讲。

核心观点:有效值保护的本质是“热量管理”。电机和功率器件的热时间常数远大于电流周期,所以 RMS 比峰值更能反映真实温升。

有效值电流保护知识体系 有效值电流保护 RMS 计算算法 软件滤波实现 热积累模型 滑动窗口 RMS 单周期 RMS 递推 RMS(省算力) 一阶低通滤波 截止频率选择 定点数实现技巧 一阶热模型 热时间常数 τ I²t 累积 保护动作阈值 + 延时

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 参数整定流程

讲了这么多理论,来点实际的。参数整定我一般按这个步骤来:

  1. 确定 RMS 计算方式:算力够用选滑动窗口,内存紧张选递推法。
  2. 选择滤波截止频率:根据应用场景查上表,先取中间值 10Hz。
  3. 标定热时间常数:查 datasheet 或做堵转实验。
  4. 设置保护阈值:一般取额定电流的 1.2~1.5 倍作为 RMS 阈值。
  5. 联调验证:带载运行,用示波器抓 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 输出到示波器,肉眼看着调,比光看寄存器快多了。