【2024 DigiKey 创意大赛】ESP-32C6- 室内数据集成 + 自动化补光
本帖最后由 御坂10032号 于 2024-10-20 15:40 编辑<p><strong><span style="font-size:22px;">简介</span></strong></p>
<p> </p>
<p>本章节主要在上一个章节的代码上修改使其支持BH1750, 然后将数据集成到HA并且配置HA实现自动化操作,自动补光等。</p>
<p> </p>
<p><strong><span style="font-size:22px;">正文</span></strong></p>
<p> </p>
<p>在上个章节中我们实现了使用C6读取AHT10并且将数据上报到MQTT,由于AHT10和BH1750都是使用IIC通讯, 因为我们可以将SCL和SDA接到这两个传感器上(接相同的SCL和SDA)然后通过I2C的Address 来选择和哪个传感器进行通讯。虽然也可以使用其他的IIC或者是使用软件模拟的方式来模拟IIC时序,但是为了方便我们直接采用之前的IIC总线。</p>
<p> </p>
<p>那么为了读取BH1750,我们需要首先在Arduino IDE中来添加BH1750的库</p>
<p> </p>
<p> </p>
<p> </p>
<p>在安装完库文件之后,我们需要在上一章节的代码中进行修改,使其支持BH1750的数据上报。</p>
<p> </p>
<p>代码如下:</p>
<p> </p>
<pre>
<code class="language-cpp">#include <Wire.h>
#include <Adafruit_AHTX0.h>
#include <WiFi.h>
#include <ArduinoMqttClient.h>
#include <Arduino_JSON.h>
#include <BH1750.h>// 添加 BH1750 库
const char *ssid = "ImmortalWrt";
const char *password = "mazha1997";
#define SDA_PIN 21// 定义 SDA 引脚
#define SCL_PIN 22// 定义 SCL 引脚
#define CONTROL_PIN 4// 定义控制引脚,用于输出高低电平
Adafruit_AHTX0 aht;
BH1750 lightMeter;// 创建 BH1750 实例
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "192.168.1.142";
int port = 1883;
const char switchTopic[] = "switch"; // 主题1
const char sensorTopic[] = "sensor"; // 主题2
void setup() {
Serial.begin(115200);// 初始化串口,用于调试
pinMode(CONTROL_PIN, OUTPUT);// 设置控制引脚为输出模式
digitalWrite(CONTROL_PIN, LOW);// 初始状态设为低电平
// 初始化 I2C,使用自定义引脚
Wire.begin(SDA_PIN, SCL_PIN);
if (!aht.begin()) {
Serial.println("Could not find AHT? Check wiring");
while (1) delay(10);
}
Serial.println("AHT10 or AHT20 found");
if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire)) {
Serial.println("Error initializing BH1750. Check wiring or I2C address.");
while (1) delay(10);
}
Serial.println("BH1750 initialized");
WiFi.begin(ssid, password);
int tryDelay = 500;
int numberOfTries = 20;
// Wait for the WiFi event
while (true) {
switch (WiFi.status()) {
case WL_NO_SSID_AVAIL: Serial.println(" SSID not found"); break;
case WL_CONNECT_FAILED:
Serial.println(" Failed - WiFi not connected! Reason: ");
return;
break;
case WL_CONNECTION_LOST: Serial.println(" Connection was lost"); break;
case WL_DISCONNECTED: Serial.println(" WiFi is disconnected"); break;
case WL_CONNECTED:
Serial.println(" WiFi is connected!");
Serial.print(" IP address: ");
Serial.println(WiFi.localIP());
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
mqttClient.setUsernamePassword("root", "mazha1997");
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
mqttClient.onMessage(onMqttMessage);// 设置消息接收回调
Serial.print("Subscribing to topic: ");
Serial.println(switchTopic);
mqttClient.subscribe(switchTopic);// 订阅开关主题
return;
default:
Serial.print(" WiFi Status: ");
Serial.println(WiFi.status());
break;
}
delay(tryDelay);
if (numberOfTries <= 0) {
Serial.println(" Failed to connect to WiFi!");
WiFi.disconnect();
return;
} else {
numberOfTries--;
}
}
}
void loop() {
// 保证处理 MQTT 消息
mqttClient.poll();
// 获取 AHT10/20 传感器数据
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);// 获取温度和湿度数据
// 获取 BH1750 光照强度数据
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
// 创建JSON对象来存储数据
JSONVar sensorData;
sensorData["temperature"] = String(temp.temperature, 2);// 保留两位小数
sensorData["humidity"] = String(humidity.relative_humidity, 2);// 保留两位小数
sensorData["lux"] = String(lux, 2);// 保留两位小数的光照强度
// 将JSON数据转换为字符串并发布到"sensor"主题
String payload = JSON.stringify(sensorData);
mqttClient.beginMessage(sensorTopic);
mqttClient.print(payload);
mqttClient.endMessage();
delay(1000);// 每秒刷新一次
}
// MQTT消息接收回调函数
void onMqttMessage(int messageSize) {
// 获取当前消息的主题
String topic = mqttClient.messageTopic();
Serial.print("Received a message with topic '");
Serial.print(topic);
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
String message = "";
while (mqttClient.available()) {
message += (char)mqttClient.read();
}
Serial.println("Message content: " + message);
// 根据不同的主题处理消息
if (topic == switchTopic) {
Serial.println("Message from topic: switchTopic");
// 将接收到的消息转换为 JSON
JSONVar parsedMessage = JSON.parse(message);
// 检查解析是否成功
if (JSON.typeof(parsedMessage) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
// 获取 status 字段
String status = (const char*)parsedMessage["status"];
if (status == "ON") {
digitalWrite(CONTROL_PIN, HIGH);// 设置 IO4 输出高电平
Serial.println("Switch turned ON, IO4 set to HIGH");
} else if (status == "OFF") {
digitalWrite(CONTROL_PIN, LOW);// 设置 IO4 输出低电平
Serial.println("Switch turned OFF, IO4 set to LOW");
} else {
Serial.println("Unknown status value");
}
}
}
</code></pre>
<p> </p>
<p> </p>
<p>这里关于BH1750的代码主要的部分在于以下代码,其他的和上一个章节相同</p>
<p> </p>
<pre>
<code class="language-cpp">BH1750 lightMeter;// 创建 BH1750 实例
//初始化BH1750
if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire)) {
Serial.println("Error initializing BH1750. Check wiring or I2C address.");
while (1) delay(10);
}
// 获取 BH1750 光照强度数据
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
</code></pre>
<p> </p>
<p>上述代码分别初始化了 BH1750, 启动IIC通讯, 以及读取BH1750的数据。 之后便将数据整合到了之前的JSON object里然后上传到MQTT</p>
<p> </p>
<pre>
<code class="language-cpp">// 创建JSON对象来存储数据
JSONVar sensorData;
sensorData["temperature"] = String(temp.temperature, 2);// 保留两位小数
sensorData["humidity"] = String(humidity.relative_humidity, 2);// 保留两位小数
sensorData["lux"] = String(lux, 2);// 保留两位小数的光照强度
// 将JSON数据转换为字符串并发布到"sensor"主题
String payload = JSON.stringify(sensorData);
mqttClient.beginMessage(sensorTopic);
mqttClient.print(payload);
mqttClient.endMessage();</code></pre>
<p> </p>
<p><strong><span style="font-size:22px;">数据集成和自动化配置</span></strong></p>
<p> </p>
<p>通常我比较喜欢晚上来写代码,但是晚上的时候虽然晚上打开了灯光,但是桌面的光照强度还是太弱了,十分累眼睛。 前一段时间买了一个可调光的台灯(20元)。 然后我直接把它拆了,留下了里面的LED灯板。 我把它通过和单片机相连,然后使用继电器控制, 当室内的环境光LUX低于一定强度的时候, 使其打开台灯进行补光。 上述的代码工作我们已经完成了,那么接下来就是数据的集成和自动化配置。</p>
<p> </p>
<p> </p>
<p>首先使用docker exec -it 命令进入 HA容器, 使用vi 编辑 configuration.yml 加入以下内容配置集成</p>
<p> </p>
<pre>
<code class="language-cpp">mqtt:
sensor:
- name: "Temperature"
unique_id: "sensor_temp_01"
state_topic: "sensor"
suggested_display_precision: 1
unit_of_measurement: "..C"
value_template: "{{ value_json.temperature }}"
- name: "Humidity"
unique_id: "sensor_humidity_02"
state_topic: "sensor"
unit_of_measurement: "%"
value_template: "{{ value_json.humidity }}"
- name: "Illuminance"
unique_id: "sensor_illuminance"
state_topic: "sensor"
unit_of_measurement: "lx"
value_template: "{{ value_json.lux }}"</code></pre>
<p> </p>
<p>然后在开发者工具中检查和重载配置。</p>
<p> </p>
<p></p>
<p> </p>
<p> </p>
<p>之后便可以在默认的dashboard中找到配置的传感器信息。</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>我们再额外配置一下继电器的控制</p>
<p> </p>
<pre>
<code class="language-cpp">switch:
- name: "Light Switch"
unique_id: "switch_light_01"
state_topic: "switch/status"
command_topic: "switch"
payload_on: "ON"
payload_off: "OFF"
state_on: "ON"
state_off: "OFF"
qos: 1
retain: true</code></pre>
<p> </p>
<p> </p>
<p>此时配置完成。</p>
<p> </p>
<p><strong><span style="font-size:22px;">自动化控制</span></strong></p>
<p> </p>
<p>我们希望在光照强度较低的时候自动开启补光。那么在HA中只用做一下的配置即可。</p>
<p> </p>
<p> </p>
<p>上述配置了关灯条件, 即光照强度低于100, 就执行下述操作</p>
<p> </p>
<p> </p>
<p>同样的道理我们配置一个开灯的操作。</p>
<p> </p>
<p> </p>
<p> </p>
<p>此时我们配置完成,让我们来看下现象。</p>
<p> </p>
<p>4a780256ec73197cbf6ecb674786e658<br />
</p>
<p> </p>
页:
[1]