sinc_sila 发表于 2024-10-16 00:09

【Follow me第二季第2期】扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA

本帖最后由 sinc_sila 于 2024-10-16 09:53 编辑

<p><span style="font-size:18px;"><span style="color:#d35400;">这章的任务是将将UNO R4 WiFi模块连接到外部的SHT40传感器,并通过MQTT协议将数据上传到Home Assistant。</span></span></p>

<h3>硬件准备</h3>

<p><strong>Arduino UNO R4</strong></p>

<p><strong>SHT40温湿度传感器</strong></p>

<div style="text-align: left;"></div>

<div style="text-align: left;"><span style="font-size:18px;">使用 Arduino IDE 中的库管理器安装适用于 Arduino 的&nbsp;<strong data-immersive-translate-walked="6ddd5d85-d2aa-4237-8ce8-bf619d6fe1e4">Adafruit SHT4X 库</strong>:</span></div>

<div style="text-align: left;">
<div style="text-align: left;"></div>

<div style="text-align: left;"></div>

<div style="text-align: left;"><span style="font-size:18px;"><strong>将范例简化后的代码:</strong></span></div>

<div style="text-align: left;">
<pre>
<code>#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(&amp;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(&amp;humidity, &amp;temp); // 从传感器获取最新的温湿度数据

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

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

<p><span style="font-size:18px;">烧录后串口打印显示:</span></p>
</div>

<div style="text-align: left;"></div>

<div style="text-align: left;">
<hr />
<p><span style="font-size:18px;">配置Home Assistant根目录中的configuration.yml :</span></p>

<pre>
<code> 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 }}"   # 从消息中提取湿度值的模板</code></pre>

<div style="text-align: left;">
<div style="text-align: left;"></div>

<p>&nbsp;</p>
</div>

<p><span style="font-size:18px;">保存后重启Home Assistant显示下图为配置成功:</span></p>

<div style="text-align: left;"></div>

<hr />
<p><span style="font-size:18px;">在进阶任务的代码基础上修改整合:</span><br />
&nbsp;</p>

<pre>
<code>#include &lt;ArduinoMqttClient.h&gt; // 引入MQTT客户端库
#include &lt;WiFiS3.h&gt; // 引入WiFi库
#include &lt;ArduinoJson.h&gt;
#include &lt;WiFiClient.h&gt; // 引入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(&amp;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; 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 &lt; 6; i++) {
    if (i &gt; 0) Serial.print(":");
    if (mac &lt; 16) Serial.print("0");
    Serial.print(mac, HEX);
}
Serial.println();
}

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

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

sensors_event_t humidity, temp; // 创建温湿度事件对象
sht4.getEvent(&amp;humidity, &amp;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&lt;200&gt; 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);
}
</code></pre>

<div style="text-align: left;"></div>

<div style="text-align: left;"></div>

<p>&nbsp;</p>
</div>

<p>&nbsp;</p>
</div>
页: [1]
查看完整版本: 【Follow me第二季第2期】扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA