https://www.bilibili.com/video/BV1B54y1V7hp?from=search&seid=227773174318710325&spm_id_from=333.337.0.0
https://zhuanlan.zhihu.com/p/74131690
(2)理解P(比例环节)作用:基础比例环节
缺点: 产生稳态误差.
疑问: 何为稳态误差 为什么会产生稳态误差.
(3)理解I(积分环节)作用:消除稳态误差.
缺点: 增加超调
疑问: 积分为何能消除稳态误差?
(4) 理解D(微分环节)作用:加大惯性响应速度,减弱超调趋势
疑问: 为何能减弱超调
2.适用系统
二阶以内线性系统(齐次性、叠加性)
一阶系统举例:
二阶系统举例:
高阶系统简化为二阶系统,那么可以用pid
非线性系统通过李雅普诺夫变换线性化之后为线性系统,可以用pid
前馈控制系统:
闭环控制系统:
双闭环:
复合控制系统(开环+闭环):
前馈-反馈复合控制系统
2.pid公式解释(形象派)
如上图,期望位置为100,设置KP为0.1,其他I、D为0,那么输出u=Kp*y
可得表格:(e:与目标误差,u:基于误差输出,L:最终输出)
次数 | e | u | L |
---|---|---|---|
0 | 0 | ||
1 | 100 | 10 | 10 |
2 | 90 | 9 | 19 |
3 | 81 | 8.1 | 27.1 |
4 | 72.9 | 7.29 | 34.39 |
5 | 65.61 | 6.561 | 40.951 |
6 | … | … | … |
最终收敛,如下图所示:
接下来看一下无人机的例子,其产生了稳态误差,需要引入I来解决:
比例项在误差不变的情况下,其值也不变,所以当有稳态误差时,其不能靠比例项来抵消误差。
积分项会累加之前的误差,从而达到解决稳态误差的作用。如图所示:
当误差为0时,积分项的误差还是存在,只是停止积累误差了,如图所示:
由于这个积分项特性,会出现超调量。
出现超调那么引入微分项:
增量式PID:
以上是位置式PID公式,接下来讲解增量式PID公式
将k-1带入公式得:
由u=u(k)-u(k-1),得:
对比区别
• 增量式算法不需要对积分项累加,控制量增量只与近几次的误差有关,计算误差对控制量
计算的影响较小。而 位置式算法要对近几次的偏差的进行积分累加,容易产生较大的累加
误差;
• 增量式算法得出的是控制量的增量,例如在阀门控制中,只输出阀门开度的变化部分,误动作影响小,必要时还可通过逻辑判断限制或禁止本次输出,不会严重影响系统的工作;而
位置式的输出直接对应对象的输出,因此对系统影响较大;
• 增量式算法控制输出的是控制量增量,并无积分作用,因此该方法适用于执行机构带积分
部件的对象,如步进电机等,而 位置式算法适用于执行机构不带积分部件的对象,如电液
伺服阀;
• 在进行 PID 控制时,位置式 PID 需要有积分限幅和输出限幅,而 增量式 PID 只需输出
限幅。
位置式 PID 优缺点:
优点:: 位置式 PID 是一种非递推式算法,可直接控制执行机构(如平衡小车),u(k) 的值和执行机构的实际位置(如小车当前角度)是一一对应的,因此在执行机构不带积分部件的对象中可以很好应用;
缺点:: 每次输出均与过去的状态有关,计算时要对 e(k) 进行累加,运算工作量大。
增量式 PID 优缺点:
优点::
1.误动作时影响小,必要时可用逻辑判断的方法去掉出错数据。
2. 手动/自动切换时冲击小,便于实现无扰动切换。
3. 算式中不需要累加。控制增量 ∆u(k) 的确定仅与最近 3 次的采样值有关。在速度闭环控制
中有很好的实时性。
缺点:
1.积分截断效应大,有稳态误差;
4. 溢出的影响大。有的被控对象用增量式则不太好;
其实两个式子表达的内容是一样的。
两pid的c语言实现:
位置式pid:
//结构体
typedef struct
{
float target_val; //目标值
float actual_val; //实际值
float err; //定义偏差值
float err_last; //定义上一个偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
float integral; //定义积分值
}_pid;
//操作:
#include "./pid/bsp_pid.h"
#include "math.h"
#include "./key/bsp_key.h"
#include "./protocol/protocol.h"
//定义全局变量
_pid pid;
/**
* @brief PID参数初始化
* @note 无
* @retval 无
*/
void PID_param_init()
{
/* 初始化参数 */
// printf("PID_init begin \n");
pid.target_val=200.0;
pid.actual_val=0.0;
pid.err=0.0;
pid.err_last=0.0;
pid.integral=0.0;
// pid.Kp = 0.31;
// pid.Ki = 0.070;
// pid.Kd = 0.3;
// pid.Kp = 0.21;
// pid.Ki = 0.070;
// pid.Kd = 0.3;
pid.Kp = 0.01;//24
pid.Ki = 0.80;
pid.Kd = 0.04;
}
/**
* @brief 设置目标值
* @param val 目标值
* @note 无
* @retval 无
*/
void set_pid_target(float temp_val)
{
pid.target_val = temp_val; // 设置当前的目标值
}
/**
* @brief 获取目标值
* @param 无
* @note 无
* @retval 目标值
*/
float get_pid_target(void)
{
return pid.target_val; // 设置当前的目标值
}
/**
* @brief 设置比例、积分、微分系数
* @param p:比例系数 P
* @param i:积分系数 i
* @param d:微分系数 d
* @note 无
* @retval 无
*/
void set_p_i_d(float p, float i, float d)
{
pid.Kp = p; // 设置比例系数 P
pid.Ki = i; // 设置积分系数 I
pid.Kd = d; // 设置微分系数 D
}
/**
* @brief PID算法实现
* @param val 实际值
* @note 无
* @retval 通过PID计算后的输出
*/
float PID_realize(float temp_val)
{
/*计算目标值与实际值的误差*/
pid.err=pid.target_val-temp_val;
/*误差累积*/
pid.integral+=pid.err;
/*PID算法实现*/
pid.actual_val=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
/*误差传递*/
pid.err_last=pid.err;
/*返回当前实际值*/
return pid.actual_val;
}
/**
* @brief 定时器周期调用函数
* @param 无
*@note 无
* @retval 无
*/
void time_period_fun()
{
static int flag=0;
static int num=0;
static int run_i=0;
if(!flag)
{
float val=PID_realize(pid.actual_val);
printf("val,%f;act,%f\n",pid.target_val,val);
run_i++;
if(abs(val-pid.target_val)<=1)
{
num++;
}
else//必须满足连续次数
{
num=0;
}
if(num>20)//稳定次数
{
printf("PID算法运行%d 次后稳定\r\n",run_i);
flag=1;
}
}
}
其中time_period_fun被当作终端的回调函数被使用:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim==(&TIM_PIDHandle))
{
LED1_TOGGLE; //红灯周期闪烁
time_period_fun();
}
}
增量pid:
typedef struct
{
float target_val; //目标值
float actual_val; //实际值
float err; //定义当前偏差值
float err_next; //定义下一个偏差值
float err_last; //定义最后一个偏差值
float Kp, Ki, Kd; //定义比例、积分、微分系数
}_pid;
看出其成员不一样,是根据其公式来定的。
主要方法有试凑法、临界比例法、一般调节法。
2.其余相关控制知识
1.积分限幅
以上讲了算法的理论,但是实际应用中还需要注意很多事项,比如当我们按住飞行器,在PI系统中,I的量会随着时间累计,可能导致I变得巨大,无人机冲上天回不来,这时我们就要对积分限幅。
2.积分分离
改变期望高度,这时e会有一个阶跃,那么p也会阶跃,I在一个较短的时间内会快速变大,这时可能会导致巨大的超调量:这时我们可以定一个阈值,超过500的误差时,,我们直接让积分值=0。
3.微分先行:
之前是让期望高度和最终输出差值作为积分项的输入,现在直接让最终输出作为微分项的输入,这样当期望高度,也就是 输入突变的情况下,不会直接影响到D。
1.前期分析
2.RM电机M3508速度环
3.RM电机6020角度双环