Files
agri_env/components/bh1750/bh1750_use.c

132 lines
4.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdio.h>
#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, "资源已释放");
}