This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
/* ================================================================================== File name: PID_REG3.H (IQ version) =====================================================================================*/ #ifndef __PIDREG3_H__ #define __PIDREG3_H__ typedef struct { _iq Ref; // Input: Reference input _iq Fdb; // Input: Feedback input _iq Err; // Variable: Error _iq Kp; // Parameter: Proportional gain _iq Up; // Variable: Proportional output _iq Ui; // Variable: Integral output _iq Ud; // Variable: Derivative output _iq OutPreSat; // Variable: Pre-saturated output _iq OutMax; // Parameter: Maximum output _iq OutMin; // Parameter: Minimum output _iq Out; // Output: PID output _iq SatErr; // Variable: Saturated difference _iq Ki; // Parameter: Integral gain _iq Kc; // Parameter: Integral correction gain _iq Kd; // Parameter: Derivative gain _iq Up1; // History: Previous proportional output } PIDREG3; typedef PIDREG3 *PIDREG3_handle; /*----------------------------------------------------------------------------- Default initalizer for the PIDREG3 object. -----------------------------------------------------------------------------*/ #define PIDREG3_DEFAULTS { 0, \ 0, \ 0, \ _IQ(1.3), \ 0, \ 0, \ 0, \ 0, \ _IQ(1), \ _IQ(-1), \ 0, \ 0, \ _IQ(0.02), \ _IQ(0.5), \ _IQ(1.05), \ 0, \ } /*------------------------------------------------------------------------------ PID Macro Definition ------------------------------------------------------------------------------*/ #define PID_REG3_MACRO(v) \ v.Err = v.Ref - v.Fdb; /* Compute the error */ \ v.Up= _IQmpy(v.Kp,v.Err); /* Compute the proportional output */ \ v.Ui= v.Ui + _IQmpy(v.Ki,v.Up) + _IQmpy(v.Kc,v.SatErr); /* Compute the integral output */ \ v.OutPreSat= v.Up + v.Ui; /* Compute the pre-saturated output */ \ v.Out = _IQsat(v.OutPreSat, v.OutMax, v.OutMin); /* Saturate the output */ \ v.SatErr = v.Out - v.OutPreSat; /* Compute the saturate difference */ \ v.Up1 = v.Up; /* Update the previous proportional output */ #define PID_REG3_POS_MACRO(v) \ v.Err = v.Ref - v.Fdb; /* Compute the error */ \ if (v.Err >= _IQ(0.5)) \ v.Err -= _IQ(1.0); /* roll in the error */ \ else if (v.Err <= _IQ(-0.5)) \ v.Err += _IQ(1.0); /* roll in the error */ \ v.Up= _IQmpy(v.Kp,v.Err); /* Compute the proportional output */ \ v.Ui= v.Ui + _IQmpy(v.Ki,v.Up) + _IQmpy(v.Kc,v.SatErr); /* Compute the integral output */ \ v.Ud = _IQmpy(v.Kd,(v.Up - v.Up1)); \ v.OutPreSat= v.Up + v.Ui + v.Ud; /* Compute the pre-saturated output */ \ v.Out = _IQsat(v.OutPreSat, v.OutMax, v.OutMin); /* Saturate the output */ \ v.SatErr = v.Out - v.OutPreSat; /* Compute the saturate difference */ \ v.Up1 = v.Up; #endif // __PIDREG3_H__ // Add the lines below if derivative output is needed following the integral update
位置在ti\controlSUITE\libs\app_libs\motor_control\math_blocks\v4.3/
在给出的文档中似乎没有对这个的说明(看大家用的这个,也打算用这个。把Kd设为0就是PI了吧)
1、Kc,积分校正增益,没明白是什么作用
2、这个是增量式PID吗?
3、SatErr,饱和差,好像是v->SatErr = v->Out - v->OutPreSat;,但不知道什么用
4、v.Ui= v.Ui + _IQmpy(v.Ki,v.Up) + _IQmpy(v.Kc,v.SatErr);也即是// Compute the integral output
v->Ui = v->Ui +v->Ki*v->Up + v->Kc*v->SatErr;其中的v->Kc*v->SatErr;怎么理解啊,为什么加上v->Ki*v->Up + v->Kc*v->SatErr,加上当前误差乘以Ki不就可以了吗?
5、// Compute the derivative output
v->Ud = v->Kd*(v->Up - v->Up1);计算微分的时候为什么用的是比例输出。
6、_iq换成了float32, _IQ(1.3)换成1.3也可以吧。想换成浮点型的。
谢谢
你好!
我是一个DSP的菜鸟不知理解的对不对,2你的这个算法好像不是增量式的PID,好像是位置式的PID,
Up= _IQmpy(v.Kp,v.Err),比例环节,
Ui= v.Ui + _IQmpy(v.Ki,v.Up)积分环节,
Ud = _IQmpy(v.Kd,(v.Up - v.Up1))微分环节,饱和差我也不是很清楚,但是位置式的PID由于积分一直在累加求和因此需要退饱和,具体怎么退饱和我没有接触过所以我说不清楚。
Ud = v->Kd*(v->Up - v->Up1)这是微分环节离散化之后的公式,以上的三个PID都是经过离散化的,
Kd(du/dt),离散化就是前后两个时间的差值,也就是
Kd*(v->Up - v->Up1)。
而增量式PID比位置式的多一步,增量式是前后两个时间位置PID的差值。
不知我理解的对不对,仅供你参考!谢谢!
谢谢您的回答,不过_iq换成了float32, _IQ(1.3)换成1.3也可以吧。想换成浮点型的。
Ui= v.Ui + _IQmpy(v.Ki,v.Up)积分环节,这个是得出积分的输出,但是不应该是
v.Ui +KI*Err吗,为什么是_IQmpy(v.Ki,v.Up),谢谢
您好!
关于这个问题,我也有疑问,我比较同意你的看法v.Ui +KI*Err,不知是不是这个PID中间还有其他的传递环节,因为我上面写的那个参考是最简单的数学模型,你的这个应该比较复杂点,所以我也没什么把握!我再查查资料,如果你弄明白了也请给我留言谢谢!
KC
积分修正系数
以直流有刷电动机转速电流双闭环控制算法为例,控制环路有两个:转速环和电流环。
转速环的PI控制器可以饱和,然而电流是瞬态量,因此内环的PI控制器是不允许饱和的,因此电流环的PI控制器有3个参数,比例、积分和抗积分饱和修正系数(Kc)
因为控制器饱和以后是失效的状态,从饱和到推饱和是需要时间的,这个延时对电流环控制来讲是不允许的,所以电流环要用抗积分饱和PI控制器
我新下载了control suit ,但是找到的pid_reg3.h和你的不一样
我的文件位置是:
内容:
/* ==================================================================================
File name: PID_REG3.H (IQ version)
=====================================================================================*/
#ifndef __PIDREG3_H__
#define __PIDREG3_H__
typedef struct { _iq Ref; // Input: Reference input
_iq Fdb; // Input: Feedback input
_iq Err; // Variable: Error
_iq Kp; // Parameter: Proportional gain
_iq Up; // Variable: Proportional output
_iq Ui; // Variable: Integral output
_iq Ud; // Variable: Derivative output
_iq OutPreSat; // Variable: Pre-saturated output
_iq OutMax; // Parameter: Maximum output
_iq OutMin; // Parameter: Minimum output
_iq Out; // Output: PID output
_iq SatErr; // Variable: Saturated difference
_iq Ki; // Parameter: Integral gain
_iq Kc; // Parameter: Integral correction gain
_iq Kd; // Parameter: Derivative gain
_iq Up1; // History: Previous proportional output
} PIDREG3;
typedef PIDREG3 *PIDREG3_handle;
/*-----------------------------------------------------------------------------
Default initalizer for the PIDREG3 object.
-----------------------------------------------------------------------------*/
#define PIDREG3_DEFAULTS { 0, \
0, \
0, \
_IQ(1.3), \
0, \
0, \
0, \
0, \
_IQ(1), \
_IQ(-1), \
0, \
0, \
_IQ(0.02), \
_IQ(0.5), \
_IQ(1.05), \
0, \
}
/*------------------------------------------------------------------------------
PID Macro Definition
------------------------------------------------------------------------------*/
#define PID_MACRO(v) \
v.Err = v.Ref - v.Fdb; /* Compute the error */ \
v.Up= _IQmpy(v.Kp,v.Err); /* Compute the proportional output */ \
v.Ui= v.Ui + _IQmpy(v.Ki,v.Up) + _IQmpy(v.Kc,v.SatErr); /* Compute the integral output */ \
v.OutPreSat= v.Up + v.Ui; /* Compute the pre-saturated output */ \
v.Out = _IQsat(v.OutPreSat, v.OutMax, v.OutMin); /* Saturate the output */ \
v.SatErr = v.Out - v.OutPreSat; /* Compute the saturate difference */ \
v.Up1 = v.Up; /* Update the previous proportional output */
#endif // __PIDREG3_H__
// Add the lines below if derivative output is needed following the integral update
// v.Ud = _IQmpy(v.Kd,(v.Up - v.Up1));
// v.OutPreSat = v.Up + v.Ui + v.Ud;
其中没有你的
PID_REG3_MACRO(v)和PID_REG3_POS_MACRO(v)
这两个
PID_REG3_MACRO(v)是PI
PID_REG3_POS_MACRO(v)是PID
你的问题2到5,pid_reg3.pdf的这两页可以接到,你看下推导下就明白了
应该是位置式的PID
我第一次看这个代码的时候也有和你一样的疑问,
主观上理解PID控制器的输出,不就是比例 加 积分 加微分嘛
但是你看这个代码里:
你也提到了微分怎么和比例有关系呢?
再有你看,其实还有积分部分还涉及到了比例系数和积分系数相乘呢,更不可理解。
但是看看文档,推到下,这些也就不是疑问了
haichao zhang 你好!
我想请教一下,就是如果我想用DSP去控制BUCK式的降压电路的PWM驱动。实现输出电压或者电流的控制。使用的PID控制是用增量式的PID控制还是位置式的。哪种好?谢谢!
看个文档,这样说的位置式PI 调节器这种算法的优点是计算精度比较高,缺点是每次都要对e(k) 进行累加, 很容易出现积分饱和的情况。但现在有抗积分饱和的了。
增量式 PI 算法与位置式 PI 算法并没有本质的区别,只是增量式 PI 算法控制的是执行机构的增量 Δu(k),这种算法的优点在于:由于输出的是增量,因此 计算错误时的产生的影响较小,这种算法的缺点在于:每次计算 Δu(k)再与前次 的计算结果u(k −1) 相加得到本次的控制输出,这就使得 Δu(k)的截断误差被逐次的累加起来,输出的误差加大。
只是照书上说的。你考虑下
这是知乎上面的一个帖子 写的很好
你仔细看下这个帖子 再去理解下TI的位置式PID_REG3和北京航空航天大学出版社出版的《电动机的DSP控制——TI公司》这本书里提到的增量式PID
知乎的这个帖子即从理论上又从编程实现上对比了两种算法的区别
feng shi的解释书本化 百度上搜的很多博客也是这么写的;bad提到的位置式具有一定的炕扰性,增量式反应比较快,我不清楚从原理上怎么体现出这些区别
知乎的这个解释还是挺好的 建议jin chao yang看下
我总结了下 写到我的个人微信公众号了 你可以看看
https://mp.weixin.qq.com/s?__biz=MzI2NDE4NTQ5NA==&mid=2657808641&idx=1&sn=101fa7ce554e4d51d9a02a26571470c5&chksm=f12e22f8c659abee54a93b934c5f8992adc5752513137c12a133c7a762e7331b091c199fe921&scene=0&key=c81d77271180a0e62461a725234a604d1a20a51c8d71a59a86241577191211e1d6133de18ee3732ec69b7f671b62652d5093c46b27b1b4fb85c6aff4a42ba7ff6ad9e68de7df4f81389a1250d8fbc31b&ascene=7&uin=MjgwNzA5NDkzMg%3D%3D&devicetype=android-22&version=26031f30&nettype=cmnet&abtest_cookie=AQABAAgAAQAkhh4AAAA%3D&pass_ticket=mRYEiupMywwCUHbOBhzmYskXjc85k9xx643ughbLKY%2Fddboo0AZ3MHujeXyRQiPj&wx_header=1