PID控制器学习随笔

对于PID的认识

PID控制器实际上是对偏差的控制
连续状态的公式:
在这里插入图片描述
将其离散化,离散化具体就是用求和代替积分,用向后差分来代替微分
在这里插入图片描述

  • T————为采样周期
  • k————为采样序号,k=0,1,2….

偏差err(K)=rin(K)-rout(K);
积分环节用加和的形式表示,即err(K)+err(K+1)+……;
微分环节用斜率的形式表示,即[err(K)-err(K-1)]/T;

位置式PID

在这里插入图片描述
Kp是比例系数
Ki是积分系数
Kd是微分系数.

比例:给误差e一个系数,这个系数就是比例系数。如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。

优点:加快系统的响应速度,提高系统的调节精度。
缺点:导致超调

积分:稳态误差是指输出稳定后与目标值有一个差值,加入误差积分项可以消除稳态误差,积分系数是误差积分项的系数。积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。

优点:消除稳态误差
缺点:导致积分饱和现象

微分:在临近目标值的时候可能会有微小的震荡,加入变化率可以做到慢慢调的目的,微分技术是误差微分即变化率前的系数。微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。

优点:改善系统的动态性能
缺点:延长系统的调节时间,但其抗干扰性差

位置式PID的优缺点

优点:位置式 PID 是一种非递推式算法,可直接控制执行机构(如平衡小车),u(k) 的值和执行机构的实际位置(如小车当前角度)是一>一对应的,因此在执行机构不带积分部件的对象中可以很好应用;
缺点:每次输出均与过去的状态有关,计算时要对 e(k) 进行累加,运算工作量大。

增量式PID

在这里插入图片描述

增量式算法的优缺点

优点:

  1. 误动作时影响小,必要时可用逻辑判断的方法去掉出错数据。
  2. 手动/自动切换时冲击小,便于实现无扰动切换。
  3. 算式中不需要累加。控制增量 Δu(k) 的确定仅与最近 3 次的采样值有关。在速度闭环控制中有很好的实时性。
    缺点:1. 积分截断效应大,有稳态误差;
  4. 溢出的影响大。有的被控对象用增量式则不太好;

c++实现

位置式PID

#include <iostream>

using namespace std;

void PID_init();
float PID_realize(float speed);

struct _pid{
float SetSpeed;//定义设定值
float ActualSpeed;//定义实际值
float err;//定义偏差值
float err_last;//定义上一个偏差值
float Kp,Ki,Kd;//定义比例、积分、微分系数
float voltage;//定义电压值(控制执行器的变量)
float integral;//定义积分值
}pid;








int main()
{
    cout<<"System begin \n";
    PID_init();
    int count=0;
    while(count<1000)
    {
    float speed=PID_realize(200.0);
    cout<<"第 "<<count<<" 次的速度为: "<<speed<<endl;
    count++;
    }
    return 0;

}


void PID_init(){
cout<<"PID_init begin \n";
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
cout<<"PID_init end \n";
}


float PID_realize(float speed){
pid.SetSpeed=speed;
pid.err=pid.SetSpeed-pid.ActualSpeed;
pid.integral+=pid.err;
pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
pid.err_last=pid.err;
pid.ActualSpeed=pid.voltage*1.0;
return pid.ActualSpeed;
}

增量式PID

#include <iostream>

using namespace std;

void PID_init();
float PID_realize(float speed);

struct _pid{
float SetSpeed;//定义设定值
float ActualSpeed;//定义实际值
float err;//定义偏差值
float err_next;//定义下一个偏差值
float err_last;//定义上一个偏差值
float Kp,Ki,Kd;//定义比例、积分、微分系数
float voltage;//定义电压值(控制执行器的变量)
float integral;//定义积分值
}pid;








int main()
{
    cout<<"System begin \n";
    PID_init();
    int count=0;
    while(count<1000)
    {
    float speed=PID_realize(200.0);
    cout<<"第 "<<count<<" 次的速度为: "<<speed<<endl;
    count++;
    }
    return 0;

}


void PID_init(){
cout<<"PID_init begin \n";
pid.SetSpeed=0.0;
pid.ActualSpeed=0.0;
pid.err=0.0;
pid.err_next=0.0;
pid.err_last=0.0;
pid.voltage=0.0;
pid.integral=0.0;
pid.Kp=0.2;
pid.Ki=0.015;
pid.Kd=0.2;
cout<<"PID_init end \n";
}


float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    float
    incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last);
    pid.ActualSpeed+=incrementSpeed;
    pid.err_last=pid.err_next;
    pid.err_next=pid.err;
    return pid.ActualSpeed;
}


调参的顺序:先调P,再调D,最后调I

调P,让曲线震荡起来
调D,阻止曲线的震荡,让曲线平滑
调I,把曲线整体调整到目标值

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值