4. 参数辨识实验平台搭建
好,咱们进入第四章。这一章讲的是ADC采样和调理电路。说白了,就是电机控制系统的“眼睛”和“耳朵”。你算法写得再漂亮,如果采回来的电流电压数据是错的,那一切都是白搭。我见过太多工程师在算法上死磕,最后发现是采样电路出了问题——嗯,那种感觉真的很崩溃。
4.1 电流采样原理
电流采样,核心就三个字:准、快、稳。在C2000平台上,主流方案有两种:采样电阻(Shunt)和霍尔电流传感器。
| 方案 | 成本 | 精度 | 带宽 | 隔离 | 典型应用 |
|---|---|---|---|---|---|
| 采样电阻 | 低 | 高(需校准) | 极高 | 无 | 低功率、低成本驱动 |
| 霍尔传感器 | 中 | 中 | 中(受限于磁环) | 有 | 中高功率、需要隔离 |
| 电流互感器 | 中高 | 中 | 低(工频为主) | 有 | 交流电机、电网侧 |
我个人习惯在低压(48V以下)的电机驱动板上用采样电阻。为什么?因为延迟小,响应快。你想想看,霍尔传感器从感应到磁场变化到输出信号,中间有微秒级的延迟,对于高速电机控制来说,这个延迟有时候会要命。
关键点:采样电阻的阻值选择是个权衡。阻值大了,信号强,但发热严重;阻值小了,信号弱,信噪比差。我一般按照V_sense_max = 0.5V来反算,留足余量。
4.2 电压采样调理
电压采样相对简单,但坑也不少。C2000的ADC输入范围是0~3.3V,而母线电压可能是310V(整流后)甚至更高。所以必须做分压+调理。
典型的调理电路包含三级:
- 分压网络:用高阻值电阻把高压降到ADC可接受范围。注意电阻的耐压和功率。
- 电压跟随器:用运放做缓冲,提高输入阻抗,防止ADC采样瞬间的电荷注入影响分压点。
- 钳位保护:在ADC引脚前加肖特基二极管,把电压钳在0~3.3V。万一电阻分压出问题,不至于烧ADC。
警告:千万不要省略钳位二极管!我曾经在一个项目中偷懒,觉得分压电阻选得够安全,结果一次上电瞬间的浪涌直接把ADC引脚打穿。从那以后,我每块板子上都加了BAT54S双肖特基二极管,成本几分钱,买个心安。
另外,运放选型要注意轨到轨。C2000的ADC在接近0V和3.3V时线性度会变差,如果你的运放输出不能到轨,那信号范围就更窄了。我个人推荐OPA340或TLV2372,便宜又好用。
4.3 ADC模块配置与校准
C2000的ADC模块功能很强大,但配置起来也容易出错。咱们直接看代码,边看边讲。
4.3.1 基本配置流程
// 初始化ADC模块
void ADC_Init(void)
{
// 1. 上电
AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // 带隙参考源上电
DELAY_US(1000); // 等待稳定,至少1ms
// 2. 设置参考源为内部参考
AdcRegs.ADCCTL1.bit.ADCREFSEL = 0; // 0:内部参考, 1:外部参考
// 3. 设置采样窗口
AdcRegs.ADCSAMPLEMODE.bit.SIMULEN0 = 0; // 顺序采样模式
AdcRegs.ADCSAMPLEMODE.bit.SIMULEN1 = 0;
// 4. 配置采样窗口持续时间
AdcRegs.ADCSOC0CTL.bit.ACQPS = 15; // 采样窗口 = (ACQPS+1) * SYSCLK
// 5. 配置触发源
AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5; // 选择ePWM1的SOCA触发
// 6. 配置通道
AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; // ADCINA0
}
这里有个细节:采样窗口(ACQPS)的设置。窗口太短,采样电容充不满,精度差;窗口太长,占用时间多,影响采样率。我一般根据信号源阻抗来算:
经验公式:采样时间 > 9 * (R_source + R_switch) * C_sample。对于C2000,C_sample约1.6pF,R_switch约500Ω。如果前级运放输出阻抗是100Ω,那采样时间至少需要9 * (100+500) * 1.6e-12 ≈ 8.6ns。实际中我取ACQPS=15(在100MHz时钟下约160ns),留足余量。
4.3.2 校准——被很多人忽略的一步
C2000的ADC有偏移误差和增益误差。出厂时虽然做过校准,但温度变化、老化都会导致漂移。如果你做的是高精度电流环,这一步不能省。
校准方法很简单:
- 偏移校准:将ADC输入短接到GND,采样N次取平均,得到偏移值。
- 增益校准:输入一个已知的精确电压(比如2.5V基准),采样后计算增益系数。
// ADC校准示例
void ADC_Calibrate(void)
{
uint32_t sum = 0;
uint16_t i;
int16_t offset;
float gain;
// 1. 偏移校准:输入短接GND
for(i = 0; i < 64; i++)
{
sum += AdcResult.ADCRESULT0;
}
offset = (int16_t)(sum / 64); // 理想应为0
// 2. 增益校准:输入已知电压V_ref
sum = 0;
for(i = 0; i < 64; i++)
{
sum += AdcResult.ADCRESULT1;
}
// 假设V_ref = 2.5V,理论值 = 2.5/3.3 * 4095 ≈ 3102
gain = 3102.0f / (float)(sum / 64);
// 3. 保存校准系数
CalibParams.offset = offset;
CalibParams.gain = gain;
}
注意:校准系数要保存在非易失性存储器中(如Flash或OTP)。每次上电时读取,而不是每次都重新校准。我习惯在产线测试时做一次完整校准,把系数烧进Flash,后续运行直接加载。
4.4 知识体系总览
下面这张图把本章的核心逻辑串起来了。从物理量到数字量,每一步都有讲究。
4.5 常见问题与避坑
最后,我把自己踩过的坑整理一下,希望能帮你省点时间。
- 采样结果跳变?先查电源纹波。ADC的参考源对噪声极其敏感,我遇到过好几次是因为数字电源和模拟电源没分开。
- 零点偏移过大?检查PCB布局。大电流回路不要靠近ADC输入走线,磁场耦合会产生直流偏置。
- 高速采样时数据丢失?看看是不是ADC结果寄存器没及时读取。C2000的ADC结果寄存器是只读的,读一次就清一次标志位。
- 温度漂移严重?内部参考源的温度系数一般在50ppm/°C左右。如果温漂超标,可以考虑用外部精密基准,比如REF3033。
一个小技巧:在调试阶段,可以用DAC输出一个已知电压,直接灌到ADC引脚,验证整个采样链路是否正确。这样能快速定位问题是出在调理电路还是ADC配置上。