本水温自动控制系统分为主控部分、显示部分、接收部分、无线部分、上位机部分共五大部分,其中主控部分和上位机部分是本次设计的重点。 普通温度传感器只能在容器的外部对温度进行采集,不能很准确的反应实时的变化量。由于加热棒停止加热一段时间内仍然有加热的功效,所以如果温度到达时才停止加热,温度一定会超出目标温度很多,所以采用PID算法可以较为准确的控制水温的变化情况。因为水有惰性,如果不进行搅拌那么一个烧杯中的水上层和下层甚至可能会差十摄氏度,所以需要让水运动起来。由于容器较小,使用电机搅拌空间不足,所以采用气泵方式。 当主控端上电后,系统对温度采集模块、加热控制模块、制冷控制模块、LCD显示模块、按键控制模块、无线传输模块进行初始化。初始化完成后,读取无线数据的接收缓冲区,判断是否接收到数据,如果收到命令则判断其命令类型并执行。检测按键是否被按下,如果被按下则处理相应的按键事件。获取当前温度,在LCD上显示,并通过无线将温度数据发送给接收端,把当前温度值传入PID算法中进行运算,得出脉冲宽度,再通过脉冲控制加热棒加热或制冷器制冷。 PID算法:#include "STC12C5A60S2.h"
#include "DisplayLED.h"
#include "USART.h"
#include "DS18B20.h"
sbit JiaRe = P3^5;
sbit KEY0 = P3^0;
sbit KEY1 = P3^1;
sbit KEY2 = P3^2;
sbit KEY3 = P3^3;
sbit LED = P3^6;
unsigned int Time_count = 0;
unsigned int TIME_MY = 1;
unsigned char JiaReFlag = 0;
unsigned char TxVALUE[RXTX_WIDTH];
typedef struct
{
signed int dState; // 保存最后一次输入
signed int iState; // 积分器状态
signed int iMax, iMin; // 积分器上下限
signed int iGain, // 积分增益
pGain, // 比例增益
dGain; // 微分增益
} SPid;
void Time0Init(void)
{
TMOD |= 0x01; // 设置定时器模式
TH0 = (65536-5000)/256; // 装初值
TL0 = (65536-5000)%256;
TR0 = 0; // 开定时器
ET0 = 1; // 定时器中断
EA = 1; // 开总中断
}
void TimeZero() interrupt 1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; // 重填TH0,TL0
Time_count ++;
if(Time_count >= 40)
Time_count = 0;
if(Time_count < TIME_MY)
{
LED = 0;
JiaRe = 0;
}
else
{
LED = 1;
JiaRe = 1;
}
}
void PWM_ChuLi(signed int re)
{
if(re < 0)
{
TIME_MY = 0;
JiaReFlag = 0;
}
else if(re > 40)
TIME_MY = 40;
else
TIME_MY = re;
}
signed int ControlPID(SPid * pid, signed int error, signed int position)
{
signed int pTerm,dTerm, iTerm;
// 计算的比例项
pTerm = pid->pGain * error;
// 对积分状态的限制
pid->iState += error;
if (pid->iState > pid->iMax)
pid->iState = pid->iMax;
else if (pid->iState < pid->iMin)
pid->iState = pid->iMin;
iTerm = pid->iGain * pid->iState;
// 计算的微分项
dTerm = pid->dGain * (position - pid->dState);
pid->dState = position;
return pTerm + iTerm/10 - dTerm;
}
void main(void)
{
signed int CommandSet = 340;
signed int position;
signed int Term;
unsigned int mLoop;
unsigned char SetFlag = 0;
SPid MyPID = {0,0,40,-40,0,4,1};
P0M0 = 0xFF;
P2M0 = 0xFF;
P1M0 = 0xFF;
// UartInit();
Time0Init();
while(1)
{
if(SetFlag == 0)
{
TmpChange();
position = GetTemperature();
Term = ControlPID(&MyPID,(CommandSet/10 - position/10 - 1),position/10);
PWM_ChuLi(Term);
}
for(mLoop = 0;mLoop< 10000;mLoop++)
{
if(KEY0 == 0)
{
while(KEY0 == 0);
SetFlag = ~SetFlag;
while(KEY0 == 0);
DelayMS(20);
while(KEY0 == 0);
DelayMS(20);
}
if(SetFlag != 0)
{
JiaReFlag = 0;
JiaRe = 1;
DisplayLED(CommandSet);
if(KEY1 == 0)
{
CommandSet += 10;
if(CommandSet > 990)
CommandSet = 990;
while(KEY1 == 0);
DelayMS(20);
while(KEY1 == 0);
DelayMS(20);
}
if(KEY2 == 0)
{
while(KEY2 == 0);
CommandSet -= 10;
if(CommandSet < position/10*10 +20)
CommandSet = position/10*10 +20;
while(KEY2 == 0);
DelayMS(20);
while(KEY2 == 0);
DelayMS(20);
}
}
else
{
DisplayLED(position);
}
if(KEY3 == 0)
{
while(KEY3 == 0);
JiaReFlag = 1;
}
if(JiaReFlag !=0)
{
LED = 0;
TR0 = 1;
}
else
{
JiaRe = 1;
TR0 = 0;
LED = 1;
}
}
}
}
全部资料51hei下载地址:
基于51单片机PID算法的自动水温控制系统.rar
(869.98 KB, 下载次数: 201)
|