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

news2024/11/17 15:31:47

一、项目介绍

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

image-20230801105049392

二、系统构架

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温度传感器实现读取温度值并打印到串口的示例:

#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算法实现热水器恒温控制的代码:

#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光敏传感器值通过串口打印的代码:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/972464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt鼠标点击事件处理:按Escape键退出程序

创建项目 Qt 入门实战教程&#xff08;目录&#xff09; 首先&#xff0c;创建一个名称为QtKeyEscape的Qt默认的窗口程序。 参考 &#xff1a;Qt Creator 创建 Qt 默认窗口程序 Qt响应键盘Escape事件 打开Qt Creator >>编辑 >> 项目 >> Headers>> …

服务运营 | MS文章精读:基于强化学习和可穿戴设备的帕金森治疗方案

作者信息&#xff1a;庞硕&#xff0c;李舒湉 编者按 帕金森疾病的治疗是一个备受关注的医疗问题。本文通过患者的可穿戴传感器收集数据&#xff0c;提出了一个基于强化学习的帕金森药物治疗方案。这是第一篇关于可穿戴治疗设备在慢性疾病管理中的应用研究。原文于2023年4月发…

如何在你的Android工程中启用K2编译器?

如何在你的Android工程中启用K2编译器&#xff1f; K2编译器是用于Kotlin代码编译的最新、高效编译器&#xff0c;你现在可以尝试使用了。 Kotlin编译器正在为Kotlin 2.0进行重写&#xff0c;新的编译器实现&#xff08;代号K2&#xff09;带来了显著的构建速度改进&#xff…

K210-调用自定义py库

调用自定义py库 导入py库文件调用py库 用过Python的朋友应该知道&#xff0c;Python是支持将自定义py库&#xff08;或者第三方py库&#xff09;放到同一个目录下调用的&#xff0c;MicroPython也是支持调用自定义py库的。在调用自定义py库之前&#xff0c;需要提前将py库文件导…

期货基础知识

一、期货是什么&#xff1f;  期货是与现货相对应&#xff0c;并由现货衍生而来。期货通常指期货合约&#xff0c;期货与现货完全不同&#xff0c;现货是实实在在可以交易的货&#xff08;商品&#xff09;&#xff0c;期货主要不是货&#xff0c;而是以某种大众产品如棉花、大…

影响Windows 和 macOS平台,黑客利用 Adobe CF 漏洞部署恶意软件

FortiGuard 实验室的网络安全研究人员发现了几个影响 Windows 和 Mac 设备的 Adobe ColdFusion 漏洞。 远程攻击者可利用Adobe ColdFusion 2021中的验证前RCE漏洞&#xff0c;获取受影响系統的控制权力。Adobe 已发布安全补丁来解决这些漏洞&#xff0c;但攻击者仍在利用这些漏…

leetcode:1941. 检查是否所有字符出现次数相同(python3解法)

难度&#xff1a;简单 给你一个字符串 s &#xff0c;如果 s 是一个 好 字符串&#xff0c;请你返回 true &#xff0c;否则请返回 false 。 如果 s 中出现过的 所有 字符的出现次数 相同 &#xff0c;那么我们称字符串 s 是 好 字符串。 示例 1&#xff1a; 输入&#xff1a;s…

鼠标悬停阴影的效果被旁边div挡住的解决办法

出现的问题 需求要求鼠标悬停某个图片上有阴影效果&#xff0c;但阴影被旁边相邻的div挡住了&#xff0c;如图所示 解决方案 给悬停的这块div增加2个css属性 $(this).css(position, relative); $(this).css(z-index, 200);新的效果如图所示 一直写后端&#xff0c;前端的…

国际网页短信软件平台搭建定制接口说明|移讯云短信系统

国际网页短信软件平台搭建定制接口说明|移讯云短信系统 通道路由功能介绍 支持地区通道分流&#xff0c;支持关键字&#xff0c;关键词通道分流&#xff0c;支持白名单独立通道&#xff0c;支持全网通道分流&#xff0c;支持通道可发地区设置&#xff0c;通道路由分组&#x…

redis 数据结构(二)

整数集合 整数集合是 Set 对象的底层实现之一。当一个 Set 对象只包含整数值元素&#xff0c;并且元素数量不时&#xff0c;就会使用整数集这个数据结构作为底层实现。 整数集合结构设计 整数集合本质上是一块连续内存空间&#xff0c;它的结构定义如下&#xff1a; typed…

QT C++ 实现网络聊天室

一、基本原理及流程 1&#xff09;知识回顾&#xff08;C语言中的TCP流程&#xff09; 2&#xff09;QT中的服务器端/客户端的操作流程 二、代码实现 1&#xff09;服务器 .ui .pro 在pro文件中添加network库 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>…

春秋云镜 CVE-2018-12530

春秋云镜 CVE-2018-12530 Metinfo 6.0.0任意文件删除 靶标介绍 Metinfo 6.0.0任意文件删除。后台密码&#xff1a;f2xWcke5KN6pfebu 启动场景 漏洞利用 /admin进入管理后台&#xff0c;admin/f2xWcke5KN6pfebu /admin/app/batch/csvup.php?fileFieldtest-1&fliename…

目标检测框架MMDetection训练自定义数据集实验记录

在上一篇博文中&#xff0c;博主完成了MMDetection框架的环境部署与推理过程&#xff0c;下面进行该框架的训练过程&#xff0c;训练的入口文件为tools/train.py&#xff0c;我们需要配置的内容如下&#xff1a; parser.add_argument(--config,default"/home/ubuntu/prog…

算法通关村16关 | 滑动窗口最长字串专题

1. 最长字串专题 1.1 无重复字符的最长字串 题目 LeetCode3 给定一个字符串s&#xff0c;请你找出其中不含有重复字符的最长字串的长度。 思路 找最长字串&#xff0c;需要知道所有无重复字串的首和尾&#xff0c;找出其中最长的&#xff0c;最少两个指针才可以完成&#xff…

冠达管理:创业板是二板市场吗?二板市场起什么作用?

说到股市的各买卖板块&#xff0c;适当一部分投资者简单被主板、二板、三板这些词绕晕&#xff0c;其中二板商场一词关于有些投资者来说是比较生疏的&#xff0c;但面对创业板这一个不是主板但也没有说明是哪个层级的板块却熟悉许多&#xff0c;那么&#xff0c;创业板是不是便…

MySQL忘记密码了怎么办?如何重置修改密码?(Windows图文教程)

1. 如果服务在启动中&#xff0c;先停止MySQL服务 打开cmd&#xff0c;在命令窗口中输入net stop mysql 2. 跳过密码登录MySQL服务 mysqld --console --skip-grant-tables --shared-memory 输入以上代码 再次打开一个新的cmd窗口&#xff0c;原来的窗口不能关闭 在新的cmd窗口中…

冠达管理:股票隔夜挂单是怎么回事?股票挂单规则?

股票的买卖时刻是周一至周五上午9:30-11:30&#xff0c;下午13:00-15:00&#xff0c;一般投资者都是买卖日早上挂单&#xff0c;但也有一些投资者会在晚上隔夜挂单.那么&#xff0c;股票隔夜挂单是怎么回事&#xff1f;股票挂单规矩是什么&#xff1f;冠达管理为我们准备了相关…

C语言malloc函数学习

malloc的全称是memory allocation&#xff0c;中文叫动态内存分配&#xff0c;用于申请一块连续的指定大小的内存块区域&#xff0c;以void*类型返回分配的内存区域地址&#xff1b; 函数原型为void *malloc(unsigned int size)&#xff0c;在内存的动态存储区中分配一个长度为…

Python 内置函数详解 (1) 数学运算

近期在外旅游,本篇是出发前定时发布的,不完整,旅游回来后再补充。 Python 内置函数 Python3.11共有75个内置函数,其来历和分类请参考:Python 新版本有75个内置函数,你不会不知道吧_Hann Yang的博客-CSDN博客 函数列表 abs aiter all …

ESXI安装vCenter Server(VCSA)

概念说明ESXI安装 https://blog.csdn.net/tongxin_tongmeng/article/details/129466704 注意&#xff1a;ESXI-->主机-->硬件-->DSN服务器和网关信息-->VCSA安装时需要使用 VCSA下载 https://customerconnect.vmware.com/cn/home 注意&#xff1a;VCSA版本与ESXI版…