PID算法理解和代码以及PID调参
PID算法理解以及调参
- 写在前面
- 正文
- 1.PID算法的基本公式
- 2.理解PID算法公式
- 3.对P、I、D三个参数的理解
- 4.补充一下电流环
- 5.调参方法
- 6.参考代码
- 7.实际控制遇到的情况
写在前面
在一年前自己学习了一下PID算法,但是对具体的过程,计算式子,并没有做到很好的理解,于是自己总结并再次学习了一遍,以此记录,希望能和大家一起讨论
---------------------------------------------------------------------------2022.9.1修改------------------------------------------------------------------------------------------
评论区有朋友指出问题,重新审查一遍发现自己确实不对,将KI和Ti两个参数直接混淆,在调参方法部分直接贴上原图与原文链接
正文
1.PID算法的基本公式
在离散化的系统中,积分是误差的累计和,微分等于当前误差值与之前的误差值的差
故PID算法的公式如下:
基本概念得先理解:
我们调整的参数是前面的Kp,Ki,Kd
而式子中的Kp×e(k),Ki×Σe(Kn),Kd*(e(k) - e(k-1))是增益,也就是P、I、D分别对应的输出
u(k)是PID算法整个的输出,也就是控制量
2.理解PID算法公式
- PID的输出就类似于一个控制量,也就是你控制一个系统的控制量的变化,就是PID算法的输出。
做一个形象的比喻:你需要控制燃气灶的温度,那么PID算法的输出就是火力的大小。你通过控制火力的大小来控制温度。 - 在控制电机里面,速度环就是控制电流的大小,来控制电机的转速达到目标转速。PID的输出就是电流的值。
- 位置环一般是用的双环控制,内环是速度环,外环是位置环。大概如下图:
- 首先位置先做一次PID计算,得到的输出是速度的值。再由速度做一次PID计算,得到的输出是电流的值,再把电流发给电调即可
3.对P、I、D三个参数的理解
P的控制作用:
- 根据公式,Kp×e(k),当我们将Kp趋于无穷大的时候,就类似一个开关的作用,用灶做比喻,当目标值大于实际值的时候,开关打开,开始加热,当目标值小于实际值的时候,火力断开,让他降温。但我们实际控制的火力有大小的。那么我们可以这么理解
当差距不大的时候,Kp*e(k)较小,那么需要输出的火力较小
当差距较大,并且温度低于目标温度的时候,那么需要输出的火力就会比较大
当差距较小,并且温度高于目标温度的时候,那么就让输出的火力为负值(假设可以降低温度),降低温度。 - 简而言之:P是为了建立目标值和当前值的一种线性关系,当你的P较大的时候,你会很快的到达目标值的附近,但是由于P过大,很容易就超过目标值,而超过目标值的时候,你的P很大,又会瞬间拉回来,但拉回来的程度会过大,也就会出现在目标值附近震荡,没办法收敛于目标值的情况。
形象的比喻就是先粗略的调试一下
D的控制作用:
由上面的理论可以得到,在趋于目标值了之后,我们的P作用就不大了,并且越靠近目标值,P的作用越小,因为P太粗暴了,让整个系统都震荡了起来。
而D的作用,根据公式。Kd*(e(k) - e(k-1)),我们可以当从0→目标值的时候,e(k)是在不断减小的,此时e(k) - e(k-1)是一个负值,再*Kd,我们可以得到,D的作用是为了给系统一个阻尼,并且系统变化的越快,这个阻尼也就越大,这就能抵消P那么粗暴的效果,让P温柔一点,在变化小的时候,D给小阻尼。在突然一个大变化的时候,阻尼就会很大, 这也就让系统不会变化过快,从而使得系统从震荡趋于稳定。
网上看到的这句话我觉得是最形象的比喻了。
I的控制作用:
- 当PD控制了之后,整个系统就已经可以趋于平衡了,但是如果是在有负载的情况下,尤其是电机要带动某个东西的情况下,很有可能会出现PID输出和消耗抵消了,从而使得系统没有办法达到目标值,例如你的温度已经到达95度,你想要去100度,但是散热的效果和你火力增加温度的效果抵消了,让你永远停在了95度,没有办法继续往上增加。
- 这时候就需要I的作用,根据公式K1×Ki×Σe(Kn),K1可以暂时不管,K1就是为了实现在某些情况下加入I,某些情况下不加入I。因为正常情况下你的系统只会受到小的扰动,但是如果突然你的系统受到一个很大的变化,如果这时候还要积分,很有可能导致这个积出来的值对整个系统造成比较大的问题,甚至引起系统的崩溃。
- 这个公式里面,就是把你之前所有的偏差进行累加,并把这个累加的值体现在输出上,这样,如果你的温度停在了95度,那么你的累加值也就会越来越大,最终你的火力也会往上走,实现温度的提升。
- I其实是对P的一个补充作用,但我们不能让I不断的累加,必须有一个累加的最大值,因为累加过大,会让积分量太大,有可能出现一个跳变,难以控制。
- 在实际的控制中,I参数其实是有一个让系统超前的作用,而超前的作用就是与D相反,D的增益起到了一个阻尼的作用,减慢你的变换,而I的增益起到了一个补助加火的作用,加速了你的变换。
4.补充一下电流环
在我们实际的控制电机的过程中,我们以DJI官网3508电机为例,其搭配有一个C620电调,在我们实际的控制中,我们用PID算法解算出来的是一个电流值,我们通过通信发送给电调,让电调控制电流的输出,但是在这个里面,其实还有一层电流环的控制,所以当我们发送了电流之后,其实电调内部还有一圈电流环,这也就导致了我们的输出其实没有那么好的实时性,是有一定延时的。
5.调参方法
- (1)
PID调试一般原则
a.在输出不振荡时,增大比例系数P。
b.在输出不振荡时,减小积分系数Ki。
c.在输出不振荡时,增大微分系数Kd。
(他们三个任何谁过大都会造成系统的震荡。)
- (2)
以上图片来自 https://blog.csdn.net/wb790238030/article/details/92809538?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control
6.参考代码
//结构体部分
typedef struct
{uint8_t enable : 1; //输出使能uint8_t enable_lim_sum_error : 1; //积分限幅使能uint8_t enable_lim_ouput : 1; //输出限幅使能uint8_t count : 4; double kp; //比例参数double ki; //积分参数double kd; //微分参数double lim_sum_error; //误差积分限幅 double lim_output; //输出限幅 防止输出过大double sum_error; //误差积分double last_error; //上一次的误差double last_last_error; //上上一次的误差double kd_output;double ki_output;double kp_output;double error_dec;double pid_output;double error;
} PID_HANDLE, *P_PID_HANDLE;//代码运算部分
double pidProcess(P_PID_HANDLE phdl, double input, double measure)
{double output = 0;double error = input - measure; //计算误差phdl->sum_error += error;//误差积分限幅if(phdl->enable_lim_sum_error == 1 && fabs(phdl->sum_error) > phdl->lim_sum_error){if(phdl->sum_error > 0)phdl->sum_error = phdl->lim_sum_error;elsephdl->sum_error = -phdl->lim_sum_error;}output = phdl->kp * error+ phdl->ki * phdl->sum_error+ phdl->kd * (error - phdl->last_error) ;phdl->kp_output = phdl->kp * error;phdl->ki_output = phdl->ki * phdl->sum_error;phdl->kd_output = phdl->kd * (error - phdl->last_error);phdl->error_dec = error - phdl->last_error;//输出限幅if(phdl->enable_lim_ouput == 1 && fabs(output) > phdl->lim_output){if(output > 0)output = phdl->lim_output;elseoutput = -phdl->lim_output;}//更新误差值phdl->last_error = error;//是否使能输出if(phdl->enable == 1){phdl->pid_output = output;return output;}else{phdl->pid_output = 0;return 0;}
}
7.实际控制遇到的情况
结合实际控制电机说明几种情况
①堵转
在实际的控制电机的过程中,堵转是一种很常见的情况。下面结合PID算法总结一下。
当我们的实际值和我们的目标值之间保持了一个恒定差值,这个时候会出现什么情况呢?
根据计算式子,会发现D的增益Kd*(e(k) - e(k-1))为0,P的增益Kp×e(k)为一个恒定值,而I的值Ki×Σe(Kn)却是在不断累计的,这也就导致了我们发送给电调的值始终保持在我们限定的最大值输出,也就是lim_output这一个值,但是电机因为处于堵转状态,没有办法旋转,而电流在其中流动,能量守恒,这一部分电流就会以热量的形式散发出去,也就导致了电机的过热。
试想一下:如果不给output限定值,那么不断累计,最终发送的电流过大,会直接导致电调或者电机的烧毁。
PID算法理解和代码以及PID调参相关推荐
- 【电机应用控制】——直流有刷电机驱动板/编码器介绍PID算法实操代码思路
目录 前言 一.电机简介 二.直流有刷电机 1.基本知识 2.直流有刷驱动板 3.编码器介绍 三.PID算法 四.实操思路 1.单环控制 2.双环控制 3.三环控制 拓:闭环死区 总结 前言 声明:学 ...
- 直流电机,传递函数,模糊控制pid算法,matlab代码
直流电机,传递函数,模糊控制pid算法,matlab代码 ID:1466674483342194夹竹丶桃
- PID算法(二)衍生PID
PID算法的精髓和缺陷 PID算法应用广泛,其核心思想就是 根据误差来消除误差. 但是它也是有一些缺点的. 微分.微分在物理上是不可实现的.只能用近似的增量,来代替微分. 积分.误差信号的积分,有时候 ...
- ML之XGBoost:利用XGBoost算法对波士顿数据集回归预测(模型调参【2种方法,ShuffleSplit+GridSearchCV、TimeSeriesSplitGSCV】、模型评估)
ML之XGBoost:利用XGBoost算法对波士顿数据集回归预测(模型调参[2种方法,ShuffleSplit+GridSearchCV.TimeSeriesSplitGSCV].模型评估) 目录 ...
- PID超详细教程——PID原理+串级PID+C代码+在线仿真调参
目录 前言 仿真调参环境 案例引入--小球位置控制 抛开案例--更专业地理解PID 由虚到实--代码编写 最后一步--PID参数调整 总结--使用PID的步骤 更进一步--串级PID 前言 很多人应该 ...
- 增量式PID与位置式PID的理解与代码实现
一.PID控制算法概述 PID 实指"比例 proportional"."积分 integral"."微分 derivative",这三项构 ...
- PID原理及python简单实现与调参
一.前言 近期在实际项目中使用到了PID控制算法,于是就该算法做一总结. 二.PID控制算法详解 2.1 比例控制算法 例子: 假设一个水缸,需要最终控制水缸的水位永远维持在1米的高度. 水位目标:T ...
- 基于bp神经网络的pid算法,基于单神经元的pid控制
基于BP神经网络的PID控制器设计 参考一下刘金琨的<先进PID控制>这本书. 例子:被控对象yout(k)=a(k)yout(k-1)/(1+yout(k-1)^2)+u(k_1)其中a ...
- 强化学习算法DQN:算法简介、创新点:回放机制target-network、伪代码、算法理解、代码实现、tensorboard展示网络结构
文章目录 DQN简介 DQN目标 Q-learning与DQN Loss Function 创新点:回放机制&target-network 算法伪代码 算法理解 代码实现 tensorboar ...
- 小白のKNN算法理解及代码实现
KNN算法 一.概述 二.代码实现 2.1 准备数据 2.2数据可视化 2.3数据归一化 2.4 划分训练集和测试集 2.5 KNN分类器的实现 三.总结 一.概述 k-近邻算法(k-Nearest ...
最新文章
- 视觉进阶 | 用于图像降噪的卷积自编码器
- 动态获得资源的路径大小写问题
- 物联网时代传感器厂商竞争格局揭秘
- 死锁的四个必要条件,及处理方法
- 简明Python3教程 16.标准库
- MacOS Server安装与应用
- linux自定义开机启动服务和chkconfig使用方法
- 浅谈ztree节点的增加和获取
- Android 功耗优化(1)----使用Battery Historian生成电量消耗报告
- MongoDB练习题
- WinEdt LaTex(一)—— hello world!
- Chap6:风险与监督[《区块链中文词典》维京甲子]
- 单片机io取反c语言,【51单片机】普通I/O口模拟SPI口C语言程序
- java网上订餐系统怎么做_基于Java的网上订餐系统
- 三极管死区电压和导通电压的区别
- 集合(二):Set : HashSet; LinkedHashSet; TreeSet
- 会员积分系统应该设几个等级?
- Dropbox + Farbox快速创建免费博客小站
- winform工具1-图片去除水印
- python--web--让python提供api服务--aiohttp
热门文章
- linux攻击主机msfconsole,关于利用kali linux2017.2中MSFCONSOLE 利用MS17-010漏洞发起攻击的坑...
- 新东方王江涛十天背单词法(艾宾浩斯记忆曲线)(适用于各阶段各种记忆背诵类的知识点,许多人成功上岸)
- protoc 编译工具
- linux安装protoc
- 千月影视选集前端,这个可以H5多端
- BootLoad中上位机与下位机交互
- 小米笔记本pro 双硬盘双系统 opencore引导安装黑苹果
- STM32F1开发指南笔记20----数码管驱动芯片TM1640解析
- Java对象转换Map(工具类)
- 【matplotlib笔记】sin图像与cos图像