从玩具车到机械臂:手把手教你用STM32和TB6612驱动模块玩转直流有刷电机双闭环控制
从玩具车到机械臂STM32与TB6612实现直流电机双闭环控制实战当你第一次看到智能小车精准停在指定位置或是机械臂稳定夹起易碎物品时是否好奇这背后的控制原理本文将带你用STM32和TB6612驱动模块从零构建直流有刷电机的双闭环控制系统。不同于单纯的理论讲解我们会通过可落地的项目案例让你真正理解速度环与位置环如何协同工作。1. 硬件搭建与基础准备1.1 核心组件选型指南在开始前需要准备以下硬件组件STM32F103C8T6最小系统板性价比极高的Cortex-M3内核控制器TB6612FNG驱动模块支持1.2A持续电流的双路H桥驱动器JGA25-370直流减速电机内置AB相编码器13线/圈5V/12V电源适配器根据电机额定电压选择杜邦线与面包板用于快速原型搭建注意TB6612的VM引脚需接电机电源5-12VVCC接逻辑电平3.3V或5V。PWMA/AIN1/AIN2控制电机APWMB/BIN1/BIN2控制电机B。1.2 电路连接示意图关键连接关系如下表所示STM32引脚TB6612引脚功能描述PA6PWMA电机A PWM信号输入PA7AIN2电机A方向控制线2PB0AIN1电机A方向控制线1PA0STBY驱动芯片使能控制PA8编码器A相电机转速/位置反馈PA9编码器B相电机转向判断// GPIO初始化示例使用HAL库 void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 配置PWM输出引脚 GPIO_InitStruct.Pin GPIO_PIN_6; GPIO_InitStruct.Mode GPIO_MODE_AF_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); // 配置方向控制引脚 GPIO_InitStruct.Pin GPIO_PIN_7|GPIO_PIN_0; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); }2. 编码器测速与位置检测2.1 正交编码器信号处理带编码器的直流电机通常输出两路相位差90°的方波信号。STM32的定时器硬件编码器接口可自动识别转向和计数// 编码器接口配置 void Encoder_Init(TIM_HandleTypeDef *htim) { TIM_Encoder_InitTypeDef sConfig {0}; htim-Instance TIM4; htim-Init.Prescaler 0; htim-Init.CounterMode TIM_COUNTERMODE_UP; htim-Init.Period 65535; htim-Init.ClockDivision TIM_CLOCKDIVISION_DIV1; sConfig.EncoderMode TIM_ENCODERMODE_TI12; sConfig.IC1Polarity TIM_ICPOLARITY_RISING; sConfig.IC1Selection TIM_ICSELECTION_DIRECTTI; sConfig.IC1Prescaler TIM_ICPSC_DIV1; sConfig.IC1Filter 0; sConfig.IC2Polarity TIM_ICPOLARITY_RISING; sConfig.IC2Selection TIM_ICSELECTION_DIRECTTI; sConfig.IC2Prescaler TIM_ICPSC_DIV1; sConfig.IC2Filter 0; HAL_TIM_Encoder_Init(htim, sConfig); HAL_TIM_Encoder_Start(htim, TIM_CHANNEL_ALL); }2.2 速度计算算法速度测量通常采用M法固定时间测脉冲数。在1ms定时中断中读取编码器计数值int16_t Get_Speed(TIM_HandleTypeDef *htim) { static int16_t last_count 0; int16_t current_count __HAL_TIM_GET_COUNTER(htim); int16_t speed current_count - last_count; last_count current_count; return speed; // 返回值与转速成正比 }提示对于低转速测量可采用T法测脉冲周期或M/T法混合测量。实际项目中建议加入滑动平均滤波。3. PID控制算法实现3.1 增量式PID控制器速度环推荐使用增量式PI控制器避免积分饱和问题typedef struct { float Kp; float Ki; float Kd; int16_t last_error; int16_t prev_error; } PID_Handle; int16_t PID_Increment(PID_Handle *hpid, int16_t target, int16_t feedback) { int16_t error target - feedback; int16_t p_term hpid-Kp * (error - hpid-last_error); int16_t i_term hpid-Ki * error; int16_t d_term hpid-Kd * (error - 2*hpid-last_error hpid-prev_error); hpid-prev_error hpid-last_error; hpid-last_error error; return p_term i_term d_term; }3.2 参数整定经验值不同电机系统的PID参数差异较大可参考以下初始值控制环KpKiKd适用场景速度环0.80.050普通直流电机位置环2.50.010.2带减速箱的定位控制调试技巧先设Ki0逐渐增大Kp直到系统开始振荡取振荡时Kp值的60%作为最终Kp缓慢增加Ki直到消除静差最后微调Kd抑制超调4. 双闭环系统整合4.1 控制架构设计典型的双闭环系统采用串级控制结构位置目标 → 位置PID → 速度目标 → 速度PID → PWM输出 → 电机 ↑ ↑ ↑ 位置反馈 速度反馈 电流反馈(可选)4.2 代码实现框架在STM32的主循环中按固定周期执行控制void Control_Loop(void) { static uint32_t last_time 0; if(HAL_GetTick() - last_time 10) return; // 10ms控制周期 last_time HAL_GetTick(); // 获取反馈信号 int16_t position __HAL_TIM_GET_COUNTER(htim4); int16_t speed Get_Speed(htim4); // 位置环计算 if(control_mode POSITION_MODE) { target_speed PID_Position(pos_pid, target_position, position); } // 速度环计算 pwm_output PID_Speed(speed_pid, target_speed, speed); pwm_output constrain(pwm_output, 0, 1000); // 限制PWM范围 // 输出控制信号 Set_PWM(pwm_output); Set_Direction(pwm_output 0); }4.3 典型问题排查当系统出现振荡或响应迟缓时检查编码器信号是否稳定可用逻辑分析仪观察电源电压是否足够且稳定PID参数是否过于激进控制周期是否合适通常5-20ms5. 项目实战机械臂关节控制5.1 运动轨迹规划以夹取动作为例需要规划三段运动快速接近阶段位置环主导减速接近阶段速度环平滑过渡精确定位阶段双环协同# 伪代码示例梯形速度规划 def trapezoid_plan(current_pos, target_pos): max_speed 500 # 编码器计数/周期 acceleration 100 distance target_pos - current_pos if abs(distance) 100: # 短距离直接到位 return distance else: # 计算加速段、匀速段、减速段 ramp_dist max_speed**2 / (2*acceleration) if abs(distance) 2*ramp_dist: # 三角规划 max_speed sqrt(abs(distance)*acceleration) ramp_dist abs(distance)/2 # 返回当前周期目标速度 if abs(distance) ramp_dist: return sign(distance) * min(max_speed, current_speed acceleration) else: return sign(distance) * max(0, abs(current_speed) - acceleration)5.2 防抖动处理技巧机械臂末端抖动可能源于传动机构间隙PID微分噪声电机转矩脉动解决方法在位置环加入死区控制if(abs(error) 5) { // 死区阈值 error 0; integral 0; // 清空积分项 }对速度反馈进行低通滤波使用前馈补偿需系统建模6. 进阶优化方向6.1 抗积分饱和策略当系统出现长时间误差时积分项会累积导致控制量饱和。改进方法// 条件积分法 if((error 0 pwm_output MAX_PWM) || (error 0 pwm_output -MAX_PWM)) { integral error; }6.2 自适应PID控制根据误差大小动态调整参数// 误差较大时增强P减弱I误差小时相反 if(abs(error) threshold) { Kp Kp_high; Ki Ki_low; } else { Kp Kp_low; Ki Ki_high; }6.3 基于模型的补偿通过电机特性曲线补偿非线性转速RPM补偿系数0-1001.2100-3001.0300-5000.9在实验室调试时发现当电机运行在低速区间时由于静摩擦力影响实际需要的PWM占空比要比理论计算值高出约20%。这个经验值可以预先写入查找表进行补偿。