parent
fb71f94a17
commit
557b074527
@ -0,0 +1,133 @@ |
||||
#include "co2_sensor.h" |
||||
|
||||
#include <esp_log.h> |
||||
#include <esp_err.h> |
||||
#include <freertos/FreeRTOS.h> |
||||
#include <freertos/task.h> |
||||
#include <driver/i2c.h> |
||||
#include <sys/time.h> |
||||
#include "voc_sensor.h" |
||||
#include "i2c_utils.h" |
||||
#include "periph_init.h" |
||||
#include "data_report.h" |
||||
|
||||
static const char *TAG = "co2"; |
||||
|
||||
#define CO2_ADDR 104 |
||||
#define CO2_I2C_NUM I2C_NUM_0 |
||||
#define TIMEOUT_MS 1000 |
||||
|
||||
static esp_err_t do_reg_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); |
||||
i2c_reg_read(cmd, CO2_ADDR, reg_addr, reg_data, length); |
||||
esp_err_t ret = i2c_master_cmd_begin(CO2_I2C_NUM, cmd, pdMS_TO_TICKS(TIMEOUT_MS)); |
||||
i2c_cmd_link_delete(cmd); |
||||
if (ret != ESP_OK) { |
||||
ESP_LOGE(TAG, "I2C read error: %s, devaddr %x, reg %d, len %d", esp_err_to_name(ret), CO2_ADDR, reg_addr, length); |
||||
} |
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, reg_data, length, ESP_LOG_DEBUG); |
||||
return ret; |
||||
} |
||||
|
||||
bool wake_up() { |
||||
esp_err_t suc; |
||||
#define TRY(x) suc=x; if(suc!=ESP_OK) return suc; |
||||
// for (int i = 0; i < 10; i++) {
|
||||
uint8_t dummy; |
||||
i2c_cmd_handle_t chain = i2c_cmd_link_create(); |
||||
TRY(i2c_master_start(chain)); |
||||
TRY(i2c_master_write_byte(chain, (CO2_ADDR << 1) | I2C_MASTER_WRITE, false)); |
||||
TRY(i2c_master_write_byte(chain, 0x30, false)); |
||||
TRY(i2c_master_start(chain)); |
||||
TRY(i2c_master_write_byte(chain, (CO2_ADDR << 1) | I2C_MASTER_READ, false)); // TODO expect ack?
|
||||
TRY(i2c_master_read(chain, &dummy, 1, I2C_MASTER_LAST_NACK)); |
||||
TRY(i2c_master_stop(chain)); |
||||
/*esp_err_t ret = */ i2c_master_cmd_begin(CO2_I2C_NUM, chain, pdMS_TO_TICKS(10)); |
||||
i2c_cmd_link_delete(chain); |
||||
// if (ret == ESP_OK) {
|
||||
vTaskDelay(pdMS_TO_TICKS(14)); |
||||
return true; |
||||
// }
|
||||
//// }
|
||||
// ESP_LOGE(TAG, "Fail to wake up");
|
||||
// return false;
|
||||
#undef TRY |
||||
} |
||||
|
||||
static esp_err_t reg_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
||||
BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(500)); |
||||
if (suc != pdPASS) { |
||||
ESP_LOGE(TAG, "Sema fail"); |
||||
return ESP_ERR_TIMEOUT; |
||||
} |
||||
if (!wake_up()) { |
||||
xSemaphoreGive(g_mux_i2c); |
||||
return ESP_ERR_TIMEOUT; |
||||
} |
||||
esp_err_t rv = do_reg_read(reg_addr, reg_data, length, timeout_ms); |
||||
xSemaphoreGive(g_mux_i2c); |
||||
ets_delay_us(12000); |
||||
return rv; |
||||
} |
||||
|
||||
static esp_err_t do_reg_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); |
||||
i2c_reg_write(cmd, CO2_ADDR, reg_addr, reg_data, length); |
||||
esp_err_t ret = i2c_master_cmd_begin(CO2_I2C_NUM, cmd, pdMS_TO_TICKS(timeout_ms)); |
||||
i2c_cmd_link_delete(cmd); |
||||
if (ret != ESP_OK) { |
||||
ESP_LOGE(TAG, "I2C write error: %s, devaddr %x, reg %d, len %d", esp_err_to_name(ret), CO2_ADDR, reg_addr, length); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
static esp_err_t reg_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
||||
BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(500)); |
||||
if (suc != pdPASS) { |
||||
ESP_LOGE(TAG, "Sema fail"); |
||||
return ESP_ERR_TIMEOUT; |
||||
} |
||||
if (!wake_up()) { |
||||
xSemaphoreGive(g_mux_i2c); |
||||
return ESP_ERR_TIMEOUT; |
||||
} |
||||
esp_err_t rv = do_reg_write(reg_addr, reg_data, length, timeout_ms); |
||||
xSemaphoreGive(g_mux_i2c); |
||||
vTaskDelay(pdMS_TO_TICKS(12)); |
||||
return rv; |
||||
} |
||||
|
||||
void co2_read_task(void *param) { |
||||
// i2c is protected by a semaphore inside the driver, no need to worry about it here
|
||||
|
||||
// continuous is the default
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(35)); |
||||
|
||||
{ |
||||
uint8_t pld[] = {0x00, 0x07, 0x00, 0x05}; |
||||
reg_write(0x96, pld, 4, TIMEOUT_MS); |
||||
} |
||||
|
||||
while (1) { |
||||
vTaskDelay(pdMS_TO_TICKS(7000)); |
||||
|
||||
uint8_t data[4] = {}; |
||||
if (ESP_OK == reg_read(0x06, data, 4, TIMEOUT_MS)) { |
||||
uint16_t filtered = (data[0] << 8) | data[1]; |
||||
uint16_t unfiltered = (data[2] << 8) | data[3]; |
||||
|
||||
ESP_LOGI(TAG, "CO2 ppm %d, raw %d", filtered, unfiltered); |
||||
|
||||
if (pdPASS == xSemaphoreTake(g_mux_data_report, pdMS_TO_TICKS(1000))) { |
||||
if (filtered > 400 && filtered < 5000) { |
||||
g_data_report.co2_ppm = (float) filtered; |
||||
g_data_report.co2_ready = true; |
||||
} else { |
||||
g_data_report.co2_ready = false; |
||||
} |
||||
} |
||||
xSemaphoreGive(g_mux_data_report); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
/**
|
||||
* TODO file description |
||||
* |
||||
* Created on 2021/12/12. |
||||
*/ |
||||
|
||||
#ifndef ESPNODE_CO2_SENSOR_H |
||||
#define ESPNODE_CO2_SENSOR_H |
||||
|
||||
void co2_read_task(void *param); |
||||
|
||||
#endif //ESPNODE_CO2_SENSOR_H
|
@ -0,0 +1,4 @@ |
||||
#include "data_report.h" |
||||
|
||||
SemaphoreHandle_t g_mux_data_report; |
||||
struct data_report g_data_report = {}; |
@ -0,0 +1,35 @@ |
||||
/**
|
||||
* TODO file description |
||||
* |
||||
* Created on 2021/12/13. |
||||
*/ |
||||
|
||||
#ifndef ESPNODE_DATA_REPORT_H |
||||
#define ESPNODE_DATA_REPORT_H |
||||
|
||||
#include <stdint-gcc.h> |
||||
#include <stdbool.h> |
||||
#include <freertos/FreeRTOS.h> |
||||
#include <freertos/semphr.h> |
||||
|
||||
struct data_report { |
||||
bool iaq_ready; |
||||
float iaq; |
||||
float iaq_static; |
||||
float iaq_co2_ppm_equiv; |
||||
float iaq_voc_ppm_equiv; |
||||
|
||||
bool thpg_ready; |
||||
float temperature; |
||||
float pressure; |
||||
float humidity; |
||||
float gasr; |
||||
|
||||
bool co2_ready; |
||||
float co2_ppm; |
||||
}; |
||||
|
||||
extern SemaphoreHandle_t g_mux_data_report; |
||||
extern struct data_report g_data_report; |
||||
|
||||
#endif //ESPNODE_DATA_REPORT_H
|
Loading…
Reference in new issue