123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- #include <sys/cdefs.h>
- /**
- * @Author: 李建
- * @Date: 2025/4/22 13:48
- * Description: 温湿度传感器
- * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
- */
- #include <esp_log.h>
- #include <esp_wifi.h>
- #include "sht30.h"
- #include "driver/i2c.h"
- #include "main.h"
- #include "lvgl_port.h"
- #include "wifi.h"
- #include "lcd_st7701.h"
- static const char *TAG = "SHT30";
- #define DRIFT_RATE 0.1524 // 根据历史数据计算的漂移率 (°C/min)
- #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
- #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
- #define ACK_VAL 0x0 /*!< I2C ack value */
- #define NACK_VAL 0x1 /*!< I2C nack value */
- int current_seconds;
- sht30_data_t sht30Data = {0};
- // 温度修正函数
- static double correct_temperature(double current_temp) {
- static const int start_seconds = 0;
- // 计算经过时间(秒)
- double elapsed_seconds = (double) (current_seconds - start_seconds);
- // 计算修正量(漂移率 × 经过分钟数)
- double correction = DRIFT_RATE * (elapsed_seconds / 60.0);
- // 应用修正
- return current_temp - correction;
- }
- static esp_err_t i2c_master_init(void) {
- int i2c_master_port = I2C_MASTER_NUM;
- i2c_config_t conf = {
- .mode = I2C_MODE_MASTER,
- .sda_io_num = I2C_MASTER_SDA_IO,
- .scl_io_num = I2C_MASTER_SCL_IO,
- .sda_pullup_en = GPIO_PULLUP_ENABLE,
- .scl_pullup_en = GPIO_PULLUP_ENABLE,
- .master.clk_speed = I2C_MASTER_FREQ_HZ,
- };
- i2c_param_config(i2c_master_port, &conf);
- return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
- }
- esp_err_t
- i2c_master_write_slave_reg(i2c_port_t i2c_num, uint8_t slave_addr, uint8_t reg_addr, uint8_t *data_wr, size_t size,
- TickType_t ticks_to_wait) {
- i2c_cmd_handle_t cmd = i2c_cmd_link_create();
- i2c_master_start(cmd);
- i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
- i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
- i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
- i2c_master_stop(cmd);
- esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, ticks_to_wait);
- i2c_cmd_link_delete(cmd);
- return ret;
- }
- esp_err_t i2c_master_read_slave_reg_16bit(i2c_port_t i2c_num, uint8_t slave_addr, uint16_t reg_addr, uint8_t *data_rd,
- size_t size, TickType_t ticks_to_wait) {
- if (size == 0) {
- return ESP_OK;
- }
- i2c_cmd_handle_t cmd = i2c_cmd_link_create();
- i2c_master_start(cmd);
- i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
- i2c_master_write_byte(cmd, reg_addr >> 8, ACK_CHECK_EN);
- i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
- i2c_master_start(cmd);
- i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
- if (size > 1) {
- i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
- }
- i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
- i2c_master_stop(cmd);
- esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, ticks_to_wait);
- i2c_cmd_link_delete(cmd);
- return ret;
- }
- /**
- * @brief 向SHT3x发送一条指令(16bit)
- *
- * @param cmd —— SHT3x指令(在SHT3x_MODE中枚举定义)
- *
- * @retval 成功返回HAL_OK(ESP_OK)
- */
- static uint8_t SHT3X_Send_Cmd(SHT30_CMD cmd) {
- uint8_t cmd_buffer[2];
- cmd_buffer[0] = cmd >> 8;
- cmd_buffer[1] = cmd;
- return i2c_master_write_slave_reg(SHT3X_I2C_BUS, SHT3X_SLAVE_ADDRESS, cmd_buffer[0], cmd_buffer + 1, 1,
- SHT3X_TICKS_TO_WAIT);
- }
- void sht3x_reset(void) {
- SHT3X_Send_Cmd(SOFT_RESET_CMD);
- vTaskDelay(20 / portTICK_PERIOD_MS);
- }
- esp_err_t sht3x_init(void) {
- return SHT3X_Send_Cmd(MEDIUM_2_CMD);
- }
- esp_err_t sht3x_read_th_raw_dat(uint8_t *dat) {
- return i2c_master_read_slave_reg_16bit(SHT3X_I2C_BUS, SHT3X_SLAVE_ADDRESS, READOUT_FOR_PERIODIC_MODE, dat, 6,
- SHT3X_TICKS_TO_WAIT);
- }
- #define CRC8_POLYNOMIAL 0x31
- static uint8_t SHT3X_CheckCrc8(uint8_t *const message, uint8_t initial_value) {
- uint8_t remainder; //余数
- uint8_t i = 0, j = 0; //循环变量
- /* 初始化 */
- remainder = initial_value;
- for (j = 0; j < 2; j++) {
- remainder ^= message[j];
- /* 从最高位开始依次计算 */
- for (i = 0; i < 8; i++) {
- if (remainder & 0x80) {
- remainder = (remainder << 1) ^ CRC8_POLYNOMIAL;
- } else {
- remainder = (remainder << 1);
- }
- }
- }
- /* 返回计算的CRC码 */
- return remainder;
- }
- /**
- * @brief 将SHT30接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
- *
- * @param dat —— 存储接收数据的地址(6个字节数组)
- *
- * @retval 校验成功 —— 返回0
- * 校验失败 —— 返回1,并设置温度值和湿度值为0
- */
- uint8_t sht3x_dat2float(uint8_t *const dat, float *temperature, float *humidity) {
- uint16_t recv_temperature = 0;
- uint16_t recv_humidity = 0;
- /* 校验温度数据和湿度数据是否接收正确 */
- if (SHT3X_CheckCrc8(dat, 0xFF) != dat[2] || SHT3X_CheckCrc8(&dat[3], 0xFF) != dat[5])
- return 1;
- /* 转换温度数据 */
- recv_temperature = ((uint16_t) dat[0] << 8) | dat[1];
- *temperature = -45 + 175 * ((float) recv_temperature / 65535) + system_setting.fix_temp;
- /* 转换湿度数据 */
- recv_humidity = ((uint16_t) dat[3] << 8) | dat[4];
- *humidity = 100 * ((float) recv_humidity / 65535) + system_setting.fix_hum;
- return 0;
- }
- LV_IMAGE_DECLARE(_wifi_mid_RGB565A8_32x32);
- LV_IMAGE_DECLARE(_wifi_weak_RGB565A8_32x32);
- void ui_wifi_lab_refresh() {
- int rssi = 0;
- if (get_wifi_status()) {
- esp_err_t ret = esp_wifi_sta_get_rssi(&rssi);
- ESP_LOGE(TAG, "RSSI:%d", rssi);
- if (ret == ESP_OK) {
- lvgl_port_lock(-1);
- if (rssi >= -50) {
- lv_image_set_src(guider_ui.screen_img_wifi, &_wifi_stron_RGB565A8_32x32);
- } else if ((rssi < -50) && (rssi >= -70)) {
- lv_image_set_src(guider_ui.screen_img_wifi, &_wifi_mid_RGB565A8_32x32);
- } else if (rssi < -70) {
- lv_image_set_src(guider_ui.screen_img_wifi, &_wifi_weak_RGB565A8_32x32);
- }
- lvgl_port_unlock();
- }
- } else {
- }
- }
- _Noreturn void i2c_sht3x_task(void *arg) {
- // 配置I2C0-主机模式,400K,指定 SCL-5,SDA-4
- //ESP_ERROR_CHECK(i2c_master_init());
- uint8_t recv_dat[6] = {0};
- ESP_LOGI(TAG, "esp32 sht3x project starting ……");
- sht3x_reset(); // 复位SHT3X
- if (sht3x_init() == ESP_OK) // 初始化SHT3X(周期测量模式)
- ESP_LOGI(TAG, "sht3x init ok.\n");
- else
- ESP_LOGE(TAG, "sht3x init fail.\n");
- vTaskDelay(1000 / portTICK_PERIOD_MS); //延时1s 等待SHT3X传感器内部采样完成
- char temp_buf[32];
- char hum_buf[32];
- for (;;) {
- if (sht3x_read_th_raw_dat(recv_dat) == ESP_OK) // 从SHT3X读取一次数据(周期测量模式下)
- {
- // 将SHT3X接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
- if (sht3x_dat2float(recv_dat, &sht30Data.temperature, &sht30Data.humidity) == 0) {
- sht30Data.temperature = correct_temperature(sht30Data.temperature);
- snprintf(temp_buf, sizeof(temp_buf), "%.1f °C", sht30Data.temperature);
- snprintf(hum_buf, sizeof(hum_buf), "%.1f %%", sht30Data.humidity);
- if (guider_ui.screen) {
- lvgl_port_lock(-1);
- //lv_label_set_text_static(guider_ui.screen_lab_env_temp_2, temp_buf);
- //lv_label_set_text_static(guider_ui.ACPage_lab_env_hum_2, hum_buf);
- lv_label_set_text_static(guider_ui.screen_lab_env_temp, temp_buf);
- lv_label_set_text_static(guider_ui.screen_lab_env_hum, hum_buf);
- lvgl_port_unlock();
- }
- } else {
- ESP_LOGE(TAG, "crc check fail.\n");
- }
- } else {
- ESP_LOGE(TAG, "read data from sht3x fail.\n");
- }
- if (lcd_st7701_get_blacklight() == false) // 如果当前背光引脚为低电平
- {
- current_seconds -= 3;
- if (current_seconds < 0) current_seconds = 0;
- } else
- current_seconds += 3;
- ui_wifi_lab_refresh();
- vTaskDelay(15000 / portTICK_PERIOD_MS);
- }
- }
- void sht30_init() {
- xTaskCreate(i2c_sht3x_task, "i2c_sht3x_task", 6 * 1024, NULL, 3, NULL);
- }
|