1. 项目概述
在电机控制领域,三相电流采样是FOC(磁场定向控制)系统的核心环节。STM32G4系列微控制器凭借其高性能ADC和丰富的定时器资源,成为实现高精度电流采样的理想选择。这个项目主要解决如何在STM32G4平台上实现三相电流的同步采样、数据转换和标定补偿,为后续的FOC算法提供准确的电流反馈。
电流采样的难点在于如何克服硬件电路的非理想特性,包括运放偏移、采样电阻误差、ADC非线性等问题。通过合理的硬件设计和软件标定,我们可以将采样误差控制在1%以内,满足大多数电机控制应用的需求。
2. 硬件设计要点
2.1 电流采样电路拓扑
常见的三相电流采样方案有三种:
- 三电阻采样(每个相线一个采样电阻)
- 双电阻采样(只在两相上安装采样电阻)
- 单电阻采样(在直流母线安装采样电阻)
对于STM32G4这类资源丰富的MCU,推荐使用三电阻采样方案。其优势在于:
- 可以同时获取三相电流瞬时值
- 采样时刻选择更灵活
- 算法处理更简单
典型的三电阻采样电路包含:
- 低阻值精密采样电阻(通常5-50mΩ)
- 差分放大电路(增益50-100倍)
- 抗混叠滤波器(截止频率10-20kHz)
- 电平移位电路(将双极性信号转换为单极性)
2.2 STM32G4的ADC配置
STM32G4的ADC模块具有以下关键特性:
- 16位分辨率,最高4MSPS采样率
- 硬件过采样功能(最高256x)
- 双采样保持电路(可用于差分测量)
- 硬件触发同步采样
推荐配置参数:
c复制hadc1.Init.Resolution = ADC_RESOLUTION_16B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_HRTIM_TRG1;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.OversamplingMode = ENABLE;
hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_256;
hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_8;
hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
3. 软件实现细节
3.1 同步采样时序控制
电流采样必须与PWM波形严格同步,通常在PWM周期中点进行采样。使用HRTIM定时器触发ADC的配置示例:
c复制// 配置HRTIM的TIMC定时器
hhrtim.Instance->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_C].PERxR = PWM_PERIOD;
hhrtim.Instance->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_C].CMP1xR = PWM_PERIOD/2;
// 配置ADC触发事件
hhrtim.Instance->sCommonRegs.ADC1R = (HRTIM_ADC_TRIG1 << HRTIM_ADC1R_ADC1_1_SHIFT);
hhrtim.Instance->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_C].OUTxR |= HRTIM_OUTXRESET_ENABLE;
3.2 电流值计算流程
原始ADC值到实际电流的转换流程:
- 读取三个ADC通道的原始值
- 减去零点偏移量
- 乘以标定系数
- 进行克拉克变换(3相转2相)
代码实现:
c复制void CalculatePhaseCurrents(void)
{
// 读取ADC值
int16_t adc_u = hadc1.Instance->DR[0];
int16_t adc_v = hadc1.Instance->DR[1];
int16_t adc_w = hadc1.Instance->DR[2];
// 零点补偿
float iu = (adc_u - offset_u) * gain_u;
float iv = (adc_v - offset_v) * gain_v;
float iw = (adc_w - offset_w) * gain_w;
// 克拉克变换
motor.I_alpha = iu;
motor.I_beta = (iv - iw) * ONE_BY_SQRT3;
}
4. 标定方法与补偿技术
4.1 零点偏移标定
零点标定步骤:
- 确保电机处于停止状态
- 采集1000个ADC样本
- 计算平均值作为零点偏移
- 存储到Flash或EEPROM
c复制void CalibrateCurrentOffset(void)
{
uint32_t sum_u = 0, sum_v = 0, sum_w = 0;
for(int i=0; i<1000; i++){
sum_u += hadc1.Instance->DR[0];
sum_v += hadc1.Instance->DR[1];
sum_w += hadc1.Instance->DR[2];
HAL_Delay(1);
}
offset_u = sum_u / 1000;
offset_v = sum_v / 1000;
offset_w = sum_w / 1000;
}
4.2 增益系数标定
增益标定需要已知电流源:
- 施加精确的直流电流(如1A)
- 测量ADC输出值
- 计算增益系数 = 理论电流 / (ADC值 - 零点偏移)
c复制void CalibrateCurrentGain(float reference_current)
{
float adc_u = hadc1.Instance->DR[0] - offset_u;
float adc_v = hadc1.Instance->DR[1] - offset_v;
float adc_w = hadc1.Instance->DR[2] - offset_w;
gain_u = reference_current / adc_u;
gain_v = reference_current / adc_v;
gain_w = reference_current / adc_w;
}
5. 常见问题与解决方案
5.1 采样噪声过大
可能原因及对策:
- PCB布局问题
- 确保采样电阻到运放的走线尽可能短
- 使用差分走线并包地处理
- 电源噪声
- 为运放使用独立的LDO供电
- 增加电源去耦电容
- 软件滤波不足
- 启用ADC硬件过采样
- 在软件中增加移动平均滤波
5.2 采样值跳变
典型现象及解决方法:
- PWM开关干扰
- 检查采样时刻是否在PWM周期中点
- 增加采样保持电路的保持电容
- 地回路干扰
- 使用隔离运放或磁耦隔离ADC
- 优化接地策略,采用星型接地
- ADC参考电压不稳
- 为VREF增加大容量储能电容
- 使用外部精密基准源
5.3 标定结果不准确
提高标定精度的技巧:
- 环境温度影响
- 在正常工作温度下标定
- 使用温度传感器进行温度补偿
- 非线性误差
- 采用多点标定(如0.5A,1A,2A)
- 使用二阶多项式拟合校正曲线
- 长期漂移
- 定期自动重新标定
- 选用低温漂采样电阻和运放
6. 性能优化技巧
6.1 利用DMA提高效率
配置DMA自动搬运ADC数据:
c复制hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
6.2 过采样技术应用
通过过采样提高有效分辨率:
c复制// 配置16倍过采样,可将12位ADC提升至14位有效分辨率
hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
6.3 实时校准策略
实现自动零点跟踪:
c复制// 在电机停止时自动更新零点偏移
if(motor.State == STOP){
offset_u = offset_u * 0.99 + adc_u * 0.01;
offset_v = offset_v * 0.99 + adc_v * 0.01;
offset_w = offset_w * 0.99 + adc_w * 0.01;
}
7. 实测数据与波形分析
7.1 静态性能测试
使用精密电流源测试的典型结果:
| 设定电流(A) | 测量电流(A) | 误差(%) |
|---|---|---|
| 0.00 | 0.002 | - |
| 0.50 | 0.498 | -0.4 |
| 1.00 | 0.997 | -0.3 |
| 2.00 | 1.992 | -0.4 |
| 5.00 | 4.981 | -0.38 |
7.2 动态响应测试
使用阶跃电流负载测试的动态特性:
- 建立时间:<50μs
- 过冲:<2%
- 稳态误差:<0.5%
7.3 实际运行波形
示波器捕获的实际运行波形显示:
- PWM频率:20kHz
- 采样时刻准确位于PWM周期中点
- 电流纹波<2%额定值
- 无明显的开关噪声干扰
8. 进阶话题与扩展
8.1 双采样技术
在PWM周期内进行两次采样(开通和关断期间),可以计算得到更精确的平均电流值。这需要:
- 配置ADC在PWM周期内触发两次
- 合理安排采样保持时间
- 在软件中计算两次采样的平均值
8.2 温度补偿
精密电流采样需要考虑温度影响:
- 测量采样电阻温度(使用NTC或集成温度传感器)
- 根据温度系数调整增益系数
- 更新公式:增益_补偿 = 标定增益 × (1 + α×(T - T标定))
8.3 故障检测
利用电流采样实现故障保护:
- 过流检测(硬件比较器+软件滤波)
- 相间不平衡检测
- 开路/短路诊断
- 接地故障检测
实现示例:
c复制// 过流保护检查
if(fabs(iu) > MAX_CURRENT || fabs(iv) > MAX_CURRENT || fabs(iw) > MAX_CURRENT){
Motor_Shutdown();
fault_flags |= OVERCURRENT_FAULT;
}
在实际项目中,我发现电流采样的稳定性很大程度上取决于PCB布局和接地策略。一个实用的技巧是在运放输入端预留π型滤波器的位置,这样可以根据实际噪声情况灵活调整滤波参数。另外,建议在标定时记录环境温度,这对后期分析测量漂移非常有帮助。