当前位置: 首页 > news >正文

【PID学习】PID算法改进

目录

一、对积分部分的改进(Ki)

1.积分限幅:

2.积分分离:

3.变速积分:

二、对微分部分的改进(Kd)

1.微分先行:

2.不完全微分:

三、对输入输出部分的改进(Out)

1.输出偏移:

2.输入死区:


 

一、对积分部分的改进(Ki)

1.积分限幅:

限制积分的幅度,防止积分深度饱和

  • 要解决的问题:如果执行器因为卡住、断电、损坏等原因误差长时间得不到消除,则误差积分会随着时间的推移无限制加大,进而达到深度饱和状态,此时PID控制器会持续输出最大的调控力,即使后续执行器恢复正常,PID控制器在短时间内也会维持最大的调控力,直到误差积分从深度饱和状态退出
  • 积分限幅实现思路:对误差积分或积分项输出进行判断,如果幅值超过指定阈值,则进行限制

积分限幅思路1 :单独对误差积分进行限幅

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*误差积分(累加)*/Sum_Error += Current_Error;/*积分限幅*/if (Sum_Error > 误差积分上限) {Sum_Error = 误差积分上限;}if (Sum_Error < 误差积分下限) {Sum_Error = 误差积分下限;}/*PID计算*/Out = Kp * Current_Error + Ki * Sum_Error + Kd * (Current_Error - Last_Error);/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

 积分限幅思路2:对整个积分项输出限幅

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;//        /*误差积分(累加)*/
//        Sum_Error += Current_Error;
//        /*积分限幅*/
//        if (Ki * Sum_Error > 误差积分上限) {Ki * Sum_Error = 误差积分上限;}
//        if (Ki * Sum_Error < 误差积分下限) {Ki * Sum_Error = 误差积分下限;}
//        /*PID计算*/
//       Out = Kp * Current_Error + Ki * Sum_Error + Kd * (Current_Error - Last_Error);/**************上下两部分等价******************//*积分项输出*/IntOut += Ki * Current_Error;/*积分项输出限幅*/if (IntOut > 积分项输出上限) {IntOut = 积分项输出上限;}if (IntOut < 积分项输出下限) {IntOut = 积分项输出下限;}/*PID计算*/Out = Kp * Current_Error + IntOut + Kd * (Current_Error - Last_Error);/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

 

2.积分分离:

误差小于一个限度才开始积分,反之则去掉积分部分

  • 要解决的问题:积分项作用一般位于调控后期,用来消除持续的误差,积分项调控过程具有滞后性,调控前期一般误差较大且不需要积分项作用,如果此时仍然进行积分,则调控进行到后期时,积分项可能已经累积了过大的调控力,这会导致超调
  • 积分分离实现思路:对误差大小进行判断,如果误差绝对值小于指定阈值,则加入积分项作用,反之,则直接将误差积分清零或不加入积分项作用

积分分离思路1:判断误差,如果误差过大直接将积分清0

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*误差积分(累加) + 积分分离*/if (fabs(Sum_Error) < 积分分离阈值){Sum_Error += Current_Error;}else{Sum_Error = 0;}      /*PID计算*/Out = Kp * Current_Error + Ki * Sum_Error + Kd * (Current_Error - Last_Error);/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

积分分离思路2:判断误差,使用标志位决定是否加入积分作用

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*误差积分(累加)*/Sum_Error += Current_Error;/*积分分离*/    if (fabs(Sum_Error) < 积分分离阈值){C = 1;}else{C = 0;}         /*PID计算*/Out = Kp * Current_Error + C * Ki * Sum_Error + Kd * (Current_Error - Last_Error);/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

 

3.变速积分:

根据误差的大小调整积分的速度

  • 要解决的问题:如果对上面的积分分离阈值没有设定好,设定值小于真实阈值,被控对象正好在阈值之外停下来,则此时控制器完全没有积分作用,误差不能消除
  • 变速积分实现思路:变速积分是积分分离的升级版,变速积分需要设计一个函数值随误差绝对值增大而减小的函数,函数值作为调整系数,用于调整误差积分的速度或积分项作用的强度。即误差越大积分越弱,误差越小积分越强(和积分分离思路一致,当误差过大时不积分防止超调,变速积分不再是简单的一刀切判断误差,而是采用渐进的方法控制积分值)

 

 变速积分思路1:调整误差积分速度

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*变速积分*/C = 1 / (k * fabs(Current_Error) + 1)  /*误差积分(累加)*/Sum_Error += C * Current_Error;/*PID计算*/Out = Kp * Current_Error + Ki * Sum_Error + Kd * (Current_Error - Last_Error);/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

变速积分思路2:调整积分项作用强度(实质和思路1一样,只不过C出现的位置变了)

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*变速积分*/C = 1 / (k * fabs(Current_Error) + 1)  /*误差积分(累加)*/Sum_Error += Current_Error;/*PID计算*/Out = Kp * Current_Error + C * Ki * Sum_Error + Kd * (Current_Error - Last_Error);/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

 

二、对微分部分的改进(Kd)

1.微分先行:

将对误差的微分替换为对实际值的微分

  • 要解决的问题:普通PID的微分项对误差进行微分,当目标值大幅度跳变时,误差也会瞬间大幅度跳变,这会导致微分项突然输出一个很大的调控力,相当于帮助P控制器进行正向调控,如果系统的目标值频繁大幅度切换,则此时的微分项不利于系统稳定
  • 微分先行实现思路:将对误差的微分替换成对实际值的微分

普通PID的微分项输出:

dout(k) = Kd * ( error(k) - error(k-1) )

 

微分先行PID的微分项输出:

dout(k) = - Kd * ( actual(k) - actual(k-1) )

        /*获取上次实际值和本次实际值*/Last_Actual = Current_Actual;Current_Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*误差积分(累加)*/Sum_Error += Current_Error;/*微分先行*/DifOut = - Kd * ( Current_Actual - Last_Actual);/*PID计算*/Out = Kp * Current_Error + C * Ki * Sum_Error + DifOut;/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

2.不完全微分:

给微分项加入一阶惯性单元(低通滤波器)

  • 要解决的问题:传感器获取的实际值经常会受到噪声干扰,而PID控制器中的微分项对噪声最为敏感,这些噪声干扰可能会导致微分项输出抖动,进而影响系统性能
  • 不完全微分实现思路:给微分项加入一阶惯性单元(低通滤波器)

注意:滤波需要时间,会导致信号产生时延

普通PID的微分项输出:

dout(k) = Kd * ( error(k) - error(k-1) )

 

不完全微分PID的微分项输出:

α取值0~1,用于调控最终PID微分输出参数本次和上次的比值,相当于两个值做加权平均

dout(k) = ( 1 - α ) * Kd * ( error(k) - error(k-1) ) + α * dout( k - 1 )

        /*获取本次实际值*/Current_Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*误差积分(累加)*/Sum_Error += Current_Error;/*不完全微分*/DifOut = (1 - a) * Kd * (Current_Error - Last_Error) + a * DifOut/*PID计算*/Out = Kp * Current_Error + C * Ki * Sum_Error + DifOut;/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

三、对输入输出部分的改进(Out)

1.输出偏移:

在非0输出时,给输出值加一个固定偏移

  • 要解决的问题:对于一些启动需要一定力度的执行器,若输出值较小,执行器可能完全无动作,这可能会引起调控误差,同时会降低系统响应速度
  • 输出偏移实现思路:若输出值为0,则正常输出0;若输出值非0,则给输出值加一个固定偏移,跳过执行器无动作的阶段

注意:输出偏移由于存在正反两面的调控,会导致系统存在振荡

if( out(k) == 0 )       out(k) = 0

if( out(k) >   0 )       out(k) += offset

if( out(k) <   0 )       out(k) -= offset

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*误差积分(累加)*/Sum_Error += Current_Error;/*PID计算*/Out = Kp * Current_Error + Ki * Sum_Error + Kd * (Current_Error - Last_Error);/*输出偏移*/if (Out > 0){Out += 偏移值;}else if (Out < 0){Out -= 偏移值;}else{Out = 0;}/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

2.输入死区:

误差小于一个限度时不进行调控

  • 要解决的问题:在某些系统中,输入的目标值或实际值有微小的噪声波动,或者系统有一定的滞后,这些情况可能会导致执行器在误差很小时频繁调控,不能最终稳定下来
  • 输入死区实现思路:若误差绝对值小于一个限度,则固定输出0,不再进行调控

if( fabs( out(k) ) < A  )      out(k) = 0

if( fabs( out(k) ) >= A)      out(k) = out(k)

 输入死区 + 输出偏移代码思路

        /*获取实际值*/Actual = 读取传感器();/*获取上次和本次误差*/Last_Error = Current_Error;Current_Error = Target - Actual;/*输入死区*/if ( fabs(Current_Error) < 死区阈值 ){Out = 0;}else{/*误差积分(累加)*/Sum_Error += Current_Error;/*PID计算*/Out = Kp * Current_Error + Ki * Sum_Error + Kd * (Current_Error - Last_Error); /*输出偏移*/if (Out > 0){Out += 偏移值;}else if (Out < 0){Out -= 偏移值;}else{Out = 0;}          }/*输出限幅*/if (Out > 输出上限) {Out = 输出上限;}if (Out < 输出下限) {Out = 输出下限;}/*执行控制*/输出至被控制对象函数(Out);

 

 

http://www.dtcms.com/a/432189.html

相关文章:

  • 引流推广app网站改版对seo影响
  • 南京代做网站h5编辑器有哪些软件
  • 在Zotero中配置PDF2zh插件并使用详细教程
  • 做图有什么网站河池市民政局门户网站建设
  • 10大免费软件下载网站wordpress模板克隆
  • MASM数据段完全指南:从基础定义到高级内存操作
  • 提供视频下载的网站做学术用的网站
  • 官方网站建设实训心得网站seo优化主要有哪些手段
  • 17.仅使用 CSS 实现的导航标签页,带滑动菜单指示器
  • 【LeetCode 每日一题】1470. 重新排列数组——(解法一)构造数组
  • 商城网站合同设计公司网站需要考虑什么
  • 银川建设网站简约的网页设计
  • 【人工智能通识专栏】第三十二讲:本地化部署模型
  • 网站怎么加关键词深圳网站建设公司小江
  • 网站开发人员介绍做网站首页看不到图片
  • ORB_SLAM2原理及代码解析:MapPoint::AddObservation() 函数
  • 炉石做任务抽奖网站装宽带一年大概需要多少钱
  • 个人网站建立 学生哈尔滨学校网站建设
  • 网站用什么软件做败sp个人网站app
  • 适合建设网站的国外服务器晋城市网站建设
  • 西安做商铺的网站网站设计公司费用
  • 专业做胶粘剂招聘网站华为云网站定制
  • 企业建站系统费用全站搜索
  • 做装饰网站公司wordpress plugins
  • 龙岗网站建设开发设计公司深圳建筑网站
  • 用空间做网站如何做好安全广州建设银行分行招聘网站
  • 公司做的网站费用如何做账wordpress 积分动力
  • 外包服务费税率泉州网站seo
  • 0.1 tensorflow例1-梯度下降法
  • 微信公众号内置手机网站wordpress置顶失败