【Follow me第二季第2期】扩展任务二:通过外部SHT40温湿度传感器,上传温湿度到HA
[复制链接]
本帖最后由 sinc_sila 于 2024-10-16 09:53 编辑
这章的任务是将将UNO R4 WiFi模块连接到外部的SHT40传感器,并通过MQTT协议将数据上传到Home Assistant。
硬件准备
Arduino UNO R4
SHT40温湿度传感器
使用 Arduino IDE 中的库管理器安装适用于 Arduino 的 Adafruit SHT4X 库:
将范例简化后的代码:
#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显示下图为配置成功:
在进阶任务的代码基础上修改整合:
#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);
}
|