基于单片机的太阳能热水器控制器设计

一、项目介绍

随着环保意识的逐渐增强,太阳能热水器作为一种清洁能源应用得越来越广泛。然而,传统的太阳能热水器控制器通常采用机械式或电子式温控器,存在精度低、控制不稳定等问题。为了解决这些问题,本项目基于单片机技术设计了一款太阳能热水器控制器,主控芯片采用STC89C52。该控制器可以实现对太阳能热水器的水温、水位等参数进行准确、稳定的控制,提高了太阳能热水器的能源利用效率和使用寿命,同时也符合节能环保的社会需求。

二、系统构架

2.1 系统设计

本系统采用主从结构,由STC89C52单片机作为主控芯片,负责控制整个太阳能热水器的运行。系统包括传感器模块、驱动模块和用户界面模块。

传感器模块包括温度传感器和光照传感器,用于实时监测水温和太阳辐射强度。驱动模块包括电磁阀和水泵,用于控制水流和热水的循环。用户界面模块包括液晶显示屏和按键,用于显示当前状态和提供用户交互。

2.2 功能设计

本设计的太阳能热水器控制器功能:

  • 温度控制:通过温度传感器实时监测水温,并根据设定的阈值控制电磁阀和水泵,以保持热水器水温在设定范围内。
  • 光照控制:通过光照传感器实时监测太阳辐射强度,判断当前是否有足够的太阳能供给,若不足,则停止水泵运行,以节约能源。
  • 时间控制:设置定时计划,控制热水器在指定时间段内工作或停止工作。
  • 用户交互:通过液晶显示屏显示当前温度、工作状态等信息,并通过按键设定参数和操作热水器。

2.3 硬件设计

硬件设计包括电路连接和外围模块选择。主控芯片STC89C52与传感器模块、驱动模块和用户界面模块通过IO口进行连接。温度传感器采用DS18B20数字温度传感器,光照传感器采用光敏电阻。

2.4 软件设计

软件设计主要包括系统初始化、传感器数据采集、控制算法和用户交互等部分。系统初始化包括IO口配置、定时器设置等。传感器数据采集通过相应的接口获取温度和光照传感器数据。控制算法根据采集到的数据进行温度和光照控制,并控制电磁阀和水泵的开关。用户交互通过液晶显示屏和按键实现,用户可以通过按键设置参数和操作热水器。

2.5 设计思路

本项目的控制器主要包括传感器模块、控制模块和显示模块三部分。其中,传感器模块用于实时检测太阳能热水器的水温、水位等参数;控制模块将传感器采集到的数据进行处理,并通过控制水泵、电磁阀等执行器来实现对太阳能热水器的水温、水位等参数进行准确、稳定的控制;显示模块则用于显示当前的水温、水位等参数。

具体的设计流程如下:

【1】确定硬件平台:采用STC89C52单片机作为主控芯片,搭建传感器模块和执行器模块,通过串口通信与PC机连接。

【2】确定传感器类型:选择DS18B20温度传感器和液位传感器作为检测太阳能热水器水温、水位的传感器。

【3】确定控制策略:根据太阳能热水器的实际情况,设计PID控制算法,通过控制水泵、电磁阀等执行器来实现对太阳能热水器的水温、水位等参数进行准确、稳定的控制。

【4】编写程序:根据硬件平台和控制策略,编写程序实现数据采集、处理和控制等功能。

【5】调试测试:将设计好的控制器与太阳能热水器进行连接测试,检查数据采集、处理和控制等功能是否正常。

2.6 实现效果

本项目设计的太阳能热水器控制器实现了对太阳能热水器的水温、水位等参数进行准确、稳定的控制。

控制器的特点:

【1】精度高:采用PID控制算法,能够对太阳能热水器的水温、水位等参数进行精确控制。

【2】控制稳定:通过控制水泵、电磁阀等执行器来实现对太阳能热水器的水温、水位等参数进行稳定控制。

【3】显示直观:通过显示模块可以直观地显示当前的水温、水位等参数。

三、代码实现

3.1 DS18B20读取温度

以下是基于STC89C52单片机和DS18B20温度传感器实现读取温度值并打印到串口的示例:

cpp 复制代码
#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; //定时器1工作在方式2
    TH1 = 0xfd; //波特率9600
    TL1 = 0xfd;
    PCON = 0x00; //波特率不加倍
    SCON = 0x50; //串口方式1,允许接收
    TR1 = 1; //定时器1开始计时
    ES = 1; //允许串口中断
​
    while(1)
    {
        temp = Get_Temp();
        temperature = (int)temp * 0.0625 * 100; //将温度值转换为实际温度,单位为°C
        printf("Temperature: %d.%dC \r\n", 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;
    }
}

代码中使用了定时器和串口中断,要注意DS18B20的引脚连接和串口通信的波特率设置。

3.2 PID算法控制温度

以下是使用STC89C52单片机和DS18B20温度传感器通过PID算法实现热水器恒温控制的代码:

cpp 复制代码
#include <reg52.h>
#include <intrins.h>
​
#define uchar unsigned char
#define uint unsigned int
​
sbit Relay = P1^0;  // 继电器控制引脚
​
// 温度传感器DS18B20相关宏定义
sbit DQ = P2^7;     // DS18B20数据线引脚
#define DQ_OUT P2 &= 0x7F
#define DQ_IN  P2 |= 0x80
​
// PID参数定义
float Kp = 1.0;     // PID比例系数
float Ki = 0.5;     // PID积分系数
float Kd = 0.2;     // PID微分系数
​
// 温度控制参数定义
float setTemp = 40.0;    // 设定的目标温度
float curTemp = 0.0;     // 当前温度
float lastTemp = 0.0;    // 上一次的温度
float error = 0.0;       // 温度误差
float integral = 0.0;    // 积分项
float derivative = 0.0;  // 微分项
float output = 0.0;      // 控制输出
​
// 延时函数
void delay(uint t) {
    while (t--);
}
​
// DS18B20初始化
uchar Init_DS18B20() {
    uchar presence = 0;
    
    DQ_OUT;
    DQ = 0;
    delay(480);     // 延时480us
    DQ = 1;
    delay(60);      // 延时60us
    
    DQ_IN;
    presence = DQ;
    delay(420);     // 延时420us
    
    return presence;
}
​
// DS18B20读取一个字节
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);     // 延时120us
    }
    
    return dat;
}
​
// DS18B20写入一个字节
void Write_DS18B20(uchar dat) {
    uchar i;
    
    for (i = 8; i > 0; i--) {
        DQ_OUT;
        DQ = 0;
        DQ = dat & 0x01;
        delay(120);     // 延时120us
        DQ = 1;
        dat >>= 1;
    }
}
​
// DS18B20温度转换
void Convert_DS18B20() {
    Init_DS18B20();
    Write_DS18B20(0xCC);    // 跳过ROM操作
    Write_DS18B20(0x44);    // 启动温度转换
}
​
// 获取DS18B20温度值
float Get_DS18B20_Temp() {
    uchar TL, TH;
    int temp = 0;
    
    Init_DS18B20();
    Write_DS18B20(0xCC);    // 跳过ROM操作
    Write_DS18B20(0xBE);    // 发送读取命令
    
    TL = Read_DS18B20();    // 读取温度低字节
    TH = Read_DS18B20();    // 读取温度高字节
    
    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();   // 获取当前温度
        
        output = PID_Control(setTemp, curTemp);   // PID控制计算
        
        if (output > 0) {
            Relay = 0;  // 继电器闭合,加热器工作
        } else {
            Relay = 1;  // 继电器断开,加热器停止工作
        }
        
        delay(1000); // 延时1s
    }
}

3.3 驱动BH1750光敏传感器

使用STC89C52单片机读取BH1750光敏传感器值通过串口打印的代码:

cpp 复制代码
#include <reg52.h>
#include <intrins.h>
​
#define uchar unsigned char
#define uint unsigned int
​
sbit SDA = P2^7;    // IIC总线数据线引脚
sbit SCL = P2^6;    // IIC总线时钟线引脚
​
// BH1750光敏传感器相关宏定义
#define BH1750_ADDR 0x23   // BH1750设备地址
#define BH1750_ON   0x01   // BH1750上电命令
#define BH1750_OFF  0x00   // BH1750下电命令
#define BH1750_CONTINUOUS_HIGH_RES_MODE  0x10   // BH1750连续高分辨率模式
​
// 延时函数
void delay(uint t) {
    while (t--);
}
​
// IIC总线起始信号
void I2C_Start() {
    SDA = 1;
    delay(1);
    SCL = 1;
    delay(1);
    SDA = 0;
    delay(1);
    SCL = 0;
    delay(1);
}
​
// IIC总线停止信号
void I2C_Stop() {
    SDA = 0;
    delay(1);
    SCL = 1;
    delay(1);
    SDA = 1;
    delay(1);
}
​
// IIC总线发送应答信号
void I2C_Ack() {
    SDA = 0;
    delay(1);
    SCL = 1;
    delay(1);
    SCL = 0;
    delay(1);
    SDA = 1;
    delay(1);
}
​
// IIC总线发送不应答信号
void I2C_NAck() {
    SDA = 1;
    delay(1);
    SCL = 1;
    delay(1);
    SCL = 0;
    delay(1);
}
​
// IIC总线接收应答信号
bit I2C_WaitAck() {
    bit ack;
    
    SDA = 1;
    delay(1);
    SCL = 1;
    delay(1);
    ack = SDA;
    SCL = 0;
    delay(1);
    
    return ack;
}
​
// IIC总线发送一个字节
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总线读取一个字节
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);      // 发送设备地址
    I2C_WaitAck();
    I2C_WriteByte(BH1750_ON);        // 上电
    I2C_WaitAck();
    I2C_Stop();
    
    delay(5);
}
​
// 启动BH1750测量
void Start_BH1750() {
    I2C_Start();
    I2C_WriteByte(BH1750_ADDR);                  // 发送设备地址
    I2C_WaitAck();
    I2C_WriteByte(BH1750_CONTINUOUS_HIGH_RES_MODE);   // 选择连续高分辨率模式
    I2C_WaitAck();
    I2C_Stop();
    
    delay(180);
}
​
// 读取BH1750测量结果
uint Read_BH1750() {
    uint value;
    
    I2C_Start();
    I2C_WriteByte(BH1750_ADDR + 1);    // 发送设备地址,读模式
    I2C_WaitAck();
    value = ((uint)I2C_ReadByte() << 8) | (uint)I2C_ReadByte();   // 读取两个字节的数据
    I2C_NAck();
    I2C_Stop();
    
    return value;
}
​
// 串口发送一个字符
void UART_SendChar(uchar chr) {
    SBUF = chr;
    while (!TI);
    TI = 0;
}
​
// 串口发送字符串
void UART_SendString(const uchar *str) {
    while (*str) {
        UART_SendChar(*str++);
    }
}
​
// 串口发送一个无符号整数
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();         // 启动测量
        lightValue = Read_BH1750();   // 读取测量结果
        
        UART_SendString("Light value: ");
        UART_SendUInt(lightValue);
        UART_SendString("\r\n");
        
        delay(1000);   // 延时1s
    }
}

在程序中,初始化了BH1750光敏传感器,使用Start_BH1750()函数启动测量,通过Read_BH1750()函数读取测量结果,在串口上打印出来。串口的初始化设置为波特率9600,发送数据时使用UART_SendString()和UART_SendUInt()函数。

四、总结

本设计基于STC89C52单片机实现了一个功能完善的太阳能热水器控制器。该控制器具有温度控制、光照控制、时间控制和用户交互等功能,可以提高太阳能热水器的性能和便捷程度。通过合理的硬件选型和软件设计,使得系统能够准确、稳定地实现对太阳能热水器的控制,提高能源利用效率,并为用户提供便利的操作界面。未来可以进一步优化和拓展该控制器,如增加远程控制功能、与智能家居系统的连接等,以满足不同用户的需求。

相关推荐
uzong2 小时前
技术故障复盘模版
后端
GetcharZp2 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程3 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研3 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi3 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国4 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy4 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
AntBlack5 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt
bobz9655 小时前
pip install 已经不再安全
后端
寻月隐君6 小时前
硬核实战:从零到一,用 Rust 和 Axum 构建高性能聊天服务后端
后端·rust·github