#include #include "esp_log.h" #include "driver/i2c_master.h" #include "bh1750.h" #include "bh1750_use.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" 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 总线 */ 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 (ret != ESP_OK) { ESP_LOGE(TAG, "I2C 总线初始化失败: %s", esp_err_to_name(ret)); 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; } /** * @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; } /** * @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, "资源已释放"); }