51单片机PID算法程序(一)PID算法

合集下载

温度控制的PID算法的C语言程序

温度控制的PID算法的C语言程序

基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。

用keil C语言来实现PID的控制。

//PID算法温控C语言2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标Desired Valueunsigned int Proportion; // 比例常数Proportional Constunsigned int Integral; // 积分常数Integral Constunsigned int Derivative; // 微分常数Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned 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^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;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晶振为准,延时时间为30us×time***********************************************************/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=1; /*释放DQ总线*/_nop_();_nop_();EA=1;}/*********************************************************** 写一字节数据子程序***********************************************************/ void write_byte(unsigned char val){unsigned char i;unsigned char temp;EA=0; /*关中断*/TR0=0;for(i=0;i<8;i++) /*写一字节数据,一次写一位*/{temp=val>>i; /*移位操作,将本次要写的位移到最低位*/temp=temp&1;write_bit(temp); /*向总线写该位*/}delay(7); /*延时120us后*/// TR0=1;EA=1; /*开中断*/}/*********************************************************** 读一位数据子程序***********************************************************/ unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0; /*拉低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=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<<i;delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/*********************************************************** 复位子程序***********************************************************/ unsigned char reset(){unsigned char presence;EA=0;DQ=0; /*拉低DQ总线开始复位*/delay(30); /*保持低电平480us*/DQ=1; /*释放总线*/delay(3);presence=DQ; /*获取应答信号*/delay(28); /*延时以完成整个时序*/EA=1;return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/}/***********************************************************获取温度子程序***********************************************************/void get_temper(){unsigned char i,j;do{i=reset(); /*复位*/}while(i!=0); /*1为无反馈信号*/i=0xcc; /*发送设备定位命令*/write_byte(i);i=0x44; /*发送开始转换命令*/write_byte(i);delay(180); /*延时*/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&0x0f);s=(s*100)/16;j=j>>4;temper=i|j; /*获取的温度放在temper中*/}/*============================================================================= =======================Initialize PID Structure=============================================================================== ======================*/void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID));}/*============================================================================= =======================PID计算部分=============================================================================== ======================*/unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,Error;Error = pp->SetPoint - NextPoint; // 偏差pp->SumError += Error; // 积分dError = pp->LastError - pp->PrevError; // 当前微分pp->PrevError = pp->LastError;pp->LastError = Error;return (pp->Proportion * Error//比例+ pp->Integral * pp->SumError //积分项+ pp->Derivative * dError); // 微分项}/***********************************************************温度比较处理子程序***********************************************************/pare_temper(){unsigned char i;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}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/800);elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;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// {}}/***************************************************** T0中断服务子程序,用于控制电平的翻转,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;}/***************************************************** 串行口中断服务程序,用于上位机通讯******************************************************/ void serve_sio() interrupt 4 using 2{/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==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=0;}EA=1; */}void disp_1(unsigned char disp_num1[6]){unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];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;else_nop_();clk=1;_nop_();}}}/*****************************************************显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/void display(){unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/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=0x21;TL0=0x40;SCON=0x50;PCON=0x00;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==0){set_temper++;flag=0;}}else if(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}else if(stop==0) {for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0){flag=0;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;}pare_temper();}TR0=0;z=1;while(1){EA=0;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=P2^1; //定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ=0; //DQ低电平delay(29); //480usDQ=1; //DQ高电平delay(3); //等待presence=DQ; //presence信号delay(25);return(presence);} //0允许,1禁止//从1-wire 总线上读取一个字节byte read_byte(viod){byte i;byte value=0;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=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);return temp.x/2;}参考资料:你把这两个程序组合就可以了PID算法PID算法是本程序中的核心部分。

单片机pid公式

单片机pid公式

单片机中的PID公式
在自动化控制领域,PID(比例-积分-微分)控制器是一种广泛使用的控制算法。

单片机,作为一种集成度高、功能丰富的微控制器,在很多自动化设备中发挥着核心控制作用。

将PID算法应用到单片机中,可以实现精确、快速的控制,提高设备的性能和稳定性。

PID控制器的核心公式如下:
误差= 设定值- 实际值
比例项= Kp * 误差
积分项= Ki * 误差的积分
微分项= Kd * 误差的微分
输出= 比例项+ 积分项+ 微分项
其中,Kp、Ki和Kd是比例、积分和微分系数,需要根据具体的控制系统进行调整,以获得最佳的控制效果。

在单片机中实现PID算法,需要编写相应的程序。

一般来说,程序会包括以下几个部分:
1.初始化部分:设置PID控制器的参数,如设定值、比例系数、积分系数和
微分系数。

2.输入部分:读取实际值,与设定值进行比较,计算误差。

3.计算部分:根据误差计算比例项、积分项和微分项,得出输出值。

4.输出部分:将输出值转换为控制信号,控制执行机构。

在实际应用中,单片机中的PID算法还需要考虑一些其他因素,如抗干扰能力、系统稳定性等。

此外,为了方便调整和控制,许多单片机还提供了PID库函数或相关模块,可以直接调用。

总之,将PID算法应用到单片机中,可以实现精确、快速的控制,提高设备的性能和稳定性。

通过合理设置参数和优化程序,可以充分发挥单片机和PID算法的优势,推动自动化设备的发展和应用。

pid算法的原理和算法

pid算法的原理和算法

pid算法的原理和算法一、pid算法简介PID(Proportional-Integral-Derivative,比例-积分-微分)算法是一种广泛应用于工业控制领域的调节算法。

它通过计算系统误差与期望值的比值(比例控制)、误差积分和误差变化率(微分控制)来调节控制器的输出,从而使被控对象达到期望状态。

二、pid算法原理1.比例(P)控制:比例控制是根据系统误差与期望值的比值来调节控制器输出。

当误差较大时,比例控制输出较大,有利于快速消除误差;当误差较小时,比例控制输出较小,有利于提高系统的稳定性。

2.积分(I)控制:积分控制是根据系统误差的积分来调节控制器输出。

当误差持续存在时,积分控制输出逐渐增大,有助于消除误差。

但过大的积分控制会导致系统响应过慢,甚至产生振荡。

3.微分(D)控制:微分控制是根据系统误差的变化速度来调节控制器输出。

它能预测系统的变化趋势,从而减小超调量和调整时间,提高系统稳定性。

三、pid算法应用1.控制器设计:PID算法可以用于设计各类控制器,如PID控制器、模糊PID控制器、自适应PID控制器等。

2.参数调节:PID算法的三个参数(Kp、Ki、Kd)需要根据被控对象的特性进行调节。

合理的参数设置可以使系统在稳定性和响应速度之间达到平衡。

四、pid算法优化与改进1.抗积分饱和:当系统误差持续存在时,积分控制输出可能超过控制器最大输出,导致积分饱和。

通过引入抗积分饱和算法,可以限制积分控制的输出,提高系统稳定性。

2.抗积分粘滞:为避免积分控制输出在零附近震荡,可以采用抗积分粘滞算法,使积分控制输出在零附近呈现出非线性特性。

3.抗积分震荡:在积分控制中引入微分项,可以减小积分震荡,提高系统稳定性。

五、pid算法在实际工程中的应用案例PID算法在我国工业控制领域得到了广泛应用,如电力系统、温度控制系统、流量控制系统等。

通过合理设计PID控制器及其参数,可以实现对被控对象的稳定控制。

51单片机PID算法程序(一)PID算法

51单片机PID算法程序(一)PID算法

式中或式中控制系统中的应用在单回路控制系统中,由于扰动作用使被控参数偏离给定值,从而产生偏差。

自动控制系统的调节单元将来自变送器的测量值与给定值相比较后产生的偏差进行比例、积分、微分(PID)运算,并输出统一标准信号,去控制执行机构的动作,以实现对温度、压力、流量、也为及其他工艺参数的自动控制。

比例作用P只与偏差成正比;积分作用I是偏差对时间的积累;微分作用D是偏差的变化率;比例(P)控制比例控制能迅速反应误差,从而减少稳态误差。

除了系统控制输入为0和系统过程值等于期望值这两种情况,比例控制都能给出稳态误差。

当期望值有一个变化时,系统过程值将产生一个稳态误差。

但是,比例控制不能消除稳态误差。

比例放大系数的加大,会引起系统的不稳定。

图2比例(P)控制阶跃响应积分(I)控制在积分控制中,控制器的输出与输入误差信号的积分成正比关系。

为了减小稳态误差,在控制器中加入积分项,积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。

这样,即使误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减少,直到等于零。

积分(I)和比例(P)通常一起使用,称为比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。

如果单独用积分(I)的话,由于积分输出随时间积累而逐渐增大,故调节动作缓慢,这样会造成调节不及时,使系统稳定裕度下降。

图3积分(I)控制和比例积分(PI)控制阶跃相应微分(D)控制在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。

由于自动控制系统有较大的惯性组件(环节)或有滞后(delay)组件,在调节过程中可能出现过冲甚至振荡。

解决办法是引入微分(D)控制,即在误差很大的时候,抑制误差的作用也很大;在误差接近零时,抑制误差的作用也应该是零。

图4微分(D)控制和比例微分(PD)控制阶跃相应总结:PI比P少了稳态误差,PID比PI反应速度更快并且没有了过冲。

单片机PID算法实现

单片机PID算法实现

单片机PID算法实现在网络上收集了一个PID控制程序,看到很多研友的毕业设计可能涉及到PID控制,这是一个PID的程序,希望能做到抛砖引玉,仅供大家参考。

/*/////////////////////////////////////////////////////////////*//* initial interrupter *//*/////////////////////////////////////////////////////////////*/void init_interrupter(void) /**/{TMOD=0x21; /* 设置计时器0工作于模式1,设置计时器1工作于模式2*/TL0=0x00; /* T0=0000定时时间为71.1ms;71.1ms*15=1.066s*/TH0=0xdc; /*T0=DC00定时时间为10ms;10ms*100=1s*/ /*T0=FC66定时时间为1m s;10ms*1000=1s*/TL1=0xfd; /* 设置串口通信速率9600bps*/TH1=0xfd;PCON=0x00; /* SMOD=0, 速率不倍增*/SCON=0x50; /* 8位数据通信,串行通信方式1,允许单片机接收数据*/IP=0x10; /*serial com is preferential*/IE=0x92; /* 定时器0, 串口中断允许;定时器1中断禁止*/rs485_receive=0;rs485_transmitte=0;TR0=1; /* 启动定时器0*/TR1=1; /* 启动定时器1*/}void tim er0_server(void) interrupt 1 using 1 /**/{TL0=0x00; TH0=0xdc;/*T0=DC00 timing interval is 10ms;10ms*100=1s*//*T0=FC66 timing interval is 1ms;10ms*1000=1s*/if (flag_serial==1){tim er0_counter_3++;if (tim er0_counter_3>11){tim er0_counter_3=0;flag_serial=0;pointer_serial_com_data=serial_com_data;counter_serial_com_data=0;}}dog=!dog;/*Tim er0 is full(10ms), feed dog*/if (timing_interval==0) {timing_interval=1;} /*tim ing_interval is lost then set it to 1 second*/tim er0_counter_1++;/*tim er0_counter_1 is software tim er. when timer0 interrupt is full, it increase autom atically*/if ((unsigned char) (tim er0_counter_1/100)==timing_interval) /*tim ing_interval arrives*/{out_flag=1;/*indexing 占空比high level begin*//*-scan 0809 to get current equipment's tem perature-*/scan_current_Tem perature();origina_address=0x82;display1_Temperature(current_Tem perature,origina_address);/*-calculate out_value-*/PID_algorithm_function(PID_mode,PP,II,DD,BB,current_Tem perature,seted_t em perature);//out_value=0.5;if (out_value>0.0) /*out_value=0.0, then 占空比is zero*/{control_0=1;ledctrl_address=0x8c;leddata_address=0xff;}//reset tim er0_counter_1 and timer0_counter_2,tim er0_counter_1=0; //indexing timing_interval's timingtim er0_counter_2=0; //indexing 占空比's timing}if(out_flag==1){tim er0_counter_2++;if (out_value<1.0){if( (unsigned char) (timer0_counter_2/out_value/100) >= timing_interval){tim er0_counter_2=0;control_0=0;ledctrl_address=0x8c;leddata_address=0x00;out_flag=0;}}}}float PID_algorithm_function(uchar PID_mode_2,floatP_2,I_2,D_2,B_2,current_Temperature_2,seted_tem perature_2){float idata delta;switch (PID_mode_2){case 1: break;/*PID mode*/case 2: D_2=0; break;/*PI m ode*/case 3: I_2=0; break;/*PD m ode*/case 4: I_2=0; D_2=0; break;/*P m ode*/}if (PID_mode_2<5)/*PID algorithm*/ek=(seted_tem perature_2-current_Tem perature_2)/99.9;delta=P_2*(ek-ek1)+I_2*ek+D_2*(ek-2.0*ek1+ek2);out_value=out_value+de lta;ek2=ek1;ek1=ek;if (out_value>1.0){out_value=1;}else if (out_value<=0){out_value=0.0;}if (PID_mode_2==5) /*BB algorithm*/{if (current_Tem perature_2-seted_temperature_2>=B_2) {out_value=0.0;} if (seted_tem perature_2-current_Temperature_2>=B_2) {out_value=1.0;} }return (out_value);}软件练习十二:将十六进制数据转换成十进制数据熟悉51 单片机指令系统,掌握程序设计方法。

基于单片机的pid控制程序

基于单片机的pid控制程序

Jesse Rei 的51 温度PID经典算法#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标Desired Valueunsigned int Proportion; // 比例常数Proportional Constunsigned int Integral; // 积分常数Integral Constunsigned int Derivative; // 微分常数Derivative Constunsigned int LastError; // Error[-1] unsigned int PrevError; // Error[-2] unsigned int SumError; // Sums of Errors };struct PID spid; // PID Control Structure unsigned int rout; // PID Response (Output) unsigned int rin; // PID Feedback (Input)sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;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;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;if(bitval==1){_nop_();DQ=1;}delay(5);DQ=1;_nop_();_nop_();EA=1;}void write_byte(unsigned char val) {unsigned char i;unsigned char temp;EA=0;TR0=0;for(i=0;i<8;i++){temp=val>>i;temp=temp&1;write_bit(temp);}delay(7);// TR0=1;EA=1;}unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0;_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=0; EA=0;for(i=0;i<8;i++){if(read_bit())value|=0x01<<i;delay(4);}EA=1;return(value);}unsigned char reset() {unsigned char presence; EA=0;DQ=0;delay(30);DQ=1;delay(3);presence=DQ;delay(28);EA=1;return(presence);}void get_temper(){unsigned char i,j;do{i=reset();} while(i!=0);i=0xcc;write_byte(i);i=0x44;write_byte(i);delay(180);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&0x0f); //得到小数部分s=(s*100)/16;j=j>>4;temper=i|j;}void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID)); //全部初始化为0}unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,Error;Error = pp->SetPoint - NextPoint; // 偏差pp->SumError += Error; // 积分dError = pp->LastError - pp->PrevError; // 当前微分pp->PrevError = pp->LastError;pp->LastError = Error;return (pp->Proportion * Error // 比例项+ pp->Integral * pp->SumError // 积分项+ pp->Derivative * dError); // 微分项}void compare_temper(){unsigned char i;if(set_temper>temper) //是否设置的温度大于实际温度{if(set_temper-temper>1) //设置的温度比实际的温度是否是大于1度{high_time=100; //如果是,则全速加热low_time=0;}else //如果是在1度范围内,则运行PID计算{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/800);elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;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=(unsignedchar)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {}}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{}void disp_1(unsigned char disp_num1[6]) {unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];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 code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0 xbe,0xe0,0xfe,0xf6};unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}void main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0; unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TH0=0x2f;TL0=0x40;SCON=0x50; PCON=0x00;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 比例常数Proportional Constspid.Integral = 8; //积分常数Integral Constspid.Derivative =6; //微分常数Derivative Constspid.SetPoint = 100; // Set PID Setpoint 设定目标Desired Valuewhile(1){if(plus==0){EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){}if(plus==0){set_temper++;flag=0;}}else if(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}else if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){}if(stop==0){flag=0;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();}TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){}if(stop==0)disp_1(phil);// break;}EA=1;}}。

51单片机延时函数

51单片机延时函数

51单片机延时函数在嵌入式系统开发中,51单片机因其易于学习和使用、成本低廉等优点被广泛使用。

在51单片机的程序设计中,延时函数是一个常见的需求。

通过延时函数,我们可以控制程序的执行速度,实现定时器功能,或者在需要的时候进行延时操作。

本文将介绍51单片机中常见的延时函数及其实现方法。

一、使用for循环延时这种方法不精确,但是对于要求不高的场合,可以用来估算延时。

cvoid delay(unsigned int time){unsigned int i,j;for(i=0;i<time;i++)for(j=0;j<1275;j++);}这个延时函数的原理是:在第一个for循环中,我们循环了指定的时间次数(time次),然后在每一次循环中,我们又循环了1275次。

这样,整个函数的执行时间就是time乘以1275,大致上形成了一个延时效果。

但是需要注意的是,这种方法因为硬件和编译器的不同,延时时间会有很大差异,所以只适用于对延时时间要求不精确的场合。

二、使用while循环延时这种方法比使用for循环延时更精确一些,但是同样因为硬件和编译器的不同,延时时间会有差异。

cvoid delay(unsigned int time){unsigned int i;while(time--)for(i=0;i<1275;i++);}这个延时函数的原理是:我们先进入一个while循环,在这个循环中,我们循环指定的时间次数(time次)。

然后在每一次循环中,我们又循环了1275次。

这样,整个函数的执行时间就是time乘以1275,大致上形成了一个延时效果。

但是需要注意的是,这种方法因为硬件和编译器的不同,延时时间会有差异,所以只适用于对延时时间要求不精确的场合。

三、使用定时器0实现精确延时这种方法需要在单片机中开启定时器0,并设置定时器中断。

在中断服务程序中,我们进行相应的操作来实现精确的延时。

这种方法需要使用到单片机的定时器中断功能,相对复杂一些,但是可以实现精确的延时。

单片机PID算法程序精编版

单片机PID算法程序精编版

单片机P I D算法程序公司内部编号:(GOOD-TMMT-MMUT-UUPTY-UUYY-DTTI-51单片机P I D算法程序(二)位置式P I D控制算法由51单片机组成的数字控制系统控制中,PID控制器是通过PID控制算法实现的。

51单片机通过AD对信号进行采集,变成数字信号,再在单片机中通过算法实现PID运算,再通过DA把控制量反馈回控制源。

从而实现对系统的伺服控制。

位置式PID控制算法位置式PID控制算法的简化示意图上图的传递函数为:(2-1)在时域的传递函数表达式(2-2)对上式中的微分和积分进行近似(2-3)式中n是离散点的个数。

于是传递函数可以简化为:(2-4)其中u(n)——第k个采样时刻的控制;KP——比例放大系数;Ki——积分放大系数;Kd——微分放大系数;T ——采样周期。

如果采样周期足够小,则(2-4)的近似计算可以获得足够精确的结果,离散控制过程与连续过程十分接近。

(2-4)表示的控制算法直接按(2-1)所给出的PID控制规律定义进行计算的,所以它给出了全部控制量的大小,因此被称为全量式或位置式PID控制算法。

缺点:1)由于全量输出,所以每次输出均与过去状态有关,计算时要对e(k)(k=0,1,…n)进行累加,工作量大。

2)因为计算机输出的u(n)对应的是执行机构的实际位置,如果计算机出现故障,输出u(n)将大幅度变化,会引起执行机构的大幅度变化,有可能因此造成严重的生产事故,这在实际生产中是不允许的。

位置式PID控制算法C51程序具体的PID参数必须由具体对象通过实验确定。

由于单片机的处理速度和ram资源的限制,一般不采用浮点数运算,而将所有参数全部用整数,运算到最后再除以一个2的N次方数据(相当于移位),作类似定点数运算,可大大提高运算速度,根据控制精度的不同要求,当精度要求很高时,注意保留移位引起的“余数”,做好余数补偿。

这个程序只是一般常用pid算法的基本架构,没有包含输入输出处理部分。

PID控制的51汇编程序

PID控制的51汇编程序

PID 控制的51汇编程序PID 控制的51汇编程序;//************************************************************ **************************************************;//功能: 电机控制的PID(积分分离) PID(void) 执行时间少于70uS/932-12MHz;//设计者: 牟联树;//日期: 2003.12.28;//版本号: 1.0;//申明:;//**************************************************************** **********************************************$NOMOD51OCRAH equ 0EFhOCRAL equ 0EEhOCRBH equ 0FBhOCRBL equ 0FAhOCRCH equ 0FDhOCRCL equ 0FChOCRDH equ 0FFhOCRDL equ 0FEhTCR21 equ 0f9h$include (REG52.INC)NAME PIDWorkPR?PID?PIDWork SEGMENT CODEPR?PID_MUL?PIDWork SEGMENT CODEPR?PID_out?PIDWork SEGMENT CODEDT?PID_k?PIDWork SEGMENT DATA PUBLICPID_Kp,PID_Ki,PID_Kd,PID_Umax,PID_Emax PUBLICPID_U,PID_En1,PID_En2,PID_Temp,PID_TempL RSEG ?DT?PID_k?PIDWork PID_Kp: DS 2 ;比例系数PID_KpL data PID_Kp+1PID_Ki: DS 2 ;积分系数PID_KiL data PID_Ki+1PID_Kd: DS 2 ;微分系数PID_KdL data PID_Kd+1PID_Umax: DS 2 ;期望最大值设定PID_UmaxL data PID_Umax+1PID_Emax: DS 2 ;积分分离的误差最大值设定PID_EmaxL data PID_Emax+1PID_U: DS 2 ;当前的采样值PID_UL data PID_U+1PID_En1: DS 2 ;上一次计算的误差值PID_En1L data PID_En1+1PID_En2: DS 2 ;上一次计算的误差的误差值PID_En2L data PID_En2+1PID_Temp: DS 4 ;计算过程中的暂存PID_TempL data PID_Temp+1PID_Temp1 data PID_Temp+2PID_Temp1L data PID_Temp+3 PUBLIC _PID RSEG ?PR?PID?PIDWork_PID: push accpush pswclr c ;有符号减法mov a,PID_UmaxL ;计算当前的误差En(PID_U里暂存运算结果) subb a,PID_ULmov PID_UL,amov a,PID_Umaxsubb a,PID_Umov PID_U,ajnb acc.7,PID_kmov a,PID_ULcpl aadd a,#1mov r7,amov a,PID_Ucpl aaddc a,#0xch a,r7sjmp PID_gPID_k: mov r7,PID_Umov a,PID_ULPID_g: clr csubb a,PID_EmaxLmov a,r7subb a,PID_Emaxjnb acc.7,PID_a ;如果En>Emax则转mov r7,PID_KiL ;Ki*Enmov r6,PID_Kimov r5,PID_ULmov r4,PID_Uacall PID_MUL ;二字节伪有符号乘法(r4-r7里暂存结果) mov a,PID_Temp1L ;PID加法子程序(将结果加入输出) add a,r7mov PID_Temp1L,amov a,PID_Temp1addc a,r6mov PID_Temp1,amov a,PID_TempLaddc a,r5mov PID_TempL,amov a,PID_Tempaddc a,r4mov PID_Temp,aPID_a: mov a,PID_En1L ;更新PID_En1xch a,PID_ULmov PID_En1L,amov a,PID_En1xch a,PID_Umov PID_En1,aclr c ;有符号减法mov a,PID_En1L ;计算当前的误差差(En-En1)subb a,PID_ULmov PID_UL,amov a,PID_En1subb a,PID_Umov PID_U,amovr7,PID_KpL ;+Kp*(En-En1)mov r6,PID_Kpmov r5,PID_ULmov r4,PID_Uacall PID_MULmov a,PID_Temp1L ;PID加法子程序(将结果加入输出) add a,r7mov PID_Temp1L,amov a,PID_Temp1addc a,r6mov PID_Temp1,amov a,PID_TempLaddc a,r5mov PID_TempL,amov a,PID_Tempaddc a,r4mov PID_Temp,aclr c ;有符号减法mov a,PID_UL ;计算误差差的差(En-En1-En2),同时更新En2 subb a,PID_En2Lmov PID_En2L,amov a,PID_Usubb a,PID_En2mov PID_En2,amovr7,PID_KdL ;+Kd*(En-En1-En2)mov r6,PID_Kdmov r5,PID_En2Lmov r4,PID_En2acall PID_MULmov a,PID_Temp1L ;PID加法子程序(将结果加入输出) add a,r7mov PID_Temp1L,amov a,PID_Temp1addc a,r6mov PID_Temp1,amov a,PID_TempLaddc a,r5mov PID_TempL,amov a,PID_Tempaddc a,r4mov PID_Temp,apop pswpop accretret;//**************************************************************** **********************************************;//功能: 电机控制电流环的PI PI_I(void) 执行时间少于50uS/932-12MHz;//设计者: 牟联树;//日期: 2003.12.28;//版本号: 1.0;//申明:;//**************************************************************** **********************************************PUBLIC _PID_outRSEG ?PR?PID_out?PIDWork_PID_out: push accpush pswclr cmov a,r6rrc amov r6,amov a,r7rrc amov r7,aout_a: mov OCRAH,r6 ;PWM更新mov OCRAL,r7mov a,r7add a,#25mov OCRBL,amov a,r6addc a,#0mov OCRBH,aorl TCR21,#080h ;PWM更新out_b: pop pswpop accret;//**************************************************************** **********************************************;//功能: 整形乘法long int PID_MUL(int a,int b)用时13.5uS/932-12MHz;//设计者: 牟联树;//日期: 2003.12.28;//版本号: 1.0;//申明:;//**************************************************************** **********************************************PUBLIC _PID_MULRSEG ?PR?PID_MUL?PIDWork_PID_MUL:PID_MUL: push accpush pswclr f0 ;符号判断mov a,r4jb acc.7,PID_Masjmp PID_MdPID_Ma: setb f0mov a,r5cpl aadd a,#1mov r5,amov a,r4cpl aaddc a,#0mov r4,aPID_Md:; mov a,r6 ; mov c,acc.7;jnb f0,PID_Mf; cpl cPID_Mf:; mov f0,c ; jb acc.7,PID_Mb ; sjmp PID_McPID_Mb:; clr c; mov a,r7; subb a,#1; cpl a; mov r7,a; mov a,r6; subb a,#0; cpl a; mov r6,aPID_Mc: mov a,r5 mov b,r7 mul abxch a,r7mov r3,bmov b,r4mul abadd a,r3mov r3,amov a,baddc a,#0xch a,r5mov b,r6mul abaddc a,r3xch a,r6xch a,r5addc a,bxch a,r5mov b,r4mul abaddc a,r5mov r5,amov a,baddc a,#0mov r4,ajb f0,PID_Me pop psw pop accretPID_Me: mov a,r7cpl aadd a,#1mov r7,amov a,r6cpl aaddc a,#0mov r6,amov a,r5 cpl a addc a,#0 mov r5,a mov a,r4 cpl a addc a,#0 mov r4,a pop psw pop acc retEND。

51单片机PID算法程序(三)增量式PID控制算法

51单片机PID算法程序(三)增量式PID控制算法

51单片机PID算法程序(一)PID算法(原创文章,转载请注明出处/tengjingshu) 比例,积分,微分的线性组合,构成控制量u(t),称为:比例(Proportional)、积分(Integrating)、微分(Differentiation)控制,简称PID控制图1控制器公式在实际应用中,可以根据受控对象的特性和控制的性能要求,灵活地采用不同的控制组合,构成比例(P)控制器比例+积分(PI)控制器比例+积分+微分(PID)控制器式中或式中控制系统中的应用在单回路控制系统中,由于扰动作用使被控参数偏离给定值,从而产生偏差。

自动控制系统的调节单元将来自变送器的测量值与给定值相比较后产生的偏差进行比例、积分、微分(PID)运算,并输出统一标准信号,去控制执行机构的动作,以实现对温度、压力、流量、也为及其他工艺参数的自动控制。

比例作用P只与偏差成正比;积分作用I是偏差对时间的积累;微分作用D 是偏差的变化率;比例(P)控制比例控制能迅速反应误差,从而减少稳态误差。

除了系统控制输入为0和系统过程值等于期望值这两种情况,比例控制都能给出稳态误差。

当期望值有一个变化时,系统过程值将产生一个稳态误差。

但是,比例控制不能消除稳态误差。

比例放大系数的加大,会引起系统的不稳定。

图2比例(P)控制阶跃响应积分(I)控制在积分控制中,控制器的输出与输入误差信号的积分成正比关系。

为了减小稳态误差,在控制器中加入积分项,积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。

这样,即使误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减少,直到等于零。

积分(I)和比例(P)通常一起使用,称为比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。

如果单独用积分(I)的话,由于积分输出随时间积累而逐渐增大,故调节动作缓慢,这样会造成调节不及时,使系统稳定裕度下降。

图3积分(I)控制和比例积分(PI)控制阶跃相应微分(D)控制在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。

51单片机PID算法程序(三)增量式PID控制算法解读

51单片机PID算法程序(三)增量式PID控制算法解读
图1
控制器公式
在实际应用中,可以根据受控对象的特性和控制的性能要求,灵活地采用不同的控制组合,构成
比例(P)控制器
比例+积分(PI)控制器
比例+积分+微分(PID)控制器
式中
或ቤተ መጻሕፍቲ ባይዱ
式中
控制系统中的应用
在单回路控制系统中,由于扰动作用使被控参数偏离给定值,从而产生偏差。自动控制系统的调节单元将来自变送器的测量值与给定值相比较后产生的偏差进行比例、积分、微分(PID)运算,并输出统一标准信号,去控制执行机构的动作,以实现对温度、压力、流量、也为及其他工艺参数的自动控制。
T ——采样周期。
如果采样周期足够小,则(2-4)的近似计算可以获得足够精确的结果,离散控制过程与连续过程十分接近。
51单片机PID算法程序(一)PID算法
(原创文章,转载请注明出处/tengjingshu)
比例,积分,微分的线性组合,构成控制量u(t),称为:比例(Proportional)、积分(Integrating)、微分(Differentiation)控制,简称PID控制
(图1,表1)
2)Atmel8-bit AVR Microcontrollers Application Note:AVR221: Discrete PID controller
(图2,图3,图4,图5,表2)
3)使用Ziegler-Nichols方法的自整定控制
/2007-03/200733042815.htm
最好的寻找PID参数的办法是从系统的数学模型出发,从想要的反应来计算参数。很多时候一个详细的数学描述是不存在的,这时候就需要实际地调节PID的参数.
Ziegler-Nichols方法

51单片机PID的算法实现程序说课讲解

51单片机PID的算法实现程序说课讲解

51单片机PID的算法实现程序用整型变量来实现PID算法,由于是用整型数来做的,所以也不是很精确,但是对于很多的使用场合,这个精度也够了,关于系数和采样电压全部是放大10倍处理的.所以精度不是很高. 但是也不是那么低,大部分的场合都够了. 实在觉得精度不够, 可以再放大10倍或者100倍处理,但是要注意不超出整个数据类型的范围就可以了.本程序包括PID计算和输出两部分.当偏差>10度全速加热,偏差在10度以内为PID计算输出. 具体的参考代码参见下面:*///================================================================// pid.H// Operation about PID algorithm procedure// C51编译器Keil 7.08//================================================================// 作者:zhoufeng// Date :2007-08-06// All rights reserved.//================================================================#include <reg52.h>#include <intrins.h>typedef unsigned char uint8;typedef unsigned int uint16;typedef unsigned long int uint32;/**********函数声明************/void PIDOutput ();void PIDOperation ();/*****************************/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; //实际值}PIDValueStr;PIDValueStr PID;uint8 out ; // 加热输出uint8 count; // 输出时间单位计数器/*********************************PID = Uk + KP*[E(k)-E(k-1)]+KI*E(k)+KD*[E(k)-2E(k-1)+E(k-2)];(增量型PID算式)函数入口: RK(设定值),CK(实际值),KP,KI,KD函数出口: U(K)//PID运算函数********************************/void PIDOperation (void){uint32 Temp[3]; //中间临时变量uint32 PostSum; //正数和uint32 NegSum; //负数和Temp[0] = 0;Temp[1] = 0;Temp[2] = 0;PostSum = 0;NegSum = 0;if( PID.RK_Uint16 > PID.RK_Uint16 ) //设定值大于实际值否?{if( PID.RK_Uint16 - PID.RK_Uint16 >10 ) //偏差大于10否?{_Uint16 = 100; } //偏差大于10为上限幅值输出(全速加热) else{Temp[0] = PID.RK_Uint16 - PID.CK_Uint16; //偏差<=10,计算E(k)PID.EkFlag_Uint8[1]=0; //E(k)为正数//数值移位PID.Ek_Uint32[2] = PID.Ek_Uint32[1];PID.Ek_Uint32[1] = PID.Ek_Uint32[0];PID.Ek_Uint32[0] = Temp[0];/****************************************/if( PID.Ek_Uint32[0] >PID.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; } //E(k)-E(k-1)为正数else{Temp[0]=PID.Ek_Uint32[0] - PID.Ek_Uint32[1]; //E(k)<E(k-1)PID.EkFlag_Uint8[0]=1; } //E(k)-E(k-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; } //E(k-2)+E(k)-2E(k-1)为正数else{Temp[2]=Temp[2]-(PID.Ek_Uint32[0]+ PID.Ek_Uint32[2]); //E(k-2)+E(k)<2E(k-1)PID.EkFlag_Uint8[2]=1; } //E(k-2)+E(k)-2E(k-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]; //正数和elseNegSum += 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]; //正数和elseNegSum += Temp[2]; //负数和/***************U(K)***************/PostSum += (uint32)_Uint16;if(PostSum > NegSum ) // 是否控制量为正数{ Temp[0] = PostSum - NegSum;if( Temp[0] < 100 ) //小于上限幅值则为计算值输出_Uint16 = (uint16)Temp[0];else_Uint16 = 100; //否则为上限幅值输出}else //控制量输出为负数,则输出0(下限幅值输出)_Uint16 = 0;}}else{ _Uint16 = 0; }}*********************************函数入口: U(K)函数出口: out(加热输出)//PID运算植输出函数********************************/void PIDOutput (void){static int i;i=_Uint16;if(i==0)out=1;else out=0;if((count++)==5)//如定时中断为40MS,40MS*5=0.2S(输出时间单位),加热周期20S(100等份) { //每20S PID运算一次count=0;i--;}}。

PID

PID
TH1=0x00; //给定初值,由0往上计数
TL1=0x00;
EA=1; //总中断打开
ET1=1; //定时器中断打开
TR1=1; //定时器开关打开
}
//定时器0的中断服务子函数,主要完成脉冲个数的读取,实际转速的计算和PID控制以及控制结
//PCF8591.h #define uchar unsigned char
//延时4us
void delay(void);
//iic初始化
void init(void);
void init()
{
SDA=1;
delay();
SCL=1;
delay()de<reg52.h> #define PCF8591 0x90 //默认为写,如果为读,则为0x91 sbit SDA=P2^0;
void start()
{
SDA=1;
delay();
SCL=1;
delay();
SDA=0;
delay();
}
// iic停止信号
void stop()
{
SDA=0;
delay();
SCL=1;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
// 计数器1初始化,用来统计定时器1计时250ms内PWM波形个数
void Init_Timer1(void)
{
TMOD |= 0x50; //使用计数模式1,16位计数器模式
(2)整定积分环节
若在比例控制下稳态误差不能满足要求,需加入积分控制。

PID算法程序范文

PID算法程序范文

PID算法程序范文比例项(P)通过将误差与比例增益相乘,直接将误差的大小线性转换为控制器的输出。

P项对应于调整控制器的灵敏度。

如果P项过大,容易导致控制器输出过冲;如果P项过小,则控制器的反应较迟钝。

积分项(I)通过将误差累加起来,并乘以积分时间进行调整,来消除持续存在的稳态误差。

I项对应于调整控制器的稳定性。

如果I项过大,容易导致控制器输出过冲;如果I项过小,则控制器对系统的纠正能力较弱。

微分项(D)通过将误差的变化率乘以微分时间进行调整,来减小系统的超调和过冲。

D项对应于调整控制器的响应速度。

如果D项过大,容易导致控制器输出的抖动;如果D项过小,则控制器对系统的抑制作用较弱。

实际应用中,根据被控对象的特性和需求,可以根据经验或实验来调整PID算法的参数。

常用的调参方法有手动调参和自动调参两种。

手动调参通过人工观察系统的响应特性,并根据经验来设置参数值。

而自动调参则是通过参数优化方法,如遗传算法、粒子群算法等,来自动最优的参数组合。

下面是一个简单的PID算法的示例程序:```python#PID算法示例程序#定义PID控制器的参数Kp=1.0Ki=0.1Kd=0.01#初始化误差项error = 0last_error = 0integral = 0#循环控制while True:#获取被控对象的实际值actual_value = get_actual_value#计算误差项error = setpoint - actual_value#计算P项P = Kp * error#计算I项integral += Ki * error#计算D项derivative = Kd * (error - last_error) #更新上次误差项last_error = error#计算PID控制器输出output = P + integral + derivative#更新被控对象的控制信号update_control_signal(output)#等待下一次采样```在实际应用中,PID算法不仅可以用于单个被控对象的控制,还可以用于多个被控对象的联合控制,或者用于非线性系统的控制。

自己写的51单片机PID控制

自己写的51单片机PID控制
int LastError; //Error[-1]
int PrevError; //Error[-2]
} PID;
//*****************************************************
//声明PID实体
//*****************************************************
{
uint i,j;
for(i=0;i<count;i++)
for(j=0;j<120;j++);
}
uint read()
{ uchar tl,th1,th2;
uint val;
while(1)
{ th1=TH0;
tl=TL0;
th2=TH0;
if(th1==th2)
break;
}
val=th1*256+tl;
RM1=0;RM2=1;
}
else
{
LM1=0;LM2=0;
RM1=0;RM2=0;
}
}
}
void zuoguai(uchar z) //小车左拐,z是控制占空比的,起调节速度的作用
{
uchar k;
for(k=1;k<=100;k++)
{
if(k<=z)
{
RM1=1;RM2=0;
LM1=0;LM2=1;
}
int IncPIDCalc(int NextPoint) //PID增量计算函数
{
int iError, iIncpid; //iError,当前误差;iIncpid,PID公式中的增量

51单片机PID算法程序

51单片机PID算法程序

51单片机PID算法程序(二)位置式PID控制算法由51单片机组成的数字控制系统控制中,PID控制器是通过PID控制算法实现的。

51单片机通过AD对信号进行采集,变成数字信号,再在单片机中通过算法实现PID运算,再通过DA把控制量反馈回控制源。

从而实现对系统的伺服控制。

位置式PID控制算法位置式PID控制算法的简化示意图? 上图的传递函数为:(2-1)?? 在时域的传递函数表达式(2-2)?? 对上式中的微分和积分进行近似(2-3)?? 式中n是离散点的个数。

?? 于是传递函数可以简化为:(2-4)其中u(n)——第k个采样时刻的控制;K P? ——比例放大系数;???K i?? ——积分放大系数;K d?? ——微分放大系数;T?? ——采样周期。

如果采样周期足够小,则(2-4)的近似计算可以获得足够精确的结果,离散控制过程与连续过程十分接近。

(2-4)表示的控制算法直接按(2-1)所给出的PID控制规律定义进行计算的,所以它给出了全部控制量的大小,因此被称为全量式或位置式PID控制算法。

缺点:1)??????????? 由于全量输出,所以每次输出均与过去状态有关,计算时要对e(k)(k=0,1,…n)进行累加,工作量大。

2)??????????? 因为计算机输出的u(n)对应的是执行机构的实际位置,如果计算机出现故障,输出u(n)将大幅度变化,会引起执行机构的大幅度变化,有可能因此造成严重的生产事故,这在实际生产中是不允许的。

位置式PID控制算法C51程序具体的PID参数必须由具体对象通过实验确定。

由于单片机的处理速度和ram资源的限制,一般不采用浮点数运算,而将所有参数全部用整数,运算到最后再除以一个2的N次方数据(相当于移位),作类似定点数运算,可大大提高运算速度,根据控制精度的不同要求,当精度要求很高时,注意保留移位引起的“余数”,做好余数补偿。

这个程序只是一般常用pid算法的基本架构,没有包含输入输出处理部分。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

式中

式中
控制系统中的应用
在单回路控制系统中,由于扰动作用使被控参数偏离给定值,从而产生偏差。

自动控制系统的调节单元将来自变送器的测量值与给定值相比较后产生的偏差进行比例、积分、微分(PID)运算,并输出统一标准信号,去控制执行机构的动作,以实现对温度、压力、流量、也为及其他工艺参数的自动控制。

比例作用P只与偏差成正比;积分作用I是偏差对时间的积累;微分作用D是偏差的变化率;
比例(P)控制
比例控制能迅速反应误差,从而减少稳态误差。

除了系统控制输入为0和系统过程值等于期望值这两种情况,比例控制都能给出稳态误差。

当期望值有一个变化时,系统过程值将产生一个稳态误差。

但是,比例控制不能消除稳态误差。

比例放大系数的加大,会引起系统的不稳定。

图2比例(P)控制阶跃响应
积分(I)控制
在积分控制中,控制器的输出与输入误差信号的积分成正比关系。

为了减小稳态误差,在控制器中加入积分项,积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。

这样,即使误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减少,直到等于零。

积分(I)和比例(P)通常一起使用,称为比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。

如果单独用积分(I)的话,由于积分输出随时间积累而逐渐增大,故调节动作缓慢,这样会造成调节不及时,使系统稳定裕度下降。

图3积分(I)控制和比例积分(PI)控制阶跃相应
微分(D)控制
在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。

由于自动控制系统有较大的惯性组件(环节)或有滞后(delay)组件,在调节过程中可能出现过冲甚至振荡。

解决办法是引入微分(D)控制,即在误差很大的时候,抑制误差的作用也很大;在误差接近零时,抑制误差的作用也应该是零。

图4微分(D)控制和比例微分(PD)控制阶跃相应
总结:
PI比P少了稳态误差,PID比PI反应速度更快并且没有了过冲。

PID比PI有更快的响应和没有了过冲。

图5
表1
注意,这里的
图6典型的PID控制器对于阶跃跳变参考输入的响应参数的调整
应用PID控制,必须适当地调整比例放大系数KP,积分时间TI和微分时间TD,使整个控制系统得到良好的性能。

最好的寻找PID参数的办法是从系统的数学模型出发,从想要的反应来计算参数。

很多时候一个详细的数学描述是不存在的,这时候就需要实际地调节PID的参数.
Ziegler-Nichols方法。

相关文档
最新文档