PID算法温控C语言.docx
/PID 算法温控 C 语言 2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID unsigned int SetPoint; /Z 设定目标 Desired Valueunsigned int Proportion; / 比例常数 Proportional Constunsigned int Integral; /Z 积分常数 Integral Constunsigned int Derivative; /Z 微分常数 Derivative Constunsigned int LastError; / Error-1unsigned int PrevError; / Error-2unsigned int SumError; / Sums of Errors);struct PID spid; / PID Control Structureunsigned int rout; / PID Response (Output)unsigned int rin; / PID Feedback (Input)sbit data1=P1 A0;sbit clk=P1 A1;sbit plus=P2A0;sbit subs=P2A1;sbit stop=P2A2;sbit output=P3A4;sbit DQ=P3A3;unsigned char flag,flag_1 =0;unsigned char high_time,low_time,count=0;占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;/*延时子程序,延时时间以12M晶振为准,延时时间为30usxtime*/void delay(unsigned char time)(unsigned char m,n;for(n=0;n<time;n+)for(m=0;m<2;m+)写位数据子程序*/ void write_bit(unsigned char bitval)(EA=0;DQ=0; /拉低DQ以开始个写时序/if(bitval=1)(_nop_();DQ=1; /如要写1,则将总线置高/)delay(5); /*延时 90us 供 DA18B20 采样/DQ=!释放DQ总线_nop_();_nop_();EA=1;/* 写一字节数据子程序*/void write_byte(unsigned char val)unsigned char i;unsigned char temp;EA=O;/关中断/TRO=O;for(i二;iv8;i+) /*写一字节数据,一次写一位/(temp:val»i; /移位操作,将本次要写的位移到最低位/temp=temp&1;write_bit(temp); /向总线写该位/)delay。);/* 延时 120us 后/ TRO=1;EA=1;/开中断/*读一位数据子程序*/unsigned char read_bit()(unsigned char i,value_bit;EA=O;DQ=O;/拉低DQ,开始读时序/_nop_();_nop_();DQ=1;/*释放总线/for(i=0;i<2;i+)value_bit=DQ;EA=1;return(value_bit);/*读字节数据子程序* /unsigned char read_byte()(unsigned char i,value=O;EA=O;for(i=0;i<8;i+)(if(read_bit()/读一字节数据,个时序中读一次,并作移位处理/value|=OxO1«i;delay(4); /延时80us以完成此次都时序,之后再读下数 据/EA=1;return(value);/*复位子程序*/ unsigned char reset()(unsigned char presence;EA=O;DQ=O; /*拉低DQ总线开始复位/delay(30); /*保持低电平 480us*/DQ=1;/*释放总线delay(3);presence=DQ; /获取应答信号/delay(28); /延时以完成整个时序EA=1;return(presence); /*返回应答信号,有芯片应答返回,无芯片则返回1*/获取温度子程序*void get_temper()(unsigned char i,j;do(i=reset(); / 复位/while(i!=0); /*!为无反馈信号/i=0xcc; /发送设备定位命令/write_byte(i);i=0x44; /发送开始转换命令/write_byte(i);delay。80);/ 延时/do(i二reset。; / 复位/while(i!=0);i=0xcc; /设备定位/write_byte(i);i=0xbe;/读出缓冲区内容/write_ byte(i);j=read_byte();i=read_byte();i=(i«4)&0x7f;s=(unsigned int)(j&OxOf);s=(s*100)/16;j=j»4;temper|j; /获取的温度放在temper中/Initialize PID Structure=二/void PIDInit (struct PID *pp) memset ( pp,0,sizeof(struct PID);)PID计算部分=二/unsigned int PIDCalc( struct PID *pp, unsigned intNextPoint)(unsigned int dError,Error;Error = pp->SetPoint - NextPoint; / 偏差pp->SumError += Error; /Z 积分dError = pp->LastError - pp->PrevError; /Z 当前微分 pp->PrevError = pp->LastError;pp->LastError = Error;return (pp->Proportion * Error比例+ pp->lntegral * pp->SumError /积分项+ pp->Derivative * dError); /Z 微分项)/* 温度比较处理子程序*/compare_temperQunsigned char i;是否设置的温度大于实if(set_temper>temper)际温度if(set_temper-temper>1)度是否是大于1度(high_time=100;low_time=0;)else运行PID计算(for(i=0;i<10;i+) get_temper();rin = s; / Read Input设置的温度比实际的温如果是,则全速加热如果是在1度范围内,则rout = PIDCalc ( &spid,rin ); / Perform PID Interation ) if (high_time<=100)high_time=(unsigned char)(rout/800);else high_time=100;Iow_time= (100-high_time);)else if(set_temper<=temper)(if(temper-set_temper>O)(high_time=O;low_time=100;)else(for(i=0;i<10;i+) get_temper();rin = s; / Read Inputrout = PIDCalc ( &spid,rin ); / Perform PID Interation)if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);)/ else/*TO中断服务子程序,用于控制电平的翻转,40us*100=4ms 周期*/void serve_T0() interrupt 1 using 1(if(+count<=(high_time)output=1;else if(count<=100)(output=0;)elsecount=0;TH0=0x2f;TL0=0xe0;*串行口中断服务程序,用于上位机通讯*void serve_sio() interrupt 4 using 2(/* EA=0;RI=0;i=SBUF;if(i=2)(while(FU=0)RI=0;set_temper=SBUF;SBUF=0x02;while(TI=0)TI=0;else if(i=3)(TI=0;SBUF=temper;while(TI=0)TI=O;)EA=1 ;*/void disp_1 (unsigned char disp_num16)(unsigned char n,a,m;for(n=0;n<6;n+)(/ k=disp_num1n;for(a=0;a<8;a+)(clk=0;m=(disp_num1 n&1);disp_num1 n=disp_num1 n»1;if(m=1)data1=1;elsedata1=0;_nop_();clk=1;_nop_();)/*显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到 的温度*/void display()(unsigned char codenumber=Oxfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6;unsigned char disp_num6;unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1=0)disp_num0=0;elsedisp_num0=0x60;k=k%100;disp_num1 =numberk/10;disp_num2=numberk%10;k=temper;k=k%100;disp_num3=numberk/10;disp_num4=numberk%10+1;disp_num5=numbers/10;disp_1 (disp_num);)/* 主程序* / main()(unsigned char z;unsigned char a,b,flag_2=1 ,count1 =0;unsigned char phil=2,0xce,0x6e,0x60,0x1c,2;TMOD=Ox21;TH0=0x2f;TL0=0x40;SCON=0x50;PCON=OxOO;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); / Initialize Structure spid.Proportion = 10; / Set PID Coefficients spid.Integral = 8;spid.Derivative =6;spid.SetPoint = 100; / Set PID Setpoint while(1)(if(plus=0)EA=0;for(a=0;a<5;a+) for(b=0;b<102;b+) if(plus=O) set_temper+;flag=O; else if(subs=O) ( for(a=0;a<5;a+) for(b=0;a<102;b+) if(subs=O) ( set_temper-;flag=O;)else if(stop=0)(for(a=0;a<5;a+)for(b=0;b<102;b+)if(stop=0) flag=O;break;EA=1;)get_temper();b=temper;if(flag_2=1) a=b;if(abs(a-b)>5) temper=a;elsetemper=b;a=temper; flag_2=0;if(+count1>30) display();count1=0;)compare_temper();)TRO=O;z=1;while(1)(EA=O;if(stop=0)(for(a=0;a<5;a+) for(b=0;b<102;b+) if(stop=0) disp_1(phil);/ break;EA=1;)/DS18b20子程序定义端口#include <REG52.H> sbit DQ=P2A1;typedef unsigned char byte;typedef unsigned int word;延时void delay(word useconds)(for(;useconds>0;useconds-);byte ow_reset(void)(byte presence;DQ=0;delay(29);DQ=1;delay(3);presence=DQ;delay(25);return(presence);个字节复位/DQ低电平/480usDQ高电平等待/presence 信号/0允许,1禁止从1-wire总线上读取byte read_byte(viod)byte i;byte value=O;for (i=8;i>0;i-)(value»=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);return(value);向1-wire总线上写个字节void write_byte(char val)(byte i;for (i=8;i>0;i-)一次写个字节DQ=O;DQ=val&OxO1;delay(5);DQ=1;val=val/2;)delay(5);读取温度)char Read_Temperature(void)(unionbyte c2;int x;temp;ow_reset();write_byte(Oxcc);write_byte(OxBE);temp.c1=read_byte();temp.cO=read_byte();ow_reset();write_byte(OxCC);write_byte(0x44);return temp.x/2;)PID算法(c语言) 2010-01-27 08:53BC31 TC30编译过,可运行。include <stdio. h> #include<math. h>struct _pid |int pv; / * integer that contains the process value*/ int sp; / * integer that contains the set point*/ float integral; /Z积分值偏差累计值float pgain;float igain;float dgain;int deadband;int last_error;);struct _pid warm, *pid;int process_point, set_point, dead_band;float p_gain, i_gain, d_gain, integral_val, new_integ;/ *pid_init DESCRIPTION This function initializes the pointers in the _pid structure to the process variable and the setpoint. *pv and *sp are integer pointers.*/void pid_init(struct _pid *warm, int process_point, int set_point)struct _pid *pid;pid = warm;pid->pv = process_point;pid->sp = set_point;)/ * pid_tune DESCRIPTION Sets the proportional gain (p_gain), integral gain (i_gain),derivitive gain (d_gain), and the dead band (dead_band) of a pid control structure _pid.设定PID参数P,LD,死区*/void pid_tune(struct _pid *pid, float p_gain, float i_gain, float d_gain, int dead_band)pid->pgain = p_gain;pid->igain = i_gain;pid->dgain = d_gain;pid->deadband = dead_band;pid->integral= integral_val;p i d->1as t_error=0;)/ * pid_setinteg DESCRIPTION Set a new value for the integral term of the pid equation.This is useful for setting the initial output of the pid controller at start up.设定输出初始值*/void pid_setinteg(struct _pid *pid, float new_integ) pid->integral = new_integ;pid->last_error = 0;)/ * pid_bumpless DESCRIPTION Bumpless transfer algorithim.When suddenly changing setpoints, or when restarting the PID equation after an extended pause, the derivative of the equation can cause a bump in the controller output. This function will help smooth out that bump.The process value in *pv should be the updated just before this function is used.pid_bumpless实现无扰切换当突然改变设定值时,或重新启动后,将引起扰动输出。这 个函数将能实现平顺扰动,在调用该函数之前需要先更新PV 值*/void pid_bumpless(struct _pid *pid)pid->last_error = (pid->sp)-(pid->pv);)/ * pid_calc DESCRIPTION Performs PID calculations for the _pid structure *a.This function uses the positional form of the pid equation, and incorporates an integral windup prevention algorithim.Rectangular integration is used, so this function must be repeated on a consistent time basis for accurate control.RETURN VALUE The new output value for the pid loop.USAGE include "control, h"*/float pid_calc(struct _pid *pid) int err;float pterm, dterm, result, ferror;/Z计算偏差err = (pid->sp) - (pid->pv);/判断是否大于死区if (abs(err) > pid->deadband)ferror = (float) err; / *do integer to float conversion only once*/Z比例项pterm = pid->pgain * ferror;if (pterm > 100 | pterm < -100)pid->integral = 0. 0;)else/Z积分项pid->integral += pid->igain * ferror;/Z输出为一一100%/如果计算结果大于100,则等于!00if (pid->integral > 100. 0)pid->integral = 100.0;/如果计算结果小于0.0,则等于 else if (pid->integral < 0. 0)pid->integral = 0. 0;)/Z微分项dterm = (float)(err - pid->last_error) * pid->dgain;result = pterm + pid->integral + dterm;)elseresult = pid->integral; /在死区范围内,保持现有输 出/Z保存上次偏差pid->last_error = err;/Z 输出 PID 值(0-100) return (result);)void main(void) float display_value;int count=0;pid = &warm;/ printf ('Enter the values of Process point, Set point, P gain, I gain, D gain n");/ scanf("%d%d%f%f%f”, &process_point, &set_point, &p_gain, &i_gain, &d_gain);/初始化参数process_point = 30;set_point = 40;p_gain = (float)(5. 2);i_gain = (float)(0. 77);d_gain = (float)(0. 18);dead_band = 2;integral_val =(float)(0. 01);printf ("The values of Process point, Set point, P gain, I gain, D gain n");printf(" %6d %6d %4f %4f %4fn", process_point, set_point, p_gain, i_gain, d_gain);printfi Enter the values of Process pointn"); while (count<=20)scanf a”, &process_point);/Z设定PV, SP值pid_init(fewarm, process_point, set_point);/初始化PID参数值pid_tune(&warm, p_gain, i_gain, d_gain, dead_band);/初始化PID输出值pid_setinteg (&warm, 0. 0);/pid_setinteg(&warm, 30. 0);/Get input value for process point pid_bumpless(fewarm);/ how to display outputdisplay_value = pid_calc(&warm);printf("%fn", display_value);/printfwarm, pv, warm, sp, warm, igain, wa rm. dgain);count+;数字PID控制算法2009-12-31 20:02首先,将连续的系统离散化。计算机控制是种采样控制,它只能根据采样时刻的偏 差值计算控制量,因此,连续PID控制算法不能直接使用, 需要采用离散化的方法。在计算机PID控制中,使用的是数 字PID控制器。采样周期T为1ms,采用Z变换对G(S)进行离散化,离 散化后的被控对象为:Transfer function:. 06684 z-2 - 0.1322 z + 0.06538z-3 - 2. 222 z'2 + 1.445 z - 0. 2229可得系统的差分方程:y(k)=-den(2)*y_l-den(3)*y_2-den(4)*y_3+num(2)*u_l+num(3)*u_2+num(4)*u_3;num =00.0668-0. 13220. 0654den =1.0000-2.22191.4448-0.2229在输入信号为单位阶跃信号时,运行附录2的数字P1D 程序,可得系统的响应如下:单位阶跃响应曲线0.40.200.10.20.30.40.50.60.70.80.918 6 0.0InoAcu ,、在 PID 参数:kp=10;ki=3000;kd=0; 调节时间 0. 15s<0. 2s;无稳态误差,超调量4%>2%。其中超调量过大 不满足系统的设计要求。利用Mat lab /Simulink软件,构建了电机控制系统的速 度仿真模型。通过仿真结果可以看出系统能平稳运行,具有 较好的静、动态特性。在此仿真模型基础上,可以十分便捷 地实现进行参数选择、调整及仿真。因此,可以从整体角度 出发对伺服系统整体参数的优化和调整进行研究。也为实际 伺服系统的设计和调试提供了新的思路数字PID程序%PID Controllerclear all;close all;ts=0. 001;sys=tf(127.4 2817 11930, 1 1501 2021 11730);dsys=c2d (sys, ts,' z'); %连续离散化 num, den=tfdata(dsys,' v');u_l=0. 0;u_2=0. 0;u_3=0. 0;y_l=0. 0;y_2=0. 0;y_3=0. 0;x=0, 0, 0'error_l=0;for k=l:1:1000 time(k)=k*ts;kp=10;ki=3000;kd=O;rin(k)=l;%Step Signalu(k)=kp*x(1)+kd*x(2)+ki*x(3);%PID Controller%Restricting the output of controller if u(k) >=10u(k)=10;endif u(k) <=-10 u(k) =-10;end%Linear modelyout(k)=-den(2)*y_l-den(3)*y_2-den(4)*y_3+num(2 )*u_l+num(3)*u_2+num(4)*u_3;error (k)=rin(k)-yout(k);%Return of parameters u 3=u 2;u 2=u 1;u l=u(k); y_3=y_2; y_2=y!y_l=yout (k); x(l)=error (k);%Calculating Px(2)=(error(k)-error_l)/ts;%Calculating Dx(3)=x(3)+error(k)*ts;%Calculating Ierror_l=error(k); end figure (1);plot (time, rin,' b', time, yout,' r');xlabel C time (s)'), ylabel (' rin, yout'); titleC单位阶跃响应曲线) grid minor比较典型的PID算法控制程序源代码2009-08-19 10:07比较典型的PID处理程序日期:2005-2-1来源:21ICbbs 作者:lookuper 字体:大中小1 * -一这是个比较典型的PID处理程序,在使用单片机作为控制 cpu时,请稍作简化,具体的PID参数必须由具体对象通过 实验确定。由于单片机的处理速度和ram资源的限制,一般 不采用浮点数运算,而将所有参数全部用整数,运算到最后再除以个2的N次方数据(相当于移位),作类似 定点数运算,可大大提高运算速度,根据控制精度的不同要 求,当精度要求很高时,注意保留移位引起的“余数”,做 好余数补偿。这个程序只是一般常用Pid算法的基本架构, 没有包含输入输出处理部分。ftinclude include/*PID FunctionThe PID (比例、积分、微分)function is used in mainly control applications. PIDCalc perfo