1. 项目背景与核心价值
作为一名嵌入式开发工程师,我最近完成了基于STM32F103的BLDC(无刷直流电机)和PMSM(永磁同步电机)驱动项目。这两种电机在现代工业自动化、消费电子和新能源汽车领域应用广泛,但市面上很多开源方案要么性能不足,要么代码可读性差。这次我决定从底层开始搭建完整的驱动框架,过程中积累了不少实战经验。
这个项目的独特之处在于:
- 采用成本仅10元左右的STM32F103C8T6最小系统板
- 同时兼容BLDC的方波驱动和PMSM的FOC控制
- 实现完整的霍尔传感器/编码器接口支持
- 代码结构清晰,便于二次开发
实测驱动24V/200W电机时,转速控制精度可达±1%,效率比常见的L298N方案提升30%以上。下面我就从硬件设计到算法实现,详细拆解这个项目的技术要点。
2. 硬件架构设计
2.1 主控选型与最小系统
STM32F103C8T6虽然属于"入门级"MCU,但其72MHz主频和丰富的外设完全能满足电机控制需求:
- 3个定时器(TIM1/TIM2/TIM4)用于PWM生成和编码器接口
- 1个ADC用于电流采样
- USART用于调试和参数配置
- 内置16KB SRAM和64KB Flash
注意:F103的ADC采样率仅1MHz,如需更高精度电流采样,建议外置专用ADC芯片如ADS1115。
2.2 功率驱动电路设计
采用经典的"预驱+MOSFET"方案:
- 预驱芯片:EG2133(替代IR2101S,内置死区控制)
- MOSFET:IRLR7843(30V/160A,Rds(on)仅3.3mΩ)
- 电流采样:0.01Ω/3W合金电阻+INA240运放
- 保护电路:
- 自恢复保险丝(过流)
- TVS二极管(过压)
- NTC热敏电阻(过热)
c复制// PWM初始化代码示例(使用TIM1)
void PWM_Init(uint16_t freq) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseStructure.TIM_Period = (SystemCoreClock / freq) - 1;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // 初始占空比0%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
2.3 传感器接口电路
根据电机类型选择不同传感器方案:
| 传感器类型 | 接口电路 | 适用电机 | 精度 |
|---|---|---|---|
| 霍尔传感器 | GPIO中断 | BLDC | 60° |
| 增量编码器 | TIM编码器模式 | PMSM | 0.1° |
| 电流传感器 | ADC采样 | 两者通用 | 10mA |
3. 软件算法实现
3.1 BLDC六步换相控制
BLDC驱动核心是正确识别转子位置并触发换相:
- 霍尔传感器信号解码(3位二进制→6个状态)
- 查表确定当前应导通的MOSFET组合
- 根据PWM占空比调节输出电压
c复制// 霍尔状态到PWM输出的映射表
const uint8_t HallToPWM[6][3] = {
{1, 0, 0}, // 状态1: A+ B- C off
{1, 0, 1}, // 状态2: A+ C- B off
{0, 0, 1}, // 状态3: B+ C- A off
{0, 1, 1}, // 状态4: B+ A- C off
{0, 1, 0}, // 状态5: C+ A- B off
{1, 1, 0} // 状态6: C+ B- A off
};
void Hall_Update(uint8_t hall_state) {
TIM1->CCR1 = duty_cycle * HallToPWM[hall_state][0];
TIM1->CCR2 = duty_cycle * HallToPWM[hall_state][1];
TIM1->CCR3 = duty_cycle * HallToPWM[hall_state][2];
}
3.2 PMSM的FOC控制
FOC(磁场定向控制)是实现PMSM高效运行的关键,主要步骤:
-
Clarke变换:将三相电流(Ia,Ib,Ic)转换为两相静止坐标系(Iα,Iβ)
math复制Iα = Ia Iβ = (Ia + 2Ib)/√3 -
Park变换:旋转坐标系转换(Iα,Iβ)→(Id,Iq)
math复制Id = Iα·cosθ + Iβ·sinθ Iq = -Iα·sinθ + Iβ·cosθ -
PI调节器:控制Id=0(最小化磁阻损耗),Iq=目标转矩
-
逆Park变换:将(Vd,Vq)转换回静止坐标系
实测发现:FOC的SVPWM调制频率建议在10-20kHz之间,太低会导致电流纹波大,太高会增加开关损耗。
3.3 速度闭环控制
采用增量式PID算法实现精准调速:
c复制typedef struct {
float Kp, Ki, Kd;
float prev_error, integral;
} PID_Controller;
float PID_Update(PID_Controller* pid, float error, float dt) {
float derivative = (error - pid->prev_error) / dt;
pid->integral += error * dt;
pid->prev_error = error;
// 抗积分饱和处理
if(pid->integral > 1000) pid->integral = 1000;
else if(pid->integral < -1000) pid->integral = -1000;
return pid->Kp*error + pid->Ki*pid->integral + pid->Kd*derivative;
}
4. 调试技巧与问题排查
4.1 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 电机抖动不转 | 霍尔相位错误 | 调整霍尔传感器安装角度 |
| 高速时失步 | PWM频率过低 | 提高PWM频率至15kHz以上 |
| 电流波形畸变 | 死区时间不足 | 设置死区时间≥500ns |
| 启动困难 | 初始位置检测错误 | 添加转子预定位程序 |
4.2 关键参数调试步骤
-
电流环调试:
- 先调P项,观察电流阶跃响应
- 再调I项,消除稳态误差
- 典型值:Kp=0.5, Ki=0.1
-
速度环调试:
- 在电流环稳定后调试
- 从较低KP开始逐步增加
- 典型值:Kp=0.2, Ki=0.05, Kd=0.01
-
位置环调试(如需):
- 使用前馈补偿提高响应速度
- 典型值:Kp=5.0, Ki=0.5
4.3 安全保护机制
必须实现的保护功能:
c复制void Safety_Check(void) {
// 过流保护(>10A)
if(Get_Current() > 10.0) {
PWM_Stop();
Set_Fault_Flag(OVERCURRENT);
}
// 堵转检测(速度<10%目标值持续500ms)
if(fabs(target_speed - actual_speed) > 0.9*target_speed) {
if(++stall_counter > 500) {
PWM_Stop();
Set_Fault_Flag(STALL);
}
} else {
stall_counter = 0;
}
}
5. 性能优化技巧
-
减少计算延迟:
- 使用STM32的硬件CRC模块加速Clark/Park变换
- 将三角函数查表存储在Flash中
- 启用FPU(STM32F4系列)
-
降低噪声干扰:
- PCB布局时使功率地与信号地单点连接
- 在MOSFET栅极串联10Ω电阻
- ADC采样使用硬件均值滤波
-
提高控制精度:
- 采用M/T法测速(兼顾高低速)
- 在PWM周期中点进行电流采样
- 使用SMO(滑模观测器)实现无传感器控制
这个项目最让我惊喜的是STM32F103的性能潜力——通过精心优化的代码,它完全可以胜任大多数中小功率电机的控制任务。后续我准备移植到STM32G4系列,利用其内置的运放和比较器进一步简化硬件设计。