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/