PID算法入门与C语言代码实现

2023-05-16

PID算法的入门理解以及C代码实现

在结束了自控原理的学习后,了解到PID算法是一种万能算法,在课设中也是经常使用到的一种算法,所以想具体的来进行以下总结与学习,如果有错漏的地方,欢迎大家共同来探讨与批评指正,嘿嘿。

文章目录

  • PID算法的入门理解以及C代码实现
  • 什么是PID算法
  • 一、三大控制算法的作用以及matlab仿真演示
    • (1)比例调节的作用:
    • (2)积分调节的作用:
    • (3)微分调节的作用:
  • 二、从计算机控制与算法的角度解析PID控制
    • 1.模拟PID控制
    • 2.数字PID控制
      • (1)位置式算法:
      • (2)增量式算法:
  • 总结


什么是PID算法

PID三个字是英文单词比例(Proportion),积分(Integral),微分(Differential coefficient)的缩写,顾名思义,PID控制就是由比例、积分、微分三种控制方法综合起来来对系统进行控制的方法,比如,飞行器要稳定飞行,而不是忽上忽下,机器人要稳定准确快速的到达目标,而不走偏,都可以用PID算法来进行反馈调节,从而让执行器做出最有利于达成目标的动作,在工程领域有着广泛的应用。


一、三大控制算法的作用以及matlab仿真演示

PID 控制器(Proportion Integration Differentiation,比例积分微分控制器)作为最早实用
化的控制器已有 70 多年的历史,是目前工业控制中应用最广泛的控制器。PID 控制器由于
其结构简单实用,且使用中无需精确的系统模型等优点,因此,95%以上的现代工业过程控
制中仍然采用 PID 结构。下图就是PID控制器的基本结构,仿真会基于如下结构进行

在这里插入图片描述
PID 控制器由比例单元 P、积分单元 I 和微分单元 D 三部分组成,其结构原理框图如图 6-1
所示。简单来说,PID 控制器就是对输入信号 r(t)和输出信号c(t)的差值 e(t)(即误差信号)进行比
例、积分和微分处理,再将其加权和作为控制信号u(t)来控制受控对象,从而完成控制过程的。
PID控制器的公式如下图所示:
在这里插入图片描述
式中, K P 、 K I 和 K D 分别为比例、积分和微分系数; T I 和 T D 分别为积分和微分时间。
一个 PID 控制器的设计重点在于设定 K P 、 K I 和 K D 三个参数的值。实际使用时,不一定
三个单元都具备,也可以只选取其中的一个或两个单元组成控制器

(1)比例调节的作用:

比例调节是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例控制只改变系统增益,不影响相位。仅采用比例控制时系统输出存在稳态误差。增大 K P 可以提高系统开环增益,减小系统稳态误差,但是会降低系统稳定性,甚至可能造成闭环系统的不稳定。,比例控制器的输出与输入误差信号成比例关系,传递函数如下
G(s)=Kp
接下来matlab仿真说明,比例调节的优缺点:
系统框图如下:
在这里插入图片描述
其中
在这里插入图片描述
在控制单元施加比例控制,并且采用不同的比例系数 K P =0.1 , 0.5 , 1 , 2 , 5 , 10 ,观察各比例系数下系统的单位阶跃响应及控制效果,matlab程序如下:

Kp=[0.1,0.5,1,2,5,10];
Go=tf(1, conv(conv([1,1],[2,1]),[3,1]) )%系统开环传递函数
for i=1:6
G=feedback(Go.*Kp(i),1)%不同比例系数下的系统闭环传递函数
step(G); hold on; %求系统的单位阶跃响应
end
gtext('Kp=0.1')gtext('Kp=0.5')gtext('Kp=1')%放置 Kp 值的文字注释
gtext('Kp=2')gtext('Kp=5')gtext('Kp=10')

运行程序得到不同比例系数下的系统单位阶跃响应曲线,如下图所示:
在这里插入图片描述
从图 中可以看出,随着比例系数 K P 值的增大,系统的响应速度加快,稳态误差减小,超调量却在增加,调节时间变长,而且随着 K P 值增大到一定程度,系统最终会变得不稳定。这也验证了前面对比例控制的描述。

(2)积分调节的作用:

是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti,Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调节可使系统稳定性下降,动态响应变慢。积分作用常与另两种调节规律结合,组成PI调节器或PID调节器,单独的积分单元的引入会带来相位滞后,为系统的稳定性带来不良影响,其传递函数为G(s)=Ki/s,仍然使用上面的框图
在这里插入图片描述
在控制单元施加积分控制 1/s ,观察施加积分控制前后系统稳态误差的变化,matlab代码如下:

Go=tf(1, conv([1,1],[2,1]) )%系统开环传递函数
Gc=tf(1,[1,0])%积分控制函数
subplot(2,1,1)step(feedback(Go,1))%原系统闭环传递函数的单位阶跃响应曲线
title('加积分控制前')subplot(2,1,2)step( feedback(Go*Gc,1))%加积分控制后系统单位阶跃响应曲线
title('加积分控制后')

运行程序得到加积分控制前后系统的单位阶跃响应曲线,如下图所示。
在这里插入图片描述
从图 中可以看出,加入积分控制前,系统的稳态误差为 0.5 ,加入积分控制后,系统的稳态误差被减小为 0 ,这也验证了积分控制可以消除稳态误差的作用。

(3)微分调节的作用:

微分作用反映系统偏差信号的变化率,具有预见性,能预见偏差变化的趋势,因此能产生超前的控制作用,在偏差还没有形成之前,已被微分调节作用消除。因此,可以改善系统的动态性能。在微分时间选择合适情况下,可以减少超调,减少调节时间。微分作用对噪声干扰有放大作用,因此过强的加微分调节,对系统抗干扰不利。此外,微分反应的是变化率,而当输入没有变化时,微分作用输出为零。微分作用不能单独使用,需要与另外两种调节规律相结合,组成PD或PID控制器。

二、从计算机控制与算法的角度解析PID控制

1.模拟PID控制

框图如下:
在这里插入图片描述
其中 ,r(t)为参考输入或称为设定值,y(t)为系统输出,e(t)=r(t)-y(t)为偏差,u(t)为PID控制器的输出,Kp为比例系数,Ti为积分时间常数,Td为微分时间常数,G(s)为被控对象传递函数。时域上可以写成:
在这里插入图片描述
经过拉普拉斯变换后并整理得D(s):
在这里插入图片描述
其中Ki=Kp/Ti称为积分系数,Kd=Kp*Td称为微分系数

2.数字PID控制

当采样周期T足够小时,可以得到如下公式:
在这里插入图片描述

(1)位置式算法:

展开上述式子,并且令积分系数Ki=Kp*T/Ti,微分系数Kd=Kp*Kd/T,则可以得到:
在这里插入图片描述
用语言来表述这个公式就是:
PID偏差=比例系数 * 当前偏差+积分系数 * 偏差之和+微分系数 * (当前偏差-上次偏差)
总结下位置式控制算法的特点:
(1)输出控制量u(k)与各次采样值相关,需要占用较多的存储空间。
(2)计算u(k)需要做误差值的累加,容易产生较大的累加误差,甚至产生累加饱和现象。
(3)控制量u(k)以全量输出,误动作影响较大。当计算机出现故障时,u(k)的大幅度变化会引起执行机构位置的大幅度变化。

以下是基于C语言的位置式PID控制算法的代码:

=====================================================================
================================*/
#include <reg52.h>
#include <string.h> //C 语言中 memset 函数头文件
/*===================================================================
=================================
PID Function
The PID (比例、积分、微分) function is used in mainly
control applications. PIDCalc performs one iteration of the PID
algorithm.
While the PID function works, main is just a dummy program showing
a typical usage.
=====================================================================
================================*/
typedef struct PID {
double SetPoint; // 设定目标 Desired value
double Proportion; // 比例常数 Proportional Const
double Integral; // 积分常数 Integral Const
double Derivative; // 微分常数 Derivative Const
double LastError; // Error[-1]
double PrevError; // Error[-2]
double SumError; // Sums of Errors
} PID;
/*===================================================================
=================================
PID 计算部分
=====================================================================
================================*/
double PIDCalc( PID *pp, double NextPoint )
{
double dError, Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = Error - pp->LastError; // 当前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error // 比例项
+ pp->Integral * pp->SumError // 积分项
+ pp->Derivative * dError // 微分项
);
}
/*===================================================================
=================================
Initialize PID Structure PID 参数初始化
=====================================================================
================================*/
void PIDInit (PID *pp)
{
memset ( pp,0,sizeof(PID));
}
/*===================================================================
=================================
Main Program 主程序
=====================================================================
================================*
double sensor (void) // Dummy Sensor Function
{
return 100.0;
}
void actuator(double rDelta) // Dummy Actuator Function
{}
void main(void)
{
PID sPID; // PID Control Structure
double rOut; // PID Response (Output)
double rIn; // PID Feedback (Input)
PIDInit ( &sPID ); // Initialize Structure
sPID.Proportion = 0.5; // Set PID Coefficients
sPID.Integral = 0.5;
sPID.Derivative = 0.0;
sPID.SetPoint = 100.0; // Set PID Setpoint
for (;;) { // Mock Up of PID Processing
rIn = sensor (); // Read Input
rOut = PIDCalc ( &sPID,rIn ); // Perform PID Interation
actuator ( rOut ); // Effect Needed Changes
}

(2)增量式算法:

当执行机构不需要控制量的全值而需要其增量时,可由位置式推导出增量式 PID 控制算法。根据上面的u(k),写出u(k-1),然后两个式子相减,得到:
在这里插入图片描述
用语言来表述公式就是:
PID偏差 = 比例×(当前偏差 - 上次偏差) + 积分 * 当前偏差 + 微分 * (当前偏差 - 2×上次偏差+上上次偏差)

增量式算法的特点:
(1)可以节省存储空间
(2)只输出控制增量,误动作影响小。
C语言代码如下:

/*==================== =====================================================
PID Function
The PID (比例、积分、微分) function is used in mainly
control applications. PIDCalc performs one iteration of the PID
algorithm.
While the PID function works, main is just a dummy program showing
a typical usage.
==========================================================================*/
typedef struct PID
{
int SetPoint; //设定目标 Desired Value
long SumError; //误差累计
double Proportion; //比例常数 Proportional Const
double Integral; //积分常数 Integral Const
double Derivative; //微分常数 Derivative Const
int LastError; //Error[-1]
int PrevError; //Error[-2]
} PID;
static PID sPID;
static PID *sptr = &sPID;
/*================================================================================
Initialize PID Structure PID 参数初始化
===============================================================================*/
void IncPIDInit(void)
{
sptr->SumError = 0;
sptr->LastError = 0; //Error[-1]
sptr->PrevError = 0; //Error[-2]
sptr->Proportion = 0; //比例常数 Proportional Const
sptr->Integral = 0; //积分常数 Integral Const
sptr->Derivative = 0; //微分常数 Derivative Const
sptr->SetPoint = 0;
}
/*===============================================================================
增量式 PID 计算部分
=================================================================================*/
int IncPIDCalc(int NextPoint)
{
register int iError, iIncpid; //当前误差
iError = sptr->SetPoint - NextPoint; //增量计算
iIncpid = sptr->Proportion * iError //E[k]项
- sptr->Integral * sptr->LastError //E[k-1]项
+ sptr->Derivative * sptr->PrevError; //E[k-2]项
//存储误差,用于下次计算
sptr->PrevError = sptr->LastError;
sptr->LastError = iError;
//返回增量值
return(iIncpid);
}

总结

本文对连续系统的PID控制理解到算法综合讲述了一遍,用matlab仿真能够更直观的理解各种调节方式对控制算法的影响,在不知道该如何对控制系统进行调试的时候,可以对照各种算法的优缺点进行选择调试,并最终使系统可以拥有正常的响应,如果要将该算法应用到实际中去,就是计算机控制的知识了,需要对传递函数进行离散化,再通过算法调控PWM等一系列方法将其实际应用,谢谢各位小伙伴们读完到这里,希望能够对大家有所帮助或者是有所启发,如果有不对的地方或者改进建议,欢迎大家的私信或者留言.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PID算法入门与C语言代码实现 的相关文章

随机推荐

  • python opencv通过4个坐标,剪裁图片(抠图)

    一 opencv 裁剪说明 效果展示 要裁剪的图片 裁剪出的单词图像 如下 这里程序我是用在paddleOCR里面 通过识别模型将识别出的图根据程序提供的坐标 即四个顶点的值 进行抠图的程序 上面的our和and就是扣的图 并进行了封装 相
  • python使用tkinter编写一个数据显示窗口(实时显示更新的数据)

    以下代码分为python3版本与python2版本 xff0c python3版本主要靠 self main window after 刷新的时间毫秒 需要刷新的函数这里为窗口的清除与插入函数 刷新函数进行 xff0c python2版本则
  • python 手眼标定OpenCV手眼标定(calibrateHandeye())一

    以下代码来源 本篇博客通过该代码 xff0c 附上记录的公式与查找连接 xff0c 方面以后调用能弄懂各个参数的意思 本篇看完看第二篇代码踩坑部分python 手眼标定OpenCV手眼标定 xff08 calibrateHandeye xf
  • ROS+VNC+Docker(docker下的可视化ROS)镜像源分享

    两个都可用 xff0c 推荐第二个毕竟要新一些 xff0c 以下docker环境中安装vscode链接的方法 1 作者 ct2034 截至本博客写的时候 xff0c 最后更新于2020 xff08 亲测感觉不错 xff09 带有完整 ros
  • 使用docker下的硬件使用(一)之双目摄像头

    本篇博客又名 xff1a 物理机 xff08 宿主机win xff09 下虚拟机 xff08 ubuntu xff09 中的docker下硬件 xff08 双目相机 xff09 调用 一 环境介绍 如下图 xff1a 我在windows10
  • AI自主图像生成 之 stable-diffusion(Anaconda+pycharm)本地部署

    无需订阅专栏 AI自主图像生成 之 stable diffusion 运行效果展示 一 介绍与实验效果 文章末尾包含 1 我已打包到百度云的部署验证成功并包含模型权重的代码文件 可直接链接完成python环境配置的anaconda环境下使用
  • AI自主图像生成 之 stable-diffusion—运行效果展示

    stable diffusion用途 xff1a 输入文字描述 xff0c 输出对应图片 The chicken with the hair parted in the middle and the suspenders is playin
  • python画甘特图

    1 使用plotly 安装包下载 span class token keyword import span plotly span class token punctuation span express span class token
  • bat 打开exe文件,并显示进度条

    如下 C camera flow njl CAM exe是你的exe文件路径 180 就是 180 s xff0c 即三分钟显示完毕 chcp span class token number 65001 span span class to
  • 基于opencv的掩膜生成 python

    代码将遍历JPG dir文件夹中的所有jpg文件 xff0c 并对于每一个jpg文件 xff0c 读取同名的JSON文件 xff0c 然后根据JSON文件中记录的标注区域的坐标在JPG图像上绘制掩膜图像 最后 xff0c 将掩膜图像保存到O
  • 用 Python 解数独(Sudoku)

    芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独 数独是 9 横 9 竖共有 81 个格子 xff0c 同时又分为 9 个九宫格 规则很简单 xff1a 每个空格填入 1 9 任意一个数字 xff0c 需要保证每个横排和竖排以
  • alembic 如何使用?

    在之前的数据库操作中 xff0c 我们新增一个字段是不是每次都得删除数据库表 xff0c 然后再重新将新创建的数据库表映射到数据库中 这样操作是不是很蛋疼 xff1f 是吧 xff1f 于是sqlalchemy作者拜尔为了解决这一问题 xf
  • ROS中用opencv库实现物体中心点提取

    老师搞了个很简陋的双目摄像头 xff0c 只能输出两个摄像头的图像 xff0c 所以为了提取定位物体中心坐标 xff0c 还得算个深度距离 先对两个摄像头图像处理一下 xff0c 基于阈值分割 xff0c 然后提取个轮廓 xff0c 计算个
  • linux c语言高级编程-目录操作

    目录操作总共有以下几个函数 xff1a 1 创建目录 int mkdir const char pathname mode t mode 2 删除目录 int rmdir const char pathname 3 查看目录状态 int s
  • BeagleBone Black使用(一):狗板简介

    前言 BeagleBone 与 Arduino 和 Raspberry Pi xff08 树莓派 xff09 可以说是目前应用最广泛的三大嵌入式开源平台 而 BeagleBone 在一定程度上可视为融合了 Arduino 与树莓派的优点 x
  • 慧数汽车大数据分析:车市竞争将由打造爆款向构建“产品矩阵”转型

    在车企只要完成年销量三十万辆的目标时 xff0c 只需认认真真培育出一款爆款车就足够了 xff0c 如哈弗H6 完成年销量50万辆的目标时 xff0c 只需认认真真培育出一两款爆款车就足够了 xff0c 如哈弗H6 43 哈弗H2 但为什么
  • 4.10 Python tuple元组详解

    元组 xff08 tuple xff09 是 Python 中另一个重要的序列结构 xff0c 和列表类似 xff0c 元组也是由一系列按特定顺序排序的元素组成 元组和列表 xff08 list xff09 的不同之处在于 xff1a 列表
  • 使用ROS和RealSense直接获取点云

    点云获取 Realsense获取内参创建ROS工作环境创建ROS工作包package向package中添加cpp代码catkin make编译失败失败1 使用ROS订阅节点 xff08 rgb和depth xff09 ROS包安装升级Rea
  • 集成单点登录

    随着现在的系统越来越多 xff08 OA考勤 xff0c 学生宿舍管理等等 xff09 在使用中是不是还在为一次一次的登录而烦恼 xff1f 或者忘了密码而尴尬 xff0c 现在 xff0c 有一个好东西来解决这个问题了 那就是单点登录 单
  • PID算法入门与C语言代码实现

    PID算法的入门理解以及C代码实现 在结束了自控原理的学习后 xff0c 了解到PID算法是一种万能算法 xff0c 在课设中也是经常使用到的一种算法 xff0c 所以想具体的来进行以下总结与学习 xff0c 如果有错漏的地方 xff0c