基于STM32的平衡球PID控制实战:从硬件选型到参数整定
1. 项目缘起与整体设计思路1.1 为什么选择平衡球作为PID实战载体做控制算法的人都有一个共识看一百遍公式不如亲手让一个真实系统稳下来。平衡球系统就是这样一个绝佳的实战载体——一根横梁一颗小球目标是通过控制横梁的倾角让小球稳定在指定位置。听起来简单但它几乎涵盖了控制工程中所有核心问题非线性动力学、传感器噪声、执行器延迟、重力扰动、摩擦不确定性。我选择这个项目是因为它比倒立摆简单比温控系统直观比电机调速有观赏性。你能亲眼看到球在梁上滚动能用手拨一下球看系统如何恢复这种即时反馈对理解PID三个参数的作用是无价的。而且整个系统的硬件成本可以压到很低——一个舵机、一个超声波或红外测距模块、一块STM32或者Arduino、一根铝型材梁加起来不到两百块。这个项目适合谁如果你已经看过PID公式但不知道Kp、Ki、Kd到底怎么影响实际系统如果你做过仿真但没碰过真实硬件如果你想让自己的控制理论知识落地那这个项目就是为你准备的。我会从算法原理讲到硬件选型从代码实现讲到调参实录把整个流程拆开揉碎。1.2 系统总体架构与信号流整个系统的信号流是这样的测距传感器实时采集小球在梁上的位置这个位置信号经过滤波后送入PID控制器控制器计算出舵机应该转动的角度舵机驱动横梁倾斜小球在重力分量作用下产生加速度位置发生变化形成闭环。这里有一个关键设计决策位置式PID还是增量式PID。位置式PID输出的是舵机角度的绝对值增量式输出的是角度的变化量。对于舵机控制我最终选择了位置式PID原因是舵机本身就是一个位置伺服系统给它绝对角度指令更自然而且位置式PID在积分饱和处理上更直观。增量式PID更适合直接驱动电机转速的场景比如速度环控制。另一个决策是单环还是串级。理论上可以加一个角度环作为内环位置环作为外环形成串级PID。但实测下来对于这种慢速系统单环PID已经足够串级反而增加了调参复杂度。除非你的舵机响应特别慢或者梁的惯量特别大否则我建议从单环开始。注意不要一上来就追求复杂方案。单环PID调好了效果已经能满足大部分场景。串级PID是锦上添花不是雪中送炭。1.3 硬件选型背后的取舍逻辑硬件选型直接决定了控制效果的上限。我踩过的坑是一开始用SG90微型舵机扭矩太小梁稍微长一点就带不动球在梁上抖得像筛糠。后来换成MG996R金属齿轮舵机扭矩够了但响应速度又成了瓶颈。最终我选的是DS3218 20kg数字舵机扭矩和速度都够用价格也在可接受范围内。测距方案我试过三种红外测距、超声波测距、激光ToF。红外测距响应快但量程短、受环境光影响大超声波量程够但刷新率低、波束角大容易误检激光ToF综合表现最好刷新率可以到100Hz以上精度毫米级。如果你预算有限红外测距也能用但要在梁上贴一条白色反光带提高信噪比。主控我用的STM32F103C8T6也就是常说的“蓝板”。原因很简单定时器资源丰富PWM输出稳定ADC采样快而且社区资料多遇到问题好查。Arduino也能做但中断响应和PWM精度会差一些调参时你会明显感觉到“手不够快”。部件型号关键参数选择理由主控STM32F103C8T672MHz, 3个通用定时器PWM精度高中断响应快舵机DS321820kg·cm, 0.16s/60°扭矩足金属齿轮耐用测距VL53L0X量程2m, 精度±3mm刷新率高抗干扰强梁铝型材长度40cm, 轻质刚性好惯量小球钢球直径2cm, 光滑滚动摩擦小运动可预测2. 核心细节解析与实操要点2.1 PID算法在平衡球上的物理意义PID三个参数在平衡球系统里各自扮演什么角色我用最直白的话解释。Kp比例项决定系统对位置偏差的“敏感程度”。球偏离目标位置越远舵机倾斜角度越大球回来的速度越快。Kp太小球慢悠悠地晃回来甚至回不来Kp太大球会在目标位置附近来回振荡像喝醉了酒。Ki积分项消除稳态误差。如果梁不是完全水平或者球的重心不在正中间光靠Kp球永远停不到目标位置总会差那么一点。Ki的作用就是“记住”这个偏差慢慢累积直到把球推到正确位置。但Ki太大会导致积分饱和球冲过头后要等很久才能回来。Kd微分项提供阻尼。球运动越快Kd产生的“反向力”越大防止球冲过头。Kd相当于给系统加了刹车让球接近目标位置时减速。没有Kd系统会振荡Kd太大系统会变得迟钝甚至因为噪声放大而抖动。用数学表达位置式PID的输出是u(t) Kp * e(t) Ki * ∫e(t)dt Kd * de(t)/dt其中e(t)是目标位置与当前位置的偏差。在代码里积分项用累加实现微分项用差分实现。实操心得调参时先把Ki和Kd设为0只调Kp。当球能在目标位置附近等幅振荡时记录此时的Kp值然后取它的60%作为最终Kp。接着加Kd从Kp的1/10开始往上加直到振荡消失。最后加Ki从Kp的1/100开始只加到能消除稳态误差就停。2.2 传感器数据处理与滤波策略测距传感器输出的原始数据一定带噪声。VL53L0X虽然精度不错但在球快速滚动时单次测量会有几毫米的跳变。如果直接把这个数据喂给PID微分项会把噪声放大成剧烈的舵机抖动。我的做法是先做中值滤波再做一阶低通滤波。中值滤波取最近5次采样的中位数能有效剔除偶发的野值。一阶低通滤波的公式是filtered alpha * raw (1 - alpha) * filtered_prevalpha取0.3到0.5之间。alpha越大响应越快但噪声越大alpha越小越平滑但延迟越大。对于平衡球我最终取0.35在响应速度和噪声抑制之间找到了平衡。还有一个细节微分项不要直接用滤波后的位置差分。因为滤波本身有延迟差分出来的速度会滞后。更好的做法是用一个单独的差分滤波器或者直接用位置式PID的微分项对误差做差分但加上一个低通滤波。我试过用卡尔曼滤波估计球的速度效果确实好但计算量大STM32F103跑起来有点吃力最后放弃了。注意滤波不是越多越好。每加一级滤波就多一份相位延迟。延迟大了Kd的效果会大打折扣系统容易振荡。我的原则是能用硬件解决的不要用软件滤波能用简单滤波解决的不要上卡尔曼。2.3 舵机控制与死区补偿舵机有一个特性死区。也就是说PWM占空比变化很小的时候舵机根本不转。DS3218的死区大约在5微秒左右。如果PID输出的角度变化小于死区舵机不动球就会一直偏下去积分项越积越大最后突然冲过头。我的解决方案是在PID输出后加一个死区补偿。如果输出变化量小于死区阈值就把它放大到刚好能驱动舵机的最小值。这样虽然牺牲了一点精度但避免了积分饱和和突然冲过头的问题。另外舵机的响应延迟也要考虑。DS3218从收到指令到转到指定角度大约需要100到150毫秒。这个延迟在PID里相当于一个纯滞后环节会降低系统的相位裕度。我的做法是在调参时把Kd适当调大一点补偿这个延迟带来的相位损失。舵机的供电也要注意。千万不要用STM32的5V输出直接给舵机供电舵机启动瞬间的电流冲击会导致主控复位。我用的是一个独立的5V 3A开关电源给舵机供电主控和舵机共地但不共电源。3. 实操过程与核心环节实现3.1 硬件搭建与接线要点硬件搭建的顺序很重要。我的建议是先搭机械结构再连电路最后写代码。机械结构不稳后面调参全是白费。梁的安装方式是舵机固定在底座上舵机臂连接梁的一端梁的另一端用一个轴承支撑保证梁可以绕轴自由转动。梁的转轴要尽量靠近梁的重心这样舵机负载最小。球放在梁上测距传感器固定在梁的正上方垂直向下照射。接线方面VL53L0X用I2C接口SCL接PB6SDA接PB7注意要加上拉电阻4.7kΩ。舵机信号线接PA0这个引脚对应TIM2_CH1可以输出PWM。舵机电源单独走线不要和主控共用一路。实操心得I2C总线上拉电阻不能省。我一开始没加上拉电阻VL53L0X时好时坏查了半天以为是传感器坏了后来加上4.7kΩ上拉电阻就稳定了。这个坑很典型新手很容易忽略。3.2 PID代码实现与参数整定代码部分我用的是位置式PID核心结构体如下typedef struct { float Kp; float Ki; float Kd; float integral; float prev_error; float integral_limit; float output_limit; } PID_Controller; float PID_Compute(PID_Controller *pid, float setpoint, float measured) { float error setpoint - measured; // 积分项累加带限幅 pid-integral error; if (pid-integral pid-integral_limit) pid-integral pid-integral_limit; else if (pid-integral -pid-integral_limit) pid-integral -pid-integral_limit; // 微分项 float derivative error - pid-prev_error; pid-prev_error error; // 计算输出 float output pid-Kp * error pid-Ki * pid-integral pid-Kd * derivative; // 输出限幅 if (output pid-output_limit) output pid-output_limit; else if (output -pid-output_limit) output -pid-output_limit; return output; }积分限幅非常重要。如果不加限幅球长时间到不了目标位置积分项会一直累加最后输出饱和球冲过头后要等很久积分才能降下来。我的积分限幅设的是输出限幅的1/3左右。调参过程我记录如下步骤KpKiKd现象调整10.500球缓慢滚动回不到目标Kp太小加倍21.000球能回来但振荡Kp合适记录30.600振荡幅度减小取60% Kp40.600.05振荡明显减弱加Kd50.600.08基本稳定有微小稳态误差Kd合适60.60.010.08稳态误差消除加Ki70.60.020.08球稳定在目标位置最终参数最终参数Kp0.6, Ki0.02, Kd0.08。这个参数下球从任意位置出发大约2秒内能稳定到目标位置超调量小于5%。3.3 调试工具与实时监控调参时如果只能靠眼睛看效率极低。我的做法是用STM32的串口把实时数据发到电脑上用VOFA或者SerialPlot画曲线。需要监控的变量有目标位置、实际位置、PID输出、积分项。串口发送的格式我用的是简单的文本协议每行一帧数据用逗号分隔target,position,output,integral\n波特率设115200每20毫秒发一帧。VOFA可以直接解析这种格式并实时绘图。看着曲线调参比盲调快十倍。注意串口发送数据会占用CPU时间如果发送频率太高会影响控制循环的实时性。我的做法是把控制循环放在定时器中断里串口发送放在主循环里两者互不干扰。控制周期我设的是10毫秒也就是100Hz足够快了。4. 常见问题与排查技巧实录4.1 球振荡不止怎么办球在目标位置附近持续振荡是最常见的问题。原因通常有三个Kp太大、Kd太小、或者系统延迟太大。排查顺序先把Ki设为0排除积分项干扰。然后逐步减小Kp直到振荡幅度明显减小。如果减小Kp后球回不到目标位置说明Kp不能再小了此时应该增大Kd。Kd从Kp的1/10开始加每次加0.01直到振荡消失。如果加了Kd还是振荡那就要检查系统延迟。用示波器看舵机信号和球位置的变化如果舵机响应明显滞后于位置变化说明延迟太大。解决办法是换更快的舵机或者降低控制周期或者用前馈补偿。4.2 球停在目标位置附近但回不到正中间这是典型的稳态误差原因是Ki太小或者根本没有Ki。但加Ki之前要先确认机械结构没有卡涩梁的转轴没有摩擦死点。如果机械没问题逐步增大Ki每次加0.005直到球能回到正中间。如果加了Ki后球开始低频振荡说明Ki太大了积分项在“过冲-回调”之间来回摆动。此时应该减小Ki或者加一个积分分离当误差大于某个阈值时暂时关闭积分项避免积分饱和。4.3 舵机抖动严重舵机抖动通常是因为PID输出变化太剧烈尤其是微分项放大了传感器噪声。解决办法在微分项后面加一个低通滤波截止频率设在20Hz左右。或者直接减小Kd但这样会牺牲阻尼效果。另一个原因是电源功率不足。舵机在快速转动时电流需求很大如果电源带不动电压会跌落舵机就会抖动。用万用表测一下舵机供电电压如果在舵机转动时电压跌落超过0.5V就要换更大功率的电源。4.4 常见问题速查表现象可能原因排查方法解决措施球振荡不止Kp太大/Kd太小先关Ki减小Kp增大Kd或减小Kp稳态误差Ki太小检查机械是否卡涩增大Ki或加积分分离舵机抖动微分噪声/电源不足测电源电压看微分项加低通滤波/换电源球冲过头积分饱和看积分项是否限幅加积分限幅响应迟钝Kp太小/Kd太大逐步增大Kp调整Kp和Kd比例球不动死区/接线错误测舵机信号加死区补偿/检查接线4.5 进阶优化方向如果基础PID已经调好了还想进一步提升性能可以尝试这几个方向。前馈补偿根据目标位置的变化率提前给舵机一个角度补偿。比如球需要从A点移动到B点前馈项会在球还没动之前就把梁倾斜一个角度让球更快启动。前馈不改变闭环稳定性但能显著提升响应速度。模糊PID根据误差和误差变化率动态调整PID参数。误差大时用大Kp快速响应误差小时用小Kp避免振荡。模糊规则表需要根据经验制定调试工作量比普通PID大但适应性强。粒子群优化整定把PID参数作为粒子群算法的优化变量以超调量、调节时间、稳态误差的加权和作为适应度函数让算法自动搜索最优参数。这个方法适合有MATLAB基础的人可以在仿真里先跑再把结果用到实物上。实操心得不要一上来就上模糊PID或者粒子群。普通PID调好了平衡球已经能稳稳停在目标位置。进阶算法是在基础扎实之后才考虑的。我见过太多人基础PID都没调明白就急着上神经网络最后连球都稳不住。5. 项目复盘与个人体会这个项目我从零开始做了大约三周中间踩了不少坑。最大的坑是电源问题——舵机和主控共用电源导致主控频繁复位查了两天才找到原因。第二个坑是I2C上拉电阻这个属于硬件常识但新手很容易忽略。第三个坑是积分饱和球冲过头后要等好几秒才能回来加了积分限幅后问题解决。调参那几天我几乎把VOFA的曲线看成了心电图。Kp从0.1试到2.0Kd从0试到0.5Ki从0试到0.1。最后发现真正好用的参数区间其实很窄Kp在0.5到0.7之间Kd在0.05到0.1之间Ki在0.01到0.03之间。超出这个范围要么振荡要么迟钝。如果让我重新做一遍我会先花半天时间把机械结构做扎实确保梁的转轴顺滑、舵机臂连接牢固、传感器安装稳固。机械上的每一丝松动都会在PID调参时被放大成剧烈的振荡。然后我会先用开环测试手动给舵机不同角度记录球的位置变化大致了解系统的静态增益和响应时间。这个开环数据对后面调参很有参考价值。最后分享一个小技巧调参时如果实在找不到合适的Kd可以先把Kd设为一个较大的值然后逐步减小直到系统刚好开始振荡再往回加一点。这个方法比从零往上加更快找到临界点。当然前提是Kp已经调好了。这个项目后续还可以扩展加一个摄像头做视觉反馈实现二维平面上的平衡控制或者加一个无线模块用手机APP实时调整PID参数或者把控制算法移植到更快的MCU上把控制周期降到1毫秒看看性能能提升多少。控制工程的乐趣就在于你永远可以做得更好。

相关新闻

Armbian换源全指南:apt源与armbian.list正确配置,告别404和慢速

Armbian换源全指南:apt源与armbian.list正确配置,告别404和慢速

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 6:51:42 阅读更多 →
跨平台换机不再头疼:全能换机如何做到五大平台一键互传

跨平台换机不再头疼:全能换机如何做到五大平台一键互传

换手机这件事,痛点往往不在“买新机”,而在“搬数据”。iPhone换安卓、鸿蒙换Windows、Mac换安卓……每一次跨平台迁移,都意味着和联系人、照片、聊天记录来一场“手动拉锯战”。更别提那些藏在各品牌官方工具里的隐性门槛:iOS的“…

2026/9/24 6:51:42 阅读更多 →
TypeScript - TypeScript 面向对象

TypeScript - TypeScript 面向对象

一、面向对象概述面向对象是程序中一个非常重要的思想,面向对象简而言之就是程序之中所有的操作都需要通过对象来完成举例来说,操作浏览器需要使用 window 对象,操作网页要使用 document 对象,操作控制台要使用 console 对象计算机…

2026/9/24 6:51:42 阅读更多 →

最新新闻

ax:面向Agentic工作负载的Kubernetes CLI编排调度入口

ax:面向Agentic工作负载的Kubernetes CLI编排调度入口

1. 从“ax”这个标题说起:一个被低估的Agentic编排入口第一次看到“ax”这个标题,很多人会以为是某个命令行工具的缩写,或者某个内部项目的代号。但把热搜词摊开来看——ax、agentic、orchestrator、Kubernetes、CLI——这几个词凑在一起&…

2026/9/25 12:49:22 阅读更多 →
基于SSM的医院招聘考试管理系统设计与实现

基于SSM的医院招聘考试管理系统设计与实现

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 摘要 本文详细阐述了一个基于SSM(SpringSpringMVCMyBatis)框架的医院招聘考试管理系统的设计与实现。文章首先介绍了系统开发的背景与意义&…

2026/9/25 12:49:22 阅读更多 →
家庭实验室实战:18台服务器、60TB存储与双K8s集群的架构与运维

家庭实验室实战:18台服务器、60TB存储与双K8s集群的架构与运维

1. 家庭实验室的缘起与整体架构设计1.1 为什么要在家里搞这么一套“重装备”很多人第一次听到“家里跑18台服务器、60TB存储、两个K8s集群”,第一反应是“这得烧多少钱、费多少电”。但如果你真的在运维、后端、存储或者AI方向干过几年,就会明白&#xf…

2026/9/25 12:49:22 阅读更多 →
Wi-Fi 7技术详解:从802.11be到MLO、320MHz与打孔机制

Wi-Fi 7技术详解:从802.11be到MLO、320MHz与打孔机制

做了这么多年网络相关的工作,最近被问得最多的协议已经不是 Wi-Fi 6,而是 Wi-Fi 7。群里动不动甩过来一张 802.11be 的参数图,问我比 Wi-Fi 6 强在哪、MLO 到底是不是噱头、320MHz 为什么宣传得天花乱坠实际却很难跑满。说实话,Wi…

2026/9/25 12:49:22 阅读更多 →
科普|开题报告总被导师批“逻辑不清”?云智变AI帮你从源头理清

科普|开题报告总被导师批“逻辑不清”?云智变AI帮你从源头理清

开题报告大概是研究生阶段最让人头疼的第一道坎。文献读了一大堆,选题方向反复推敲,可初稿交上去,导师的批注永远是那几个词:“研究问题不聚焦”“文献综述像流水账”“方法跟内容对不上”。问题到底出在哪? 其实&…

2026/9/25 12:49:22 阅读更多 →
WPScan 插件版本检测实战:以 bonaire 的 CHANGELOG.md 为例解读 ChangeLog 动态查找器

WPScan 插件版本检测实战:以 bonaire 的 CHANGELOG.md 为例解读 ChangeLog 动态查找器

网络安全漏洞扫描渗透测试应用安全CLI 【免费下载链接】wpscan WPScan WordPress security scanner. Written for security professionals and blog maintainers to test the security of their WordPress websites. Contact us via contactwpscan.com 项目地址: ht…

2026/9/25 12:48:22 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →