mirror of
https://git.beihong.wang/wangbeihong/iot-bedroom-environment-controller.git
synced 2026-04-23 19:33:05 +08:00
refactor(display): migrate from ST7735S to ST7789 driver
- Rename component directory from lvgl_st7735s_use to lvgl_st7789_use - Update CMakeLists.txt to register new source files - Add comprehensive README documentation for ST7789 configuration - Add time_alarm module with SNTP synchronization and alarm management - Add sensors header for sensor abstraction layer
This commit is contained in:
298
main/sensors.c
Normal file
298
main/sensors.c
Normal file
@@ -0,0 +1,298 @@
|
||||
#include "sensors.h"
|
||||
#include "esp_log.h"
|
||||
#include "ahtxx.h"
|
||||
#include "bh1750.h"
|
||||
#include "sgp30/sgp30.h"
|
||||
#include "driver/i2c_master.h"
|
||||
|
||||
|
||||
static const char *TAG = "sensors";
|
||||
|
||||
// 实际全局变量定义(从 main.c 抽取到这里)
|
||||
sensor_data_t g_sensor_data = {0};
|
||||
i2c_master_bus_handle_t bus_handle = NULL;
|
||||
i2c_master_dev_handle_t dev_handle = NULL;
|
||||
|
||||
esp_err_t i2c_master_init(void)
|
||||
{
|
||||
/* 如果本地已有句柄,直接返回(避免重复初始化) */
|
||||
if (bus_handle != NULL)
|
||||
{
|
||||
ESP_LOGI(TAG, "I2C bus already initialized (local handle)");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* 优先尝试获取已有的总线句柄(其它模块可能已初始化) */
|
||||
esp_err_t ret = i2c_master_get_bus_handle(I2C_MASTER_NUM, &bus_handle);
|
||||
if (ret == ESP_OK)
|
||||
{
|
||||
ESP_LOGI(TAG, "I2C bus already initialized (existing handle)");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* 如果不是未初始化的常见返回(ESP_ERR_INVALID_STATE),记录警告并尝试创建 */
|
||||
if (ret != ESP_ERR_INVALID_STATE && ret != ESP_ERR_INVALID_ARG)
|
||||
{
|
||||
ESP_LOGW(TAG, "i2c_master_get_bus_handle returned %s, will try to create new bus", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
i2c_master_bus_config_t i2c_mst_config = {
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.i2c_port = I2C_MASTER_NUM,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.glitch_ignore_cnt = 7,
|
||||
.flags.enable_internal_pullup = true,
|
||||
};
|
||||
|
||||
ret = i2c_new_master_bus(&i2c_mst_config, &bus_handle);
|
||||
if (ret == ESP_OK)
|
||||
{
|
||||
ESP_LOGI(TAG, "I2C master bus initialized successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* 若创建失败且是已被占用的状态,再次尝试取句柄(防止竞态) */
|
||||
if (ret == ESP_ERR_INVALID_STATE)
|
||||
{
|
||||
esp_err_t get_ret = i2c_master_get_bus_handle(I2C_MASTER_NUM, &bus_handle);
|
||||
if (get_ret == ESP_OK)
|
||||
{
|
||||
ESP_LOGW(TAG, "I2C bus already acquired by other module; obtained existing handle");
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "i2c_new_master_bus failed and get_bus_handle also failed: %s / %s", esp_err_to_name(ret), esp_err_to_name(get_ret));
|
||||
return get_ret;
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "i2c_new_master_bus failed: %s", esp_err_to_name(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void i2c0_ahtxx_task(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
ahtxx_config_t ahtxx_config = I2C_AHT30_CONFIG_DEFAULT;
|
||||
ahtxx_handle_t ahtxx_handle = NULL;
|
||||
|
||||
esp_err_t ret = ahtxx_init(bus_handle, &ahtxx_config, &ahtxx_handle);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "AHTxx init failed, sensor invalid, err=0x%x", ret);
|
||||
while (1)
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.ahtxx_valid = false;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
float temperature, humidity;
|
||||
while (1)
|
||||
{
|
||||
ret = ahtxx_get_measurement(ahtxx_handle, &temperature, &humidity);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "AHTxx read failed, err=0x%x", ret);
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.ahtxx_valid = false;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.temperature = temperature;
|
||||
g_sensor_data.humidity = humidity;
|
||||
g_sensor_data.ahtxx_valid = true;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "AHTxx: temperature=%.1f°C, humidity=%.1f%%", temperature, humidity);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
void i2c0_bh1750_task(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
bh1750_handle_t bh1750_handle = NULL;
|
||||
|
||||
// 使用默认地址创建 BH1750 设备
|
||||
esp_err_t ret = bh1750_create(bus_handle, BH1750_I2C_ADDRESS_DEFAULT, &bh1750_handle);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "BH1750 create failed, sensor invalid, err=0x%x", ret);
|
||||
while (1)
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.bh1750_valid = false;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
// 设置测量模式为连续高分辨率模式
|
||||
ret = bh1750_set_measure_mode(bh1750_handle, BH1750_CONTINUE_1LX_RES);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "BH1750 set measure mode failed, err=0x%x", ret);
|
||||
}
|
||||
|
||||
// 上电
|
||||
ret = bh1750_power_on(bh1750_handle);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "BH1750 power on failed, err=0x%x", ret);
|
||||
}
|
||||
|
||||
float lux;
|
||||
while (1)
|
||||
{
|
||||
ret = bh1750_get_data(bh1750_handle, &lux);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "BH1750 read failed, err=0x%x", ret);
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.bh1750_valid = false;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.lux = lux;
|
||||
g_sensor_data.bh1750_valid = true;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "BH1750: illuminance=%.1f lux", lux);
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
void i2c0_sgp30_task(void *pvParameters)
|
||||
{
|
||||
(void)pvParameters;
|
||||
|
||||
// SGP30 配置
|
||||
sgp30_config_t sgp30_config = {
|
||||
.i2c_master_port = I2C_MASTER_NUM,
|
||||
.i2c_address = 0x58, // SGP30 默认地址
|
||||
};
|
||||
|
||||
// 初始化 SGP30
|
||||
esp_err_t ret = sgp30_init(&sgp30_config);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "SGP30 init failed, err=0x%x", ret);
|
||||
while (1)
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.sgp30_valid = false;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "SGP30 initialized successfully");
|
||||
|
||||
uint16_t co2_ppm, tvoc_ppb;
|
||||
while (1)
|
||||
{
|
||||
ret = sgp30_read_measurements(&co2_ppm, &tvoc_ppb);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "SGP30 read failed, err=0x%x", ret);
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.sgp30_valid = false;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
g_sensor_data.co2_ppm = co2_ppm;
|
||||
g_sensor_data.tvoc_ppb = tvoc_ppb;
|
||||
g_sensor_data.sgp30_valid = true;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "SGP30: CO2=%d ppm, TVOC=%d ppb", co2_ppm, tvoc_ppb);
|
||||
}
|
||||
|
||||
// SGP30 建议每秒读取一次
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
void get_sensor_data(sensor_data_t *data)
|
||||
{
|
||||
if (data != NULL)
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
*data = g_sensor_data;
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_sensor_data(void)
|
||||
{
|
||||
if (xSensorDataMutex != NULL && xSemaphoreTake(xSensorDataMutex, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
// 传感器日志已移除,保持占位
|
||||
xSemaphoreGive(xSensorDataMutex);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t sensors_init(void)
|
||||
{
|
||||
esp_err_t err = i2c_master_init();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(TAG, "i2c_master_init failed: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
BaseType_t ok = xTaskCreate(i2c0_ahtxx_task, "i2c0_ahtxx_task", 4096, NULL, 5, NULL);
|
||||
if (ok != pdPASS)
|
||||
{
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
ok = xTaskCreate(i2c0_bh1750_task, "i2c0_bh1750_task", 4096, NULL, 5, NULL);
|
||||
if (ok != pdPASS)
|
||||
{
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
ok = xTaskCreate(i2c0_sgp30_task, "i2c0_sgp30_task", 4096, NULL, 5, NULL);
|
||||
if (ok != pdPASS)
|
||||
{
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sensors_read(void)
|
||||
{
|
||||
// 保留占位,如需单次读可以实现
|
||||
return ESP_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user