基于嵌入式的智能台灯系统

news2024/11/19 8:44:29

基于嵌入式的智能台灯系统

功能说明

通过微信小程序控制台灯的亮灭及亮度。采集温湿度传到微信小程序上,台灯可以显示实时北京时间。

功能展示

01智能台灯演示

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订阅的那个地址发布信息。

硬件制作


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

硬件选型

  • ESP32开发板(VSCode+PlatformIO环境)
  • DHT11温湿度传感器
  • 两颗LED灯(模拟台灯)
  • 0.96寸OLED屏
  • 杜邦线若干

硬件连接

在这里插入图片描述
如图所示,需要注意的是LED串联电阻1K到10K都可以,主要起限流作用。如果多个LED并联显示的话也可选择更小的。

硬件程序


程序采用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 = "";
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);
    // Lamp_Duty = Json["target"].as<String>();
    Lamp_Duty = Json["value"].as<unsigned char>();
    if (Lamp_Duty > 100)
        Lamp_Duty = 100;
    Lamp_Num = Json["num"].as<bool>();
    Debug = Json["debug"].as<unsigned char>();
    
    Serial.print("value:"); // 串口打印:来自订阅的主题:
    Serial.println(Lamp_Duty);           // 串口打印订阅的主题
    Serial.print("num:"); // 串口打印:来自订阅的主题:
    Serial.println(Lamp_Num);           // 串口打印订阅的主题
}

void WiFi_Click(void)
{
    while (WiFi.status() != WL_CONNECTED) // 若WiFi接入成功WiFi.status()会返回 WL_CONNECTED
    {
        Serial.println("连接wifi中"); // 串口输出:连接wifi中
        WiFi.begin(ssid, password);   // 接入WiFi函数(WiFi名称,密码)重新连接wif
        delay(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["temperature"] = Temp;
    jsonDocument["humidity"] = Humi;
    serializeJson(jsonDocument, payload); // 将j
    Serial.println(payload);
    client.publish(mqttpub, payload);     // 向服务器发送的信息(主题,内容)son转换为字符串
}

初始化、主函数及时间片

void Time_Slice(void)
{
    if (F_Time_10ms)
    {
        F_Time_10ms = 0;
        Display();
    }
    if (F_Time_100ms)
    {
        F_Time_100ms = 0;
        Log_Print();
        Ctrl_Lamp();
    }
    if (F_Time_2s)
    {
        F_Time_2s = 0;
        DHT11_Get();
        Pub_Mqtt();
        TimeClient.update();
        Serial.println(TimeClient.getFormattedTime());
    }
}

void setup()
{
    pinMode(LED_Pin_Gnd, OUTPUT);
    digitalWrite(LED_Pin_Gnd, 0);
    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();
    PWM_Init();
    TimeClient.begin();
    TimeClient.setTimeOffset(28800); //+1地区偏移3600
    u8g2.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();
}

硬件修改代码作为己用

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

初始化修改

#define LED_Pin 2		//系统LED灯 不用修改
#define DHT11_Pin 4		//DHT11连接的IO口 可修改
#define DHTTYPE DHT11	//DHT11	不用修改

#define Lamp_Pin1 12	//LED控制输出IO 可修改
#define Lamp_Pin2 13	//LED控制输出IO 可修改
#define LED_Pin_Gnd 14	//LED控制输出地 可修改

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函数中修改地方

    Lamp_Duty = Json["value"].as<unsigned char>();//接受的Json格式的键名称,跟你发送的对应起来,后边格式也要解析成相应格式
    if (Lamp_Duty > 100)		//这里可以做一些逻辑判断等
        Lamp_Duty = 100;
    Lamp_Num = Json["num"].as<bool>();
    Debug = Json["debug"].as<unsigned char>();

Pub_Mqtt函数中修改地方

jsonDocument["temperature"] = Temp;		//要发送的Json的键名称
jsonDocument["humidity"] = Humi;
serializeJson(jsonDocument, payload); 
Serial.println(payload);
client.publish(mqttpub, payload);     // 向服务器发送的信息(主题,内容)son转换为字符串

微信小程序制作


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

软件程序

  • 引入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的API
                      that.getLocation();
                    } else {
                      wx.showToast({
                        title: "授权失败",
                        icon: "none",
                        duration: 1000,
                      });
                    }
                  },
                });
              }
            },
          });
        } else if (res.authSetting["scope.userLocation"] == undefined) {
          //调用wx.getLocation的API
          that.getLocation();
        } else {
          //res.authSetting['scope.userLocation'] == true
          //调用wx.getLocation的API
          that.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, //填入自己申请到的Key
              location: 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, //填入自己申请到的Key
                  city: 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,
        })
      } catch (error) {
        console.log("JSON解析失败!");
      }
    })
  }

修改代码作为己用

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

程序初始化

const KEY = "1acc1391bf1593cf96f258d2f9ebe552";	//注意这里是高德地图的KEY 不是Mqtt服务器的KEY

const 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/88731183

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

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

相关文章

【机器学习】半监督学习

一、问题假设 要利用无标签样本进行训练&#xff0c;必须对样本的分布进行假设&#xff1f; 二、启发式算法 自训练和协同训练是两种常用的半监督学习的方法&#xff0c;它们的主要区别在于使用的模型的数量和类型。 自训练&#xff1a;自训练是一种使用单个模型的半监督学习的…

【EI会议征稿通知】2024年机器学习与智能计算国际学术会议(MLIC 2024)

2024年机器学习与智能计算国际学术会议&#xff08;MLIC 2024&#xff09; 2024 International Conference on Machine learning and intelligent computing 智能计算与机器学习被广泛应用于大数据分析、人工智能、智能制造、智能交通、智能电网、智慧城市、智慧医疗、金融科…

语境化语言表示模型-ELMO、BERT、GPT、XLnet

一.语境化语言表示模型介绍 语境化语言表示模型&#xff08;Contextualized Language Representation Models&#xff09;是一类在自然语言处理领域中取得显著成功的模型&#xff0c;其主要特点是能够根据上下文动态地学习词汇和短语的表示。这些模型利用了上下文信息&#xf…

人工智能行业的发展前景如何?

人工智能&#xff08;AI&#xff09;已经成为如今科技领域的热门话题之一&#xff0c;从图像识别到自动驾驶&#xff0c;从语音助手到智能机器人&#xff0c;AI技术正在改变我们的生活方式。随着技术的不断发展和应用的扩大&#xff0c;人工智能行业的发展前景无疑是非常广阔的…

ios 1x/2x/3x

asset文件下可以配置1x/2x/3x图&#xff0c;然后不同机型屏幕会根据[UIScreen mainScreen].scale,自动按需读取相关图片,imageView可以根据image自动适应,需求有个包体积优化&#xff0c;使用 3x图webp格式替换asset图片&#xff0c;由于代码没有根据image尺寸自适应没有进行si…

构建基于RHEL9系列(CentOS9,AlmaLinux9,RockyLinux9等)的Nginx1.24.0的RPM包

本文适用&#xff1a;rhel9系列&#xff0c;或同类系统(CentOS9,AlmaLinux9,RockyLinux9等) 文档形成时期&#xff1a;2023年 因系统版本不同&#xff0c;构建部署应略有差异&#xff0c;但本文未做细分&#xff0c;对稍有经验者应不存在明显障碍。 因软件世界之复杂和个人能力…

【JVM】初识 Jvm

目录 什么是JVM JVM 的功能 常见的JVM 什么是JVM JVM 的全程是 Java Virtual Machine ( java 虚拟机 &#xff09; JVM 是一种用于计算设备的规范&#xff0c;也是一个虚构出来的计算机&#xff0c;通过在实际的计算机上仿真模拟各种计算机功能实现&#xff0c;JVM 屏蔽了…

函数——自制函数(c++)

今天进入自制函数。 自制函数&#xff0c;需要自己定义其功能。比如&#xff0c;设置一个没有参数没有返回值的积木&#xff0c;叫“aaa”。那么&#xff0c;如果想要运行“aaa”&#xff0c;就需要以下代码&#xff1a; void aaa(); 告诉系统有“aaa”…

如何从多个文件夹里各提取相应数量的文件放一起到新文件夹中形成多文件夹组合

首先&#xff0c;需要用到的这个工具&#xff1a; 百度 密码&#xff1a;qwu2蓝奏云 密码&#xff1a;2r1z 说明一下情况 文件夹&#xff1a;1、2、3里面分别放置了各100张动物的图片&#xff0c;模拟实际情况的各种文件 操作&#xff1a;这里演示的是从3个文件夹里各取2张图…

恒创科技:解决Windows服务器磁盘空间不足的问题

​  服务器硬盘的大小是决定空间是否充足的主要因素。但在日常使用中&#xff0c;服务器和网站备份会消耗大量存储空间&#xff0c;如果维护不当&#xff0c;最终将耗尽您的容量。同样&#xff0c;日志文件、临时文件和数据库可以在硬盘驱动器上或回收站中无休止地建立。当您…

MidTool的GPT-4:开启智能语言新纪元

MidTool平台上的GPT-4是由OpenAI开发的最新一代语言预测模型。与前一代GPT-3相比&#xff0c;GPT-4在理解深度、文本生成的连贯性和创造性方面都有了显著的提升。这意味着用户可以期待更加自然、更加精准的交流体验&#xff0c;以及更高质量的内容创作。 1. 无缝对话体验 在M…

高效构建Java应用:Maven入门和进阶(四)

高效构建Java应用&#xff1a;Maven入门和进阶&#xff08;四&#xff09; 四. Maven聚合和继承特性4.1 Maven工程继承关系4.2 Maven工程聚合关系 四. Maven聚合和继承特性 4.1 Maven工程继承关系 继承概念 Maven 继承是指在 Maven 的项目中&#xff0c;让一个项目从另一个项目…

使用 Docker 部署 Halo 博客系统

:::info 项目地址&#xff1a;https://github.com/halo-dev/halo ::: 一、Halo 介绍 1&#xff09;Halo 简介 Halo 是一款强大易用的开源建站工具&#xff0c;它让你无需太多的技术知识就可以快速搭建一个博客、网站或者内容管理系统。具备可插拔架构、主题套用、富文本编辑器…

05-微服务Sentinel流量哨兵

一、Sentinel介绍 1.1 什么是Sentinel 分布式系统的流量防卫兵&#xff1a;随着微服务的普及&#xff0c;服务调用的稳定性变得越来越重要。Sentinel以“流量”为切入点&#xff0c;在流量控制、断路、负载保护等多个领域开展工作&#xff0c;保障服务可靠性。特点&#xff1…

MyBatis实战指南(二):工作原理与基础使用详解

MyBatis是一个优秀的持久层框架&#xff0c;它支持定制化SQL、存储过程以及高级映射。那么&#xff0c;它是如何工作的呢&#xff1f;又如何进行基础的使用呢&#xff1f;本文将带你了解MyBatis的工作原理及基础使用。 一、MyBatis的工作原理 1.1 MyBatis的工作原理 工作原理…

Vue基础-搭建Vue运行环境

这篇文章介绍了在Vue.js项目中进行开发环境搭建的关键步骤。包括node.js安装和配置、安装Vue及Vue CLI工具、安装webpack模板、安装vue-router、创建Vue项目等步骤。这篇文章为读者提供了清晰的指南&#xff0c;帮助他们快速搭建Vue.js开发环境&#xff0c;为后续的项目开发奠定…

小汪,TCP连接和断连夺命6连问你可能扛得住?

目录 TCP三次握手连接和四次挥手断连的几处疑问 一、建立连接&#xff0c;为什么是三次握手&#xff0c;而不是二次握手&#xff1f; 二、为什么每次建立 TCP 连接时&#xff0c;初始化的序列号都要求不一样呢&#xff1f; 三、断开连接&#xff0c;为什么是四次握手&#x…

HarmonyOS 开发基础(八)Row和Column

HarmonyOS 开发基础&#xff08;八&#xff09;Row和Column 一、Column 容器 1、容器说明&#xff1a; 纵向容器主轴方向&#xff1a;从上到下纵向交叉轴方向&#xff1a;从左到右横向 2、容器属性&#xff1a; justifyContent&#xff1a;设置子元素在主轴方向的对齐格式…

30道JVM综合面试题详解含答案(值得珍藏)

1. 描述一下JVM加载Class文件的原理机制? Java中的所有类&#xff0c;都需要由类加载器装载到JVM中才能运行。类加载器本身也是一个类&#xff0c;而它的工作就是把class文件从硬盘读取到内存中。在写程序的时候&#xff0c;我们几乎不需要关心类的加载&#xff0c;因为这些都…

流程控制详解

1、Java流程控制 主要涉及三大流程控制&#xff1a;顺序、分支、循环 如下图&#xff1a; 1&#xff09;流程2 存在对用户名和密码的校验&#xff0c;是否为空&#xff0c;存在分支控制 2&#xff09;流程3 用户名和密码在数据库是否存在&#xff0c;存在分支控制 3&#xf…