上期已成功添加远程开关传感器
这期我们添加台灯传感器,实现照明应用
本期主控芯片来自前几期参加论坛活动中的ESP32 S3 TFT Reverse开发板
搭配LTR-329环境光传感器本地动态调整灯光亮度
灯板使用的是8颗WS2812芯片组成的灯板,有点事可以直接使用USB接口的5V工作电源供电,无需额外电源
接下来看看硬件组成

下面到了软件代码环节
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include "Adafruit_LTR329_LTR303.h"
#include <WiFi.h>
#include <ArduinoHA.h> // ArduinoHA 2.1.0
// ====================== 硬件配置 ======================
#define WS2812_PIN 13 // WS2812数据引脚
#define LED_COUNT 8 // WS2812灯珠数量
#define MIN_LUX 50 // 最低环境光阈值
#define MAX_LUX 1000 // 最高环境光阈值
#define FILTER_WINDOW 5 // 滤波窗口大小
// WiFi配置
#define SECRET_SSID "wiif"
#define SECRET_PASS "password"
// MQTT配置(Home Assistant的MQTT服务器信息)
#define BROKER_ADDR "192.168.1.100" // 如192.168.1.100
#define BROKER_PORT 1883 // MQTT默认端口
#define MQTT_USER "admin" // HA的MQTT认证用户名
#define MQTT_PASS "public" // HA的MQTT认证密码
// ====================== 全局变量 ======================
// 灯光控制相关
Adafruit_NeoPixel strip(LED_COUNT, WS2812_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_LTR329 ltr = Adafruit_LTR329();
float luxHistory[FILTER_WINDOW] = {0};
int historyIndex = 0;
float maxLux = 0.0;
float minLux = 999999.0;
bool lightState = false; // 灯光总开关状态(仅HA控制)
uint8_t autoBrightness = 0; // ESP32自动计算的亮度(0-255)
uint32_t warmYellow = strip.Color(255, 200, 50); // 暖黄色
// HA MQTT相关(完全照搬你的可编译代码)
WiFiClient wifiClient;
byte mac[] = {0x00, 0x10, 0xFA, 0x6E, 0x38, 0x4C}; // 自定义MAC地址
HADevice device(mac, sizeof(mac));
HAMqtt mqtt(wifiClient, device);
HASwitch ledSwitch("smartLight");
// 仅保留必要的时间戳(无MQTT connected()相关逻辑)
unsigned long lastSensorRead = 0;
// ====================== HA回调函数 ======================
// HA控制灯光亮灭(仅修改逻辑,不新增API)
void onSwitchCommand(bool state, HASwitch* sender) {
Serial.print("HA控制 - 灯光状态: ");
Serial.println(state ? "开启" : "关闭");
lightState = state; // 仅由HA控制开关
digitalWrite(LED_BUILTIN, (state ? HIGH : LOW));
// 仅使用你可编译的API
sender->setState(state);
}
// ====================== 核心功能函数 ======================
void setup() {
Serial.begin(115200);
while (!Serial) delay(10); // 等待串口初始化
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// 1. 初始化WS2812
strip.begin();
strip.show();
strip.setBrightness(0);
// 2. 初始化LTR329(保留你的代码,增加简单容错)
Wire.setTimeout(100); // I2C读取超时,避免卡死
if (!ltr.begin()) {
Serial.println("LTR329传感器初始化失败!仅保留HA控灯功能");
} else {
ltr.setGain(LTR3XX_GAIN_2);
ltr.setIntegrationTime(LTR3XX_INTEGTIME_100);
ltr.setMeasurementRate(LTR3XX_MEASRATE_500);
Serial.println("LTR329初始化成功!");
}
// 3. 连接WiFi(保留你的代码,增加超时)
Serial.print("连接WiFi: ");
Serial.println(SECRET_SSID);
WiFi.begin(SECRET_SSID, SECRET_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi连接成功!");
Serial.print("ESP32 IP地址: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nWiFi连接超时!");
}
// 4. 初始化HA设备(完全照搬你的代码)
device.setName("智能台灯");
device.setSoftwareVersion("1.0.1");
// 5. 配置HA灯光实体(完全照搬你的代码)
ledSwitch.setIcon("mdi:lightbulb");
ledSwitch.setName("My Light");
ledSwitch.onCommand(onSwitchCommand);
// 6. 连接MQTT Broker(完全照搬你的代码)
mqtt.begin(BROKER_ADDR, BROKER_PORT, MQTT_USER, MQTT_PASS);
Serial.println("HA MQTT初始化完成!");
ledSwitch.setState(lightState);
// 初始化历史数据数组
for (int i = 0; i < FILTER_WINDOW; i++) {
luxHistory[i] = 0.0;
}
}
void loop() {
// 1. 优先处理MQTT通信(你的代码,无修改)
mqtt.loop();
if (lightState) {
unsigned long now = millis();
// 500ms读取一次,避免频繁读取占用CPU导致MQTT卡顿
if (now - lastSensorRead > 500) {
processAutoBrightnessAdjust();
lastSensorRead = now;
}
}
if (lightState) {
strip.setBrightness(100);
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, warmYellow);
}
} else {
strip.setBrightness(0);
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, 0); // 确保彻底关闭
}
}
strip.show();
// 3. 极小延时,避免阻塞MQTT(从200ms改为10ms)
delay(20);
}
/**
* 自动调节亮度(保留你的逻辑,增加读取容错)
*/
void processAutoLightAdjust() {
bool valid;
uint16_t ch0, ch1;
if (ltr.newDataAvailable()) {
valid = ltr.readBothChannels(ch0, ch1);
if (valid) {
float rawLux = calculateLux(ch0, ch1);
updateLuxMinMax(rawLux);
float filteredLux = filterLux(rawLux);
// 自动计算亮度
autoBrightness = calculateAutoBrightness(filteredLux);
// 打印自动调节信息
Serial.print("自动调节 - 滤波后lux: "); Serial.print(filteredLux);
Serial.print(" | 亮度: "); Serial.println(autoBrightness);
}
}
}
// 兼容函数名(避免修改太多)
void processAutoBrightnessAdjust() {
processAutoLightAdjust();
}
/**
* 计算原始Lux值(完全照搬你的代码)
*/
float calculateLux(uint16_t ch0, uint16_t ch1) {
if (ch0 == 0) return 0.0;
float ratio = (float)ch1 / ch0;
float lux;
if (ratio < 0.45) lux = 1.7743 * ch0 + 1.1059 * ch1;
else if (ratio < 0.64) lux = 1.2664 * ch0 + 1.6757 * ch1;
else if (ratio < 0.85) lux = 0.9441 * ch0 + 2.0918 * ch1;
else lux = 0.6226 * ch0 + 2.5835 * ch1;
return lux / 2.0; // 增益补偿
}
/**
* 更新最大/最小Lux值(完全照搬你的代码)
*/
void updateLuxMinMax(float currentLux) {
if (currentLux <= 0) return;
if (currentLux > maxLux) maxLux = currentLux;
if (currentLux < minLux) minLux = currentLux;
}
/**
* 滑动平均滤波(完全照搬你的代码)
*/
float filterLux(float currentLux) {
luxHistory[historyIndex] = currentLux;
historyIndex = (historyIndex + 1) % FILTER_WINDOW;
float sum = 0.0;
int validCount = 0;
for (int i = 0; i < FILTER_WINDOW; i++) {
if (luxHistory[i] > 0) {
sum += luxHistory[i];
validCount++;
}
}
return validCount > 0 ? sum / validCount : 0.0;
}
/**
* 计算自动亮度值(完全照搬你的代码)
*/
uint8_t calculateAutoBrightness(float lux) {
if (lux < MIN_LUX) return 255;
else if (lux > MAX_LUX) return 0;
else return map(lux, MIN_LUX, MAX_LUX, 255, 0);
}
/**
* 应用灯光输出(小幅优化,不新增API)
*/
void updateLightOutput() {
noInterrupts(); // 避免中断干扰
if (lightState) {
strip.setBrightness(autoBrightness);
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, warmYellow);
}
} else {
strip.setBrightness(0);
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, 0); // 确保彻底关闭
}
}
strip.show();
interrupts();
}烧录后界面

后续观看home assistant面板展示

至此台灯传感器也已经添加完毕
台灯亮灯效果

台灯关灯效果

台灯动态调光日志

我要赚赏金
