用STM32F103C8T6+TMC2209给步进电机做个‘防丢步’闭环:手把手移植野火PID代码

张开发
2026/4/16 14:43:11 15 分钟阅读

分享文章

用STM32F103C8T6+TMC2209给步进电机做个‘防丢步’闭环:手把手移植野火PID代码
STM32F103C8T6TMC2209步进电机闭环控制实战从野火PID代码移植到防丢步实现最近在做一个需要精确控制步进电机位置的小项目时遇到了一个让人头疼的问题——电机偶尔会丢步。这个问题在低速时不太明显但一旦提高速度位置偏差就会累积到无法忽视的程度。经过一番研究发现给步进电机加上位置闭环是个不错的解决方案。本文将分享如何基于STM32F103C8T6和TMC2209驱动芯片通过移植野火的PID控制代码实现一个可靠的防丢步闭环系统。1. 硬件准备与连接在开始代码移植前我们需要先确保硬件连接正确。这套系统主要由三部分组成STM32F103C8T6最小系统板、TMC2209步进电机驱动板和MT6816磁编码器。核心硬件清单STM32F103C8T6最小系统板蓝色药丸板TMC2209步进电机驱动模块42步进电机带MT6816磁编码器逻辑电平转换器如果需要稳压电源12V/2A以上硬件连接有几个关键点需要注意连接点STM32引脚TMC2209引脚备注脉冲信号PA8 (TIM1_CH1)STEP使用定时器输出PWM方向信号PB5DIR普通GPIO即可使能信号PB6EN低电平有效编码器A相PA0-正交编码器接口编码器B相PA1-正交编码器接口提示TMC2209的VIO引脚需要连接到3.3V如果模块是5V逻辑电平需要添加电平转换电路。实际接线时建议先用万用表检查所有电源连接是否正确特别是确保电机电源和逻辑电源没有短路。我曾因为一个错接的GND导致TMC2209无法正常工作排查了半天才发现问题。2. 开发环境搭建与基础工程创建我习惯使用STM32CubeIDE进行开发它集成了STM32CubeMX配置工具和Eclipse开发环境对STM32系列支持很好。下面是环境搭建的具体步骤下载并安装STM32CubeIDE最新版本即可创建一个新的STM32工程选择STM32F103C8系列配置系统时钟为72MHz外部8MHz晶振启用SWD调试接口Serial Wire配置必要的GPIO和定时器关键外设配置// 定时器1配置 - 用于生成步进脉冲 TIM_HandleTypeDef htim1; htim1.Instance TIM1; htim1.Init.Prescaler 0; htim1.Init.CounterMode TIM_COUNTERMODE_UP; htim1.Init.Period 1000; // 初始频率 htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(htim1); // 编码器接口配置 - 定时器2 TIM_Encoder_InitTypeDef sEncoderConfig; TIM_MasterConfigTypeDef sMasterConfig; htim2.Instance TIM2; htim2.Init.Prescaler 0; htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 0xFFFF; htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; sEncoderConfig.EncoderMode TIM_ENCODERMODE_TI12; sEncoderConfig.IC1Polarity TIM_ICPOLARITY_RISING; sEncoderConfig.IC1Selection TIM_ICSELECTION_DIRECTTI; sEncoderConfig.IC1Prescaler TIM_ICPSC_DIV1; sEncoderConfig.IC1Filter 0; sEncoderConfig.IC2Polarity TIM_ICPOLARITY_RISING; sEncoderConfig.IC2Selection TIM_ICSELECTION_DIRECTTI; sEncoderConfig.IC2Prescaler TIM_ICPSC_DIV1; sEncoderConfig.IC2Filter 0; HAL_TIM_Encoder_Init(htim2, sEncoderConfig);3. 野火PID代码移植与适配野火的电机控制代码结构清晰很适合作为基础进行修改。我们需要重点关注的是PID控制部分的移植。原始代码是为特定硬件编写的我们需要做以下适配主要修改点硬件抽象层(HAL)适配编码器接口修改PID参数调整策略速度限制和保护机制移植后的PID控制函数核心逻辑如下void Stepper_PID_Ctrl(void) { static int32_t last_position 0; int32_t current_position __HAL_TIM_GET_COUNTER(htim2); int32_t position_delta current_position - last_position; last_position current_position; if(motor_enabled motor_running) { // 计算PID输出 float pid_output PID_Calculate(pid, target_position, current_position); // 处理方向 if(pid_output 0) { HAL_GPIO_WritePin(DIR_GPIO_Port, DIR_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(DIR_GPIO_Port, DIR_Pin, GPIO_PIN_RESET); } // 限制最大速度 pid_output fabsf(pid_output); if(pid_output MAX_SPEED) pid_output MAX_SPEED; // 更新PWM频率 uint32_t pulse_period (SystemCoreClock / 2) / (PULSE_PER_REV * pid_output); __HAL_TIM_SET_AUTORELOAD(htim1, pulse_period); __HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, pulse_period / 2); } }注意野火原始代码中使用的是基本定时器中断调用PID计算这里我们改为了在主循环中调用实际应用中可以根据需求选择合适的方式。PID参数初始化也很关键对于步进电机通常可以先设置为PID_Init(pid, 0.8f, 0.05f, 0.01f); // Kp, Ki, Kd pid.max_output MAX_SPEED; // 限制最大输出 pid.integral_limit 1000; // 积分限幅4. 系统调试与性能优化系统搭建完成后调试是确保闭环控制有效的关键步骤。我总结了一套实用的调试流程编码器测试先确认编码器读数是否正确手动旋转电机观察编码器计数值变化检查方向是否正确正转时数值增加测试一圈的计数值是否符合预期根据编码器分辨率开环测试先不使用PID测试电机基本运动发送固定频率脉冲观察电机转动测试不同速度下的运动平稳性确认方向控制信号有效PID参数整定按照先P后I最后D的顺序调整先将Ki和Kd设为0逐步增加Kp直到系统开始振荡取振荡临界值的50-60%作为初始Kp然后加入Ki消除静差注意积分饱和问题最后加入Kd抑制超调常见问题及解决方案问题现象可能原因解决方法电机不转使能信号未正确设置检查EN引脚电平电机振动但不转电流设置过小调整TMC2209 Vref位置偏差大机械传动有回差检查联轴器或增加预紧高速时丢步加速度过大降低加速度或提高电流调试时可以借助串口打印实时数据下面是一个简单的数据监控函数void Monitor_PID_Performance(void) { static uint32_t last_time 0; if(HAL_GetTick() - last_time 100) { // 每100ms打印一次 last_time HAL_GetTick(); printf(Target: %d, Actual: %d, Output: %.1f\r\n, target_position, __HAL_TIM_GET_COUNTER(htim2), pid.output); } }5. 高级功能扩展基础闭环功能实现后可以考虑添加一些增强功能自适应PID调参根据速度自动调整PID参数运动轨迹规划实现S曲线加减速故障检测堵转检测、过流保护网络监控通过WiFi或蓝牙监控运行状态以自适应PID为例可以根据速度范围切换不同的PID参数void Update_PID_Params(float speed) { if(speed LOW_SPEED_THRESHOLD) { pid.Kp 0.5f; pid.Ki 0.02f; pid.Kd 0.005f; } else if(speed MID_SPEED_THRESHOLD) { pid.Kp 0.8f; pid.Ki 0.05f; pid.Kd 0.01f; } else { pid.Kp 1.2f; pid.Ki 0.03f; // 高速时减小积分分量 pid.Kd 0.02f; } }6. 实际应用中的经验分享在完成这个项目过程中我积累了一些值得分享的经验TMC2209的静音模式很实用但要注意在闭环控制时适当调整spreadCycle参数编码器安装的同轴度对测量精度影响很大使用联轴器时要确保对中电源质量不可忽视电机启动时的电流冲击可能导致MCU复位在PCB布局时将编码器信号线远离电机电源线可以减少干扰一个特别容易忽视的问题是机械共振。有次调试时发现电机在特定速度下振动特别大后来通过调整机械结构和添加橡胶垫解决了问题。这也提醒我机电一体化系统需要同时考虑电气和机械因素。

更多文章