[作品提交] 【Follow me第二季第2期】任务汇总

sinc_sila   2024-10-16 00:18 楼主

  由于工作出差的原因,我未能在既定时间内完成任务,对此我深表歉意,并衷心感谢您给予我在规定时间之外完成任务的宝贵机会。

此次DigiKey与EEWorld共同发起的Follow me活动第二季的第二期,通过使用Arduino UNO R4 WiFi,为我提供了一个令人难忘的学习经历。

 

以下是此次任务的汇总报告:


购买原件展示:
1、Arduino UNO R4 WiFi

2、SHT40温湿度传感器扩展板

3、Qwiic连接线

 

Snipaste_2024-10-16_00-23-17.jpg

  Arduino UNO R4 WiFi是一款采用32位Arm® Cortex®-M4 Renesas RA4M1微控制器的开发板,集成了支持Wi-Fi®和蓝牙功能的ESP32模块,赋予了它强大的运算能力和丰富的连接选项。该板配备了32kB的SRAM和256kB的闪存,工作频率可达48MHz。其USB端口已升级至USB-C标准,并且最大电源供应电压提升至24V。此外,Arduino UNO R4 WiFi还提供了一个CAN总线接口,使得用户能够通过连接多个扩展板来简化布线并实现多样化的功能。板载的Qwiic连接器设计使得创建即插即用的项目变得轻而易举。

  SHT4x是一款高性能的数字传感器平台,专门设计用于精确测量不同精度级别的相对湿度和温度。该传感器通过I2C接口提供多个预设的I2C地址选项,同时维持极低的功耗水平,仅为0.4 μW。内置的电源调节加热器支持三个不同的加热等级,确保传感器能够在恶劣的环境条件下稳定运行。其四针双平面无引线封装设计非常适合于表面贴装技术(SMT)的应用,并可选择性地配备专利PTFE[1]薄膜或易于移除的保护盖。每款传感器均配有依据ISO17025标准的特定校准证书,并可通过独一无二的序列号进行识别。


任务思路:

一、搭建Arduino开发环境

  1. 硬件准备

  2. 软件准备

    • 安装Arduino IDE
    • 配置开发板型号和端口
  3. 入门任务:点灯

    • 编写简单的代码,通过Arduino控制LED灯的开关
    • 学习基本的数字输入输出操作
    • 串口通信
    • 使用Arduino的串口功能与计算机进行通信
    • 编写代码实现通过串口控制LED灯的状态

二、基础任务:LED矩阵+DAC正弦波+放大信号+ADC采集

  1. LED矩阵

    • 熟悉板载12x8 LED 矩阵的原理
    • 实现滚动类的显示
  2. DAC正弦波

    • 使用Arduino的DAC输出正弦波信号
    • 学习模拟输出的基本操作
  3. 放大信号

    • 使用OPAMP放大DAC输出的正弦波信号
    • 观察放大后的信号效果
  4. ADC采集

    • 使用Arduino的ADC功能采集外部模拟信号
    • 学习模拟输入的基本操作

三、进阶任务:通过UNRAID NAS系统中的docker搭建EMQX和Home Assistant

  1. UNRAID NAS系统配置

    • 安装并配置UNRAID NAS系统
    • 安装Docker并创建容器
  2. 搭建EMQX

    • 在Docker中安装并配置EMQX MQTT服务器
    • 确保EMQX能够正常运行并接受连接
  3. 搭建Home Assistant

    • 在Docker中安装并配置Home Assistant
    • 配置Home Assistant连接到EMQX MQTT服务器

四、实现MQTT控制与温湿度监测

  1. MQTT控制板载LED灯

    • 编写Arduino代码,使其能够通过MQTT协议接收Home Assistant的控制命令
    • 实现通过Home Assistant页面控制板载LED灯的功能
  2. 读取SHT40温湿度并通过MQTT上传

    • 连接SHT40温湿度传感器到Arduino
    • 编写代码读取温湿度数据并通过MQTT协议上传到Home Assistant
    • 在Home Assistant面板上显示实时温湿度数据

任务实现:

1、入门任务分帖:

环境搭建:

打开arduino软件,将开发板连接到电脑,选择对应的串口:

此时已完成了编写代码前的准备。

入门任务:点亮板载LED灯并且串口打印Hello EEWorld!

通过开发板提供的原理图我们可以看到用户LED的引脚为:DL4(黄色)。

打开文件--》示例--》Basics--》Bink 
创建一个Bink基础示例,并在此基础上增加串口打印。

未命名文件.png

 

Arduino的内置LED每隔一秒闪烁一次,并在每次LED状态改变时通过串口发送"Hello EEWorld!"消息:

void setup() {
  // 初始化内置LED引脚为输出模式。
  pinMode(LED_BUILTIN, OUTPUT);
  
  // 初始化串口通信,波特率为9600
  Serial.begin(9600);
}

// loop函数会无限次地反复运行
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // 打开LED(HIGH表示高电压水平)
  Serial.println("Hello EEWorld!"); // 通过串口打印消息
  delay(1000);                      // 等待一秒钟
  
  digitalWrite(LED_BUILTIN, LOW);   // 关闭LED,通过使电压变为LOW
  Serial.println("Hello EEWorld!"); // 再次通过串口打印消息
  delay(1000);                      // 等待一秒钟
}

效果展示视频:

【Follow me第二季第2期】入门任务 - 搭建环境 - Blink - 串口打印 - DigiKey得捷技术专区 - 电子工程世界-论坛

 

【Follow me第二季第2期】入门任务 - 搭建环境 - Blink - 串口打印 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)

2、基础任务分帖:

Arduino UNO R4 WiFi配有内置 12x8 LED 矩阵,可对其进行编程以显示图形、动画、充当界面,甚至玩游戏。

UNO R4 WiFi 的 LED 矩阵库的工作原理是创建一个帧,然后将其加载到显示该帧的缓冲区中。

帧就是我们所说的在任意给定时刻显示在矩阵上的“图像”。如果动画是一系列图像,则帧就是该系列中的其中一个图像。

为了控制 UNO R4 WiFi 上的 12x8 LED 矩阵,您需要至少 96 位大小的内存空间。该库提供了两种方法来做到这一点。

我们接下来的代码将使用官方提供的LED 矩阵工具来创建:

按照上述步骤,我们让led矩阵分别"DigKey”的两个首字母“D”和“K”,间隔时间500ms。

 

未命名文件 (2).png
// 引入Arduino_LED_Matrix库,用于控制LED矩阵
#include "Arduino_LED_Matrix.h"

// 创建一个ArduinoLEDMatrix对象,用于操作LED矩阵
ArduinoLEDMatrix matrix;

void setup() {
  // 初始化串口通信,波特率为115200
  Serial.begin(115200);
  // 初始化LED矩阵
  matrix.begin();
}

// 定义一个常量数组D,用于存储字母"D"的LED矩阵数据
const uint32_t D[] = {
  0x1e011010,
  0x81081081,
  0x81101e0,
};

// 定义一个常量数组K,用于存储字母"K"的LED矩阵数据
const uint32_t K[] = {
  0x10813014,
  0x1801401,
  0x30108108,
};

void loop(){
  // 将字母"D"的LED矩阵数据加载到matrix对象中,并显示在LED矩阵上
  matrix.loadFrame(D);
  // 延时500毫秒,让字母"D"显示一段时间
  delay(500);

  // 将字母"K"的LED矩阵数据加载到matrix对象中,并显示在LED矩阵上
  matrix.loadFrame(K);
  // 延时500毫秒,让字母"K"显示一段时间
  delay(500);
}

效果展示:

【Follow me第二季第2期】LED矩阵+DAC正弦波+放大信号+ADC采集 - DigiKey得捷技术专区 - 电子工程世界-论坛

 

未命名文件 (1).png

 

滚动文本代码:

// 引入Arduino图形库和LED矩阵库
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"

// 创建一个ArduinoLEDMatrix对象,用于控制LED矩阵
ArduinoLEDMatrix matrix;

void setup() {
  // 初始化LED矩阵
  matrix.begin();
}

void loop() {
  // 开始绘制图形
  matrix.beginDraw();

  // 设置画笔颜色为白色(0xFFFFFFFF表示ARGB格式的白色)
  matrix.stroke(0xFFFFFFFF);
  // 设置文本滚动速度为100毫秒
  matrix.textScrollSpeed(100);

  // 定义要显示的文本内容
  const char text[] = "  EEWorld!  ";
  // 设置文本字体为5x7点阵字体
  matrix.textFont(Font_5x7);
  // 设置文本起始位置和颜色(0, 1表示从第二行开始,0xFFFFFF表示白色)
  matrix.beginText(0, 1, 0xFFFFFF);
  // 在LED矩阵上打印文本
  matrix.println(text);
  // 设置文本滚动方向为向左滚动
  matrix.endText(SCROLL_LEFT);

  // 结束绘制图形
  matrix.endDraw();
}

代码效果:

【Follow me第二季第2期】LED矩阵+DAC正弦波+放大信号+ADC采集 - DigiKey得捷技术专区 - 电子工程世界-论坛_2

DAC正弦波:

Arduino UNO R4 WiFi 具有内置DAC (数模转换器),用于将数字信号转换为模拟信号。此功能可用于构建大量有趣的音频项目,但也可用作专业实验室设备,例如廉价的函数发生器。

接线方式:

未命名文件 (3).png

用OPAMP放大DAC信号;用ADC采集并且打印数据到串口:

#include "analogWave.h" // 包含用于模拟波形生成的库
#include <OPAMP.h> // 包含OPAMP库

analogWave wave(DAC); // 创建一个analogWave类的实例,使用DAC引脚

int freq = 10; // 频率,单位为赫兹,可根据需要更改
unsigned long previousMillis = 0; // 存储上一次读取ADC值的时间
const unsigned long interval = 10; // 读取ADC值的时间间隔,单位为毫秒

void setup() {
  Serial.begin(921600); // 初始化串行通信,波特率为921600
  wave.sine(freq); // 生成初始频率的正弦波

  OPAMP.begin(OPAMP_SPEED_LOWSPEED); // 初始化OPAMP为低速模式

  analogReadResolution(12); // 将模拟读取分辨率更改为12位
}

void loop() {
  unsigned long currentMillis = millis(); // 获取当前时间

  // 每隔interval毫秒读取一次ADC值
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis; // 更新上一次读取的时间

    int adcValue = analogRead(A5); // 返回0-4095之间的值
    Serial.println(adcValue); // 将ADC值打印到串行监视器
  }

}

串口波形显示:

 

【Follow me第二季第2期】LED矩阵+DAC正弦波+放大信号+ADC采集 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)

3、进阶任务1分帖:

通过Wi-Fi,利用MQTT协议接入HA:

MQTT部署:

我通过UNRAID NAS系统中的Docker部署EMQX:

通过18083端口来进行web端访问:

测试MQTT连接:

未命名文件 (4).png

1.Arduino UNO R4 WiFi 烧录以下代码:

#include <ArduinoMqttClient.h> // 引入MQTT客户端库
#include <WiFiS3.h> // 引入WiFi库
#include <WiFiClient.h> // 引入WiFi客户端库

char ssid[] = "Sinc"; // WiFi网络名称
char pass[] = "xc12345678"; // WiFi密码
int status = WL_IDLE_STATUS; // WiFi连接状态

const char broker[] = "xxxx"; // MQTT代理服务器地址
int port = 1883; // MQTT代理服务器端口
const char topic[] = "Aht10"; // MQTT主题

WiFiClient wifiClient; // 创建WiFi客户端对象
MqttClient mqttClient(wifiClient); // 创建MQTT客户端对象,并传入WiFi客户端对象

void setup() {
 Serial.begin(9600); // 初始化串口通信
 while (!Serial) {} // 等待串口监视器打开

 if (WiFi.status() == WL_NO_MODULE) {
   Serial.println("与WiFi模块通信失败!"); // 如果没有检测到WiFi模块,则停止程序
   while (true);
 }

 String fv = WiFi.firmwareVersion(); // 获取WiFi固件版本
 if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
   Serial.println("请升级固件"); // 如果固件版本过低,则提示升级
 }

 // 尝试连接到WiFi网络
 while (status != WL_CONNECTED) {
   Serial.print("尝试连接到WPA SSID: ");
   Serial.println(ssid);
   status = WiFi.begin(ssid, pass); // 连接到WiFi网络
   delay(10000); // 等待10秒看是否连接成功
 }

 Serial.println("已连接到网络"); // 连接成功后的提示
 printCurrentNet(); // 打印当前网络信息
 printWifiData(); // 打印WiFi数据

 // 尝试连接到MQTT代理服务器
 if (!mqttClient.connect(broker, port)) {
   Serial.print("MQTT连接失败!错误代码 = ");
   Serial.println(mqttClient.connectError()); // 如果连接失败,则打印错误代码
   while (1); // 停止程序
 }
 Serial.println("已连接到MQTT"); // 连接成功后的提示
}

// 打印当前网络信息
void printCurrentNet() {
 Serial.print("SSID: "); Serial.println(WiFi.SSID()); // 打印网络名称
 byte bssid[6]; WiFi.BSSID(bssid); printMacAddress(bssid); // 打印路由器MAC地址
 Serial.print("信号强度 (RSSI):"); Serial.println(WiFi.RSSI()); // 打印信号强度
 Serial.print("加密类型: "); Serial.println(WiFi.encryptionType(), HEX); // 打印加密类型
 Serial.println();
}

// 打印MAC地址
void printMacAddress(byte mac[]) {
 for (int i = 0; i < 6; i++) {
   if (i > 0) Serial.print(":");
   if (mac[i] < 16) Serial.print("0");
   Serial.print(mac[i], HEX);
 }
 Serial.println();
}

// 打印WiFi数据
void printWifiData() {
 IPAddress ip = WiFi.localIP(); // 获取本地IP地址
 Serial.print("IP地址: "); Serial.println(ip); // 打印IP地址
 byte mac[6]; WiFi.macAddress(mac); Serial.print("MAC地址: "); printMacAddress(mac); // 打印MAC地址
}

// 主循环
void loop() {
 mqttClient.beginMessage(topic); // 开始发送MQTT消息
 mqttClient.print("Hello EEworld and Digikey!"); // 发送消息内容
 mqttClient.endMessage(); // 结束发送MQTT消息
 delay(1000); // 延迟1秒
}

烧录后串口通讯显示:

 

下载MQTT 客户端工具可以直观的观察到MQTT主题通讯:

Home Assistant部署:

同样UNRAID NAS系统中的Docker部署Home Assistant

通过18083端口来进行web端访问:

配置MQTT:

参考官方配置方式: MQTT - Home Assistant (home-assistant.io)

配置-->设备与服务-->集成-->添加集成-->搜索MQTT-->点击配置域名端口等信息:

然后完成就配置成功了,下面是成功界面

通过配置configuration.yml文件,在Home Assistant首页创建了一个开关控制板载LED灯:

找到homeassistant的根目录中的configuration.yml文件打开:

在此代码基础上增加以下代码:

mqtt:
  switch:
    - unique_id: R4_led         #设备ID
      name: "R4_led"            #设备名称
      state_topic: "Aht10"      #订阅端口
      command_topic: "Aht10"    #同上
      payload_on: "1"           #开灯的指令
      payload_off: "2"          #关灯的指令

保存代码后重启homeassistant,显示以下按钮表示创建成功:

未命名文件 (5).png

修改代码来控制板载led:

#include <ArduinoMqttClient.h> // 引入MQTT客户端库
#include <WiFiS3.h> // 引入WiFi库
#include <WiFiClient.h> // 引入WiFi客户端库

char ssid[] = "Sinc"; // WiFi网络名称
char pass[] = "xc12345678"; // WiFi密码
int status = WL_IDLE_STATUS; // WiFi连接状态

const char broker[] = "XXXX"; // MQTT代理服务器地址
int port = 1883; // MQTT代理服务器端口
const char topic[] = "Aht10"; // MQTT主题

WiFiClient wifiClient; // 创建WiFi客户端对象
MqttClient mqttClient(wifiClient); // 创建MQTT客户端对象,并传入WiFi客户端对象

void setup() {
  Serial.begin(9600); // 初始化串口通信
  while (!Serial) {} // 等待串口监视器打开

// 初始化内置LED引脚为输出模式。
  pinMode(LED_BUILTIN, OUTPUT);

  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("与WiFi模块通信失败!"); // 如果没有检测到WiFi模块,则停止程序
    while (true);
  }

  // 尝试连接到WiFi网络
  while (status != WL_CONNECTED) {
    Serial.print("尝试连接到WPA SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass); // 连接到WiFi网络
    delay(10000); // 等待10秒看是否连接成功
  }

  Serial.println("已连接到网络"); // 连接成功后的提示
  printCurrentNet(); // 打印当前网络信息
  printWifiData(); // 打印WiFi数据

  // 尝试连接到MQTT代理服务器
  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT连接失败!错误代码 = ");
    Serial.println(mqttClient.connectError()); // 如果连接失败,则打印错误代码
    while (1); // 停止程序
  }
  Serial.println("已连接到MQTT"); // 连接成功后的提示

   // 订阅主题
 mqttClient.subscribe(topic);

 Serial.print("等待主题上的消息: ");
 Serial.println(topic);
 Serial.println();

   // 设置消息接收回调
 mqttClient.onMessage(onMqttMessage);

}

void printCurrentNet() {
  Serial.print("SSID: "); Serial.println(WiFi.SSID()); // 打印网络名称
  byte bssid[6]; WiFi.BSSID(bssid); printMacAddress(bssid); // 打印路由器MAC地址
  Serial.print("信号强度 (RSSI):"); Serial.println(WiFi.RSSI()); // 打印信号强度
  Serial.print("加密类型: "); Serial.println(WiFi.encryptionType(), HEX); // 打印加密类型
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 0; i < 6; i++) {
    if (i > 0) Serial.print(":");
    if (mac[i] < 16) Serial.print("0");
    Serial.print(mac[i], HEX);
  }
  Serial.println();
}

void printWifiData() {
  IPAddress ip = WiFi.localIP(); // 获取本地IP地址
  Serial.print("IP地址: "); Serial.println(ip); // 打印IP地址
  byte mac[6]; WiFi.macAddress(mac); Serial.print("MAC地址: "); printMacAddress(mac); // 打印MAC地址
}

void loop() {
 // 定期调用poll()以允许库接收MQTT消息并
 // 发送MQTT保持活动信号,以避免被代理断开连接
 mqttClient.poll();
}

void onMqttMessage(int messageSize) {
  // 我们收到了一条消息,打印出主题和内容
  Serial.println("收到一条消息:");
  Serial.print(mqttClient.messageTopic());
  Serial.print(", 长度 ");
  Serial.print(messageSize);
  Serial.println(" 字节:");

  // 使用Stream接口打印内容
  String message;
  while (mqttClient.available()) {
    message += (char)mqttClient.read();
  }
  Serial.println(message);

  // 检查消息内容并控制LED
  if (message == "1") {
    digitalWrite(LED_BUILTIN, HIGH); // 打开LED
    Serial.println("LED_BUILTIN 已打开");
  } else if (message == "2") {
    digitalWrite(LED_BUILTIN, LOW); // 关闭LED
    Serial.println("LED_BUILTIN 已关闭");
  }

  Serial.println();
}

串口显示消息:

视频效果展示:

【Follow me第二季第2期】进阶任务 :通过Wi-Fi,利用MQTT协议接入HA - DigiKey得捷技术专区 - 电子工程世界-论坛

【Follow me第二季第2期】进阶任务 :通过Wi-Fi,利用MQTT协议接入HA - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)

4、进阶任务2分帖:

将UNO R4 WiFi模块连接到外部的SHT40传感器,并通过MQTT协议将数据上传到Home Assistant。

硬件准备

Arduino UNO R4

SHT40温湿度传感器

使用 Arduino IDE 中的库管理器安装适用于 Arduino 的 Adafruit SHT4X 库

将范例简化后的代码:

未命名文件 (7).png
#include "Adafruit_SHT4x.h" // 引入SHT40传感器的Adafruit库
Adafruit_SHT4x sht4; // 创建SHT40传感器对象

void setup() {
  Serial.begin(115200); // 初始化串口通信,波特率为115200
  Serial.println(F("SGP40 test with SHT40 compensation")); // 打印开始测试的信息

  // 设置SHT40传感器的测量精度
  sht4.setPrecision(SHT4X_HIGH_PRECISION); // 设置为高精度
  // 根据设置的精度打印信息
  switch (sht4.getPrecision()) {
    case SHT4X_HIGH_PRECISION: 
      Serial.println(F("SHT40 set to High precision")); // 高精度
      break;
    case SHT4X_MED_PRECISION: 
      Serial.println(F("SHT40 set to Medium precision")); // 中精度
      break;
    case SHT4X_LOW_PRECISION: 
      Serial.println(F("SHT40 set to Low precision")); // 低精度
      break;
  }

  // 配置SHT40传感器的内置加热器状态
  sht4.setHeater(SHT4X_NO_HEATER); // 关闭加热器
  // 打印当前加热器的状态
  switch (sht4.getHeater()) {
    case SHT4X_NO_HEATER: 
      Serial.println(F("SHT40 Heater turned OFF")); // 加热器关闭
      break;
    // 其他加热器设置...
  }

  // 初始化SHT40传感器
  if (!sht4.begin(&Wire1)) { // 如果传感器初始化失败
    Serial.println(F("SHT40 sensor not found!")); // 打印错误信息
    while (1); // 停止程序执行
  } else {
    Serial.print(F("SHT40 detected!\t")); // 打印传感器检测到的信息
    Serial.print(F("Serial number:\t")); // 打印序列号信息
    Serial.println(sht4.readSerial(), HEX); // 打印传感器的序列号(十六进制)
  }
  Serial.println(F("----------------------------------")); // 打印分隔线
}

void loop() {
  sensors_event_t humidity, temp; // 创建温湿度事件对象
  sht4.getEvent(&humidity, &temp); // 从传感器获取最新的温湿度数据

  float t = temp.temperature; // 获取温度值
  Serial.println("温度 *C = " + String(t)); // 打印温度值
  float h = humidity.relative_humidity; // 获取相对湿度值
  Serial.println("湿度 % = " + String(h)); // 打印湿度值

  delay(1000); // 延时1秒,之后再次进行测量
}

烧录后串口打印显示:

配置Home Assistant根目录中的configuration.yml :

 sensor:
   - unique_id: R4_温度                              # 设备ID,唯一标识这个温度传感器
     name: "R4_温度"                                 # 设备名称,显示在Home Assistant界面上的名称
     state_topic: "STH40"                            # 订阅端口,用于接收温度传感器数据的消息
     suggested_display_precision: 1                  # 建议显示的小数位数
     unit_of_measurement: "°C"                       # 测量单位,摄氏度
     value_template: "{{ value_json.temperature }}"  # 从消息中提取温度值的模板
   - unique_id: R4_湿度                              # 设备ID,唯一标识这个湿度传感器
     name: "R4_湿度"                                 # 设备名称,显示在Home Assistant界面上的名称
     state_topic: "STH40"                            # 订阅端口,用于接收湿度传感器数据的消息
     unit_of_measurement: "%"                        # 测量单位,百分比
     value_template: "{{ value_json.humidity }}"     # 从消息中提取湿度值的模板

保存后重启Home Assistant显示下图为配置成功:

在进阶任务的代码基础上修改整合:

未命名文件 (6).png
#include <ArduinoMqttClient.h> // 引入MQTT客户端库
#include <WiFiS3.h> // 引入WiFi库
#include <ArduinoJson.h>
#include <WiFiClient.h> // 引入WiFi客户端库
#include "Adafruit_SHT4x.h" // 引入SHT40传感器的Adafruit库

Adafruit_SHT4x sht4; // 创建SHT40传感器对象

char ssid[] = "xcxc"; // WiFi网络名称
char pass[] = "xc12345678"; // WiFi密码
int status = WL_IDLE_STATUS; // WiFi连接状态

const char broker[] = "XXXXXXXXX"; // MQTT代理服务器地址
int port = 1883; // MQTT代理服务器端口
const char topic[] = "SHT40"; // MQTT主题

WiFiClient wifiClient; // 创建WiFi客户端对象
MqttClient mqttClient(wifiClient); // 创建MQTT客户端对象,并传入WiFi客户端对象

void setup() {
  Serial.begin(115200); // 初始化串口通信
  while (!Serial) {} // 等待串口监视器打开
  Serial.println(F("SGP40 test with SHT40 compensation")); // 打印开始测试的信息


  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("与WiFi模块通信失败!"); // 如果没有检测到WiFi模块,则停止程序
    while (true);
  }

  // 尝试连接到WiFi网络
  while (status != WL_CONNECTED) {
    Serial.print("尝试连接到WPA SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass); // 连接到WiFi网络
    delay(10000); // 等待10秒看是否连接成功
  }

  Serial.println("已连接到网络"); // 连接成功后的提示
  printCurrentNet(); // 打印当前网络信息
  printWifiData(); // 打印WiFi数据

  // 尝试连接到MQTT代理服务器
  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT连接失败!错误代码 = ");
    Serial.println(mqttClient.connectError()); // 如果连接失败,则打印错误代码
    while (1); // 停止程序
  }
  Serial.println("已连接到MQTT"); // 连接成功后的提示

   // 订阅主题
 mqttClient.subscribe(topic);

 Serial.print("等待主题上的消息: ");
 Serial.println(topic);
 Serial.println();

   // 设置消息接收回调
 mqttClient.onMessage(onMqttMessage);

   // 设置SHT40传感器的测量精度
  sht4.setPrecision(SHT4X_HIGH_PRECISION); // 设置为高精度
  Serial.println("SHT40 set to High precision"); // 打印高精度

  // 配置SHT40传感器的内置加热器状态
  sht4.setHeater(SHT4X_NO_HEATER); // 关闭加热器
  // 打印当前加热器的状态
  switch (sht4.getHeater()) {
    case SHT4X_NO_HEATER: 
      Serial.println(F("SHT40 Heater turned OFF")); // 加热器关闭
      break;
  }

  // 初始化SHT40传感器
  if (!sht4.begin(&Wire1)) { // 如果传感器初始化失败
    Serial.println(F("SHT40 sensor not found!")); // 打印错误信息
    while (1); // 停止程序执行
  } else {
    Serial.print(F("SHT40 detected!\t")); // 打印传感器检测到的信息
    Serial.print(F("Serial number:\t")); // 打印序列号信息
    Serial.println(sht4.readSerial(), HEX); // 打印传感器的序列号(十六进制)
  }
  Serial.println(F("----------------------------------")); // 打印分隔线

}

void printCurrentNet() {
  Serial.print("SSID: "); Serial.println(WiFi.SSID()); // 打印网络名称
  byte bssid[6]; WiFi.BSSID(bssid); printMacAddress(bssid); // 打印路由器MAC地址
  Serial.print("信号强度 (RSSI):"); Serial.println(WiFi.RSSI()); // 打印信号强度
  Serial.print("加密类型: "); Serial.println(WiFi.encryptionType(), HEX); // 打印加密类型
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 0; i < 6; i++) {
    if (i > 0) Serial.print(":");
    if (mac[i] < 16) Serial.print("0");
    Serial.print(mac[i], HEX);
  }
  Serial.println();
}

void printWifiData() {
  IPAddress ip = WiFi.localIP(); // 获取本地IP地址
  Serial.print("IP地址: "); Serial.println(ip); // 打印IP地址
  byte mac[6]; WiFi.macAddress(mac); Serial.print("MAC地址: "); printMacAddress(mac); // 打印MAC地址
}

void loop() {
  // 发送MQTT保持活动信号,以避免被代理断开连接
  mqttClient.poll();

  sensors_event_t humidity, temp; // 创建温湿度事件对象
  sht4.getEvent(&humidity, &temp); // 从传感器获取最新的温湿度数据

  if (isnan(temp.temperature) || isnan(humidity.relative_humidity)) {
    Serial.println("Failed to read from SHT40 sensor!");
    return;
  }

  float t = temp.temperature; // 获取温度值
  float h = humidity.relative_humidity; // 获取相对湿度值

  Serial.println("温度 *C = " + String(t));
  Serial.println("湿度 % = " + String(h));

  // 创建一个JSON对象
  StaticJsonDocument<200> doc;
  doc["temperature"] = t;
  doc["humidity"] = h;

  // 将JSON对象转换为字符串
  String jsonString;
  serializeJson(doc, jsonString);

  // 发送JSON字符串到MQTT代理服务器
  mqttClient.beginMessage(topic); // 使用之前定义的topic
  mqttClient.print(jsonString);
  mqttClient.endMessage();

  delay(1000); // 延迟5秒发送下一次数据
}

void onMqttMessage(int messageSize) {
  // 我们收到了一条消息,打印出主题和内容
  Serial.println("收到一条消息:");
  Serial.print(mqttClient.messageTopic());

  // 使用Stream接口打印内容
  String message;
  while (mqttClient.available()) {
    message += (char)mqttClient.read();
  }
  Serial.println(message);
}

烧录后串口显示:

ha页面显示:

【Follow me第二季第2期】扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)


代码分享:

Blink.ino (629 Bytes)
(下载次数: 2, 2024-10-16 10:08 上传)
LED_Matrix_1.ino (958 Bytes)
(下载次数: 2, 2024-10-16 10:08 上传)
LED_Matrix_2.ino (946 Bytes)
(下载次数: 3, 2024-10-16 10:08 上传)
DAC.ino (711 Bytes)
(下载次数: 1, 2024-10-16 10:08 上传)
DAC_OPAMP_ADC.ino (1.05 KB)
(下载次数: 2, 2024-10-16 10:08 上传)
HA_MQTT_TEST.ino (2.86 KB)
(下载次数: 1, 2024-10-16 10:08 上传)
HA_MQTT_LED.ino (3.59 KB)
(下载次数: 3, 2024-10-16 10:08 上传)
HA_MQTT_SHT40.ino (5.17 KB)
(下载次数: 1, 2024-10-16 10:08 上传)

 

任务视频演示:

 

FollowMe 第二季:1-2 - FollowMe 第二季:2 - Arduino UNO R4 Wi-Fi 及任务讲解 - EEWORLD大学堂

FollowMe 第二季:3-4 - FollowMe 第二季:2 - Arduino UNO R4 Wi-Fi 及任务讲解 - EEWORLD大学堂

 

任务总结:

 

在DigiKey与EEWorld共同发起的Follow me活动中,我从Arduino基础开发逐步过渡到复杂系统集成,完成了以下任务:

  1. Arduino开发环境搭建与基础任务: 成功安装Arduino IDE,配置开发板,编写代码控制LED灯并进行串口通信,掌握了数字输入输出操作。

  2. LED矩阵与信号处理任务: 熟悉LED矩阵原理,实现滚动显示,使用DAC输出正弦波,学习模拟输出与输入操作,并使用OPAMP放大信号。

  3. 进阶任务:UNRAID NAS系统与智能家居集成: 配置UNRAID NAS系统,安装Docker,搭建EMQX MQTT服务器与Home Assistant,实现智能家居控制。

  4. MQTT控制与温湿度监测: 编写Arduino代码通过MQTT协议控制LED灯,连接SHT40传感器读取温湿度数据并上传至Home Assistant显示。

感悟:

  • Arduino开发直观有趣,适合初学者。
  • 模拟信号处理增强了电路设计能力。
  • UNRAID NAS与Docker的使用简化了软件部署与管理。
  • MQTT协议展示了物联网设备通信的高效性。
  • 整个过程提升了我的技术水平,增强了对嵌入式系统与智能家居的理解与应用能力。

感谢DigiKey与EEWorld提供的宝贵学习机会!

任务视频演示:

FollowMe 第二季:1-2 - FollowMe 第二季:2 - Arduino UNO R4 Wi-Fi 及任务讲解 - EEWORLD大学堂

FollowMe 第二季:3-4 - FollowMe 第二季:2 - Arduino UNO R4 Wi-Fi 及任务讲解 - EEWORLD大学堂

本帖最后由 sinc_sila 于 2024-11-1 14:25 编辑

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复