一、項(xiàng)目介紹
隨著環(huán)保意識(shí)的逐漸增強(qiáng),太陽能熱水器作為一種清潔能源應(yīng)用得越來越廣泛。然而,傳統(tǒng)的太陽能熱水器控制器通常采用機(jī)械式或電子式溫控器,存在精度低、控制不穩(wěn)定等問題。為了解決這些問題,本項(xiàng)目基于單片機(jī)技術(shù)設(shè)計(jì)了一款太陽能熱水器控制器,主控芯片采用STC89C52。該控制器可以實(shí)現(xiàn)對太陽能熱水器的水溫、水位等參數(shù)進(jìn)行準(zhǔn)確、穩(wěn)定的控制,提高了太陽能熱水器的能源利用效率和使用壽命,同時(shí)也符合節(jié)能環(huán)保的社會(huì)需求。
二、系統(tǒng)構(gòu)架
2.1 系統(tǒng)設(shè)計(jì)
本系統(tǒng)采用主從結(jié)構(gòu),由STC89C52單片機(jī)作為主控芯片,負(fù)責(zé)控制整個(gè)太陽能熱水器的運(yùn)行。系統(tǒng)包括傳感器模塊、驅(qū)動(dòng)模塊和用戶界面模塊。
傳感器模塊包括溫度傳感器和光照傳感器,用于實(shí)時(shí)監(jiān)測水溫和太陽輻射強(qiáng)度。驅(qū)動(dòng)模塊包括電磁閥和水泵,用于控制水流和熱水的循環(huán)。用戶界面模塊包括液晶顯示屏和按鍵,用于顯示當(dāng)前狀態(tài)和提供用戶交互。
2.2 功能設(shè)計(jì)
本設(shè)計(jì)的太陽能熱水器控制器功能:
- 溫度控制:通過溫度傳感器實(shí)時(shí)監(jiān)測水溫,并根據(jù)設(shè)定的閾值控制電磁閥和水泵,以保持熱水器水溫在設(shè)定范圍內(nèi)。
- 光照控制:通過光照傳感器實(shí)時(shí)監(jiān)測太陽輻射強(qiáng)度,判斷當(dāng)前是否有足夠的太陽能供給,若不足,則停止水泵運(yùn)行,以節(jié)約能源。
- 時(shí)間控制:設(shè)置定時(shí)計(jì)劃,控制熱水器在指定時(shí)間段內(nèi)工作或停止工作。
- 用戶交互:通過液晶顯示屏顯示當(dāng)前溫度、工作狀態(tài)等信息,并通過按鍵設(shè)定參數(shù)和操作熱水器。
2.3 硬件設(shè)計(jì)
硬件設(shè)計(jì)包括電路連接和外圍模塊選擇。主控芯片STC89C52與傳感器模塊、驅(qū)動(dòng)模塊和用戶界面模塊通過IO口進(jìn)行連接。溫度傳感器采用DS18B20數(shù)字溫度傳感器,光照傳感器采用光敏電阻。
2.4 軟件設(shè)計(jì)
軟件設(shè)計(jì)主要包括系統(tǒng)初始化、傳感器數(shù)據(jù)采集、控制算法和用戶交互等部分。系統(tǒng)初始化包括IO口配置、定時(shí)器設(shè)置等。傳感器數(shù)據(jù)采集通過相應(yīng)的接口獲取溫度和光照傳感器數(shù)據(jù)??刂扑惴ǜ鶕?jù)采集到的數(shù)據(jù)進(jìn)行溫度和光照控制,并控制電磁閥和水泵的開關(guān)。用戶交互通過液晶顯示屏和按鍵實(shí)現(xiàn),用戶可以通過按鍵設(shè)置參數(shù)和操作熱水器。
2.5 設(shè)計(jì)思路
本項(xiàng)目的控制器主要包括傳感器模塊、控制模塊和顯示模塊三部分。其中,傳感器模塊用于實(shí)時(shí)檢測太陽能熱水器的水溫、水位等參數(shù);控制模塊將傳感器采集到的數(shù)據(jù)進(jìn)行處理,并通過控制水泵、電磁閥等執(zhí)行器來實(shí)現(xiàn)對太陽能熱水器的水溫、水位等參數(shù)進(jìn)行準(zhǔn)確、穩(wěn)定的控制;顯示模塊則用于顯示當(dāng)前的水溫、水位等參數(shù)。
具體的設(shè)計(jì)流程如下:
【1】確定硬件平臺(tái):采用STC89C52單片機(jī)作為主控芯片,搭建傳感器模塊和執(zhí)行器模塊,通過串口通信與PC機(jī)連接。
【2】確定傳感器類型:選擇DS18B20溫度傳感器和液位傳感器作為檢測太陽能熱水器水溫、水位的傳感器。
【3】確定控制策略:根據(jù)太陽能熱水器的實(shí)際情況,設(shè)計(jì)PID控制算法,通過控制水泵、電磁閥等執(zhí)行器來實(shí)現(xiàn)對太陽能熱水器的水溫、水位等參數(shù)進(jìn)行準(zhǔn)確、穩(wěn)定的控制。
【4】編寫程序:根據(jù)硬件平臺(tái)和控制策略,編寫程序?qū)崿F(xiàn)數(shù)據(jù)采集、處理和控制等功能。
【5】調(diào)試測試:將設(shè)計(jì)好的控制器與太陽能熱水器進(jìn)行連接測試,檢查數(shù)據(jù)采集、處理和控制等功能是否正常。
2.6 實(shí)現(xiàn)效果
本項(xiàng)目設(shè)計(jì)的太陽能熱水器控制器實(shí)現(xiàn)了對太陽能熱水器的水溫、水位等參數(shù)進(jìn)行準(zhǔn)確、穩(wěn)定的控制。
控制器的特點(diǎn):
【1】精度高:采用PID控制算法,能夠?qū)μ柲軣崴鞯乃疁?、水位等參?shù)進(jìn)行精確控制。
【2】控制穩(wěn)定:通過控制水泵、電磁閥等執(zhí)行器來實(shí)現(xiàn)對太陽能熱水器的水溫、水位等參數(shù)進(jìn)行穩(wěn)定控制。
【3】顯示直觀:通過顯示模塊可以直觀地顯示當(dāng)前的水溫、水位等參數(shù)。
三、代碼實(shí)現(xiàn)
3.1 DS18B20讀取溫度
以下是基于STC89C52單片機(jī)和DS18B20溫度傳感器實(shí)現(xiàn)讀取溫度值并打印到串口的示例:
#include <reg52.h>
#include <intrins.h>
#define DQ P3_7
typedef unsigned char uchar;
typedef unsigned int uint;
sbit LED=P1^0;
void Delay1ms(uint);
void Delay10us(uint);
uchar Init_DS18B20();
void Write_DS18B20(uchar dat);
uchar Read_DS18B20();
int Get_Temp();
void main()
{
uchar temp;
int temperature;
TMOD = 0x20; //定時(shí)器1工作在方式2
TH1 = 0xfd; //波特率9600
TL1 = 0xfd;
PCON = 0x00; //波特率不加倍
SCON = 0x50; //串口方式1,允許接收
TR1 = 1; //定時(shí)器1開始計(jì)時(shí)
ES = 1; //允許串口中斷
while(1)
{
temp = Get_Temp();
temperature = (int)temp * 0.0625 * 100; //將溫度值轉(zhuǎn)換為實(shí)際溫度,單位為°C
printf("Temperature: %d.%dC rn", temperature / 100, temperature % 100);
Delay1ms(500); //每隔500ms讀取一次溫度值并打印到串口
}
}
void Delay1ms(uint cnt)
{
uint i, j;
for (i = 0; i < cnt; i++)
{
for (j = 0; j < 110; j++);
}
}
void Delay10us(uint cnt)
{
while(cnt--);
}
uchar Init_DS18B20()
{
uchar i;
DQ = 1;
Delay10us(5);
DQ = 0;
Delay10us(80);
DQ = 1;
Delay10us(5);
i = DQ;
Delay10us(20);
return i;
}
void Write_DS18B20(uchar dat)
{
uchar i;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
DQ = dat & 0x01;
Delay10us(5);
DQ = 1;
dat >>= 1;
}
}
uchar Read_DS18B20()
{
uchar i, j, dat = 0;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
DQ = 1;
_nop_();
j = DQ;
Delay10us(5);
dat = (j << 7) | (dat >> 1);
}
return dat;
}
int Get_Temp()
{
uchar TL, TH;
int temp;
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay1ms(750);
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
TL = Read_DS18B20();
TH = Read_DS18B20();
temp = TH;
temp <<= 8;
temp |= TL;
return temp;
}
void UART_Isr() interrupt 4
{
if (RI == 1)
{
RI = 0;
}
if (TI == 1)
{
TI = 0;
}
}
代碼中使用了定時(shí)器和串口中斷,要注意DS18B20的引腳連接和串口通信的波特率設(shè)置。
3.2 PID算法控制溫度
以下是使用STC89C52單片機(jī)和DS18B20溫度傳感器通過PID算法實(shí)現(xiàn)熱水器恒溫控制的代碼:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit Relay = P1^0; // 繼電器控制引腳
// 溫度傳感器DS18B20相關(guān)宏定義
sbit DQ = P2^7; // DS18B20數(shù)據(jù)線引腳
#define DQ_OUT P2 &= 0x7F
#define DQ_IN P2 |= 0x80
// PID參數(shù)定義
float Kp = 1.0; // PID比例系數(shù)
float Ki = 0.5; // PID積分系數(shù)
float Kd = 0.2; // PID微分系數(shù)
// 溫度控制參數(shù)定義
float setTemp = 40.0; // 設(shè)定的目標(biāo)溫度
float curTemp = 0.0; // 當(dāng)前溫度
float lastTemp = 0.0; // 上一次的溫度
float error = 0.0; // 溫度誤差
float integral = 0.0; // 積分項(xiàng)
float derivative = 0.0; // 微分項(xiàng)
float output = 0.0; // 控制輸出
// 延時(shí)函數(shù)
void delay(uint t) {
while (t--);
}
// DS18B20初始化
uchar Init_DS18B20() {
uchar presence = 0;
DQ_OUT;
DQ = 0;
delay(480); // 延時(shí)480us
DQ = 1;
delay(60); // 延時(shí)60us
DQ_IN;
presence = DQ;
delay(420); // 延時(shí)420us
return presence;
}
// DS18B20讀取一個(gè)字節(jié)
uchar Read_DS18B20() {
uchar i, j, dat = 0;
for (i = 8; i > 0; i--) {
DQ_OUT;
DQ = 0;
dat >>= 1;
_nop_();
_nop_();
_nop_();
DQ = 1;
DQ_IN;
if (DQ) {
dat |= 0x80;
}
delay(120); // 延時(shí)120us
}
return dat;
}
// DS18B20寫入一個(gè)字節(jié)
void Write_DS18B20(uchar dat) {
uchar i;
for (i = 8; i > 0; i--) {
DQ_OUT;
DQ = 0;
DQ = dat & 0x01;
delay(120); // 延時(shí)120us
DQ = 1;
dat >>= 1;
}
}
// DS18B20溫度轉(zhuǎn)換
void Convert_DS18B20() {
Init_DS18B20();
Write_DS18B20(0xCC); // 跳過ROM操作
Write_DS18B20(0x44); // 啟動(dòng)溫度轉(zhuǎn)換
}
// 獲取DS18B20溫度值
float Get_DS18B20_Temp() {
uchar TL, TH;
int temp = 0;
Init_DS18B20();
Write_DS18B20(0xCC); // 跳過ROM操作
Write_DS18B20(0xBE); // 發(fā)送讀取命令
TL = Read_DS18B20(); // 讀取溫度低字節(jié)
TH = Read_DS18B20(); // 讀取溫度高字節(jié)
temp = TH;
temp <<= 8;
temp |= TL;
return (float)temp / 16.0; // 返回溫度值
}
// PID控制算法
float PID_Control(float setValue, float currentValue) {
error = setValue - currentValue;
integral += error;
derivative = currentValue - lastTemp;
output = Kp * error + Ki * integral + Kd * derivative;
lastTemp = currentValue;
return output;
}
void main() {
while (1) {
curTemp = Get_DS18B20_Temp(); // 獲取當(dāng)前溫度
output = PID_Control(setTemp, curTemp); // PID控制計(jì)算
if (output > 0) {
Relay = 0; // 繼電器閉合,加熱器工作
} else {
Relay = 1; // 繼電器斷開,加熱器停止工作
}
delay(1000); // 延時(shí)1s
}
}
3.3 驅(qū)動(dòng)BH1750光敏傳感器
使用STC89C52單片機(jī)讀取BH1750光敏傳感器值通過串口打印的代碼:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SDA = P2^7; // IIC總線數(shù)據(jù)線引腳
sbit SCL = P2^6; // IIC總線時(shí)鐘線引腳
// BH1750光敏傳感器相關(guān)宏定義
#define BH1750_ADDR 0x23 // BH1750設(shè)備地址
#define BH1750_ON 0x01 // BH1750上電命令
#define BH1750_OFF 0x00 // BH1750下電命令
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // BH1750連續(xù)高分辨率模式
// 延時(shí)函數(shù)
void delay(uint t) {
while (t--);
}
// IIC總線起始信號(hào)
void I2C_Start() {
SDA = 1;
delay(1);
SCL = 1;
delay(1);
SDA = 0;
delay(1);
SCL = 0;
delay(1);
}
// IIC總線停止信號(hào)
void I2C_Stop() {
SDA = 0;
delay(1);
SCL = 1;
delay(1);
SDA = 1;
delay(1);
}
// IIC總線發(fā)送應(yīng)答信號(hào)
void I2C_Ack() {
SDA = 0;
delay(1);
SCL = 1;
delay(1);
SCL = 0;
delay(1);
SDA = 1;
delay(1);
}
// IIC總線發(fā)送不應(yīng)答信號(hào)
void I2C_NAck() {
SDA = 1;
delay(1);
SCL = 1;
delay(1);
SCL = 0;
delay(1);
}
// IIC總線接收應(yīng)答信號(hào)
bit I2C_WaitAck() {
bit ack;
SDA = 1;
delay(1);
SCL = 1;
delay(1);
ack = SDA;
SCL = 0;
delay(1);
return ack;
}
// IIC總線發(fā)送一個(gè)字節(jié)
void I2C_WriteByte(uchar dat) {
uchar i;
for (i = 0; i < 8; i++) {
SDA = (dat & 0x80) >> 7;
dat <<= 1;
delay(1);
SCL = 1;
delay(1);
SCL = 0;
delay(1);
}
}
// IIC總線讀取一個(gè)字節(jié)
uchar I2C_ReadByte() {
uchar i, dat = 0;
SDA = 1;
delay(1);
for (i = 0; i < 8; i++) {
SCL = 1;
delay(1);
dat = (dat << 1) | SDA;
SCL = 0;
delay(1);
}
return dat;
}
// 初始化BH1750光敏傳感器
void Init_BH1750() {
I2C_Start();
I2C_WriteByte(BH1750_ADDR); // 發(fā)送設(shè)備地址
I2C_WaitAck();
I2C_WriteByte(BH1750_ON); // 上電
I2C_WaitAck();
I2C_Stop();
delay(5);
}
// 啟動(dòng)BH1750測量
void Start_BH1750() {
I2C_Start();
I2C_WriteByte(BH1750_ADDR); // 發(fā)送設(shè)備地址
I2C_WaitAck();
I2C_WriteByte(BH1750_CONTINUOUS_HIGH_RES_MODE); // 選擇連續(xù)高分辨率模式
I2C_WaitAck();
I2C_Stop();
delay(180);
}
// 讀取BH1750測量結(jié)果
uint Read_BH1750() {
uint value;
I2C_Start();
I2C_WriteByte(BH1750_ADDR + 1); // 發(fā)送設(shè)備地址,讀模式
I2C_WaitAck();
value = ((uint)I2C_ReadByte() << 8) | (uint)I2C_ReadByte(); // 讀取兩個(gè)字節(jié)的數(shù)據(jù)
I2C_NAck();
I2C_Stop();
return value;
}
// 串口發(fā)送一個(gè)字符
void UART_SendChar(uchar chr) {
SBUF = chr;
while (!TI);
TI = 0;
}
// 串口發(fā)送字符串
void UART_SendString(const uchar *str) {
while (*str) {
UART_SendChar(*str++);
}
}
// 串口發(fā)送一個(gè)無符號(hào)整數(shù)
void UART_SendUInt(uint val) {
uchar i, len;
uchar buf[5];
len = 0;
do {
buf[len++] = val % 10 + '0';
val /= 10;
} while (val);
for (i = len; i > 0; i--) {
UART_SendChar(buf[i-1]);
}
}
void main() {
uint lightValue;
Init_BH1750(); // 初始化BH1750光敏傳感器
// 串口初始化, 波特率9600
TMOD = 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
SCON = 0x50;
TR1 = 1;
while (1) {
Start_BH1750(); // 啟動(dòng)測量
lightValue = Read_BH1750(); // 讀取測量結(jié)果
UART_SendString("Light value: ");
UART_SendUInt(lightValue);
UART_SendString("rn");
delay(1000); // 延時(shí)1s
}
}
在程序中,初始化了BH1750光敏傳感器,使用Start_BH1750()函數(shù)啟動(dòng)測量,通過Read_BH1750()函數(shù)讀取測量結(jié)果,在串口上打印出來。串口的初始化設(shè)置為波特率9600,發(fā)送數(shù)據(jù)時(shí)使用UART_SendString()和UART_SendUInt()函數(shù)。
四、總結(jié)
本設(shè)計(jì)基于STC89C52單片機(jī)實(shí)現(xiàn)了一個(gè)功能完善的太陽能熱水器控制器。該控制器具有溫度控制、光照控制、時(shí)間控制和用戶交互等功能,可以提高太陽能熱水器的性能和便捷程度。通過合理的硬件選型和軟件設(shè)計(jì),使得系統(tǒng)能夠準(zhǔn)確、穩(wěn)定地實(shí)現(xiàn)對太陽能熱水器的控制,提高能源利用效率,并為用戶提供便利的操作界面。未來可以進(jìn)一步優(yōu)化和拓展該控制器,如增加遠(yuǎn)程控制功能、與智能家居系統(tǒng)的連接等,以滿足不同用戶的需求。