diff --git a/components/bh1750/bh1750_use.c b/components/bh1750/bh1750_use.c index 20c49d2..f95a51e 100644 --- a/components/bh1750/bh1750_use.c +++ b/components/bh1750/bh1750_use.c @@ -8,124 +8,50 @@ static const char *TAG = "BH1750_USE"; -#define BH1750_READ_RETRY_COUNT 3 -#define BH1750_MEASURE_DELAY_MS 200 -#define BH1750_RETRY_INTERVAL_MS 30 - static i2c_master_bus_handle_t s_i2c_bus_handle = NULL; static bh1750_handle_t s_bh1750_handle = NULL; -/** - * @brief 初始化 BH1750 传感器及其所需的 I2C 总线 - */ +i2c_master_bus_handle_t bh1750_get_i2c_bus_handle(void) +{ + return s_i2c_bus_handle; +} + esp_err_t bh1750_user_init(void) { - // 1. 配置并初始化 I2C 总线 (Master Bus) - i2c_master_bus_config_t bus_config = { - .clk_source = I2C_CLK_SRC_DEFAULT, - .i2c_port = I2C_NUM_0, - .scl_io_num = BH1750_I2C_SCL_IO, - .sda_io_num = BH1750_I2C_SDA_IO, - .glitch_ignore_cnt = 7, - }; - - esp_err_t ret = i2c_new_master_bus(&bus_config, &s_i2c_bus_handle); + if (s_i2c_bus_handle == NULL) { + i2c_master_bus_config_t bus_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = I2C_NUM_0, + .scl_io_num = (gpio_num_t)BH1750_I2C_SCL_IO, + .sda_io_num = (gpio_num_t)BH1750_I2C_SDA_IO, + .glitch_ignore_cnt = 7, + }; + ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &s_i2c_bus_handle)); + } + + esp_err_t ret = bh1750_create(s_i2c_bus_handle, BH1750_I2C_ADDRESS_DEFAULT, &s_bh1750_handle); if (ret != ESP_OK) { - ESP_LOGE(TAG, "I2C 总线初始化失败: %s", esp_err_to_name(ret)); + ESP_LOGE(TAG, "BH1750 设备创建失败"); return ret; } - // 2. 创建 BH1750 设备句柄 (使用驱动默认地址 0x23) - ret = bh1750_create(s_i2c_bus_handle, BH1750_I2C_ADDRESS_DEFAULT, &s_bh1750_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "BH1750 设备创建失败: %s", esp_err_to_name(ret)); - if (s_i2c_bus_handle) { - i2c_del_master_bus(s_i2c_bus_handle); - s_i2c_bus_handle = NULL; - } - return ret; - } - - // 3. 初始上电 - ret = bh1750_power_on(s_bh1750_handle); - if (ret == ESP_OK) { - ESP_LOGI(TAG, "BH1750 初始化成功"); - } - - return ret; + return bh1750_power_on(s_bh1750_handle); } -/** - * @brief 读取一次光照强度数据 (Lux) - */ esp_err_t bh1750_user_read(float *lux) { - if (lux == NULL) { - return ESP_ERR_INVALID_ARG; - } - - if (s_bh1750_handle == NULL) { - return ESP_ERR_INVALID_STATE; - } - - esp_err_t ret = ESP_FAIL; - for (int attempt = 1; attempt <= BH1750_READ_RETRY_COUNT; ++attempt) { - // 单次模式每次读取前都先上电,避免传感器处于掉电状态导致返回 0 - ret = bh1750_power_on(s_bh1750_handle); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "上电失败(第%d次): %s", attempt, esp_err_to_name(ret)); - vTaskDelay(pdMS_TO_TICKS(BH1750_RETRY_INTERVAL_MS)); - continue; - } - - // 设置测量模式:单次高分辨率模式 (1lx) - ret = bh1750_set_measure_mode(s_bh1750_handle, BH1750_ONETIME_1LX_RES); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "设置测量模式失败(第%d次): %s", attempt, esp_err_to_name(ret)); - vTaskDelay(pdMS_TO_TICKS(BH1750_RETRY_INTERVAL_MS)); - continue; - } - - // 根据数据手册,单次高分辨率模式需要约 120ms-180ms 测量时间 - vTaskDelay(pdMS_TO_TICKS(BH1750_MEASURE_DELAY_MS)); - - ret = bh1750_get_data(s_bh1750_handle, lux); - if (ret != ESP_OK) { - ESP_LOGW(TAG, "数据读取失败(第%d次): %s", attempt, esp_err_to_name(ret)); - vTaskDelay(pdMS_TO_TICKS(BH1750_RETRY_INTERVAL_MS)); - continue; - } - - // 在强光/室内环境下长期 0 Lux 通常不合理,重试一次可规避偶发总线抖动 - if (*lux <= 0.0f && attempt < BH1750_READ_RETRY_COUNT) { - ESP_LOGW(TAG, "读取到 0 Lux,准备重试(第%d次)", attempt); - vTaskDelay(pdMS_TO_TICKS(BH1750_RETRY_INTERVAL_MS)); - continue; - } - - return ESP_OK; - } - - if (ret == ESP_OK && *lux <= 0.0f) { - ESP_LOGW(TAG, "连续读取均为 0 Lux,请优先检查 I2C 上拉电阻和传感器供电"); - return ESP_OK; - } - - return ret; + if (s_bh1750_handle == NULL) return ESP_ERR_INVALID_STATE; + + bh1750_power_on(s_bh1750_handle); + bh1750_set_measure_mode(s_bh1750_handle, BH1750_ONETIME_1LX_RES); + vTaskDelay(pdMS_TO_TICKS(180)); + return bh1750_get_data(s_bh1750_handle, lux); } -/** - * @brief 释放 BH1750 相关资源 - */ void bh1750_user_deinit(void) { if (s_bh1750_handle) { bh1750_delete(s_bh1750_handle); s_bh1750_handle = NULL; } - if (s_i2c_bus_handle) { - i2c_del_master_bus(s_i2c_bus_handle); - s_i2c_bus_handle = NULL; - } - ESP_LOGI(TAG, "资源已释放"); } diff --git a/components/bh1750/include/bh1750_use.h b/components/bh1750/include/bh1750_use.h index 3f01625..f3fe0d5 100644 --- a/components/bh1750/include/bh1750_use.h +++ b/components/bh1750/include/bh1750_use.h @@ -2,27 +2,28 @@ #define BH1750_USE_H #include "esp_err.h" +#include "driver/i2c_master.h" #ifdef __cplusplus extern "C" { #endif -// 定义使用的 I2C 引脚(根据你的硬件实际连接修改) -#define BH1750_I2C_SCL_IO 1 // ESP32-S3 建议引脚 -#define BH1750_I2C_SDA_IO 2 // ESP32-S3 建议引脚 +// 定义使用的 I2C 引脚 +#define BH1750_I2C_SCL_IO 1 +#define BH1750_I2C_SDA_IO 2 /** * @brief 初始化 BH1750 传感器及其所需的 I2C 总线 - * - * @return esp_err_t 成功返回 ESP_OK */ esp_err_t bh1750_user_init(void); +/** + * @brief 获取 I2C 总线句柄,以便其他传感器(如 AHT30)共用总线 + */ +i2c_master_bus_handle_t bh1750_get_i2c_bus_handle(void); + /** * @brief 读取一次光照强度数据 (Lux) - * - * @param lux [out] 存储结果的指针 - * @return esp_err_t 成功返回 ESP_OK */ esp_err_t bh1750_user_read(float *lux); @@ -35,4 +36,4 @@ void bh1750_user_deinit(void); } #endif -#endif // BH1750_USE_H +#endif diff --git a/dependencies.lock b/dependencies.lock index 12b54b5..4637342 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -1,4 +1,28 @@ dependencies: + espressif/aht30: + component_hash: 939149f0f4a3aad63b8f9bf04218fdeb01c34062f73847fee99e90a619461ad3 + dependencies: + - name: idf + require: private + version: '>=5.2' + - name: espressif/sensor_hub + registry_url: https://components.espressif.com + require: public + version: ^0.1.4 + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.0.0 + espressif/cmake_utilities: + component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f + dependencies: + - name: idf + require: private + version: '>=4.1' + source: + registry_url: https://components.espressif.com + type: service + version: 0.5.3 espressif/esp_lvgl_port: component_hash: b6360960f47b6776462e7092861b3ea66477ffb762a01baa0aecbb3d74cd50f4 dependencies: @@ -13,6 +37,38 @@ dependencies: registry_url: https://components.espressif.com/ type: service version: 2.7.2 + espressif/i2c_bus: + component_hash: 804ec068d163570fd367b279a310ca383484630d2310c586b50def0bcf21de13 + dependencies: + - name: espressif/cmake_utilities + registry_url: https://components.espressif.com + require: private + version: '*' + - name: idf + require: private + version: '>=4.0' + source: + registry_url: https://components.espressif.com + type: service + version: 1.5.1 + espressif/sensor_hub: + component_hash: b3e72f3e2d10e165b972b17fff889f294b1a685769efacf73ec8f1e92152d1d5 + dependencies: + - name: espressif/cmake_utilities + registry_url: https://components.espressif.com + require: private + version: 0.* + - name: espressif/i2c_bus + registry_url: https://components.espressif.com + require: public + version: 1.* + - name: idf + require: private + version: '>=4.4' + source: + registry_url: https://components.espressif.com + type: service + version: 0.1.4 idf: source: type: idf @@ -25,8 +81,9 @@ dependencies: type: service version: 9.5.0 direct_dependencies: +- espressif/aht30 - espressif/esp_lvgl_port - idf -manifest_hash: fa314ee0d60a34ffe2dea85313c7369c0c4b16079167ed05ad45e0cadad2199d +manifest_hash: 15dd4fd3d660b11406a1dde8c0ec0b63f12e3cd4064ff9026e70648e3f7bc8a3 target: esp32s3 version: 2.0.0 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 79e8ee3..8da7334 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "main.cpp" INCLUDE_DIRS "." - REQUIRES nvs_flash esp_wifi sntp_time esp_event esp_system wifi-connect ui lvgl_st7789_use efuse relay_ctrl) + REQUIRES nvs_flash esp_wifi sntp_time aht30 esp_event esp_system wifi-connect ui lvgl_st7789_use efuse relay_ctrl bh1750) diff --git a/main/idf_component.yml b/main/idf_component.yml index 2c48139..694ab0f 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -15,3 +15,4 @@ dependencies: # # All dependencies of `main` are public by default. # public: true espressif/esp_lvgl_port: ^2.7.2 + espressif/aht30: ^1.0.0 diff --git a/main/main.cpp b/main/main.cpp index bdb2364..0dda797 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -17,14 +17,14 @@ #include "esp_system.h" #include "esp_efuse.h" #include "esp_efuse_table.h" +#include "bh1750_use.h" +#include "aht30.h" #define TAG "MAIN" -typedef struct -{ +typedef struct { char time_str[32]; - char mac_str[20]; - char uid_str[20]; + float lux; float temp; float humidity; } env_data_t; @@ -35,22 +35,16 @@ static SemaphoreHandle_t s_env_data_lock = NULL; static bool wait_for_wifi_connected(TickType_t timeout_ticks) { const TickType_t start_ticks = xTaskGetTickCount(); - while ((xTaskGetTickCount() - start_ticks) < timeout_ticks) - { - if (wifi_connect_get_status() == WIFI_CONNECT_STATUS_CONNECTED) - { - return true; - } + while ((xTaskGetTickCount() - start_ticks) < timeout_ticks) { + if (wifi_connect_get_status() == WIFI_CONNECT_STATUS_CONNECTED) return true; vTaskDelay(pdMS_TO_TICKS(200)); } - return wifi_connect_get_status() == WIFI_CONNECT_STATUS_CONNECTED; + return false; } static void env_data_update_system_info(void) { - if (s_env_data_lock == NULL) - return; - + if (s_env_data_lock == NULL) return; time_t now; struct tm timeinfo; time(&now); @@ -60,17 +54,13 @@ static void env_data_update_system_info(void) xSemaphoreTake(s_env_data_lock, portMAX_DELAY); strncpy(s_env_data.time_str, time_buf, sizeof(s_env_data.time_str)); - xSemaphoreGive(s_env_data_lock); - set_var_local_time(s_env_data.time_str); } static void ui_task(void *arg) { - (void)arg; - for (;;) - { + for (;;) { env_data_update_system_info(); lvgl_port_lock(0); ui_tick(); @@ -83,42 +73,70 @@ extern "C" void app_main(void) { vTaskDelay(pdMS_TO_TICKS(100)); ESP_LOGI(TAG, "--- APP STARTING ---"); - s_env_data_lock = xSemaphoreCreateMutex(); - // 2. 初始化 Wi-Fi + // 1. 初始化 Wi-Fi ESP_ERROR_CHECK(wifi_connect_init()); - // 3. 初始化显示屏和 LVGL + // 2. 初始化显示屏和 LVGL start_lvgl_demo(); - // 4. 初始化 UI + // 3. 初始化 UI lvgl_port_lock(100 / portTICK_PERIOD_MS); ui_init(); lvgl_port_unlock(); - set_var_door_status("关闭"); - set_var_food_status("良好"); - set_var_hum_status("有人"); - set_var_hot_status("开"); - set_var_cool_status("关"); - set_var_fan_status("开"); - set_var_light_status("开"); - + // 7. 创建 UI 任务 xTaskCreate(ui_task, "ui_task", 8192, NULL, 5, NULL); - if (wait_for_wifi_connected(pdMS_TO_TICKS(15000))) - { - ESP_LOGI(TAG, "IP: %s", wifi_connect_get_ip()); + if (wait_for_wifi_connected(pdMS_TO_TICKS(15000))) { set_var_system_ip(wifi_connect_get_ip()); } - // 1. 初始化继电器 (避开 Octal PSRAM/Flash 所占用的引脚) - // ESP32-S3 N16R8 使用 8线 PSRAM,占用 GPIO 33-37 + // 4. 初始化继电器 (避开 PSRAM 引脚) static const relay_config_t relay_cfg[RELAY_CTRL_ID_MAX] = { - {.pin = GPIO_NUM_38, .active_high = true}, // 示例改为常用 GPIO + {.pin = GPIO_NUM_38, .active_high = true}, {.pin = GPIO_NUM_39, .active_high = false}, {.pin = GPIO_NUM_40, .active_high = false}, + }; - ESP_ERROR_CHECK(relay_ctrl_init(relay_cfg)); + relay_ctrl_init(relay_cfg); + + // 5. 初始化 I2C 总线并注册传感器 (共享总线) + ESP_ERROR_CHECK(bh1750_user_init()); + i2c_master_bus_handle_t i2c_bus = bh1750_get_i2c_bus_handle(); + + // AHT30 挂载到同一条 I2C 总线上 + aht30_handle_t aht30_dev = NULL; + ESP_ERROR_CHECK(aht30_create(i2c_bus, AHT30_I2C_ADDRESS, &aht30_dev)); + + // 6. 创建传感器读取任务 + xTaskCreate([](void *arg) { + aht30_handle_t aht30 = (aht30_handle_t)arg; + for (;;) { + float lux = 0.0f, temp = 0.0f, hum = 0.0f; + // 读取 BH1750 + if (bh1750_user_read(&lux) == ESP_OK) { + set_var_light_val(lux); + } + // 读取 AHT30 + if (aht30_get_temperature_humidity_value(aht30, &temp, &hum) == ESP_OK) { + set_var_temp(temp); + set_var_humity_val(hum); + } + + + // 数据存入共享结构体 + if (s_env_data_lock) { + xSemaphoreTake(s_env_data_lock, portMAX_DELAY); + s_env_data.lux = lux; + s_env_data.temp = temp; + s_env_data.humidity = hum; + xSemaphoreGive(s_env_data_lock); + } + vTaskDelay(pdMS_TO_TICKS(1000)); + } + }, "sensor_task", 4096*2, (void*)aht30_dev, 6, NULL); + + }