深入浅出 PID 算法:原理、实现与应用实战

在工业控制、机器人运动控制、智能家居温控等场景中,PID 算法一直是当之无愧的 “控制利器”。它结构简单、鲁棒性强、参数调整灵活,即使在复杂的非线性系统中,也能实现稳定的闭环控制。本文将从原理到实战,带你彻底搞懂 PID 算法。

一、PID 算法是什么?

PID 是 Proportional(比例)、Integral(积分)、Derivative(微分) 的缩写,它是一种闭环控制算法,核心思想是通过偏差(设定值与实际值的差值) 来计算控制量,从而让系统的实际输出无限接近设定值。

举个简单的例子:你想让空调把室温稳定在 25℃(设定值),但当前室温是 30℃(实际值),偏差就是 25-30 = -5℃。PID 控制器会根据这个偏差,自动调整空调的制冷功率,最终让室温稳定在 25℃。

PID 算法的核心公式(连续域):u(t)=Kp​⋅e(t)+Ki​⋅∫0t​e(τ)dτ+Kd​⋅dtde(t)​其中:

  • u(t):控制器输出的控制量
  • e(t)=SP−PV:偏差(设定值 SP - 实际值 PV)
  • Kp​:比例系数
  • Ki​:积分系数
  • Kd​:微分系数

而在实际工程中,我们使用的是离散化的 PID(因为计算机是周期性采样计算),离散化后的公式更具实用价值:u(k)=Kp​⋅e(k)+Ki​⋅∑0k​e(i)T+Kd​⋅Te(k)−e(k−1)​其中:

  • k:当前采样周期
  • T:采样周期
  • e(k):当前周期偏差
  • e(k−1):上一周期偏差

二、P、I、D 各自的作用

PID 的三个环节各司其职,相辅相成,缺少任何一个环节,控制效果都会大打折扣。

1. 比例环节(P):当下的偏差,当下纠正

比例环节的输出与当前偏差成正比,公式:Pout​=Kp​⋅e(k)。

它的作用是即时响应偏差:偏差越大,比例输出越大,控制作用越强。

  • 优点:反应快,能快速减小偏差。
  • 缺点:仅靠比例环节,系统会存在稳态误差(比如空调始终差 1℃到设定值);Kp​ 过大会导致系统震荡,甚至不稳定。

2. 积分环节(I):消除过去的稳态误差

积分环节的输出与偏差的累积和成正比,公式:Iout​=Ki​⋅∑0k​e(i)T。

它的作用是消除稳态误差:只要存在偏差,积分就会不断累积,直到偏差为 0,积分输出才会停止变化。

  • 优点:彻底解决比例环节的稳态误差问题。
  • 缺点:积分环节具有滞后性,Ki​ 过大会导致系统超调量增大(比如空调温度冲到 23℃再回调到 25℃),甚至震荡。

3. 微分环节(D):预判未来的偏差变化趋势

微分环节的输出与偏差的变化率成正比,公式:Dout​=Kd​⋅Te(k)−e(k−1)​。

它的作用是预判偏差的变化趋势,提前给出抑制性的控制量:偏差变化越快,微分输出越大,能有效抑制系统超调。

  • 优点:改善系统的动态特性,减小超调,加快系统响应速度。
  • 缺点:微分环节对噪声非常敏感(比如传感器的微小波动会被放大);Kd​ 过大会导致系统抗干扰能力下降,控制量波动剧烈。

三、PID 的三种常见形式

在实际应用中,我们会根据系统需求选择不同的 PID 形式:

1. 位置式 PID

就是我们上面提到的离散化公式:u(k)=Kp​⋅e(k)+Ki​⋅∑0k​e(i)T+Kd​⋅Te(k)−e(k−1)​特点:输出 u(k) 是绝对的控制量(比如电机的目标转速、阀门的开度);积分项会累积,当系统出现较大偏差时,积分饱和可能导致控制量超出范围。

2. 增量式 PID

通过计算相邻两次控制量的差值来输出,公式推导:Δu(k)=u(k)−u(k−1)=Kp​[e(k)−e(k−1)]+Ki​e(k)T+Kd​Te(k)−2e(k−1)+e(k−2)​特点:输出是控制量的增量,不会出现积分饱和;适用于步进电机等需要增量控制的场景;抗干扰能力比位置式强。

3. 微分先行 PID

将微分环节的输入从偏差改为实际值 PV,避免设定值 SP 突变时微分环节输出剧烈波动。适用场景:设定值需要频繁调整的系统(比如机器人轨迹跟踪)。

四、PID 参数整定:从理论到实战

PID 控制效果的好坏,关键在于参数整定(调整 、、)。参数整定没有万能公式,但有一套成熟的工程方法。

1. 经验整定法(试凑法)

这是最常用的现场整定方法,核心思路:先比例,后积分,再微分

  1. 令 ,,逐渐增大 Kp​,直到系统输出出现轻微震荡,此时的 Kp​ 记为临界比例系数 Kcr​。
  2. 减小 Kp​ 到 0.6∼0.8Kcr​,逐渐增大 Ki​,直到稳态误差消除,且系统无明显超调。
  3. 逐渐增大 Kd​,直到系统超调量减小,响应速度加快,同时避免噪声放大。

2. Ziegler-Nichols 整定法

一种基于临界参数的整定方法,步骤:

  1. 令 ,,缓慢增大 Kp​,直到系统输出出现持续等幅震荡,记录此时的临界比例系数 Kcr​ 和临界震荡周期 Tcr​。
  2. 根据以下经验公式计算参数:
控制规律Kp​Ki​Kd​
P0.5Kcr​00
PI0.45Kcr​1.2Kp​/Tcr​0
PID0.6Kcr​2Kp​/Tcr​Kp​Tcr​/8
注意:该方法是经验公式,实际参数需要根据系统特性微调。

五、C 语言实现位置式 PID(实战代码)

下面给出一个简单的位置式 PID 实现代码,可直接移植到 STM32、51 单片机等嵌入式平台:

c

运行

typedef struct { float SetPoint; // 设定值 float ActualPoint;// 实际值 float Kp; // 比例系数 float Ki; // 积分系数 float Kd; // 微分系数 float Error[3]; // 偏差数组 e(k),e(k-1),e(k-2) float Integral; // 积分累积值 float Output; // 控制量输出 } PID_TypeDef; // PID初始化 void PID_Init(PID_TypeDef *pid, float kp, float ki, float kd, float set) { pid->Kp = kp; pid->Ki = ki; pid->Kd = kd; pid->SetPoint = set; pid->Error[0] = 0; pid->Error[1] = 0; pid->Error[2] = 0; pid->Integral = 0; pid->Output = 0; } // PID计算函数(位置式) float PID_Calculate(PID_TypeDef *pid, float actual) { pid->ActualPoint = actual; // 计算当前偏差 pid->Error[0] = pid->SetPoint - pid->ActualPoint; // 积分项(带积分限幅,防止积分饱和) pid->Integral += pid->Error[0]; // 积分限幅,根据实际系统调整 if (pid->Integral > 1000) pid->Integral = 1000; if (pid->Integral < -1000) pid->Integral = -1000; // 位置式PID计算 pid->Output = pid->Kp * pid->Error[0] + pid->Ki * pid->Integral + pid->Kd * (pid->Error[0] - pid->Error[1]); // 更新偏差历史值 pid->Error[2] = pid->Error[1]; pid->Error[1] = pid->Error[0]; // 控制量限幅,根据实际系统调整 if (pid->Output > 2000) pid->Output = 2000; if (pid->Output < 0) pid->Output = 0; return pid->Output; } 

六、PID 算法的常见应用场景

PID 算法的应用几乎遍布所有需要闭环控制的领域:

  1. 工业控制:温度、压力、流量、液位的控制(比如化工反应釜温控)。
  2. 机器人领域:机械臂关节的位置控制、AGV 小车的速度与航向控制。
  3. 智能家居:空调温控、扫地机器人的路径跟踪、热水器温度控制。
  4. 汽车电子:发动机转速控制、自动驾驶的车速控制、刹车防抱死系统(ABS)。

七、总结与常见问题

  1. PID 的核心优势:结构简单、易于实现、鲁棒性强,无需精确的系统数学模型。
  2. 常见问题及解决方法
    • 稳态误差:增大积分系数 Ki​,或引入积分分离策略(偏差大时关闭积分,偏差小时开启积分)。
    • 系统震荡:减小比例系数 Kp​ 和微分系数 Kd​,增大采样周期 T。
    • 积分饱和:增加积分限幅,或采用增量式 PID。
    • 抗干扰差:对传感器数据滤波,减小微分系数 Kd​。

Read more

《算法闯关指南:优选算法--模拟》--43.数青蛙

《算法闯关指南:优选算法--模拟》--43.数青蛙

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 43. 数青蛙 * 解法(模拟+分情况讨论): * 算法思路: * C++算法代码: * 算法总结&&笔记展示: * 结尾: 前言: 聚焦算法题实战,系统讲解三大核心板块:优选算法:剖析动态规划、二分法等高效策略,学会寻找“最优解”。 递归与回溯:掌握问题分解与状态回退,攻克组合、排列等难题。 贪心算法:理解“局部最优”到“全局最优”的思路,解决区间调度等问题 内容以题带点,讲解思路与代码实现,帮助大家快速提升代码能力。 43. 数青蛙

By Ne0inhk
【大数据存储与管理】分布式文件系统HDFS:06 HDFS的数据读写过程

【大数据存储与管理】分布式文件系统HDFS:06 HDFS的数据读写过程

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈大数据技术原理与应用 ⌋ ⌋ ⌋专栏系统介绍大数据的相关知识,分为大数据基础篇、大数据存储与管理篇、大数据处理与分析篇、大数据应用篇。内容包含大数据概述、大数据处理架构Hadoop、分布式文件系统HDFS、分布式数据库HBase、NoSQL数据库、云数据库、MapReduce、Hadoop再探讨、数据仓库Hive、Spark、流计算、Flink、图计算、数据可视化,以及大数据在互联网领域、生物医学领域的应用和大数据的其他应用。 【GitCode】专栏资源保存在我的GitCode仓库:https://gitcode.com/Morse_Chen/BigData_principle_application。 文章目录 * 一、读数据的过程 * 二、写数据的过程 * 小结 在介绍 HDFS 的数据读写过程之前,需要简单介绍一下相关的类。FileSystem 是一个通用文件系统的抽象基类,可以被分布式文件系统继承,所有可能使用

By Ne0inhk
Flutter for OpenHarmony:more 极致算法与数据结构工具集(Dart 官方推荐的高效扩展) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:more 极致算法与数据结构工具集(Dart 官方推荐的高效扩展) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 Flutter 和 Dart 的标准库提供了 List, Map, Set 以及基本的 Math 库。这对于普通 APP 开发够用了。 但是,如果你要开发: * 一个高性能的游戏引擎(需要位运算、四叉树)。 * 一个复杂的数据分析工具(需要统计学算法)。 * 一个缓存系统(需要 LRU 策略)。 * 一个自定义的解析器(需要字符集处理)。 标准库就显得捉襟见肘了。 more 是 Dart 社区中质量极高的一个工具库(作者是 Google 工程师)。它汇集了大量高效的数据结构、数学算法、迭代器扩展和缓存策略。它的座右铭是“更多功能,更少废话”。 对于 OpenHarmony 应用,尤其是涉及高性能计算或复杂逻辑处理的场景,

By Ne0inhk
【leetcode】队列 + 宽搜,树形结构层序遍历的基础与变化

【leetcode】队列 + 宽搜,树形结构层序遍历的基础与变化

前言 🌟🌟本期讲解关于力扣的几篇题解的详细介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-ZEEKLOG博客 🔥 你的点赞就是小编不断更新的最大动力                                        🎆那么废话不多说直接开整吧~~   目录 📚️1.N叉树的层序遍历 🚀1.1题目描述 🚀1.2思路讲解 🚀1.3题目代码 📚️2.二叉树锯齿形遍历 🚀2.1题目描述 🚀2.2思路讲解 🚀2.3题目代码 📚️3.二叉树最大宽度 🚀3.1题目描述 🚀3.2思路讲解 🚀3.3题目代码 📚️4.总结 📚️1.N叉树的层序遍历 🚀1.1题目描述 给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。 树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。 如下图所示: 输入:

By Ne0inhk