一种位置式PID的程序实现
我在网上搜到一个PID的程序,看起来不错,而且微分环节还带低通滤波的,然后稍加修改留给自己用,应该可以用吧,请大家看看怎么样 还没看 先顶一下 先顶一下{:lol:} 还是把程序贴出来方便看:
/*
@struct sPID
@brief manage all the parameters related to PID control
*/
typedef struct
{
float kp;
float ki;
float kd;
float dt; // delta time(sample time)
float imax;
float last_error;
float integrator; // integrator value
float last_derivative;// last derivative for low-pass filter
float derivative;
float output;
float ouput_max;
/// Low pass filter cut frequency for derivative calculation.
float filter; // Set to"1 / ( 2 * PI * f_cut )";
// Examples for filter:
// f_cut = 10 Hz -> _filter = 15.9155e-3
// f_cut = 15 Hz -> _filter = 10.6103e-3
// f_cut = 20 Hz -> _filter =7.9577e-3
// f_cut = 25 Hz -> _filter =6.3662e-3
// f_cut = 30 Hz -> _filter =5.3052e-3
}sPID;
/*
@function Get_PID()
@brief compute PID ouput value according to the error
@param error: current error between set point and point value
PID: the pointer of the PID structure
@return PID output value
*/
float Get_PID(float error, sPID *PID)
{
// Compute proportional component
PID->output = error * PID->kp;
// Compute derivative component if time has elapsed
if ((fabs(PID->kd) > 0) && (PID->dt > 0))
{
PID->derivative = (error - PID->last_error) / PID->dt;
// discrete low pass filter, cuts out the
// high frequency noise that can drive the controller crazy
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) * (PID->derivative - PID->derivative);
// update state
PID->last_error= error;
PID->last_derivative= PID->derivative;
// add in derivative component
PID->output += PID->kd * PID->derivative;
}
// Compute integral component if time has elapsed
if ((fabs(PID->ki) > 0) && (PID->dt > 0))
{
PID->integrator += (error * PID->ki) * PID->dt;
if (PID->integrator < -PID->imax)
PID->integrator = -PID->imax;
else if (PID->integrator > PID->imax)
PID->integrator = PID->imax;
PID->output += PID->integrator;
}
//Limit output
if(PID->output < -PID->ouput_max)
PID->output = -PID->output_max;
else if(PID->ouput > PID->ouput_max)
PID->output = PID->ouput_max;
return PID->output;
} 顶起来了 看了楼主的帖子后受益匪浅,绑定 PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) * (PID->derivative - PID->derivative);
这句话是不是后面有问题啊,这个滤波是怎么起作用的 这个式子有低通滤波的作用,具体原理我也不太清楚,不过应该是对的,我在很多地方都看到过。 好,有空看看 3.5控制核心——数字PID
在控制系统中,将偏差的比例P、积分I、微分D通过线性组合构成控制量的PID控制器获得了广泛的应用,它结构简单,参数容易调整,不需要确切的数学模型。即通过采集实时转速值与设定值的偏差,利用软件编程实现转速调节的运算,单片机实现PID控制的类型分为位置式和增量式两种:
位置式PID控制:其输入e (t)与输出u (t)的关系
u(t)=kp(e(t)+1/TI∫e(t)dt+TD*de(t)/dt) (式3.5-1)
从式3.5-1可以看出:
位置式PID控制存在缺点:
1)由于全量输出,所以每次输出均与过去状态有关,计算时要对e(k)(k=0,1,…n)进行累加,工作量大。
2)因为计算机输出的u(n)对应的是执行机构的实际位置,如果计算机出现故障,输出u(n)将大幅度变化,会引起执行机构的大幅度变化,有可能因此造成严重的生产事故,这在实际生产中是不允许的。
故本系统采用增量式数字PID算法,表达式推导 式3.5-1 U(t2)与U(t1)相减:
式中:—比例常数;—积分时间常数;_微分时间常数;
T—采样周期
对比位置PID控制方法增量式PID优点:
1)增量式PID的输出的是控制量增量,并无积分作用,因此,这种方法适用于执行机构带积分部件的对象。如步进电机;而位置式PID适用于执行机构不带积分环节的对象。
增量式PID输出的是控制量增量,若计算机出现故障,误动作影响较小,而执行机构本身有记忆功能,可仍保持原位,不会严重影响系统的工作,而位置式的输出直接对应对象的输出,因此对系统影响较大。 /************************************************
增量控制PID函数体
51单片机最不擅长浮点数计算,转换成int型计算
*************************************************/
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
{
unsigned int dError,Error,pError;
//增量法计算公式:
//Pdt=Kp*+Ki*E(t)+Kd*
Error = set_temper - NextPoint; // 偏差E(t)
pError=Error-pp->LastError; //E(t)-E(t-1)
dError=Error-2*pp->LastError+pp->PrevError; //E(t)-2*E(t-1)+E(t-2)
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (
pp->Proportion * pError //比例
+ pp->Integral *Error//积分项
+ pp->Derivative * dError // 微分项
);
}
单片机控制推荐这种函数。位置式纯机械运算控制非常有效,比如发动机燃油 “机械控制计算机”。纯凸轮-液压-顶杠机构。 收了。研究下。 单片机没试过用float 宣告 ,会不会导致速度变慢?? 10楼的朋友我就是用的你的那个PID温度控制那个,还有很多地方不怎么明白,我QQ393283319加下,希望你帮我解释下,谢谢 学习洛!! 下下来读源码…… 收下,有空研究一下! xjj123456789 发表于 2012-4-17 09:52 static/image/common/back.gif
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) *...
这一句好像是有问题的
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) * (PID->derivative - PID->derivative);
// update state更新状态
PID->last_error= error;
PID->last_derivative= PID->derivative;
后面有一个:PID->last_derivative= PID->derivative;
查找后发现整个程序中只有这一句出现了PID->last_derivative 这个变量,没意义啊。
应该是:
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) * (PID->last_derivative - PID->derivative);
或者:
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) * (PID->derivative - PID->last_derivative);
但是我对这个算法还是不理解额…… xjj123456789 发表于 2012-4-17 09:52 static/image/common/back.gif
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PID->dt)) *...
这一句好像是有问题的
wwwymq 发表于 2012-5-7 23:41 static/image/common/back.gif
这一句好像是有问题的
PID->derivative = PID->derivative +
(PID->dt / ( PID->filter + PI ...
多谢大家指正,
应该是PID->derivative = PID->derivative +(PID->dt / ( PID->filter + PID->dt)) * (PID->derivative - PID->last_derivative);
经过大家的指正,经过修改后的PID文件传上来 应该不错,收藏了。 过后在看 看不懂 顶一下,好东西。。。 看了,还不大懂
好贴,mark一个 mark{:smile:} EleHero2012 发表于 2012-5-9 10:41 static/image/common/back.gif
多谢大家指正,
应该是PID->derivative = PID->derivative +(PID->dt / ( PID->filter + PID->dt)) * ( ...
错了,应该是
PID->derivative = PID->last_derivative +(PID->dt / ( PID->filter + PID->dt)) * ( ...
可以看这里:http://en.wikipedia.org/wiki/Low-pass_filter. 位置式
不同的算法,记下先。 开样子 是不错 很不错学习了 本帖最后由 qwe2231695 于 2013-12-16 03:12 编辑
这个里面带有“不完全微分”优化技术。APM飞控里面就引用了这种方法 。为了避免微分引起的抖动。cuts out the high frequency noise that can drive the controller crazy。 谢谢分享 好不容易找到这样的贴顶一下顺便研究一下 也在学习PID控制技术, mark....... 下载,学习 感谢大神共享 正在努力学习中!! 标记,一种位置式PID的程序实现
页:
[1]