4、ADC采样与电流检测:双电阻采样原理、ADC注入组配置、同步触发模式、电流重构算法、采样偏移校准

电流检测是FOC的「眼睛」。你想想看,如果连电机三相电流都读不准,后面的Clark变换、Park变换全是白搭。这一章我们就把ADC采样这块硬骨头啃下来。

4.1 双电阻采样原理

为什么用双电阻,而不是三电阻?说白了,成本与精度的平衡。三电阻采样需要三个电流传感器,双电阻只用在两相下桥臂串采样电阻,第三相电流通过基尔霍夫定律算出来:IC = -(IA + IB)。

我在项目中遇到过一个问题:双电阻采样对PWM占空比有「盲区」。当某一相占空比接近0%或100%时,采样窗口太短,ADC根本来不及转换。这时候就需要电流重构算法来补位。

采样方式 电阻数量 优点 缺点
双电阻 2 成本低,计算量小 存在采样盲区
三电阻 3 无盲区,精度高 成本高,PCB面积大
单电阻 1 成本最低 重构算法复杂,低速性能差
关键点:双电阻采样必须在PWM周期的特定时刻触发ADC,这个时刻就是下桥臂导通、电流流过采样电阻的瞬间。

4.2 ADC注入组配置

GD32的ADC有个好东西叫「注入组」。常规的规则组用于连续采样,而注入组可以「插队」——优先级更高,适合在PWM中断里抢时间采样。

我个人习惯这样配置注入组:

  1. 使能ADC时钟,配置分频系数(一般ADC时钟不要超过14MHz)
  2. 设置注入组通道数为2(对应A相和B相电流)
  3. 配置采样时间:我一般设7.5个周期,够稳
  4. 使能注入组中断,用于读取结果
// 注入组配置示例
adc_insermode_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE);
adc_inserted_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_7POINT5);
adc_inserted_channel_config(ADC0, 1, ADC_CHANNEL_1, ADC_SAMPLETIME_7POINT5);
adc_external_trigger_inserted_config(ADC0, ENABLE, ADC_EXT_TRIGGER_INSERTED_T0TRGOUT);
adc_interrupt_enable(ADC0, ADC_INT_INSERTED);
小技巧:注入组转换结果存放在ADC_IDATA0~IDATA3寄存器中,记得按通道顺序读取,别搞混了。

4.3 同步触发模式

ADC采样必须和PWM同步,否则采到的电流值毫无意义。GD32的定时器可以输出TRGO信号,直接触发ADC注入组转换。

为什么会这样?因为FOC需要在PWM周期的中点采样电流,此时相电流最稳定,纹波最小。

我建议的配置流程:

  • 定时器0配置为主模式,输出TRGO信号
  • TRGO触发源选择为「更新事件」或「OC1REF」
  • ADC0配置为外部触发注入组模式,触发源选择T0TRGOUT
// 定时器TRGO配置
timer_master_slave_mode_config(TIMER0, TIMER_MASTER_SLAVE_MODE_ENABLE);
timer_master_output_trigger_source_select(TIMER0, TIMER_MASTER_UPDATE);
注意:触发信号的电平和边沿要匹配。GD32的ADC触发默认是上升沿,如果定时器输出的是高电平脉冲,记得检查极性。

4.4 电流重构算法

前面提到双电阻有采样盲区,怎么解决?靠重构算法。

当某一相占空比太小时,该相电流无法采样。这时候我们利用另外两相电流和三相电流之和为零的特性,反推出缺失的那一相。

我曾经踩过一个坑:重构算法在低速大扭矩时频繁触发,导致电流波形畸变。后来发现是采样窗口设置太短,ADC转换没完成就进入了重构分支。

重构算法的核心逻辑:

  1. 判断当前扇区(根据SVPWM的扇区号)
  2. 确定哪一相电流无法采样
  3. 用另外两相电流计算缺失相:Imiss = -(Ia + Ib)
  4. 如果两相都无法采样(极端情况),保持上一次采样值
// 电流重构伪代码
if (sector == 1 || sector == 4) {
    // A相无法采样
    I_a = -(I_b + I_c);
} else if (sector == 2 || sector == 5) {
    // B相无法采样
    I_b = -(I_a + I_c);
} else {
    // C相无法采样
    I_c = -(I_a + I_b);
}
经验值:当占空比小于5%或大于95%时,强制进入重构模式。这个阈值可以根据你的采样时间和ADC转换速度微调。

4.5 采样偏移校准

ADC采样有个「零漂」问题。即使电机不转,ADC读到的电流值也不是0,而是几十到几百个LSB的偏移。这个偏移如果不校准,FOC会认为电机一直在转,导致失控。

校准方法很简单:电机静止时,连续采样N次(我一般取100次),取平均值作为偏移量。然后在每次采样结果中减去这个偏移量。

// 偏移校准示例
#define CALIBRATION_SAMPLES 100

uint16_t offset_a = 0, offset_b = 0;

void current_calibration(void) {
    uint32_t sum_a = 0, sum_b = 0;
    for (int i = 0; i < CALIBRATION_SAMPLES; i++) {
        sum_a += adc_inserted_read(ADC0, 0);
        sum_b += adc_inserted_read(ADC0, 1);
    }
    offset_a = sum_a / CALIBRATION_SAMPLES;
    offset_b = sum_b / CALIBRATION_SAMPLES;
}

// 使用时
int32_t current_a = (int32_t)adc_value_a - (int32_t)offset_a;
建议:每次电机启动前做一次偏移校准。如果环境温度变化大,可以在运行过程中定期校准(电机静止时)。

4.6 本章知识结构图

下面这张图把ADC采样与电流检测的完整链路串起来了,从硬件采样到软件重构,一目了然。

ADC采样与电流检测知识结构图 双电阻采样硬件 PWM定时器TRGO ADC注入组配置 同步触发模式:TRGO → ADC注入组 正常采样:两相电流直接读取 盲区处理:电流重构算法 采样偏移校准:零漂消除 输出:I_A, I_B, I_C 给Clark变换 注意:盲区判断阈值 占空比 < 5% 或 > 95%

4.7 常见问题与避坑

  • 采样值跳变:检查ADC参考电压是否稳定,VREF引脚加104电容
  • 重构算法频繁触发:调整盲区阈值,或者增加采样窗口时间
  • 偏移校准后仍有偏差:可能是运放电路失调,需要硬件上做偏置调整
  • ADC转换结果始终为0:检查触发信号是否到达,用示波器量TRGO引脚
重要提醒:双电阻采样对PCB布局敏感。采样电阻的地线要单独走,不要和功率地混在一起。我曾经因为地线没处理好,ADC读数噪声高达50LSB,折腾了两天才找到原因。