研发埠
标题:
怎样用C程序能实现PID倒立摆系统?
[打印本页]
作者:
徐依淼
时间:
2014-2-24 13:55
标题:
怎样用C程序能实现PID倒立摆系统?
作者:
杨鹏飞
时间:
2014-2-24 13:59
#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为对应的为正数 uint8 KP_Uint8; //比例系数uint8 KI_Uint8; //积分系数uint8 KD_Uint8; //微分显示uint16 Uk_Uint16; //上一时刻的控制电压 uint16 RK_Uint16; //设定值 uint16 CK_Uint16; //实际值 uint8 Vaule_Flag; //输出的值正负标志位,0为正,1为负}PIDValueStr; PIDValueStr PID; //定义一个结P构体uint16 out ; // 加热输出(PID运算后的输出值) /*********************************************************************************** 增量型PID算式
ID :Uk=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; //正数和 uint32 NegSum; //负数和 Temp[0] = 0; //给储存中间临时变量赋初值 Temp[1] = 0; Temp[2] = 0; PostSum = 0; //给存储所有的正数变量赋初值 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 不在设定的PID调控范围之内就全速加热 out = 100; //偏差大于piancha=10为上限幅值输出(全速加热) // PID.Uk_Uint16 = full_speed; //全速时的加热值,更具实际情况可自由设定 这里full_speed=100; } else //如果偏差小于 piancha=10 再调节的范围内就计算储存起来 { //下面就是PID算法 Temp[0] = PID.RK_Uint16 - PID.CK_Uint16; // 计算出当前偏差值E(k) PID.EkFlag_Uint8[1]=0; //E(k)为正数 的标志位 0为正,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] >
ID.Ek_Uint32[1] ) //E(k)>E(k-1) 为正数 { Temp[0]=PID.Ek_Uint32[0] - PID.Ek_Uint32[1]; //E(k)-E(k-1) 保存 PID.EkFlag_Uint8[0]=0; // 设定标志位 0为正,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)为正数 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)] /************************以下部分代码是讲所有的正数项叠加,负数项叠加**************************/ /**************************************KP*[E(k)-E(k-1)]********************************************/ if(PID.EkFlag_Uint8[0]==0) PostSum += Temp[0]; //正数和 else NegSum += Temp[0]; //负数和 /*************************************** KI*E(k)*************************************************/ if(PID.EkFlag_Uint8[1]==0) PostSum += Temp[1]; //正数和 else ; //空操作,E(K)>0 /************************************KD*[E(k-2)+E(k)-2E(k-1)]*************************************/ if(PID.EkFlag_Uint8[2]==0) PostSum += Temp[2]; //正数和 else NegSum += Temp[2]; //负数和 /**********************************************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;}
欢迎光临 研发埠 (http://bbs.yanfabu.com/)
Powered by Discuz! X3.2