怎样用C程序能实现PID倒立摆系统?
#include "stc12.h" #include <intrins.h>#include"pid.h" typedefunsignedcharuint8; typedefunsignedintuint16; typedefunsignedlong intuint32; /*********************************函数声明****************** 结构体设定***********************************************************/ typedef struct PIDValue { uint32Ek_Uint32;//差值保存,给定和反馈的差值 uint8EkFlag_Uint8;//差值标志位符号,1则对应的为负数,0为对应的为正数 uint8KP_Uint8;//比例系数uint8KI_Uint8;//积分系数uint8KD_Uint8;//微分显示uint16Uk_Uint16;//上一时刻的控制电压 uint16RK_Uint16;//设定值 uint16CK_Uint16;//实际值uint8Vaule_Flag;//输出的值正负标志位,0为正,1为负}PIDValueStr; PIDValueStrPID;//定义一个结P构体uint16out ;// 加热输出(PID运算后的输出值)/*********************************************************************************** 增量型PID算式:PID :Uk=KP*+KI*E(k)+KD*函数入口: RK(设定值),CK(实际值),KP,KI,KDPID比例参数函数出口: U(K) PID运算函数 **************************************************************************************/ uint16 PID_Calc(uint16 PIDinput) { uint32Temp;//中间临时变量 uint32PostSum;//正数和 uint32NegSum;//负数和 Temp = 0;//给储存中间临时变量赋初值Temp = 0; Temp = 0; PostSum = 0;//给存储所有的正数变量赋初值NegSum= 0;//给存储所有的负值变量赋初值PID.RK_Uint16=180;//设定值为180PID.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 不在设定的PID调控范围之内就全速加热out = 100;//偏差大于piancha=10为上限幅值输出(全速加热) // PID.Uk_Uint16 = full_speed;//全速时的加热值,更具实际情况可自由设定 这里full_speed=100; } else//如果偏差小于 piancha=10 再调节的范围内就计算储存起来{//下面就是PID算法 Temp = PID.RK_Uint16 - PID.CK_Uint16;// 计算出当前偏差值E(k) PID.EkFlag_Uint8=0;//E(k)为正数 的标志位 0为正,1为负//数值移位 PID.Ek_Uint32 = PID.Ek_Uint32;//存储E(k-2)PID.Ek_Uint32 = PID.Ek_Uint32;//储存E(k-1)PID.Ek_Uint32 = Temp;//存储E(k)/****************************************************************************************/ if( PID.Ek_Uint32 >PID.Ek_Uint32 )//E(k)>E(k-1) 为正数{ Temp=PID.Ek_Uint32 - PID.Ek_Uint32;//E(k)-E(k-1) 保存PID.EkFlag_Uint8=0;// 设定标志位 0为正,1为负} else//E(k)<E(k-1) { Temp=PID.Ek_Uint32 - PID.Ek_Uint32;//E(k)-E(k-1)为负数 PID.EkFlag_Uint8=1; } /*****************************************************************************************/ Temp=PID.Ek_Uint32*2 ;// 2E(k-1) if( (PID.Ek_Uint32+ PID.Ek_Uint32)>Temp )//E(k-2)+E(k)>2E(k-1) { Temp=(PID.Ek_Uint32+ PID.Ek_Uint32)-Temp;//E(k-2)+E(k)-2E(k-1)为正数 PID.EkFlag_Uint8=0; } else//E(k-2)+E(k)-2E(k-1)为负数 { Temp=Temp-(PID.Ek_Uint32+ PID.Ek_Uint32);//2E(k-1)-(E(k-2)+E(k))PID.EkFlag_Uint8=1; } /**********************************************************************************************/ Temp = (uint32)PID.KP_Uint8 * Temp;// KP* Temp = (uint32)PID.KI_Uint8 * PID.Ek_Uint32;// KI*E(k) Temp = (uint32)PID.KD_Uint8 * Temp;// KD* /************************以下部分代码是讲所有的正数项叠加,负数项叠加**************************/ /**************************************KP*********************************************/ if(PID.EkFlag_Uint8==0) PostSum += Temp;//正数和 else NegSum += Temp;//负数和 /*************************************** KI*E(k)*************************************************/ if(PID.EkFlag_Uint8==0) PostSum += Temp;//正数和 else ;//空操作,E(K)>0 /************************************KD**************************************/ if(PID.EkFlag_Uint8==0) PostSum += Temp;//正数和 else NegSum += Temp;//负数和 /**********************************************U(K)*************************************************/ //PostSum += (uint32)PID.Uk_Uint16; if(PostSum > NegSum )// 是否控制量为正数 { out= PostSum - NegSum;PID.Vaule_Flag=0;//PID调节值是正值} else//控制量输出为负数 {out=NegSum-PostSum; PID.Vaule_Flag=1;//PID调节值是负值} }//return out; }else//如果设定值小于实际值,就是当前的值大于设定值,就不进行PID计算直接输出 0 { out = 0;} return out;}
页:
[1]