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:
Wang Beihong
2026-03-29 02:31:29 +08:00
parent 8c33fe7411
commit f0ac50642d
50 changed files with 15494 additions and 3282 deletions

298
main/sensors.c Normal file
View 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;
}