4. 软件校准方法(一):单次采样校准法
说到零位校准,很多工程师第一反应就是「上电测一次偏置,然后减掉」。嗯,这其实就是单次采样校准法的核心思路。我个人习惯叫它「傻瓜校准法」——不是贬义,而是因为它简单、直接、有效。
但你别小看它。我在项目中遇到过不少情况,明明只是做个单次采样校准,结果反而把系统搞得更糟了。为什么?因为没搞清楚它的适用边界。
4.1 原理:一次采样,终身补偿
单次采样校准法的原理,说白了就是一句话:在电机静止时,把电流传感器输出的值读进来,这个值就是零位偏置。
你想想看,当电机不转、没有电流流过时,理想的电流采样值应该是0。但实际电路中,运放的输入偏置、ADC的偏移量、温度漂移……这些乱七八糟的东西叠加在一起,让读出来的值变成了一个非零常数。我们把这个常数记下来,以后每次采样都减去它,不就校准了吗?
核心公式:
Iactual = Iraw - Ioffset
其中 Ioffset 就是电机静止时采到的值。
这个方法在教科书上叫「硬件触发单次采样校准」,但我更喜欢叫它「一次定终身」。因为一旦这个 Ioffset 被写入非易失性存储器,它就会一直用下去,直到下次校准。
4.2 实现步骤:五步走
我一般把实现过程拆成5步,每一步都有坑,咱们一个一个说。
- 确保电机处于静止状态
这一步看似简单,其实最容易翻车。我曾经遇到过一上电电机就微微抖动的案例,查了半天发现是PWM使能时序有问题,导致电机还没进入静止状态就开始采样了。所以我的建议是:在采样前,强制封锁PWM输出至少10ms,确保电流完全衰减到0。 - 启动ADC采样
通常我会配置ADC为软件触发模式,连续采样N次(N一般取16或32)。为什么要多次采样?因为单次采样受噪声影响太大,你想想看,如果正好在噪声尖峰时采了一次,那整个系统的零位就偏了。 - 计算平均值
把N次采样的结果累加,然后除以N。这里有个小技巧:如果N是2的幂次(比如16、32、64),可以用右移代替除法,速度快很多。 - 存储偏置值
把计算出的平均值写入EEPROM或Flash。注意:写入前要判断这个值是否在合理范围内。如果采到的偏置值异常大(比如超过ADC满量程的10%),说明硬件可能有问题,这时候应该报错而不是写入。 - 应用补偿
每次ADC转换完成后,在中断服务程序里直接减去偏置值。我习惯在DMA传输完成回调里做这件事,这样不占用CPU时间。
我的小技巧: 在存储偏置值时,同时存储一个校验和(比如简单的累加和)。下次上电时先校验数据完整性,防止EEPROM被意外改写导致校准失效。这个坑我踩过,后来就长记性了。
4.3 代码示例:基于STM32的实现
下面是我在一个风机项目里用过的代码片段,芯片是STM32F103,ADC1采样电流,DMA传输。
// 单次采样校准函数
// 返回值:0-成功,1-失败(电机未静止或偏置异常)
uint8_t Calibrate_ZeroOffset(void)
{
uint32_t sum = 0;
uint16_t raw_value;
uint8_t i;
// 第一步:确保电机静止
TIM_Cmd(TIM1, DISABLE); // 关闭PWM
delay_ms(20); // 等待电流衰减
// 第二步:连续采样32次
for(i = 0; i < 32; i++)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
raw_value = ADC_GetConversionValue(ADC1);
sum += raw_value;
}
// 第三步:计算平均值(右移5位 = 除以32)
zero_offset = sum >> 5;
// 第四步:合理性检查
if(zero_offset > 409) // 假设12位ADC,10%阈值
{
return 1; // 偏置异常,返回失败
}
// 第五步:写入EEPROM
Write_EEPROM(ADDR_OFFSET, zero_offset);
Write_EEPROM(ADDR_CHECKSUM, Calc_Checksum(zero_offset));
// 重新使能PWM
TIM_Cmd(TIM1, ENABLE);
return 0;
}
// 每次ADC转换完成后的补偿
void ADC_IRQHandler(void)
{
uint16_t adc_raw = ADC_GetConversionValue(ADC1);
int16_t adc_calibrated = (int16_t)adc_raw - (int16_t)zero_offset;
// 后续处理...
}
注意: 上面的代码里,adc_calibrated 是 int16_t 类型。如果 raw_value 小于 zero_offset,结果会是负数。这在电流双向流动的场合是正常的,但如果你用的是单极性ADC,需要额外处理符号问题。
4.4 适用场景
单次采样校准法最适合以下场景:
- 环境温度变化小的场合(比如室内设备、工业控制柜)
- 对成本敏感的产品(家电、风扇、水泵等)
- 上电后不需要频繁启停的系统
- 硬件设计比较成熟,温漂已经控制在可接受范围内
我做过一个空调室外机项目,用的就是单次采样校准。因为空调上电后基本不会断电,而且环境温度变化有热敏电阻做辅助补偿,单次校准完全够用。
4.5 局限性:为什么有时候它不灵
这个方法最大的问题,就是它假设零位偏置是恒定不变的。但现实世界不是这样的。
| 影响因素 | 对零位的影响 | 单次校准能否应对 |
|---|---|---|
| 温度漂移 | 运放偏置随温度变化,可达±5% | ❌ 不能 |
| 电源电压波动 | ADC参考电压变化导致偏置偏移 | ❌ 不能 |
| 器件老化 | 长时间使用后偏置缓慢变化 | ❌ 不能 |
| 采样噪声 | 单次采样受噪声影响大 | ✅ 多次平均可缓解 |
| 电机反电动势 | 电机未完全静止时产生干扰 | ✅ 延长等待时间可缓解 |
我曾经在一个户外设备上吃过亏。产品在实验室调试时一切正常,零位校准后电流波形漂亮得很。结果到了夏天,现场反馈说电机低速时抖动厉害。我跑过去一看,机箱温度60多度,零位偏置已经漂了将近8%。单次校准法在这种场景下,就是白费功夫。
总结一下: 单次采样校准法适合「环境稳定、成本敏感、精度要求不高」的场合。如果你的系统工作温度范围超过40°C,或者对低速性能有较高要求,我建议你直接跳到下一节,看看动态校准法。
4.6 知识体系图
下面这张图把单次采样校准法的核心逻辑串起来了,你可以对照着理解。
从这张图可以看得很清楚:单次采样校准法是一条直线流程,从「确保静止」到「应用补偿」一步到位。但它的局限性也很明显——一旦环境变了,这条直线就断了。
所以我的建议是:先用单次采样校准法快速验证硬件和软件通路是否正常。如果测试下来发现零位漂移在可接受范围内,那就用这个方法,省时省力。如果不行,再考虑更复杂的动态校准方案。