这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 开源硬件 » 【RaspberryPi5开发板方案创意赛】基于树莓派5的智能家居系统-过程贴-

共1条 1/1 1 跳转至

【RaspberryPi5开发板方案创意赛】基于树莓派5的智能家居系统-过程贴-台灯传感器添加

工程师
2025-12-28 20:43:47     打赏

上期已成功添加远程开关传感器


这期我们添加台灯传感器,实现照明应用


本期主控芯片来自前几期参加论坛活动中的ESP32 S3 TFT Reverse开发板

搭配LTR-329环境光传感器本地动态调整灯光亮度

灯板使用的是8颗WS2812芯片组成的灯板,有点事可以直接使用USB接口的5V工作电源供电,无需额外电源

接下来看看硬件组成

20251228170818.jpg

下面到了软件代码环节

#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();
}

烧录后界面

image.png

后续观看home assistant面板展示

image.png

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


台灯亮灯效果

ha-light-on.jpg

台灯关灯效果

ha-light-off.jpg

台灯动态调光日志

light-value-auto=change.PNG




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]