1. 项目背景与核心需求
在工业自动化和智能硬件领域,直流电机控制一直是个经典课题。最近接手了一个需要精确控制直流电机转速和扭矩的项目,选用了TB6593FNG驱动芯片搭配STM32F103RC主控的方案。这个组合在中小功率直流电机控制中很常见,但要把性能调到最优状态,中间有不少门道值得分享。
TB6593FNG是东芝出品的一款双H桥电机驱动IC,最大输出电流3A(峰值5A),内置过热保护和低电压检测,PWM频率最高可达100kHz。而STM32F103RC作为Cortex-M3内核的MCU,72MHz主频加上丰富的外设,正好能满足实时控制的需求。两者配合可以实现从简单开环控制到带编码器反馈的闭环控制。
2. 硬件设计关键点
2.1 驱动电路设计
TB6593FNG的典型应用电路需要注意几个细节:
- 电源部分必须加足够容量的去耦电容,我的方案是在VM引脚(电机电源)就近放置一个100μF电解电容并联0.1μF陶瓷电容
- 电流检测电阻选用0.1Ω/2W的金属膜电阻,布局时要尽量靠近芯片的IS引脚
- 散热处理:在PCB上设计足够的铜箔面积,必要时加散热片。实测连续工作下芯片温度会达到60℃左右
重要提示:电机电源和逻辑电源一定要分开供电!我最初尝试共用5V电源,电机启动瞬间导致MCU复位,后来改用独立12V电机电源后问题解决。
2.2 STM32接口配置
STM32F103RC需要配置以下关键外设:
- TIM1或TIM8用于生成PWM信号(建议用互补输出模式)
- ADC1用于电流检测(采样IS引脚电压)
- 至少一个UART用于调试输出
- 如果做闭环控制,还需要配置编码器接口(TIM2/TIM3/TIM4)
配置代码示例:
// PWM初始化 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructure.TIM_Period = 999; // 10kHz PWM TIM_TimeBaseStructure.TIM_Prescaler = 71; // 72MHz/(71+1)=1MHz 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 = 500; // 初始占空比50% TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE);3. 控制算法实现
3.1 基础驱动逻辑
TB6593FNG有四种控制模式:
- IN1=H, IN2=L:正转
- IN1=L, IN2=H:反转
- IN1=IN2=H:刹车
- IN1=IN2=L:滑行
实际项目中我采用PWM+方向的控制方式:
- 用PWM引脚控制速度
- 用另一个GPIO控制方向
- 刹车功能保留用于紧急停止
3.2 PID速度控制
当需要精确控制转速时,需要实现PID算法。以带编码器的电机为例:
typedef struct { float Kp, Ki, Kd; float integral; float prev_error; } PID_Controller; float PID_Update(PID_Controller* pid, float error, float dt) { pid->integral += error * dt; float derivative = (error - pid->prev_error) / dt; pid->prev_error = error; return pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; } // 在定时中断中调用 void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { static uint32_t last_encoder = 0; uint32_t current_encoder = TIM_GetCounter(TIM3); // 编码器值 float speed = (current_encoder - last_encoder) / (0.001f * ENCODER_RESOLUTION); last_encoder = current_encoder; float error = target_speed - speed; float output = PID_Update(&pid, error, 0.001f); // 限制输出范围 output = fmaxf(fminf(output, 1000), 0); TIM_SetCompare1(TIM1, (uint16_t)output); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }参数整定经验:
- 先设Ki=0, Kd=0,逐渐增大Kp直到出现轻微振荡
- 然后加入Ki,约为Kp/100开始尝试
- 最后加入Kd改善动态响应
- 我的最终参数:Kp=0.8, Ki=0.005, Kd=0.1(具体值需根据电机特性调整)
4. 性能优化技巧
4.1 PWM频率选择
通过实验对比不同PWM频率的表现:
- 1kHz:电机噪音明显,但扭矩响应快
- 10kHz:折中选择,噪音小,响应尚可
- 20kHz以上:超过人耳范围,但驱动损耗增加
最终选择10kHz作为工作频率,在TB6593FNG的数据手册推荐范围内。
4.2 死区时间设置
当使用互补PWM输出时,必须设置死区时间防止上下管直通:
TIM_BDTRInitTypeDef TIM_BDTRInitStructure; TIM_BDTRInitStructure.TIM_DeadTime = 0x18; // 约1us死区 TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Disable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Disable; TIM_BDTRInitStructure.TIM_AOE = TIM_AOE_Disable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);4.3 电流保护实现
利用ADC监测IS引脚电压,当超过阈值时立即切断输出:
#define CURRENT_THRESHOLD 2.0f // 2A void ADC1_2_IRQHandler(void) { if(ADC_GetITStatus(ADC1, ADC_IT_JEOC) == SET) { float current = (ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1) * 3.3f / 4096) / 0.1f; if(current > CURRENT_THRESHOLD) { TIM_CtrlPWMOutputs(TIM1, DISABLE); Fault_Handler(); } ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); } }5. 实测性能数据
使用250W直流有刷电机测试,负载为磁粉制动器:
| 控制模式 | 转速波动率 | 响应时间(ms) | 效率 |
|---|---|---|---|
| 开环PWM | ±15% | 50 | 78% |
| PID闭环 | ±2% | 20 | 85% |
| 带前馈补偿 | ±1% | 10 | 87% |
前馈控制的实现要点:
float feedforward = target_speed * 0.8f; // 前馈系数需实测确定 float pid_output = PID_Update(&pid, error, dt); float final_output = feedforward + pid_output;6. 常见问题排查
6.1 电机抖动不转
可能原因及解决方案:
- 电源功率不足:换用更大电流的电源
- PWM频率过高:尝试降低到5-10kHz
- 死区时间不足:增加死区设置
- 电机线接触不良:检查接线端子
6.2 转速控制不稳定
排查步骤:
- 检查编码器信号是否正常(可用逻辑分析仪)
- 确认PID采样周期是否合适(建议1-10ms)
- 检查电源电压波动(示波器看VM引脚)
- 尝试增加速度滤波:
#define FILTER_GAIN 0.1f filtered_speed = filtered_speed * (1 - FILTER_GAIN) + new_speed * FILTER_GAIN;6.3 驱动芯片过热
降温措施:
- 优化PCB散热设计(增加铜箔、加散热片)
- 降低PWM频率(但不要低于5kHz)
- 检查是否长时间工作在制动模式
- 考虑换用更大封装的TB6593FNG(如HZIP25-P-1)
经过三周的调试和优化,这套系统最终实现了±1%的转速控制精度,响应时间在10ms以内。最关键的收获是:电机控制是个系统工程,硬件设计、参数整定、保护机制缺一不可。下次再做类似项目,我会优先考虑使用带电流检测反馈的驱动方案,可以进一步提升控制性能。