尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

STM32 增量式 PID 电机调速实战:从编码器读取到 PWM 输出 3 步闭环

STM32 增量式 PID 电机调速实战:从编码器读取到 PWM 输出 3 步闭环
📅 发布时间:2026/7/10 8:51:58

STM32 增量式 PID 电机调速实战:从编码器读取到 PWM 输出 3 步闭环

在智能车和机器人开发中,精确控制电机转速是确保系统稳定运行的关键。本文将带你用STM32实现一个完整的增量式PID电机调速系统,包含编码器测速、PID计算和PWM输出的全流程代码实现。不同于理论讲解,我们直接从嵌入式工程师的角度出发,提供可立即复用的代码模块和调试技巧。

1. 系统架构设计与硬件连接

直流有刷电机的闭环控制系统需要三个核心组件:编码器测速模块、PID控制算法和PWM驱动模块。整个系统的信号流如下图所示:

编码器脉冲 → STM32定时器 → 速度计算 → PID算法 → PWM占空比 → 电机驱动 → 电机转速

硬件连接要点:

  • 编码器信号线接至STM32定时器的编码器接口(如TIM4_CH1/TIM4_CH2)
  • PWM输出引脚连接电机驱动芯片的输入(如TIM3_CH1)
  • 电机驱动输出接电机两极

提示:正交编码器建议使用带硬件滤波的电路,避免脉冲抖动影响测速精度。

常用电机驱动芯片配置对比:

驱动芯片最大电流工作电压控制方式典型应用
TB66121.2A2.5-13.5V双路PWM小型机器人
DRV88331.5A2.7-10.8VPH/EN模式微型车模
L298N2A5-35V双全桥教育套件

2. 编码器测速与速度计算

STM32的定时器编码器接口模式能自动计数正交编码脉冲,我们只需定期读取计数值并清零。以下是配置步骤:

// TIM4编码器接口模式初始化 void Encoder_Init(void) { TIM_Encoder_InitTypeDef sConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim4.Instance = TIM4; htim4.Init.Prescaler = 0; htim4.Init.CounterMode = TIM_COUNTERMODE_UP; htim4.Init.Period = 0xFFFF; htim4.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 = 6; // 适当滤波 sConfig.IC2Polarity = TIM_ICPOLARITY_RISING; sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; sConfig.IC2Prescaler = TIM_ICPSC_DIV1; sConfig.IC2Filter = 6; HAL_TIM_Encoder_Init(&htim4, &sConfig); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig); HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL); }

速度计算采用M法(固定时间测脉冲数),在定时中断中执行:

// 5ms定时中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM6) { // 5ms定时器 static int32_t last_count = 0; int32_t current_count = TIM4->CNT; g_motor_speed = (current_count - last_count) * 200; // 转换为RPM last_count = current_count; } }

速度计算优化技巧:

  • 对于低转速电机,可改用T法(测脉冲间隔时间)
  • 添加滑动平均滤波:speed_filter = 0.9*speed_filter + 0.1*raw_speed
  • 考虑齿轮比换算:实际转速 = 编码器转速 / 减速比

3. 增量式PID算法实现

增量式PID相比位置式PID具有抗积分饱和、手动/自动切换无冲击等优势。其离散公式为:

Δu(k) = Kp*[e(k)-e(k-1)] + Ki*e(k) + Kd*[e(k)-2e(k-1)+e(k-2)]

STM32上的C语言实现:

typedef struct { float Kp, Ki, Kd; float prev_error, prev_prev_error; int16_t output_limit; } IncPID_Controller; void IncPID_Init(IncPID_Controller *pid, float Kp, float Ki, float Kd, int16_t limit) { pid->Kp = Kp; pid->Ki = Ki; pid->Kd = Kd; pid->output_limit = limit; pid->prev_error = pid->prev_prev_error = 0; } int16_t IncPID_Compute(IncPID_Controller *pid, int16_t target, int16_t feedback) { float error = target - feedback; float delta = pid->Kp*(error - pid->prev_error) + pid->Ki*error + pid->Kd*(error - 2*pid->prev_error + pid->prev_prev_error); pid->prev_prev_error = pid->prev_error; pid->prev_error = error; // 输出限幅 static int16_t output = 0; output += (int16_t)delta; output = (output > pid->output_limit) ? pid->output_limit : (output < -pid->output_limit) ? -pid->output_limit : output; return output; }

电机控制中常用PI而非完整PID的原因:

  1. 电机转速变化相对缓慢,微分作用易引入高频噪声
  2. 积分项已能有效消除静差,微分带来的改善有限
  3. 减少一个参数可简化调试过程

4. PWM输出与电机驱动

将PID输出转换为PWM占空比,通过H桥驱动电机。关键配置:

// TIM3 PWM初始化 void PWM_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim3.Instance = TIM3; htim3.Init.Prescaler = 71; // 1MHz计数频率 htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 999; // 1kHz PWM htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim3); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); } // 设置电机方向和PWM void Motor_SetOutput(int16_t pwm) { if(pwm >= 0) { HAL_GPIO_WritePin(MOTOR_DIR_GPIO_Port, MOTOR_DIR_Pin, GPIO_PIN_SET); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm); } else { HAL_GPIO_WritePin(MOTOR_DIR_GPIO_Port, MOTOR_DIR_Pin, GPIO_PIN_RESET); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, -pwm); } }

PWM频率选择建议:

  • 有刷电机:1-20kHz(过高会导致MOS管发热)
  • 无刷电机:8-16kHz(避免可闻噪声)
  • 舵机:50-333Hz

5. 参数调试实战技巧

调试增量式PI参数时,建议按以下步骤:

  1. 初始化所有参数为0,逐步增加Kp直到系统开始振荡
  2. 记录临界振荡时的Kp值(Kc)和振荡周期(Pc)
  3. 根据Ziegler-Nichols法则设置初始参数:
    • Kp = 0.6*Kc
    • Ki = 0.5*Pc
  4. 微调观察响应曲线,优化目标:
    • 上升时间快
    • 超调量<10%
    • 稳态误差接近0

典型调试问题解决方案:

现象可能原因解决方法
电机抖动Kp过大减小Kp,增加低通滤波
转速不稳积分饱和限制积分项,使用抗饱和算法
响应慢Ki太小适当增加Ki,但需防止振荡
反向超调微分过强减小Kd或去掉微分项

通过串口输出实时数据辅助调试:

printf("Target:%d,Actual:%d,PWM:%d\r\n", target_speed, actual_speed, pwm_output);

可将数据导入Excel或MATLAB绘制响应曲线,直观分析系统性能。

相关新闻

  • Unity/UE开发者迁移指南:Godot 4移动端2D渲染管线实战
  • 拒绝被坑!吕梁黄金回收避坑指南,6家良心店大公开 - 清奢黄金上门回收
  • 常德闲置黄金哪里卖?6家靠谱黄金回收门店大盘点,全区域覆盖超省心 - 清奢黄金上门回收

最新新闻

  • 抖音直播间数据抓取利器:轻松获取实时弹幕与互动信息
  • 辽宁顶入式搅拌器选型应参考哪些企业资质指标 - 自由和远方
  • 机器人仿真开发实战:使用RobotStudio构建工业机器人应用的完整指南
  • 2026 西安地埋管道渗水维修高性价比防水修缮公司 TOP4:精准测漏长效堵漏 专业防水公司排名推荐(2026年5月防水补漏最新TOP权威排名) - 冠盾建筑修缮
  • 数据分析入门:Excel、SQL、Tableau、Python免费自学路径全解析
  • 万国中国官方售后服务网络全指南|官方网站权威认证(2026年7月最新) - 万国中国服务中心

日新闻

  • OpenClaw本地化部署:xParse文档解析引擎实战指南
  • 蓝牙 5.4 协议栈深度解析:从 HCI 到 L2CAP 的 7 层数据流
  • PyTorch nn.CrossEntropyLoss 实战:3种权重设置与标签平滑对比(附代码)

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号