基于嵌入式的智能智能通风系统

基于嵌入式的智能智能通风系统

功能说明

通过微信小程序控制窗户的开关状体以及倒计时开关和定时开关,小程序上实时显示当前温度湿度和光照强度。

功能展示

02智能通风系统

Mqtt服务器

  • http://www.yoyolife.fun/iot:Mqtt服务器,我是在这里注册的,免费一个,之后每个2块钱每月。主要是结构简单,用起来容易。
  • 下位机即ESP32要选择mqtt地址:t.yoyolife.fun 端口:1883地址(里边有三个地址)
  • 微信小程序要选择mqtt:wss地址:t.yoyolife.fun/mqtt 端口:8084地址,不可选错
  • 两边的发布和订阅要对应起来,一个发布一个订阅,跟串口的Tx、Rx一样。服务器的主题可以随意定,意为服务器要监听哪个地址。
  • 设备ID即是用户名,密码即是密码。
  • 调试软件为mqttx,可自行下载https://mqttx.app/zh,调试下位机的时候可以连接上边提到的微信小程序8084那个端口,即服务器地址:wss://t.yoyolife.fun、端口:8084、Path:/mqtt、用户名即设备ID、密码即密码,然后订阅ESP32发布的那个地址,或者向ESP32订阅的那个地址发布信息。

程序思路

        下位机每隔1秒发送当前状态数据,上位机改变值之后发送一次当前改变的数据。下位机接收之后再去分析是哪个数据,再去解析。
        关于时间思路:接受NTP时间后,转为北京时间,然后将时间化为分钟,即小时x60+分钟。精度到分钟,然后秒等于0的话执行一次。然后上位机发送倒计时后,当前时间再加上倒计时的时间,得到一个时间A,当当前时间再走到时间A时就是倒计时结束的时间。关于定时开和定时关,也是如此,将时间化为分钟传递给下位机,下位机再获取当前时间去对比。

硬件制作


采用的是ESP32+微信小程序+Mqtt协议。

硬件选型

  • ESP32开发板(VSCode+PlatformIO环境)
  • DHT11温湿度传感器
  • 光敏电阻
  • 0.96寸OLED屏
  • SG90舵机(用来开关窗户)
  • 杜邦线若干

硬件连接

在这里插入图片描述
如图所示,需要注意的是光敏电阻接的是模拟位引脚,共电共地要外接可以找一排排针然后一端全部连在一起,板子3V3和GND出来后,分别插在一排上,然后需要共地和共电的地方插到排针上,注意千万要区分开来,否则短路会烧坏板子。

硬件程序


程序采用VSCode+PlatformIO环境。安装以下库

  • ArduinoJson 库:解析Mqtt协议收发的json格式数据。
  • DHT sensor library库:用于DHT11采集温湿度数据。
  • NTPClient 库:获取网络NTP时间。
  • PubSubClient 库:Mqtt通讯协议。
  • U8g2 库:OLED显示库。
代码展示

以下展示部分重要代码,完整完成在文章末尾。

Mqtt连接

const char *ssid = "Hide_2805";                            // ESP32连接的WiFi账号
const char *password = "asdfghjkl";                        // WiFi密码
const char *mqttServer = "t.yoyolife.fun";                 // 要连接到的服务器IP
const int mqttPort = 1883;                                 // 要连接到的服务器端口号
const char *mqttUser = "75bdfb62a1c56065949702a3a6430e38"; // MQTT服务器账号
const char *mqttPassword = "123465";                       // MQTT服务器密码
const char *mqttsub = "/iot/4432/wsy";                     // MQTT订阅主题
const char *mqttpub = "/iot/4432/waa";                     // MQTT发送主题WiFiClient espClient;                              // 定义wifiClient实例
PubSubClient client(espClient);                    // 定义PubSubClient的实例DynamicJsonDocument Json(1024);                    // 定义Json实例String Debug_Mqtt = "";// Mqtt回调函数
void callback(char *topic, byte *payload, unsigned int length)
{String Str = "";Serial.print("来自订阅的主题:"); // 串口打印:来自订阅的主题:Serial.println(topic);           // 串口打印订阅的主题Serial.print("信息:");          // 串口打印:信息:for (int i = 0; i < length; i++) // 使用循环打印接收到的信息{Serial.print((char)payload[i]);Str += (char)payload[i];}Serial.println();Serial.println("-----------------------");Debug_Mqtt = Str;deserializeJson(Json, Str);if (Json.containsKey("debug")){Debug = Json["debug"].as<unsigned char>();}// 倒计时if (Json.containsKey("time")){Time = Json["time"].as<unsigned char>();if (Time)Time = Now_Time + Time;}if (Json.containsKey("open")){Open_Time = Json["open"].as<unsigned int>();if(Open_Time)Open_State = 1;elseOpen_State = 0;}if (Json.containsKey("close")){Close_Time = Json["close"].as<unsigned int>();if(Close_Time)Close_State = 1;elseClose_State = 0;Serial.println("Close_Time");Serial.println(Close_Time);}if (Json.containsKey("Win_State")){Win_State = Json["Win_State"].as<bool>();if (Win_State)Ment = true;elseMent = false;}Serial.print("Json:");      // 串口打印:来自订阅的主题:Serial.println(Debug_Mqtt); // 串口打印订阅的主题
}void WiFi_Click(void)
{while (WiFi.status() != WL_CONNECTED) // 若WiFi接入成功WiFi.status()会返回 WL_CONNECTED{Serial.println("连接wifi中"); // 串口输出:连接wifi中WiFi.begin(ssid, password);   // 接入WiFi函数(WiFi名称,密码)重新连接wifdelay(2000);                  // 若尚未连接WiFi,则进行重连WiFi的循环}Serial.println("wifi连接成功");         // 连接wifi成功之后会跳出循环,串口并输出:wifi连接成功client.setServer(mqttServer, mqttPort); // MQTT服务器连接函数(服务器IP,端口号)client.setCallback(callback);           // 设定回调方式,当ESP32收到订阅消息时会调用此方法while (!client.connected())             // 是否连接上MQTT服务器{Serial.println("连接服务器中");                            // 串口打印:连接服务器中if (client.connect("ESP32Client", mqttUser, mqttPassword)) // 如果服务器连接成功{Serial.println("服务器连接成功"); // 串口打印:服务器连接成功}else{Serial.print("连接服务器失败"); // 串口打印:连接服务器失败Serial.print(client.state());   // 重新连接函数delay(2000);}}client.subscribe(mqttsub);                    // 连接MQTT服务器后订阅主题Serial.print("已订阅主题,等待主题消息...."); // 串口打印:已订阅主题,等待主题消息client.publish(mqttpub, "Hello from ESP32");  // 向服务器发送的信息(主题,内容)
}void Pub_Mqtt(void)
{char payload[200];StaticJsonDocument<200> jsonDocument; // 声明一个Json格式变量jsonDocument["windowstate"] = Ment;jsonDocument["temperature"] = Temp;jsonDocument["humidity"] = Humi;jsonDocument["light"] = Light;serializeJson(jsonDocument, payload);Serial.println(payload);client.publish(mqttpub, payload); // 向服务器发送的信息(主题,内容)son转换为字符串
}

主函数及时间片

// 时间片
void Time_Slice(void)
{if (F_Time_10ms){F_Time_10ms = 0;}if (F_Time_100ms){F_Time_100ms = 0;Display();Log_Print();// Ctrl_Motor();Ctrl_Window();}if (F_Time_500ms){F_Time_500ms = 0;Light = analogRead(LIGHT_PIN);Light = 100 - (Light * 100 / 4095);}if (F_Time_2s){F_Time_2s = 0;DHT11_Get();Pub_Mqtt();TimeClient.update();Serial.println(TimeClient.getFormattedTime());Hour = TimeClient.getHours();Min = TimeClient.getMinutes();Sec = TimeClient.getSeconds();Now_Time = Hour * 60 + Min;}if (F_Time_5s){F_Time_5s = 0;Serial.print("目前时间");Serial.println(Now_Time);Serial.print("开窗时间");Serial.println(Open_Time);Serial.print("关窗时间");Serial.println(Close_Time);Serial.print("倒计时时间");Serial.println(Time);}
}
// 初始化
void setup()
{Sys_Init();U8g2_Init();u8g2.setCursor(0, 8);u8g2.print("U8g2 OK!");u8g2.sendBuffer();Serial.begin(115200); // 串口函数,波特率设置u8g2.setCursor(0, 8 + 12 * 1);u8g2.print("串口 OK!");u8g2.sendBuffer();WiFi_Click();u8g2.setCursor(0, 8 + 12 * 2);u8g2.print("WiFi OK!");u8g2.sendBuffer();Timer0_Init();Motor_Init();TimeClient.begin();TimeClient.setTimeOffset(28800); //+1地区偏移3600u8g2.setCursor(0, 8 + 12 * 3);u8g2.print("NTP OK!");u8g2.sendBuffer();DHT.begin();u8g2.setCursor(0, 8 + 12 * 4);u8g2.print("DHT11 OK!");u8g2.sendBuffer();delay(2000);
}
// 主函数
void loop()
{client.loop(); // 回旋接收函数  等待服务器返回的数据Time_Slice();
}

舵机控制函数

// 控制窗户
void Ctrl_Window(void)
{if (Open_State){if (Open_Time == Now_Time){Ment = true;Open_State = 0;}}if (Close_State){if (Close_Time == Now_Time){Ment = false;Close_State = 0;}}if (Time){if (Time == Now_Time){Time = 0;Ment = !Ment;}}if (Ment){ledcWrite(2, 26);}else{ledcWrite(2, 70);}
}

硬件修改代码作为己用

用户如需借用代码,只需修改关键部分即可,例如Mqtt的Key、发布订阅地址,WiFi的账号密码等。

初始化修改

// 硬件宏定义
#define LED_Pin 2 // 板载LED
#define DHT11_Pin 4
#define DHTTYPE DHT11
#define LIGHT_PIN 33#define MOTOR_A1 12 // 预留步进电机
#define MOTOR_A2 14
#define MOTOR_A3 27
#define MOTOR_A4 26#define Lamp_Pin1 12
#define Lamp_Pin2 13
#define LED_Pin_Gnd 14
#define DuJ_Pin 25 // 开窗舵机const char *ssid = "Hide_2805";                            // ESP32连接的WiFi账号
const char *password = "asdfghjkl";                        // WiFi密码
const char *mqttServer = "t.yoyolife.fun";                 // 要连接到的服务器IP
const int mqttPort = 1883;                                 // 要连接到的服务器端口号
const char *mqttUser = "75bdfb62a1c56065949702a3a6430e38"; // MQTT服务器账号
const char *mqttPassword = "123465";                       // MQTT服务器密码
const char *mqttsub = "/iot/4432/wsy";                     // MQTT订阅主题
const char *mqttpub = "/iot/4432/waa";                     // MQTT发送主题

callback函数中修改地方

// 倒计时
if (Json.containsKey("time"))	// 判断当前接受的是哪个字符串
{Time = Json["time"].as<unsigned char>();	// 做一些处理if (Time)Time = Now_Time + Time;
}

Pub_Mqtt函数中修改地方

jsonDocument["windowstate"] = Ment;// 需要发布的Json键和值
jsonDocument["temperature"] = Temp;
jsonDocument["humidity"] = Humi;
jsonDocument["light"] = Light;

微信小程序制作


软件采用的是微信开发者工具,下载软件即可使用,无需复杂环境,成品直接发布就能使用,方便快捷。

软件程序

  • 引入Mqtt的js包。
  • 请求获取系统地址权限,请求天气API(高德),获取当地天气。
  • 请求Mqtt服务器,订阅相关地址。
  • 获取接受的数据,Json解析。
  • 按键像相关地址发布Json数据。

下边是具体代码。

天气数据

  getUserLocation: function () {let that = this;wx.getSetting({success: (res) => {console.log("天气", res);if (res.authSetting["scope.userLocation"] != undefined &&res.authSetting["scope.userLocation"] != true) {wx.showModal({title: "请求授权当前位置",content: "需要获取您的地理位置,请确认授权",success: function (res) {if (res.cancel) {wx.showToast({title: "拒绝授权",icon: "none",duration: 1000,});} else if (res.confirm) {wx.openSetting({success: function (dataAu) {if (dataAu.authSetting["scope.userLocation"] == true) {wx.showToast({title: "授权成功",icon: "success",duration: 1000,});//再次授权,调用wx.getLocation的APIthat.getLocation();} else {wx.showToast({title: "授权失败",icon: "none",duration: 1000,});}},});}},});} else if (res.authSetting["scope.userLocation"] == undefined) {//调用wx.getLocation的APIthat.getLocation();} else {//res.authSetting['scope.userLocation'] == true//调用wx.getLocation的APIthat.getLocation();}},});},getLocation() {let that = this;wx.getLocation({type: "wgs84",success(res) {console.log("经纬度", res);if (res?.errMsg === "getLocation:ok") {/* ----------------通过经纬度获取地区编码---------------- */wx.request({url: "https://restapi.amap.com/v3/geocode/regeo?parameters",data: {key: KEY, //填入自己申请到的Keylocation: res.longitude + "," + res.latitude, //传入经纬度},header: {"content-type": "application/json",},success: function (res) {console.log("坐标转换和查询天气", res.data);wx.setStorageSync("city",res.data.regeocode.addressComponent.adcode //地区编码);that.setData({location: res.data.regeocode.addressComponent.city +" " +res.data.regeocode.addressComponent.district,});wx.request({url: "https://restapi.amap.com/v3/weather/weatherInfo",data: {key: KEY, //填入自己申请到的Keycity: res.data.regeocode.addressComponent.adcode, //传入地区编码},header: {"content-type": "application/json",},success: function (weather) {console.log("天气", weather.data);that.setData({temp: weather.data.lives[0].temperature, //温度weatherText: weather.data.lives[0].weather, //天气描述 晴天 下雨天...welcome: "今天的天气是 " + weather.data.lives[0].weather + ",又是爱豆的一天!", //欢迎语});},});},});}},});},

Mqtt协议

  connectMqtt() {let that = this;const options = {connectTimeout: 4000,address: "t.yoyolife.fun/mqtt", //输入的地址port: 8084, //输入的端口号username: "75bdfb62a1c56065949702a3a6430e38", //输入的用户名password: "123465", //输入的密码};console.log("address是:", options.address);client = mqtt.connect(MQTTADDRESS, options); //连接client.on("connect", (e) => {console.log('连接成功');})client.on("reconnect", (error) => {console.log("正在重连:", error);wx.showToast({icon: "none",title: "正在重连",});});client.on("error", (error) => {console.log("连接失败:", error);wx.showToast({icon: "none",title: "mqtt连接失败",});});// 订阅一个主题let message = this.data.push;client.subscribe(this.data.push, {qos: 0}, function (err) {if (!err) {console.log("订阅成功", message);wx.showToast({icon: "none",title: "添加成功",});}});client.on("message", (topic, message) => {console.log("收到地址:", topic);console.log("收到消息:", message.toString());let getMessage = {}; //收到的消息try {getMessage = JSON.parse(message); //收到的消息转换成json对象console.log(getMessage);that.setData({temperature: getMessage.temperature,humidity: getMessage.humidity,light: getMessage.light,windowsta: getMessage.windowstate,})} catch (error) {console.log("JSON解析失败!");}})}

修改代码作为己用

用户如需借用代码,只需修改关键部分即可,例如Mqtt的Key、发布订阅地址,WiFi的账号密码等。

程序初始化

const KEY = "1acc1391bf1593cf96f258d2f9ebe552";	//注意这里是高德地图的KEY 不是Mqtt服务器的KEYconst app = getApp();
import mqtt from "../../utils/mqtt.min";		//加载的Mqtt协议的文件名
const MQTTADDRESS = "wxs://t.yoyolife.fun/mqtt"; //mqtt服务器地址

data中数据

    welcome: "你好,这里是Shiboven。",//主页显示push: "/iot/4432/waa", //订阅地址subscr: "/iot/4432/wsy", //发布地址

connectMqtt函数

    const options = {connectTimeout: 4000,		//重连时间address: "t.yoyolife.fun/mqtt", //Mqtt服务器地址port: 8084, //Mqtt服务器端口号username: "75bdfb62a1c56065949702a3a6430e38", //Mqtt用户名password: "123465", //Mqtt密码};

总结

项目本身功能简单,但是包含内容还是挺多的,扩展的话也比较容易。

项目地址:
https://download.csdn.net/download/weixin_42320020/88758864

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

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

相关文章

Web自动化测试中的接口测试

1、背景 1.1 Web程序中的接口 1.1.1 典型的Web设计架构 web是实现了基于网络通信的浏览器客户端与远程服务器进行交互的应用&#xff0c;通常包括两部分&#xff1a;web服务器和web客户端。web客户端的应用有html&#xff0c;JavaScript&#xff0c;ajax&#xff0c;flash等&am…

Linux下进程子进程的退出情况

进程的退出分为了两大类&#xff0c;一类是正常的退出&#xff0c;另一类是非正常的退出。 正常退出时有五种情况&#xff0c;分别是 ①main函数调用return ②进程调用exit(),标准c库 ③进程调用_exit()或者_Exit()&#xff0c;属于系统调用 ④进程最后一个线程返回 ⑤最…

linux单机部署mysql(离线环境解压即可)

一、下载官网压缩包&#xff08;tar.gz&#xff09; MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/根据自己的操作系统发行版本、位数、gclib版本、mysql版本来选择对应的压缩包 比如我是 linux系统debian10&#xff08;官网只有linux ge…

vue:菜单栏联动内容页面tab

一、需求 需要实现效果&#xff1a;左侧菜单栏与右侧内容部分联动&#xff0c;当点击左侧的菜单&#xff0c;右侧会展示对应的tab&#xff0c;没有点击时&#xff0c;不展示&#xff08;如刚进入页面没有点击菜单&#xff0c;则没有tab&#xff09;&#xff1b;点击后没有关闭…

玖章算术NineData通过阿里云PolarDB产品生态集成认证

近日&#xff0c;玖章算术旗下NineData 云原生智能数据管理平台 (V1.0&#xff09;正式通过了阿里云PolarDB PostgreSQL版 (V11)产品集成认证测试&#xff0c;并获得阿里云颁发的产品生态集成认证。 测试结果表明&#xff0c;玖章算术旗下NineData数据管理平台 (V1.0&#xff…

Maxwell介绍

一、介绍 介绍&#xff1a;它读取MySQL binlog并将数据更改作为JSON写入Kafka、Kinesis和其他流媒体平台&#xff08;目前支持&#xff1a;kafka、RabbitMQ、Redis、file、Kinesis、Nats、Google Cloud Pub/Sub、Google Cloud Bigquery、SNS&#xff09; 版本&#xff1a;从v1.…

【车载开发系列】Autosar DCM诊断管理模块

【车载开发系列】Autosar DCM诊断管理模块 【车载开发系列】Autosar DCM诊断管理模块 【车载开发系列】Autosar DCM诊断管理模块一. DCM模块概念二. DCM模块与Autosar其他模块关系1&#xff09;Dcm和PduR的交互2&#xff09;Dcm和ComM模块的交互3&#xff09;Dcm和Dem的交互4&a…

RocketMQ常见面试题及答案梳理

1、RocketMQ有什么作用&#xff1f; 异步:数据的产生方不需要关心谁来使用数据&#xff0c;只需要将数据发送到broker,后续需要管消费流程&#xff0c;Rocket也有保证消息可靠性的方案消峰&#xff1a;正常业务系统当流量激增时&#xff0c;有可能会将系统压垮&#xff0c;有了…

ChatGPT正确打开方式与GPT-4.5的key最新获取方式

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言4.5key价格泄漏ChatGPT4.0使用地址ChatGPT正确打开方式最新功能语音助手存档…

【2015~2024】大牛直播SDK演化史

大牛直播SDK的由来 大牛直播SDK始于2015年&#xff0c;最初我们只是想做个低延迟的RTMP推拉流解决方案&#xff0c;用于移动单兵等毫秒级延迟的场景下&#xff0c;我们先是实现了Android平台RTMP直播推送模块&#xff0c;当我们用市面上可以找到的RTMP播放器测试时延的时候&am…

网络设备的分类和功能、机柜布局、网络设备安装

网络互连设备根据不同层实现的机理不一样&#xff0c;又具体分为五类&#xff1a; 1、网络传输介质互联设备 2、网络物理层互联设备 3、数据链路层互联设备 4、网络层互联设备 5、应用层互联设备 常用设备 网络互联设备--互联设备 1、中继器 中继器是局域网互连的最简单…

恒创科技:云存储和网盘怎么区分出来?

随着互联网的发展&#xff0c;数据存储已成为人们日常生活中不可或缺的一部分。云存储和网盘是经常被人们提及的两种存储方式&#xff0c;均通过网络进行数据存储和访问的服务。但&#xff0c;它们在技术实现、数据安全性、访问方式和数据容量等方面存在一定的差异。要区分&…

三甲医院预约挂号系统源码,具备后台管理端和用户使用端,用户使用端包括:微信公众号、支付宝小程序

随着医疗行业的不断发展&#xff0c;预约挂号管理系统已成为医院管理中不可或缺的一部分。 预约挂号管理系统是一款综合性的预约挂号管理系统&#xff0c;帮助医院实现全方位的信息化管理&#xff0c;提高医疗服务质量和效率。支撑公众号、小程序、手机网上预约。 一款服务适用…

企业用户注册阿里云账号:为何选择企业实名认证及其五大优势

在数字化时代&#xff0c;云计算已成为企业运营不可或缺的一部分。阿里云&#xff0c;作为领先的云服务提供商&#xff0c;为企业用户提供了丰富的云产品和解决方案。但在享受这些服务之前&#xff0c;企业用户需要完成阿里云账号的注册和实名认证。本文将深入探讨为何企业用户…

小程序打包发行流程

工具 HBuilder X 、微信开发者工具、微信公众平台地址&#xff08;微信公众平台&#xff09; 配置 一、manifest.json 配置 通过 HBuilder X 打开 manifest.json 文件&#xff0c;找到 微信小程序配置&#xff0c;填写 微信小程序AppID&#xff0c;此 AppID 必须是本人有权…

Jvm相关知识(面试高级必备)

类的实例化顺序 先静态、先父后子 先静态&#xff1a;父静态>子静态 优先级&#xff1a;父类>子类 静态代码块>非静态代码块>构造函数 一个类的实例化过程&#xff1a; ①&#xff0e;父类的static代码块&#xff0c;当前类的static; ②&#xff0e;顺序执行…

freeswitch on centos dockerfile模式

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 centos7 docker上编译安装fs的流程记录&#xff0c;本文使用dockerfile模式。 环境 docker engine&#xff1a;Version 24.0.6 centos docker&#xff1a;7 freeswitch&#xff1a;v1.6.20 dockerfile 创建空目录…

力扣电话号码的组合

文章目录 题目说明做题思路代码实现代码解析 题目链接 题目说明 首先我们先分析一下这个题目题目中说呢先给出一个字符串这个字符串其实就是这个九键数字我们要按照要求将数字所代表的字符进行自由组合形成一个字符串并且这个字符串的长度和输入的数字字符串长度相同&#xff0…

第11章 GUI Page500~504 步骤三十二:打开画板文件02

各个图元类新增GetTypeName_Static()&#xff0c;并将原来的GetTypeName()改为调用静态方法实现&#xff1a; 直线&#xff1a; 圆&#xff1a; 十字&#xff1a; 矩形&#xff1a; 文字&#xff1a; tool_4_save_load.hpp添加两行 tool_4_save_load.cpp增加&#xff1a; 增加…

【资治通鉴】古代纪年法 ( 天干地支纪年法 | 木星纪年法 | 太岁纪年法 | 星次 | 天球 | 黄道带 | 四象二十八星宿 )

文章目录 一、天干地支纪年法二、木星纪年法1、星次2、天球3、黄道带 三、太岁纪年法四、四象二十八星宿1、四象与二十八星宿关联2、二十八星宿与星次关联3、西游记中的二十八星宿 2024 年 使用 天干地支纪年法是 甲辰年 , 使用 太岁纪年法是 阏逢执徐 ; 一、天干地支纪年法 天…