基于51单片机的温度PID算法控制系统proteus仿真原理图PCB

功能介绍:
0本系统采用STC89C52作为单片机
1液晶实时显示当前温度和设定温度值
2可通过旋钮设定温度,设定范围30~80℃
3当温度超出设定温度±1.5℃时,蜂鸣器报警提醒
4按键可设定PID参数
5.采用DC002作为电源接口可直接输入5V给整个系统供电

原理图:
在这里插入图片描述

PCB :
在这里插入图片描述

主程序:

#include "reg52.h"
#include "tlc0832.h"
#include "delay.h"
#include "math.h"

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

#define T25 (273.15+25) //T25
#define Bx (4050.0) //B值
#define Ka (273.15) //绝对零度
#define Rp (10000.0) //ntc串联电阻
#define ntcR25 (10000.0) //25度时电阻

/*****************引脚定义*********************************/
// 继电器控制
sbit RELAY_HEAT = P1^3;
sbit RELAY_COOL = P1^4;

/********************************/
// lcd液晶
sbit LCD_RS = P3^5;
sbit LCD_EN = P3^6;
/********************************/

//蜂鸣器
sbit SPEAKER = P3^7;

/*****************变量定义(声明)*********************************/
int freq = 500, pwm = 0;
uchar setflag = 0, pageflag = 0, ok = 0;
float set_temp = 0;
float KP = 100, KI = 10, KD = 0;
uint pul_count = 0;
float ek = 0, ek1 = 0, ek2 = 0;
float keytemp = 0;

uchar code str[16] = "    welcome!    ";
uchar code str1[16] = " temperature PID";
uchar code str2[16] = "set-T     now-T ";
uchar code str3[16] = "P:     I:     D:";
uchar code str4[16] = "set-P:       ";
uchar code str5[16] = "set-I:       ";
uchar code str6[16] = "set-D:       ";
void Init(void); //初始化函数
float ReadTemp(void); //读取温度
void delay(uint n);
void writecom(uchar com); //LCD写命令
void writedata(uchar date); //LCD写数据
void initlcd(); //初始化LCD
float keyscan(void); //按键扫描
//uchar keyscans(void);
void lcdnumdisplay(uchar pos, double f); //LCD显示
void lcdnumdisplays(uchar pos, double f); //LCD显示
//uint read_pul();
void mypid(float Kp, float Ki, float Kd, uint count, uint point); //PID

void main()
{
	uchar i;
	float scantemp;
	float adnum0 = 0;
	float temperature = 0;
	bit init0, init1, init2, init3, init4;
	Init();
	initlcd();
	writecom(0x80);
	for (i = 0; i < 16; i++)
		writedata(str[i]);
	writecom(0x80 + 0x40);
	for (i = 0; i < 16; i++)
		writedata(str1[i]);
	delay(2000);

	while (1)
	{
        if (setflag == 0) //
		{
			adnum0 = ReadADC(AIN1_GND); //读取AD值
			temperature = ReadTemp(); //读取温度
			if (init0 == 0)
			{
				initlcd();
				writecom(0x80);
				for (i = 0; i < 16; i++)
					writedata(str2[i]);  //显示温度
				init0 = 1;
				init1 = 0;
				init2 = 0;
				init3 = 0;
				init4 = 0;
			}
			lcdnumdisplays(0x80 + 0x40, (float)set_temp); // set_temp
			lcdnumdisplays(0x80 + 0x4a, (float)temperature);
		}
        if (setflag != 0 && pageflag == 0) //显示PID参数
		{
			if (init1 == 0)
			{
				initlcd();
				writecom(0x80);
				for (i = 0; i < 16; i++)
					writedata(str3[i]);
				init0 = 0;
				init1 = 1;
				init2 = 0;
				init3 = 0;
				init4 = 0;
			}
			lcdnumdisplays(0x80 + 0x40, KP);
			lcdnumdisplays(0x80 + 0x46, KI);
			lcdnumdisplays(0x80 + 0x4D, KD);
		}
		if (setflag != 0 && pageflag == 1) //设置P
		{
			if (init2 == 0)
			{
				initlcd();
				writecom(0x80);
				for (i = 0; i < 16; i++)
					writedata(str4[i]);
				init0 = 0;
				init1 = 0;
				init2 = 1;
				init3 = 0;
				init4 = 0;
			}
			lcdnumdisplays(0x80 + 0x40, scantemp);
			if (ok == 1)
			{
				KP = scantemp;
				ok = 0;
			}
		}
		if (setflag != 0 && pageflag == 2) //设置I
		{
			if (init3 == 0)
			{
				initlcd();
				writecom(0x80);
				for (i = 0; i < 16; i++)
					writedata(str5[i]);
				init0 = 0;
				init1 = 0;
				init2 = 0;
				init3 = 1;
				init4 = 0;
			}
			lcdnumdisplays(0x80 + 0x40, scantemp);
			if (ok == 1)
			{
				KI = scantemp;
				ok = 0;
			}
		}
		if (setflag != 0 && pageflag == 3) //设置D
		{
			if (init4 == 0)
			{
				initlcd();
				writecom(0x80);
				for (i = 0; i < 16; i++)
					writedata(str6[i]);
				init0 = 0;
				init1 = 0;
				init2 = 0;
				init3 = 0;
				init4 = 1;
			}
			lcdnumdisplays(0x80 + 0x40, scantemp);
			if (ok == 1)
			{
				KD = scantemp;
				ok = 0;
			}
		}
        
		set_temp = 100 * (float)(adnum0) / 255 - 20;
		// pwm=set_temp;
		mypid(KP, KI, KD, temperature, set_temp);
		
		if (temperature >= set_temp - 1.5 && temperature <= set_temp + 1.5) //在温度范围以内,关闭蜂鸣器
		{
			SPEAKER = 1;
		}
		else //否则开启蜂鸣器
		{
			SPEAKER = 0; //蜂鸣器报警
		}
		
        scantemp = keyscan();
	}
}

float ReadTemp(void)
{
    float current = 0;
    float Rt = 0;
    float f_tempVolt = 0;    //温度对应电压
    float f_temp = 0;
    
    f_tempVolt = 5 * (float)ReadADC(AIN0_GND) / 255; //读取电压
    current = (5 - f_tempVolt) / Rp; //计算电流值
    Rt = f_tempVolt / current; //计算电阻值
    
    f_temp = ((Bx * T25) / (T25 * (log(Rt) - log(ntcR25)) + Bx)) - Ka;

    delay(5);
    return f_temp;
}

void mypid(float Kp, float Ki, float Kd, uint count, uint point)
{
	static float Uk;
	ek = point - count;
	//   if(ek>=5&&ek<=-5)   //积分分离
	{
		Uk = Kp * (ek - ek1) + Ki * ek + Kd * (ek - 2 * ek1 + ek2);
	}
	//   else
	//   Uk=Kp*ek;
	pwm = Uk;
	// lcdnumdisplays(0x80+0x4a,(float)pwm);
	if (pwm > freq)
		pwm = freq;
	if (pwm <= 0)
	{
		pwm = 0;
		RELAY_HEAT = 1;
		RELAY_COOL = 0;
	}
	if (pwm > 0)
	{
		RELAY_HEAT = 0;
		RELAY_COOL = 1;
	}
	ek2 = ek1;
	ek1 = ek;
}
//uint read_pul()
//{
//	uint t1, th1, th2;
//	uint val;
//	while (1)
//	{
//		th1 = TH1;
//		t1 = TL1;
//		th2 = TH1;
//		if (th1 == th2)
//			break;
//	}
//	val = th1 * 256 + t1;
//	return val;
//}

void delay(uint n)
{
	uint i, j;
	for (i = n; i > 0; i--)
		for (j = 1; j > 0; j--)
			;
}

void Init(void) //初始化函数
{
	TMOD = 0x51;
	TH0 = (65536 - 10) / 256;
	TL0 = (65536 - 10) % 256;
	EA = 1;
	ET0 = 1;
	TR0 = 1;
	TH1 = 0;
	TL1 = 0;
	TR1 = 1;
}

void Timer_0(void) interrupt 1 //中断
{
//	static ulong t_count = 0;
	static uint num_count = 0;
	TR0 = 0;
	TH0 = (65536 - 10) / 256;
	TL0 = (65536 - 10) % 256;
	TR0 = 1;
	num_count++;
	//	   t_count++;
	//	   if(t_count==2320)
	//	         {
	//			     t_count=0;
	//				 TR1=0;
	//				 pul_count=read_pul();
	//		         TH1=0;
	//		         TL1=0;
	//				 TR1=1;
	//	         }
	if (num_count > freq)
		num_count = 0; // 1khz;
}
// lcd写命令
void writecom(uchar com)
{
	LCD_RS = 0;
	P0 = com;
	delay(1);
	LCD_EN = 1;
	delay(1);
	LCD_EN = 0;
}
// lcd写数据
void writedata(uchar date)
//初始化lcd
{
	LCD_RS = 1;
	P0 = date;
	delay(1);
	LCD_EN = 1;
	delay(1);
	LCD_EN = 0;
}
// LCD初始化
void initlcd()
{
	writecom(0x38);
	delay(1);
	writecom(0x0c);
	delay(1);
	writecom(0x06);
	delay(1);
	writecom(0x01);
	delay(5);
}

仿真演示视频:
https://www.bilibili.com/video/BV1824y1o7Ys/

实物演示视频:
https://www.bilibili.com/video/BV1Te4y1n7F4/

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于51单片机PID温度调节控制系统Proteus仿真设计,主要包括硬件电路设计和软件程序编写两个部分。 硬件电路设计方面,需要根据温度传感器获取的温度信号,通过A/D转换将模拟信号转换为数字信号,然后经过51单片机进行处理。在这个过程中,需要设计51单片机的外围电路,如时钟电路、复位电路、显示电路等。同时,还需要设计控制系统的输入和输出电路,用于接收和输出控制信号。最后,将设计好的硬件电路连线,并与51单片机进行连接。 软件程序编写方面,需要先编写51单片机的初始化和配置程序,包括对外围设备的初始化设置,如温度传感器、显示屏等。然后,根据PID控制算法的要求,编写相应的PID控制算法程序。在程序中,需要根据温度测量值和设定值的差异进行控制,通过调整输出控制信号,实现温度的稳定控制。最后,需要编写显示程序,将温度控制器的工作状态和温度显示在显示屏上。 最后,在Proteus软件中进行仿真设计。使用51单片机模型搭建硬件电路,并将编写好的软件程序加载入模型中。通过仿真模拟,可以验证温度控制系统的稳定性、准确性和可靠性。可以观察传感器测量的温度值与设定值之间的差异,以及PID控制器对温度的调节程度。通过不断修改和优化控制算法和参数,来改进系统的控制效果。 总之,基于51单片机PID温度调节控制系统Proteus仿真设计涉及到硬件电路设计和软件程序编写两个方面,通过仿真模拟来验证和优化控制系统的稳定性和准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值