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

1.本系统采用STC89C52作为单片机
2.采用液晶LCD1602液晶实时显示相关数据
3.采用矩阵键盘可设置PID相关参数
4.采用L298驱动功率电阻模拟加热过程
5.当温度超过设定值的一定范围启动声光报警系统
6.DC002直接5V电源输入
7.支持按键和旋钮两种温度设定模式,设定范围30~80℃;通过滑动变阻器旋钮可无极设置温度值
8.采用NTC电阻实时测量温度变化

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

PCB:
在这里插入图片描述

主程序:

#include "reg51.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度时电阻
//#define RA (0.00335)
//#define RB (0.000259)
//#define RC (0.00000305)
//#define RD (-0.000000272)
//#define RE (-0.0000000648)

/*****************引脚定义*********************************/
// l298n
sbit RELAY_HEAT = P1^4;
sbit RELAY_COOL = P1^5;
sbit ENA = P1^6;
/********************************/
// AD芯片
sbit CLOCK = P1^0;
sbit D_IN  = P1^1;
sbit D_OUT = P1^2;
sbit _CS   = P1^3;
/********************************/
// 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 = 10, KI = 1, 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);
uint adcread(uchar port);
float ReadTemp(void);
void delay(uint n);
void writecom(uchar com);
void writedata(uchar date);
void initlcd();
float keyscan(void);
//uchar keyscans(void);
void lcdnumdisplay(uchar pos, double f);
void lcdnumdisplays(uchar pos, double f);
//uint read_pul();
void mypid(float Kp, float Ki, float Kd, uint count, uint point);

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

	//	RELAY_HEAT=1;RELAY_COOL=0;
	//	while(1);
	while (1)
	{
		set_temp = 460 * (float)(adnum0) / 4095;
		// pwm=set_temp;
		mypid(KP, KI, KD, adnum1, set_temp);
		scantemp = keyscan();
		if (adnum1 >= set_temp - 1.5 && adnum1 <= set_temp + 1.5)
		{
			SPEAKER = 1;
		}
		else
		{
			SPEAKER = 0;
		}
		if (setflag == 0)
		{
			adnum0 = adcread(1);
			adnum1 = ReadTemp();
			if (init0 == 0)
			{
				initlcd();
				writecom(0x80);
				for (i = 0; i < 16; i++)
					writedata(str2[i]); // shuming
				init0 = 1;
				init1 = 0;
				init2 = 0;
				init3 = 0;
				init4 = 0;
			}
			lcdnumdisplays(0x80 + 0x40, (float)set_temp); // set_temp
			lcdnumdisplays(0x80 + 0x4a, (float)adnum1);
		}

		if (setflag != 0 && pageflag == 0)
		{
			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)
		{
			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)
		{
			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)
		{
			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;
			}
		}
	}
}

float ReadTemp(void)
{
    float current = 0;
    float Rt = 0;
    float f_tempVolt = 0;    //温度对应电压
    float f_temp = 0;
    
    f_tempVolt = 5 * (float)adcread(0) / 4096; //读取电压
    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 = 0;
		RELAY_COOL = 1;
	}
	if (pwm > 0)
	{
		RELAY_HEAT = 1;
		RELAY_COOL = 0;
	}
	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;
}

仿真演示视频:
https://www.bilibili.com/video/BV1me4y187np/
实物演示视频:
https://www.bilibili.com/video/BV1rG4y1z7yc/

  • 2
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值