导航:首页 > 编程语言 > pid控温pwm程序

pid控温pwm程序

发布时间:2024-12-22 03:09:26

㈠ 8位单片机PID控制PWM的算法如何实现,C语言计算

PID控制在8位单片机中仍然有广泛的应用,比如温度控制,利用比例、积分、微分补偿来做恒温补偿控制,当然由于有这些数学处理,用C语言相对方便一些,以下是一个具体的实例。

#include<reg51.h>

#include<intrins.h>

#include<math.h>

#include<string.h>

struct PID {

unsigned int SetPoint; // 设定目标 Desired Value

unsigned int Proportion; // 比例常数 Proportional Const

unsigned int Integral; // 积分常数 Integral Const

unsigned int Derivative; // 微分常数 Derivative Const

unsigned 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;

/***********************************************************

延时子程序,延时时间以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)); //全部初始化为0

}

/*====================================================================================================

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); // 微分项

}

/***********************************************************

温度比较处理子程序

***********************************************************/

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 Input

rout = PIDCalc ( &spid,rin ); // Perform PID Interation

}

if (high_time<=100)

high_time=(unsigned char)(rout/800);

else

high_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 Input

rout = PIDCalc ( &spid,rin ); // Perform PID Interation

}

if (high_time<100)

high_time=(unsigned char)(rout/10000);

else

high_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;

}

else

count=0;

TH0=0x2f;

TL0=0xe0;

}

/*****************************************************

串行口中断服务程序,用于上位机通讯

******************************************************/

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

data1=0;

_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;

else

disp_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 Const

spid.Integral = 8; //积分常数 Integral Const

spid.Derivative =6; //微分常数 Derivative Const

spid.SetPoint = 100; // Set PID Setpoint 设定目标 Desired Value

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;

else

temper=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;

}

}

㈡ 基于单片机AT89c51的数字PID控制直流电机PWM调速系统C语言程序

首先弄清楚PID是一种控制算法!!!
1,“如果用单片机恒温可以使温度到达预定值就停止加热,低了就加热,用一个温度传感器反馈,这样算是一个自动控制吗”你这是控制系统,但是效果会非常差,尤其是对于温度控制这种大惯性系统,达到预定值就停止加热,但是由于惯性,温度肯定会继续上升,电炉烧水的时候,水开了,断电之后水还要沸腾一定时间的(沸腾是很消耗能量的,由此可见如果是加热的话温度上升更严重,你也可以自己用温度计试试看);“低了就加热”是同样的道理。如果系统对控制精度有要求,你这样做肯定达不到要求。PID是一种控制算法,相对于其他控制算法来说算是最简单的了。PID能够做到在温度快要达到设定值的时候降低加热功率,让温度上升速度变慢,最终稳定在设定值。如果用你的直接控制,温度会在设定值上下振荡,永远不会停在设定值。
2,一般的控制系统都需要加反馈,以构成闭环控制系统,相对的还有开环控制系统。开环控制系统,举个例子,就是你加热的时候事先计算好大约需要多少热量,然后考虑一下环境影响,计算出加热时间,然后控制加热系统按照你这个时间加热。你觉得这样的系统能够稳定工作吗?环境稍稍有变动就挂了!开环控制系统的特点就是很容易受到环境的影响;闭环控制系统就稳定很多,你用1L水可用,2L水也行,500W电能用,1000W电炉也能用,这就是闭环的优点。
因此,大多数的控制系统都是闭环的,开环很少单独使用,即使用到了也是有闭环的。开环其实也是有优点的,开环在控制系统里面叫做前馈(跟反馈对应的),比如你的系统里面电源电压上升了,加热速度肯定会变快,如果你对电源电压采样,将采样的结果输入到闭环里面,对闭环做一个轻微的修正,控制的精度会更好,这就是开环的优势,它是超前的,能够预知结果(根据地源电压提高就能知道需要降低输出功率了)。
说完这些,你应该明白了,反馈是必需的(前馈也可以要,但是不是必需的),PID不能被取代(除非你用其它更复杂的控制算法)。

㈢ pid怎么通过pwm调速

关于问题1,被控系统的性能有很多种,这涉及到自动控制原理的知识,比如惯性,不是说输入给定值2000的PWM,输出就一定能立马变成200的转速,这个过程中还存在的时间的滞后、超调量、稳定时间,以及最终的稳定值与200之间的误差等等,所以针对被控系统,我们常用PID算法,P可以快速减少误差,I可以消除累计误差,D可以超前控制消除余差,并通过负反馈闭环控制,通过PID公式中P/I/D三个参数的改变,就能改善被控系统的控制性能,当输入为2000PWM时,稳准快地使输出成为200转速。
关于问题2,PID分两种,增量式的PID的公式是根据每次的设定值与反馈值进行比较做差值,通过公式计算出输出的变化量△y,如果你需要直接输出y,那么这次的输出量y(k)应该等于上次的输出y(k-1)+△y(增量),懂了吗?
认真手敲,希望采纳

阅读全文

与pid控温pwm程序相关的资料

热点内容
cf格式文件怎么打开 浏览:684
红色边框app哪个好用 浏览:110
文件如何安装成应用 浏览:897
克拉克森农场在哪个APP 浏览:656
哪里编写和运行8086汇编程序 浏览:484
linuxusb安装 浏览:837
行政管理和加工中心编程哪个好 浏览:146
少儿编程程序有哪些 浏览:740
win10标准用户权限 浏览:146
excel怎么另存dbf文件 浏览:211
乐视超443升级版 浏览:769
qq适合什么项目推广 浏览:184
dnf二觉文件 浏览:142
百度云如何自动同步文件夹 浏览:936
初始的宽带帐号和密码是什么意思 浏览:544
苹果5如何打开4g网络 浏览:113
win10下win7虚拟机鼠标 浏览:202
苏州哪里学编程最好 浏览:459
电脑文件贴图片 浏览:411
索尼录制视频没电了文件打不开 浏览:472

友情链接