当前位置: 首页 > news >正文

基于NodeMCU的物联网电灯控制系统设计

最终效果

基于NodeMCU的物联网电灯控制系统设计

小程序关灯

上图展现了小程序关灯过程的数据传输过程:用户下达关灯指令→小程序下发关灯指令→MQTT服务器接收关灯指令→下位机接收与处理关灯指令。

项目介绍

该项目是“物联网实验室监测控制系统设计(仿智能家居)”项目中的“家电控制设计”中的“电灯控制”子项目,最前者还包括“物联网设计”、“环境监测设计”、“门禁系统设计计”和“小程序设计”等内容。本文只介绍“电灯控制”部分。

项目功能实现的大致思路为:单片机先识别出当前处在的控制模式:为自动模式时,单片机采集光照传感器传来的光照强度数据,以此来控制灯的开闭;为手动模式时,用户的语音指令和小程序上的开关是一对双开关。单片机会识别这对双开关的最后一次命令,以此来控制灯的开闭。为自动模式或语音控制时,单片机会将灯的状态实时更新到MQTT服务器上,使小程序上的开关状态得到及时更新。控制模式通过语音指令切换。

硬件设计

接线

ESP-12F

GY-302

LU_ASR01

LED

3v3

VCC

5V

GND

GND

G

D1

SCL

D2

SDA

D7

+

D8

-

RX

TX

PCB设计

此电路板仅是为了代替杜邦线而已,上面只有引脚排座,而没有任何电子元件。

工程 - 立创开源硬件平台

成本

ESP-12F

GY-302

LU_ASR01

LED

27.9

7.4

47.5

2.5

其中共需85元左右来购买该项目所需的模块。此外还需1根数据线、焊接工具(电烙铁、锡丝、引脚排座)、PCB打板或若干杜邦线。

软件设计

LU-ASR01

该功能实现的原理及流程可参考:Arduino中借助LU-ASR01实现语音识别-CSDN博客

使用LU-ASR01语音识别开发板的语音识别功能。当语音识别模块识别到特定语音时,通过串口输出特定字符。此时,NodeMCU的串口会接收到这个特定字符,从而得知用户说出的特定语音。待识别语音、输出字符和输出语音之间的对应关系如下表所示:

待识别语音

输出字符

输出语音

自动模式

a

已进入自动模式

手动模式

m

已进入手动模式

开灯

1

已开灯

关灯

0

已关灯

代码

天问Block IDE中的程序如下:

ESP-12F

本次的开发环境为Arduino IDE,开发板型号为NodeMCU 0.9 (ESP-12 Module)。

本系统软件部分的流程如下图所示。初始化完成之后,系统默认进入自动模式(60LX为实验室环境昏暗与明亮的分界值)。之后会根据语音、小程序或光照值数据控制灯状态。

连接WiFi以及与MQTT服务器双向通信,可参考:利用ESP-01S中继实现STM32F103C8T6与MQTT服务器的串口双向通信_stm32串口接收esp01s数据-CSDN博客

获取光照强度,可参考:Arduino中使用GY-302测量环境中的光照强度-CSDN博客

解析JSON数据,可参考:Arduino中解析JSON数据-CSDN博客

控制LED,可参考:未完待续

代码

Arduino IDE中的程序如下:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Arduino.h>
#include <Wire.h> //IIC
#include <math.h>// 设置wifi接入信息和MQTT服务器
const char* wifiname = "DOILMSBOIOT";
const char* password = "doilmsboiot";
const char* mqttServer = "broker.emqx.io";bool receive_MQTT_message_flag = false;  //1表示收到来自MQTT的信息但还未处理,0表示未收到来自MQTT的信息或已处理WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);// 待解析的json文件
String json = "{\"lamp\":0}";// 创建DynamicJsonDocument对象
const size_t capacity = JSON_OBJECT_SIZE(1) + 24 ;   //1表示待解析的JSON对象中有1对数据,24为解析过程中需要的额外空间,可在此网站计算 https://arduinojson.org/v6/assistant/#/step1
DynamicJsonDocument doc(capacity);bool lamp_Bool_MQTT = false ; //  解析出的来自MQTT的灯的开关状态int BH1750address = 0x23;   //GY-302-BH1750的iic通讯地址
byte buff[2];   //用来储存GY-302-BH1750的iic传来的原始数据
long int light = 0;   //光照值char serial_information = '\0';    //从串口获得的信息bool auto_flag = true;  //是否为自动模式,即用光照传感器的值来决定灯的开关状态。它的反面为手动模式,可通过串口(语音)和MQTT(小程序)控制void setup() 
{Serial.begin(9600); WiFi.mode(WIFI_STA);    //设置ESP8266工作模式为无线终端模式connectWifi();    // 连接WiFimqttClient.setServer(mqttServer, 1883);   // 设置MQTT服务器和端口号mqttClient.setCallback(receiveCallback);    // 设置MQTT订阅回调函数connectMQTTserver();    // 连接MQTT服务器Wire.begin(); //iic启动led_initial();
}void loop() 
{  if (mqttClient.connected())   // 如果开发板成功连接服务器{ mqttClient.loop();          // 处理信息(收到信息后的回调函数)以及心跳} else                          // 如果开发板未能成功连接服务器{                      connectMQTTserver();        // 则尝试连接服务器并订阅主题}if (receive_MQTT_message_flag == 1) //收到来自MQTT的信息但还未处理{     deserializeJson(doc, json);  // 反序列化数据// 解析收到的数据信息lamp_Bool_MQTT = doc["lamp"].as<bool>();}BH1750_Init(BH1750address);if (BH1750_Read(BH1750address) == 2)    //如果光照模块有数据传来{light = ((buff[0] << 8) | buff[1]) / 1.2;Serial.print(light,DEC);Serial.println(" lx");}if (Serial.available() > 0)   //如果串口有数据传来{serial_information = Serial.read();Serial.print("接收到的串口数据为:");Serial.println(serial_information);}  if(serial_information == 'm')  //manual手动模式{auto_flag = false;serial_information = '\0';}if(serial_information == 'a')  //auto自动模式{auto_flag = true;serial_information = '\0';}if(auto_flag == true)  //如果为自动模式{if(light < 60)  //光线弱{turn_on_light();    //开灯pubMQTTmsg(true);}else    //光线强{turn_off_light();  //关灯pubMQTTmsg(false);}}else      //如果为手动模式,即可通过串口(语音)和MQTT(小程序)控制{if(serial_information == '1')  //收到的串口(语音)指令为开灯,且尚未处理此信息{turn_on_light();pubMQTTmsg(true);serial_information = '\0';}if(serial_information == '0')   //收到的串口(语音)指令为关灯,且尚未处理此信息{turn_off_light();pubMQTTmsg(false);serial_information = '\0';}if(receive_MQTT_message_flag == true && lamp_Bool_MQTT == true)  //收到的MQTT(小程序)指令为开灯,且尚未处理此信息{turn_on_light();receive_MQTT_message_flag = false;}if(receive_MQTT_message_flag == true && lamp_Bool_MQTT == false) //收到的MQTT(小程序)指令为关灯,且尚未处理此信息{turn_off_light();receive_MQTT_message_flag = false;}}delay(200);
}int BH1750_Read(int address) 
{int i = 0;Wire.beginTransmission(address);Wire.requestFrom(address, 2);while (Wire.available()) {buff[i] = Wire.read();  // receive one bytei++;}Wire.endTransmission();return i;
}void BH1750_Init(int address)
{Wire.beginTransmission(address);Wire.write(0x10);   Wire.endTransmission();
}// 连接MQTT服务器并订阅主题
void connectMQTTserver()
{// 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)String clientId = "esp8266-" + WiFi.macAddress();if (mqttClient.connect(clientId.c_str()))     //如果成功连接MQTT服务器{ Serial.print("MQTT Server Has Connected. ");Serial.print("Server Address: ");Serial.println(mqttServer);Serial.print("ClientId: ");Serial.println(clientId);subscribeTopic(); // 订阅指定主题} else {Serial.print("MQTT Server Connect Failed. Client State:");Serial.println(mqttClient.state());delay(3000);}   
}// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) 
{Serial.print("Message with the topic of [ ");Serial.print(topic);Serial.println(" ] has been received.");Serial.print("Content: ");for (int i = 0; i < length; i++) {Serial.print((char)payload[i]);json[i] = (char)payload[i];   //将收到的信息赋给json,以便后续解析和发射信号}Serial.println("");receive_MQTT_message_flag = 1;   //表示收到来自MQTT的信息但还未处理Serial.print("Message Length (Bytes) :  ");Serial.println(length);Serial.println(" ");
}void pubMQTTmsg(bool led_status)  //向MQTT发布消息
{String topicString = "deviceControl2";     //发布信息的主题char publishTopic[topicString.length() + 1];  strcpy(publishTopic, topicString.c_str());String messageString = led_status ? "{\"lamp\":true}" : "{\"lamp\":false}";      //发布信息的内容char publishMsg[messageString.length() + 1];   strcpy(publishMsg, messageString.c_str());if(mqttClient.publish(publishTopic, publishMsg, true))  //如果成功发布信息;publish函数第三个参数用于设置保留信息{Serial.print("Publish Topic: ");Serial.println(publishTopic);Serial.print("Publish Retained message: ");Serial.println(publishMsg); Serial.println("");   } else  //如果未能成功发布信息{Serial.println("Message Publish Failed."); }
}// 订阅指定主题
void subscribeTopic()
{String topicString = "deviceControl3/lamp";   // 订阅的主题名称char subTopic[topicString.length() + 1];  strcpy(subTopic, topicString.c_str());if(mqttClient.subscribe(subTopic))    //如果成功订阅主题{Serial.print("Subscrib Topic: ");Serial.println(subTopic);Serial.println("");} else {Serial.print("订阅主题失败");}  
}// ESP8266连接wifi
void connectWifi()  
{WiFi.begin(wifiname, password);Serial.println("Connecting to WiFi");while (WiFi.status() != WL_CONNECTED) //等待WiFi连接,当wifi未连接时,持续输出".";成功连接后输出连接成功信息{delay(1000);Serial.print(".");}Serial.println("");Serial.println("WiFi Connected!");  Serial.println(""); 
}void led_initial()  //灯初始化
{pinMode(D7, OUTPUT);pinMode(D8, OUTPUT);
}void turn_on_light()    //开灯
{digitalWrite(D7, HIGH);digitalWrite(D8, LOW);
}void turn_off_light()   //关灯
{digitalWrite(D7, LOW);digitalWrite(D8, HIGH);  
}

相关文章:

基于NodeMCU的物联网电灯控制系统设计

最终效果 基于NodeMCU的物联网电灯控制系统设计 小程序关灯 上图展现了小程序关灯过程的数据传输过程&#xff1a;用户下达关灯指令→小程序下发关灯指令→MQTT服务器接收关灯指令→下位机接收与处理关灯指令。 项目介绍 该项目是“物联网实验室监测控制系统设计&#xff08;…...

Linux驱动开发 IIC I2C驱动 编写APP访问EEPROM AT24C02

在嵌入式开发中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种常用的串行通信协议&#xff0c;广泛应用于与外设&#xff08;如 EEPROM、传感器、显示屏等&#xff09;进行数据交换。AT24C02 是一种常见的 I2C EEPROM 存储器&#xff0c;它提供 2Kbit…...

Linux应用软件编程-多任务处理(线程)

线程&#xff1a;轻量级的进程&#xff0c;线程的栈区独立&#xff08;8M&#xff09;&#xff0c;与同一进程中的其他线程共用进程的堆区&#xff0c;数据区&#xff0c;文本区。 进程是操作系统资源分配的最小单位&#xff1b;线程是cpu任务调度的最小单位。 1. 线程的创建…...

VITUREMEIG | AR眼镜 算力增程

根据IDC发布的《2024年第三季度美国AR/VR市场报告》显示&#xff0c;美国市场AR/VR总出货量增长10.3%。其中&#xff0c;成立于2021年的VITURE增长速度令人惊艳&#xff0c;同比暴涨452.6%&#xff0c;成为历史上增长最快的AR/VR品牌。并在美国AR领域占据了超过50%的市场份额&a…...

Jenkins管理多版本python环境

场景&#xff1a;项目有用到python3.8和3.9&#xff0c;python环境直接安装在jenkins容器内。 1、进入jenkins容器 docker exec -it jenkins /bin/bash 2、安装前置编译环境 # 提前安装&#xff0c;以便接下来的配置操作 apt-get -y install gcc automake autoconf libtool ma…...

Flutter富文本实现学习

Flutter 代码如何实现一个带有富文本显示和交互的页面。 前置知识点学习 RealRichText RealRichText 和 ImageSpan 不是 Flutter 框架中内置的组件&#xff0c;而是自定义的组件或来自第三方库。这些组件的实现可以提供比标准 RichText 更丰富的功能&#xff0c;比如在富文本…...

如何解决 OpenAI API 连接问题:降级 urllib3 版本

如何解决 OpenAI API 连接问题&#xff1a;降级 urllib3 版本 在使用 OpenAI API 时&#xff0c;很多开发者可能会遇到连接问题&#xff0c;特别是在使用 Python 代码与 OpenAI 进行交互时。常见的错误包括 ProxyError、SSLError 和 MaxRetryError&#xff0c;它们通常表示在通…...

【C语言】库函数常见的陷阱与缺陷(三):内存分配函数[4]--free

C语言中的free函数用于释放之前通过malloc、calloc或realloc动态分配的内存。然而,在使用free函数时,开发者可能会遇到一些陷阱和缺陷。 一、功能与用法 free 函数是 C 语言中用于释放动态分配内存的关键函数。在程序使用 malloc、calloc 或 realloc 等函数在堆上分配了内存…...

论文分享 | PromptFuzz:用于模糊测试驱动程序生成的提示模糊测试

大语言模型拥有的强大能力可以用来辅助多种工作&#xff0c;但如何有效的辅助仍然需要人的精巧设计。分享一篇发表于2024年CCS会议的论文PromptFuzz&#xff0c;它利用模型提示生成模糊测试驱动代码&#xff0c;并将代码片段嵌入到LLVM框架中执行模糊测试。 论文摘要 制作高质…...

AWS K8s 部署架构

Amazon Web Services&#xff08;AWS&#xff09;提供了一种简化的Kubernetes&#xff08;K8s&#xff09;部署架构&#xff0c;使得在云环境中管理和扩展容器化应用变得更加容易。这个架构的核心是AWS EKS&#xff08;Elastic Kubernetes Service&#xff09;&#xff0c;它是…...

JavaSE笔记(四)

Java泛型与集合类 在前面我们学习了最重要的类和对象,了解了面向对象编程的思想,注意,非常重要,面向对象是必须要深入理解和掌握的内容,不能草草结束。在本章节,我们会继续深入了解,从我们的泛型开始,再到我们的数据结构,最后再开始我们的集合类学习。 走进泛型 为…...

C语言基础——指针(5)

一&#xff0e; 函数指针变量 1. 函数指针变量的定义&#xff1a; 类比数组指针变量&#xff0c;数组指针变量是存放数组地址的变量&#xff0c;那么同理&#xff0c;函数指针变量就是存放函数地址的变量。 2. 创建函数指针变量&#xff1a; 函数是有地址的&#xff0…...

curl+openssl 踩坑笔记

curl编译&#xff1a;点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …...

Unity 实现Canvas显示3D物体

新建一个UI相机&#xff0c;选择渲染层为UI 将主相机的渲染层去掉UI层 、 将Canvas的RenderMode设置为Screen Space - Camera,将RenderCamera设置为UI相机 新建3D物体的UI父物体&#xff0c;并将3D物体的层级设置为UI层 适当的放缩3DObjParent&#xff0c;让3D物体能显示出来…...

【Docker命令】如何使用`docker exec`在容器内执行命令

大家好&#xff0c;今天我们来聊聊Docker容器管理中的一个非常有用的命令&#xff1a;docker exec。在日常工作中&#xff0c;我们经常需要在运行中的Docker容器内执行各种命令&#xff0c;docker exec正是帮助我们实现这一需求的利器。下面我将通过一个简单的例子&#xff0c;…...

NetSuite Formula(HTML)超链打开Transaction

当Saved Search作为Sublist应用在Form时&#xff0c;如果Document Number是Group过的&#xff0c;则会出现如下超链失效的情况。 解决办法&#xff1a; 可以利用Saved Search中的Formula&#xff08;HTML&#xff09;功能来构建超链&#xff0c;用于打开Transaction。 以下图…...

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…...

git clone ssh 设置代理

Linux配置方法 编辑 ~/.ssh/config 文件 Host github.com Hostname github.com ProxyCommand nc -v -x 127.0.0.1:1080 %h %pwindows配置方法 编辑 C:\Users\当前用户名.ssh\config 文件 Host github.com Hostname github.com ProxyCommand connect -S 127.0.0.1:1080 %h %…...

RK3568平台(USB篇)USB网络共享

使用RK的USB网络共享,在内核里面已经有了,这不需要自己写驱动程序,只需要把内核自带的USB网络共享的驱动添加上去即可。 一.RNDIS 协议简介 RNDIS 是微软定义的一种协议,它允许通过 USB 接口实现网络连接。通过 RNDIS,USB 设备可以充当网络适配器,允许主机通过 USB 与设…...

vite 打包时:JavaScript heap out of memory(内存溢出)

出错原因分析&#xff1a; 执行命令 npm run build 时出现以下错误提示&#xff1a; vite v3.2.7 building for production... 11:22:34 transforming (3) src\main.tsWARN Browserslist: caniuse…...

【服务器学习专栏 1.2 -- 带外管理】

请阅读 嵌入式学习必备专栏 文章目录 Overview服务器带外管理BMC 介绍BMC 特点BMC 工作原理 Overview 从技术的角度&#xff0c;网络管理可分为带外管理&#xff08;out-of-band&#xff09;和带内管理&#xff08;in-band&#xff09;两种管理模式。 带内管理&#xff0c;是指…...

微服务のGeteWay

目录 概念&#xff1a; 三大核心&#xff1a; 工作流程&#xff1a; 9527网关如何做路由映射&#xff1a; GetWay高级特性&#xff1a; 按服务名动态路由服务&#xff1a; 断言Route Predicate Factories &#xff1a; 获取当前时区时间&#xff1a; After Route &…...

html+css+js网页设计 美食 美食家6个页面

htmlcssjs网页设计 美食 美食家6个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…...

IntelliJ Idea常用快捷键详解

文章目录 IntelliJ Idea常用快捷键详解一、引言二、文本编辑与导航1、文本编辑2、代码折叠与展开 三、运行和调试四、代码编辑1、代码补全 五、重构与优化1、重构 六、使用示例代码注释示例代码补全示例 七、总结 IntelliJ Idea常用快捷键详解 一、引言 在Java开发中&#xff…...

服务器虚拟化:它是什么以及有什么好处?

运行虚拟服务器有助于创建更高效的 IT 基础架构。 随着业务每天收集的数据量逐年激增&#xff0c;传统的物理服务器已经无法单独满足业务需求。 相反&#xff0c;许多组织正在转向虚拟化的力量。 这是我们创建物理实体的虚拟版本的过程&#xff0c;在计算中&#xff0c;通常指…...

Python爬虫完整代码拿走不谢

对于新手做Python爬虫来说是有点难处的&#xff0c;前期练习的时候可以直接套用模板&#xff0c;这样省时省力还很方便。 使用Python爬取某网站的相关数据&#xff0c;并保存到同目录下Excel。 直接上代码&#xff1a; import re import urllib.error import urllib.request…...

MLA:多头潜在注意力

MLA:多头潜在注意力 多头潜在注意力(MLA)机制是一种在深度学习模型中用于处理序列数据的注意力机制的改进形式,以下是对其原理和示例的详细介绍: 原理 低秩键值联合压缩:MLA机制利用低秩键值联合压缩来消除注意力模块中的某些计算,从而提高模型的运行速度和性能。在传…...

阿里云大模型ACP高级工程师认证模拟试题

阿里云大模型ACP高级工程师认证模拟试题 0. 引言1. 模拟试题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题多选题单选题单选题单选题多选题多选题单选题多选题单…...

游戏引擎学习第67天

reviewing “apron”概念以更新区域 我们正在进行模拟区域的扩展工作&#xff0c;目标是通过增加一个更大的区域来支持更丰富的互动&#xff0c;尤其是那些可能超出摄像机视野的内容。现有的模拟区域包括摄像机能看到的区域和其周围的环境区域&#xff0c;但为了保证更高效的游…...

Nginx知识详解(理论+实战更易懂)

目录 一、Nginx架构和安装 1.1 Nginx 概述 1.1.1 nginx介绍 1.1.2?Nginx 功能介绍 1.1.3?基础特性 1.1.4?Web 服务相关的功能 1.2?Nginx 架构和进程 1.2.1?Nginx 进程结构 1.2.2?Nginx 进程间通信 1.2.3?Nginx 启动和 HTTP 连接建立 1.2.4?HTTP 处理过程 1…...