当前位置:首页 » 编程语言 » 增量式pidc语言

增量式pidc语言

发布时间: 2024-07-02 16:39:27

1. 求一下增量式和位置式PID的C语言程序

增量式PID:

typedefstruct{
floatscope;//输出限幅量
floataim;//目标输出量
floatreal_out;//实际输出量
floatKp;
floatKi;
floatKd;
floate0;//当前误差
floate1;//上一次误差
floate2;//上上次误差
}PID_Type;

#definemin(a,b)(a<b?a:b)
#definemax(a,b)(a>b?a:b)
#definelimiter(x,a,b)(min(max(x,a),b))
#defineexchange(a,b,tmp)(tmp=a,a=b,b=tmp)
#definemyabs(x)((x<0)?-x:x)

floatpid_acc(PID_Type*pid)
{
floatout;
floatep,ei,ed;

pid->e0=pid->aim-pid->real_out;
ep=pid->e0-pid->e1;
ei=pid->e0;
ed=pid->e0-2*pid->e1+pid->e2;
out=pid->Kp*ep+pid->Ki*ei+pid->Kd*ed;
out=limiter(out,-pid->scope,pid->scope);
pid->e2=pid->e1;
pid->e1=pid->e0;
returnout;
}

位置式PID:

typedefstruct{
floatscope;//输出限幅量
floataim;//目标输出量
floatreal_out;//反馈输出量
floatKp;
floatKi;
floatKd;
floatSum;
floate0;//当前误差
floate1;//上一次误差
}PID_Type;

#definemax(a,b)(a>b?a:b)
#definemin(a,b)(a<b?a:b)
#definelimiter(x,a,b)(min(max(x,a),b))

floatpid_pos(PID_Type*p)
{
floatpe,ie,de;
floatout=0;

p->e0=p->aim-p->real_out;//计算当前误差

p->Sum+=p->e0;//误差积分

de=p->e0-p->e1;//误差微分

pe=p->e0;
ie=p->Sum;

p->e1=p->e0;

out=pe*(p->Kp)+ie*(p->Ki)+de*(p->Kd);

out=limiter(out,-p->scope,p->scope);//输出限幅
returnout;
}

亲手移植到我的stm32小车上 调试3个参数后正常使用。

2. PID算法的C语言实现

基本流程

积分环节:主要是用来消除 静差 (系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累积的过程,把累积的误差加到原来系统上以抵消系统造成的静差)

微分环节:反映了偏差信号的变化规律,根据偏差信号的变化规律来进行超前调节,从而增加系统的快速性

对上述公式进行离散化(采样):两个公式

增量型PID:

通过增量型PID公式可以看出,最终表达结果和最近三次的偏差有关,最终输出结果应该为:

首先定义结构变量体:

然后初始化变量

最后编写控制算法

基本算法,没有考虑死区问题,没有设定上下限

在启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,导致控制量超过执行机构可能允许的最大动作范围对应的极限控制量,从而引起较大的超调,甚至是振荡。

为了克服这个问题,引入积分分离的概念,即当被控量和设定值偏差较大时,取消积分作用;当被控量接近设定值时,引入积分控制,以消除静差,提高精度。

abs :绝对值

令index=0使积分环节失效

积分饱和现象:如果系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置。此时计算器输出量超出正常运行范围而进入饱和区,一旦系统出现反向偏差,输出量将逐渐从饱和区退出,进入饱和区越深则退出饱和区时间越长,在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应改变,造成性能恶化。

采用梯形积分能够减小余差,提高精度

改变积分系数,若偏差大,积分作用减弱,系数减小;若偏差小,积分作用增强,系数增大。

变积分PID的基本思想是设法改变积分项的累加速度,使其与偏差大小对应。

使整个系统的稳定速度非常快

比例系数Kp的作用是加快系统的响应速度提高系统的调节精度

积分系数Ki的作用是消除系统的稳态误差

微分系数Kd的作用是改善系统的动态特性

反应系统性能的两个参数是系统误差和误差变化律

3. c璇瑷 绋嫔簭 鍊掔珛鎽 姹傚姪 pid搴旂敤

#include "stc12.h"
#include <intrins.h>
#include"pid.h"

typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long int uint32;

/*********************************鍑芥暟澹版槑******************

缁撴瀯浣撹惧畾

***********************************************************/
typedef struct PIDValue
{
uint32 Ek_Uint32[3]; //宸鍊间缭瀛桡纴缁椤畾鍜屽弽棣堢殑宸鍊
uint8 EkFlag_Uint8[3]; //宸鍊兼爣蹇椾綅绗﹀彿锛1鍒椤瑰簲镄勪负璐熸暟锛0涓哄瑰簲镄勪负姝f暟
uint8 KP_Uint8; //姣斾緥绯绘暟
uint8 KI_Uint8; //绉鍒嗙郴鏁
uint8 KD_Uint8; //寰鍒嗘樉绀
uint16 Uk_Uint16; //涓娄竴镞跺埢镄勬带鍒剁数铡
uint16 RK_Uint16; //璁惧畾鍊
uint16 CK_Uint16; //瀹为檯鍊
uint8 Vaule_Flag; //杈揿嚭镄勫兼h礋镙囧织浣嶏纴0涓烘o纴1涓鸿礋
}PIDValueStr;

PIDValueStr PID; //瀹氢箟涓涓缁扬鏋勪綋
uint16 out ; // 锷犵儹杈揿嚭(PID杩愮畻钖庣殑杈揿嚭鍊)

/***********************************************************************************
澧为噺鍨婸ID绠楀纺:PID 锛歎k=KP*[E(k)-E(k-1)]+KI*E(k)+KD*[E(k)-2E(k-1)+E(k-2)]

鍑芥暟鍏ュ彛: RK(璁惧畾鍊),CK(瀹为檯鍊),KP,KI,KD PID姣斾緥鍙傛暟
鍑芥暟鍑哄彛: U(K)
PID杩愮畻鍑芥暟
**************************************************************************************/
uint16 PID_Calc(uint16 PIDinput)
{
uint32 Temp[3]; //涓闂翠复镞跺彉閲
uint32 PostSum; //姝f暟鍜
uint32 NegSum; //璐熸暟鍜
Temp[0] = 0; //缁椤偍瀛树腑闂翠复镞跺彉閲忚祴鍒濆
Temp[1] = 0;
Temp[2] = 0;

PostSum = 0; //缁椤瓨鍌ㄦ墍链夌殑姝f暟鍙橀噺璧嫔埯鍊
NegSum = 0; //缁椤瓨鍌ㄦ墍链夌殑璐熷煎彉閲忚祴鍒濆
PID.RK_Uint16=180; //璁惧畾鍊间负180
PID.CK_Uint16=PIDinput; //杈揿叆鍊

if( PID.RK_Uint16 > PID.CK_Uint16 ) //濡傛灉璁惧畾鍊煎ぇ浜庡疄闄呭硷纴灏辨槸褰揿墠镄勫兼瘆璁惧畾鍊煎皬
{
if( PID.RK_Uint16 - PID.CK_Uint16 >10 ) //璁$畻锅忓樊鏄钖﹀ぇ浜 piancha=10 ( 杩欓噷镄10鐢 piancha 𨱒ヨ惧畾澶у皬锛屾牴鎹瀹为檯𨱍呭喌璁惧畾)
//if( PID.RK_Uint16 - PID.CK_Uint16 >piancha )
{ //濡傛灉锅忓樊澶т簬 piancha=10 涓嶅湪璁惧畾镄凯ID璋冩带锣冨洿涔嫔唴灏卞叏阃熷姞鐑
out = 100; //锅忓樊澶т簬piancha=10涓轰笂闄愬箙鍊艰緭鍑(鍏ㄩ熷姞鐑)
// PID.Uk_Uint16 = full_speed; //鍏ㄩ熸椂镄勫姞鐑鍊硷纴镟村叿瀹为檯𨱍呭喌鍙镊鐢辫惧畾 杩欓噷full_speed=100锛
}
else //濡傛灉锅忓樊灏忎簬 piancha=10 鍐嶈皟鑺傜殑锣冨洿鍐呭氨璁$畻鍌ㄥ瓨璧锋潵
{ //涓嬮溃灏辨槸PID绠楁硶

Temp[0] = PID.RK_Uint16 - PID.CK_Uint16; // 璁$畻鍑哄綋鍓嶅亸宸鍊糆(k)
PID.EkFlag_Uint8[1]=0; //E(k)涓烘f暟 镄勬爣蹇椾綅 0涓烘o纴1涓鸿礋
//鏁板肩Щ浣
PID.Ek_Uint32[2] = PID.Ek_Uint32[1]; //瀛桦偍E(k-2)
PID.Ek_Uint32[1] = PID.Ek_Uint32[0]; //鍌ㄥ瓨E(k-1)
PID.Ek_Uint32[0] = Temp[0]; //瀛桦偍E(k)
/****************************************************************************************/
if( PID.Ek_Uint32[0] >PID.Ek_Uint32[1] ) //E(k)>E(k-1) 涓烘f暟
{
Temp[0]=PID.Ek_Uint32[0] - PID.Ek_Uint32[1]; //E(k)-E(k-1) 淇濆瓨
PID.EkFlag_Uint8[0]=0; // 璁惧畾镙囧织浣 0涓烘o纴1涓鸿礋
}
else //E(k)<E(k-1)
{
Temp[0]=PID.Ek_Uint32[1] - PID.Ek_Uint32[0]; //E(k)-E(k-1)涓鸿礋鏁
PID.EkFlag_Uint8[0]=1;
}
/*****************************************************************************************/
Temp[2]=PID.Ek_Uint32[1]*2 ; // 2E(k-1)

if( (PID.Ek_Uint32[0]+ PID.Ek_Uint32[2])>Temp[2] ) //E(k-2)+E(k)>2E(k-1)
{
Temp[2]=(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2])-Temp[2]; //E(k-2)+E(k)-2E(k-1)涓烘f暟
PID.EkFlag_Uint8[2]=0;
}
else //E(k-2)+E(k)-2E(k-1)涓鸿礋鏁
{
Temp[2]=Temp[2]-(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2]); //2E(k-1)-(E(k-2)+E(k))
PID.EkFlag_Uint8[2]=1;
}
/**********************************************************************************************/
Temp[0] = (uint32)PID.KP_Uint8 * Temp[0]; // KP*[E(k)-E(k-1)]
Temp[1] = (uint32)PID.KI_Uint8 * PID.Ek_Uint32[0]; // KI*E(k)
Temp[2] = (uint32)PID.KD_Uint8 * Temp[2]; // KD*[E(k-2)+E(k)-2E(k-1)]

/************************浠ヤ笅閮ㄥ垎浠g爜鏄璁叉墍链夌殑姝f暟椤瑰彔锷狅纴璐熸暟椤瑰彔锷**************************/

/**************************************KP*[E(k)-E(k-1)]********************************************/
if(PID.EkFlag_Uint8[0]==0)
PostSum += Temp[0]; //姝f暟鍜
else
NegSum += Temp[0]; //璐熸暟鍜
/*************************************** KI*E(k)*************************************************/
if(PID.EkFlag_Uint8[1]==0)
PostSum += Temp[1]; //姝f暟鍜
else
; //绌烘搷浣滐纴E(K)>0
/************************************KD*[E(k-2)+E(k)-2E(k-1)]*************************************/
if(PID.EkFlag_Uint8[2]==0)
PostSum += Temp[2]; //姝f暟鍜
else
NegSum += Temp[2]; //璐熸暟鍜
/**********************************************U(K)*************************************************/
//PostSum += (uint32)PID.Uk_Uint16;

if(PostSum > NegSum ) // 鏄钖︽带鍒堕噺涓烘f暟
{
out= PostSum - NegSum;
PID.Vaule_Flag=0; //PID璋冭妭鍊兼槸姝e
}

else //鎺у埗閲忚緭鍑轰负璐熸暟
{
out=NegSum-PostSum;
PID.Vaule_Flag=1; //PID璋冭妭鍊兼槸璐熷
}

}
//return out;
}
else //濡傛灉璁惧畾鍊煎皬浜庡疄闄呭硷纴灏辨槸褰揿墠镄勫煎ぇ浜庤惧畾鍊,灏变笉杩涜孭ID璁$畻鐩存帴杈揿嚭 0

{
out = 0;
}

return out;

}

4. 谁能帮我用C语言编写“积分分离式PID控制器”及“微分先行式PID控制器”。

这是C语言的悄世察程序用的的积分分离,增量式算法你可以看看~在我用的片子是89C52
/*********************************************************/
/* 名称启茄: float PIDprocess1 */
/* 功能: PID adjust */
/* 说明: */
/* 调用: */
/* 输入: float xdata *Yn, float xdata *Rn */
/* 返回返兆值: deltaPn */
/*********************************************************/
float PIDprocess1()
{
int data E_0;
float data deltaPn,deltaPi,deltaPp,deltaPd,PsumCopy;

E_0=SetTemperature1-CurrentTemperature1;

if(abs(E_0)>Emax)
{
deltaPp=(float)Kp*(E_0-E_11);
deltaPd=(float)Kd*(E_0-2*E_11+E_21);
// if(deltaPd>=dPdmax) deltaPd=0;
deltaPn=deltaPp+deltaPd;
}
else
{
if(abs(E_0)>E0)
{
deltaPi=(float)Ki*E_0*(Emax-abs(E_0))/(Emax-E0);
}
else
{ //小误差时的处理
deltaPi=(float)Ki*E_0;
// if(fabs(deltaPi)<dPimin) deltaPi=0;
}
deltaPp=(float)Kp*(E_0-E_11);
deltaPd=(float)Kd*(E_0-2*E_11+E_21);
// if(deltaPd>=dPdmax) deltaPd=0;
deltaPn=deltaPp+deltaPi+deltaPd;
}

/* if(fabs(deltaPn)>dPmax)
{
if(deltaPn>0) deltaPn=dPmax;
else deltaPn=-dPmax;
} */
Psum1+=deltaPn;
PsumCopy=Psum1;

if(PsumCopy>Pmax) PsumCopy=Pmax;
if(PsumCopy<Pmin) PsumCopy=Pmin;

E_21=E_11;
E_11=E_0;

return(PsumCopy);
}
/*********************************************************/
/* 名称: float PIDprocess2 */
/* 功能: PID adjust */
/* 说明: */
/* 调用: */
/* 输入: float xdata Yn, float xdata Rn */
/* 返回值: Psum2 */
/*********************************************************/
float PIDprocess2()
{
int data E_0;
float data deltaPn,deltaPi,PsumCopy;

E_0=SetTemperature2-CurrentTemperature2;

if(abs(E_0)>Emax)
{
deltaPn=(float)Kp*(E_0-E_12)+(float)Kd*(E_0-2*E_12+E_22);
}
else
{
if(abs(E_0)>E0)
{
deltaPi=(float)Ki*E_0*(Emax-abs(E_0))/(Emax-E0);
}
else
{ //小误差时的处理
deltaPi=(float)Ki*E_0;
}
deltaPn=(float)Kp*(E_0-E_12)+deltaPi+(float)Kd*(E_0-2*E_12+E_22);
}

/* if(fabs(deltaPn)>dPmax)
{
if(deltaPn>0) deltaPn=dPmax;
else deltaPn=-dPmax;
}*/
Psum2+=deltaPn;
PsumCopy=Psum2;

if(PsumCopy>Pmax) PsumCopy=Pmax;
if(PsumCopy<Pmin) PsumCopy=Pmin;

E_22=E_12;
E_12=E_0;

return(PsumCopy);
}

5. 什么是pid算法,难学吗,用C语言,plc怎么实现

一、什么是PID:

PID即:Proportional(比例)、Integral(积分)、Differential(微分)的缩写。顾名思义,PID控制算法是结合比例、积分和微分三种环节于一体的控制算法,它是连续系统中技术最为成熟、应用最为广泛的一种控制算法,该控制算法出现于20世纪30至40年代,适用于对被控对象模型了解不清楚的场合。 ---网络

二、PID是否难学:

在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。 ---【1】

三、PID算法的C语言源码

PID 控制算法可以分为位置式 PID和增量式 PID控制算法

详细见参考【1】【2】


参考:

【1】PID算法

【2】简易PID算法的快速扫盲(超详细+过程推导+C语言程序)

热点内容
安卓手机哪个功能可以录音 发布:2024-07-04 23:04:35 浏览:980
老款安卓线和新款有什么区别 发布:2024-07-04 22:27:27 浏览:642
水密码喷雾有什么作用 发布:2024-07-04 22:04:10 浏览:707
车载导航android 发布:2024-07-04 21:47:53 浏览:305
buttonandroid圆角边框 发布:2024-07-04 21:46:23 浏览:957
东软学编程 发布:2024-07-04 21:44:08 浏览:610
怎么查看编译错误 发布:2024-07-04 21:39:05 浏览:646
c语言数组的赋值 发布:2024-07-04 21:23:47 浏览:562
d数据库英文 发布:2024-07-04 21:23:10 浏览:374
linux脚本中的 发布:2024-07-04 21:14:42 浏览:566