PID控制算法学习笔记分享

目录

一、参数设定

二、PID计算公式

三、位置式PID代码实现

四、增量式PID代码实现

五、两种控制算法的优缺点

六、PID算法的改进


一、参数设定

  1. 比例系数(kp):P项的作用是根据当前误差的大小来产生一个控制量。它直接与误差成正比,误差越大,控制量的变化越大。P项可以提高系统的响应速度,但可能会导致系统的超调和稳态误差

  2. 积分时间(Ti):I项的作用是累积误差并产生一个控制量。它可以消除系统的稳态误差,因为它会积累误差并持续地调整控制量,直到误差为零。然而,I项可能会导致系统的超调和振荡。

  3. 微分常数(Td):D项的作用是根据误差变化的速度来产生一个控制量。它可以提高系统的稳定性,因为它可以减小误差的快速变化。D项可以抑制超调和减小振荡,但可能会增加系统的灵敏度

PD算法:适用于惯性较大的设备,比如舵机。

PI算法:适用于不允许有静差的设备。

二、PID计算公式

1)位置式PID

2)增量式PID

三、位置式PID代码实现

#define IntegralMAX 2000

//pid结构体
typedef struct
 {
     float target_val;               //目标值
     float temp_val;                 //当前值
     float actual_val;                       //输出控制值
     float err;                              //定义偏差值
     float err_last;                         //定义上一个偏差值
     float Kp,Ki,Kd;                         //定义比例、积分、微分系数
     float sum;                              //定义历史偏差
 }pid_t; 
//pid算法实现
 void PID_realize(pid_t *pid)
{
     /*目标值只在这里参与计算,计算目标值与实际值的误差*/
    pid->err=pid->target_val - pid->temp_val;
     /*误差累积*/
    pid->sum+=pid.err;
    //此处可以进行误差限幅
    //*if(pid->integral > IntegralMAX) pid->integral = IntegralMAX;
    // else if(pid->integral < -IntegralMAX) pid->integral = -IntegralMAX;
    //*

     /*PID算法实现*/
    pid->actual_val = pid->Kp*pid->err + pid->Ki*pid->sum
                      + pid->Kd*(pid->err - pid->err_last);
     /*误差传递*/
    pid->err_last=pid->err;

}

位置式 PID 适用于执行机构不带积分部件的对象,如舵机和平衡小车的直立和温控系统的控制。

四、增量式PID代码实现

 /*pid*/
 typedef struct
 {
     float target_val;     //目标值
     float actual_val;     //实际输出值
     float temp_val;       //当前值
     float err;            //定义当前偏差值
     float err_next;       //定义下一个偏差值
     float err_last;       //定义最后一个偏差值
     float Kp, Ki, Kd;     //定义比例、积分、微分系数
 }_pid;
//增量式PID算法实现
void PID_realize(pid_t *pid)
 {
     /*目标值只在这里参与计算,计算目标值与实际值的误差*/
     pid->err = pid->target_val - pid->temp_val;
     /*PID算法实现*/
     float increment_val = pid->Kp*(pid->err - pid->err_next) + pid->Ki*pid->err + pid->Kd*(pid->err - 2 * pid->err_next + pid->err_last);
     /*累加*/
     pid->actual_val += increment_val;
     /*传递误差*/
     pid->err_last = pid->err_next;
     pid->err_next = pid->err;
 }

可见,增量式PID不需要进行累加,能对其产生影响的只有最近的三次的采样,容易通过加权处理获得比较好的控制效果,并且在系统发生问题时,增量式不会严重影响系统的工作。

增量式PID控制输出的是控制量增量,并无积分作用,因此该方法适用于执行机构带积分部件的对象,如步进电机等。

五、两种控制算法的优缺点

1)位置式PID的优缺点

优点:

①位置式PID是一种非递推式算法,可直接控制执行机构(如平衡小车),u(k)的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构不带积分部件的对象中可以很好应用

缺点:

①每次输出均与过去的状态有关,计算时要对e(k)进行累加,运算工作量大。

2)增量式PID优缺点:

优点:

①误动作时影响小,必要时可用逻辑判断的方法去掉出错数据。

②手动/自动切换时冲击小,便于实现无扰动切换。当计算机故障时,仍能保持原值。

③算式中不需要累加。控制增量Δu(k)的确定仅与最近3次的采样值有关。

缺点:

①积分截断效应大,有稳态误差;

②溢出的影响大。有的被控对象用增量式则不太好;

六、PID算法的改进

1)积分饱和

位置式PID在积分项达到饱和时,误差仍然会在积分作用下继续累积,一旦误差开始反向变化,系统需要一定时间从饱和区退出。

解决方法:

1、积分限幅:在积分积累达到最大值时,停止积分的积累。

//积分限幅
if(pid->integral > IntegralMAX) pid->integral = IntegralMAX;
else if(pid->integral < -IntegralMAX) pid->integral = -IntegralMAX;

2、变速积分:

在系统误差较大时对积分进行积累会导致积分过饱和,此后需要很长的一段时间进行消除。所以我们希望在系统偏差大时积分作用应减弱甚至全无,而在偏差小时则应加强。变速积分可以根据系统偏差大小改变积分的速度。

使用变速积分后I项的表达式:

其中系数f 为:

当积分误差小于B时,对误差进行全积累;当误差大于A+B时,不积累;当误差处于两者之间时,积累量和误差值是线性关系

若A=0,f取值为0或1,此时为积分分离

3、抗积分饱和

是在计算输出的时候,先判断上一时刻的控制量U(k-1)是否已经超出了限制范围。若U(k-1)>Umax,则只累加负偏差;若U(k-1)<Umin,则只累加正偏差。从而避免控制量长时间停留在饱和区。

2)梯形积分

在积分项中,默认是按矩形方式来计算积分,将矩形积分改为梯形积分可以提高运算精度。即在每次计算积分时,积累的误差总是修改为当前误差与上一次误差的平均值。

3)不完全微分

从PID控制的基本原理我们知道,微分信号的引入可改善系统的动态特性,但也存在一个问题,那就是容易引进高频干扰,在偏差扰动突变时尤其显出微分项的不足。为了解决这个问题人们引入低通滤波方式来解决这一问题。

位置式PID的微分部分计算公式:

增量式PID的微分部分计算公式:

其中\alpha为不完全微分系数。

4)死区PID控制

在实际控制中可能总是存在微小的静差难以消除,导致系统频繁地不稳定,这时就可以引入带死区的PID算法,即在偏差达到一定程度时才进行调节,否则认为已经到达目标值。

5)步进式PID

所谓步进式PID算法,实际就是在设定值发生阶跃变化时,不直接对阶跃信号进行响应,而是在一定的时间内逐步改变设定值,直至使设定值达到目标值。这种逐步改变设定值的办法使得对象运行平稳。适用于高精度伺服系统的位置跟踪。

其基本思想是设定一个适当的步长,每次控制移动一个步长的值,直到达到目标值。

float StepInProcessing(pid_t *vPID)
{
  float stepIn=(vPID->maximum-vPID->minimum))*0.1;
  float kFactor=0.0;

  if(fabs(vPID->actual_val - vPID->target_val)<=stepIn)
  {
    vPID->actual_val = vPID->target_val;
  }
  else
  {
    if(vPID->actual_val - vPID->target_val > 0)
    {
      kFactor=-1.0;
    }
    else if(vPID->actual_val - vPID->target_val < 0)
    {
      kFactor=1.0;
    }
    else
    {
      kFactor=0.0;
    }
    vPID->actual_val = vPID->actual_val + kFactor*stepIn;
  }

  return vPID->actual_val;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/724250.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 953 (Div. 2) A - C 题解

因为有事只做了A-C&#xff0c;都比较简单&#xff0c;全是很简单的思维&#xff0c;明天有空还会添加上D&#xff0c;如果有人需要可以明天常来看看&#xff01; 进入正题&#xff1a; A. Alice and Books 题意&#xff1a;给你n个数字&#xff0c;将这些数字分到两堆里&am…

【C++初阶路】--- 类和对象(中)

目录 一、this指针1.1 this指针的引出1.2 this指针的特性1.3. C语言和C实现Stack的对比 二、类的6个默认成员函数三、构造函数3.1 概念3.2 特性 一、this指针 1.1 this指针的引出 如下定义一个日期类Date class Date { public://void InitDate(Date* const this, int year …

APP自动化测试-Appium常见操作之详讲

一、基本操作 1、点击操作 示例&#xff1a;element.click() 针对元素进行点击操作 2、初始化&#xff1a;输入中文的处理 说明&#xff1a;如果连接的是虚拟机&#xff08;真机无需加这两个参数&#xff0c;加上可能会影响手工输入&#xff09;&#xff0c;在初始化配置中…

Java--Arrays类

1.数组的工具java.util.Arrays 2.由于数组对象本身并没有什么方法可以供我们调用&#xff0c;但API中提供了一个工具类Arrays供我们使用&#xff0c;从而可以对数据对象进行一些基本的操作。 3.查看JDK帮助文档 4.Arrays类中的方法都是static修饰静态的静态方法&…

minSdkVersion、targetSdkVersion、compileSdkVersion三者的作用解析

minSDK和targetSDK&#xff0c;这两者相当于一个区间。你能够用到targetSDK中最新的API和最酷的新功能&#xff0c;但又需要向后(向下)兼容到minSDK&#xff0c;保证这个区间内的设备都能够正常的执行你的APP。换句话说&#xff0c;想使用Android刚刚推出的新特性&#xff0c;但…

6 PXE高效批量网络装机

6.1部署PXE远程安装服务 在大规模的Liunx应用环境中&#xff0c;如web群集&#xff0c;分布式计算等&#xff0c;服务器往往并不配备光驱设备&#xff0c;在这种情况下&#xff0c;如何为数十乃至上百台服务器裸机快速安装系统呢&#xff1f;传统的USB光驱&#xff0c;移动硬盘…

零编程数据可视化展示:十个简易案例!

数据可视化是呈现数据内在价值的最终手段。数据可视化实例利用各种图表和图形设计手段&#xff0c;合乎逻辑地展示复杂而不直观的数据。为了让用户直观清楚地了解他们想要的数据及其比较关系&#xff0c;数据可视化实例的呈现至关重要。即时设计整理了10个数据可视化实例&#…

17-C语言中的变量生命周期——自动存储期、青苔存储期、自定义存储期

17-C语言中的变量生命周期——自动存储期、青苔存储期、自定义存储期 文章目录 17-C语言中的变量生命周期——自动存储期、青苔存储期、自定义存储期一、自动存储期示例 二、静态存储期2.1 示例 三、自定义存储期3.1 如何申请内存3.2 如何释放内存3.3 如何清空内存3.4 示例 概念…

【学习DayNa】信息系统开发整理

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 结构化方法 结构是指系统内各个组成要素之间的相互联系、相互作用的框架。结构化开发方法就是…

需求工程师的基本职责(合集)

需求工程师的基本职责1 职责&#xff1a; 1、负责用户需求调研、用户需求分析&#xff0c;明确用户需求分析&#xff0c;明确用户功能需求、业务需求&#xff0c;转换成软件需求说明。 2、收集、分析、整理、提炼系统需求&#xff0c;能够对业务流程提出优化建议并写成系统功能…

音视频入门基础:H.264专题(1)——H.264官方文档下载

音视频入门基础&#xff1a;H.264专题系列文章&#xff1a; 音视频入门基础&#xff1a;H.264专题&#xff08;1&#xff09;——H.264官方文档下载 音视频入门基础&#xff1a;H.264专题&#xff08;2&#xff09;——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…

SpringBoot整合Minio(支持公有及私有bucket)

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; SpringBoot整合Minio(支持公有及私有bucket) ⏱️ 创作时间&#xff1…

第6章 设备驱动程序(4)

目录 6.5 块设备操作 6.5.5 请求结构 6.5.6 BIO 6.5.7 提交请求 6.5.8 I/O调度 6.5.9 ioctl实现 本专栏文章将有70篇左右&#xff0c;欢迎关注&#xff0c;查看后续文章。 6.5 块设备操作 6.5.5 请求结构 struct request { //放在请求队列上&#xff0…

Go Gin框架

一、Gin介绍 Gin是一个用Go编写的HTTPweb框架。它是一个类似于martini但拥有更好性能的API框架, 优于httprouter&#xff0c;速度提高了近 40 倍。点击此处访问Gin官方中文文档。 二、安装 1、安装Gin go get -u github.com/gin-gonic/gin 2、代码中引入 import "githu…

【Docker】——安装镜像和创建容器,详解镜像和Dockerfile

前言 在此记录一下docker的镜像和容器的相关注意事项 前提条件&#xff1a;已安装Docker、显卡驱动等基础配置 1. 安装镜像 网上有太多的教程&#xff0c;但是都没说如何下载官方的镜像&#xff0c;在这里记录一下&#xff0c;使用docker安装官方的镜像 Docker Hub的官方链…

进阶篇05——存储过程、存储函数、触发器

存储过程 简介 基本语法 创建和调用 -- 创建名为p1的存储过程&#xff0c;小括号里可以跟参数 -- 存储过程个人觉得就是SQL里的函数 create procedure p1() begin-- begin 和 end 之间是封装的SQL语句-- 可以是一条SQL也可以是多条SQLselect * from student; end;-- 调用存储…

【FreeRTOS】估算栈的大小

参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》 目录 估算栈的大小回顾简介计算说明估计函数用到的栈有多大合计 估算栈的大小 回顾 上一篇文章链接&#xff1a;http://t.csdnimg.cn/Cc8b4 传送门: 上一篇文章 上一篇文章创建的三个任务 /* 创建任务&#xff1a;声 *…

vivado SITE

描述 SITE是一个设备对象&#xff0c;表示许多不同类型的逻辑资源之一 可在目标Xilinx FPGA上获得。 SITE包括SLICE/CLB&#xff0c;它们是基本逻辑元件&#xff08;BEL&#xff09;的集合&#xff0c;如 查找表&#xff08;LUT&#xff09;、触发器、多路复用器&#xff0c;携…

网页钓鱼-克隆修改--劫持口令下载后门

免责声明:本文仅做技术交流与学习... 目录 1-右键另存为 2-goblin项目(不推荐) 修改goblin.yaml文件 运行exe ​编辑 3-Setoolkit (kali自带) 网页克隆---> 1-右键另存为 --不行就再定位元素进行修改. 2-goblin项目(不推荐) GitHub - xiecat/goblin: 一款适用于红蓝…

力扣每日一题 6/19 排序+动态规划

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 2713.矩阵中严格递增的单元格数【困难】 题目&#xff1a; 给你一个下标从…