|
|
@ -15,7 +15,8 @@ static const char *TAG = "co2"; |
|
|
|
|
|
|
|
|
|
|
|
#define CO2_ADDR 104 |
|
|
|
#define CO2_ADDR 104 |
|
|
|
#define CO2_I2C_NUM I2C_NUM_0 |
|
|
|
#define CO2_I2C_NUM I2C_NUM_0 |
|
|
|
#define TIMEOUT_MS 1000 |
|
|
|
#define TIMEOUT_MS 500 |
|
|
|
|
|
|
|
#define SEMA_TIMEOUT_MS 2000 |
|
|
|
|
|
|
|
|
|
|
|
static esp_err_t do_reg_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
|
|
|
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_cmd_handle_t cmd = i2c_cmd_link_create(); |
|
|
@ -42,10 +43,11 @@ bool wake_up() { |
|
|
|
TRY(i2c_master_write_byte(chain, (CO2_ADDR << 1) | I2C_MASTER_READ, false)); // TODO expect ack?
|
|
|
|
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_read(chain, &dummy, 1, I2C_MASTER_LAST_NACK)); |
|
|
|
TRY(i2c_master_stop(chain)); |
|
|
|
TRY(i2c_master_stop(chain)); |
|
|
|
/*esp_err_t ret = */ i2c_master_cmd_begin(CO2_I2C_NUM, chain, pdMS_TO_TICKS(10)); |
|
|
|
/*esp_err_t ret = */ i2c_master_cmd_begin(CO2_I2C_NUM, chain, pdMS_TO_TICKS(TIMEOUT_MS)); |
|
|
|
i2c_cmd_link_delete(chain); |
|
|
|
i2c_cmd_link_delete(chain); |
|
|
|
// if (ret == ESP_OK) {
|
|
|
|
// if (ret == ESP_OK) {
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(14)); |
|
|
|
// ets_delay_us(5000);
|
|
|
|
|
|
|
|
ets_delay_us(12000); |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//// }
|
|
|
|
//// }
|
|
|
@ -55,7 +57,7 @@ bool wake_up() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static esp_err_t reg_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
|
|
|
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)); |
|
|
|
BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(SEMA_TIMEOUT_MS)); |
|
|
|
if (suc != pdPASS) { |
|
|
|
if (suc != pdPASS) { |
|
|
|
ESP_LOGE(TAG, "Sema fail"); |
|
|
|
ESP_LOGE(TAG, "Sema fail"); |
|
|
|
return ESP_ERR_TIMEOUT; |
|
|
|
return ESP_ERR_TIMEOUT; |
|
|
@ -66,7 +68,7 @@ static esp_err_t reg_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, |
|
|
|
} |
|
|
|
} |
|
|
|
esp_err_t rv = do_reg_read(reg_addr, reg_data, length, timeout_ms); |
|
|
|
esp_err_t rv = do_reg_read(reg_addr, reg_data, length, timeout_ms); |
|
|
|
xSemaphoreGive(g_mux_i2c); |
|
|
|
xSemaphoreGive(g_mux_i2c); |
|
|
|
ets_delay_us(12000); |
|
|
|
vTaskDelay(pdMS_TO_TICKS(12)); |
|
|
|
return rv; |
|
|
|
return rv; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -82,7 +84,7 @@ static esp_err_t do_reg_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static esp_err_t reg_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, uint32_t timeout_ms) { |
|
|
|
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)); |
|
|
|
BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(SEMA_TIMEOUT_MS)); |
|
|
|
if (suc != pdPASS) { |
|
|
|
if (suc != pdPASS) { |
|
|
|
ESP_LOGE(TAG, "Sema fail"); |
|
|
|
ESP_LOGE(TAG, "Sema fail"); |
|
|
|
return ESP_ERR_TIMEOUT; |
|
|
|
return ESP_ERR_TIMEOUT; |
|
|
@ -102,17 +104,22 @@ void co2_read_task(void *param) { |
|
|
|
|
|
|
|
|
|
|
|
// continuous is the default
|
|
|
|
// continuous is the default
|
|
|
|
|
|
|
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(35)); |
|
|
|
for (int retry = 1; retry <= 10; retry++) { |
|
|
|
|
|
|
|
uint8_t pld[] = {0x00, 0x05, 0x00, 0x05}; |
|
|
|
{ |
|
|
|
if (ESP_OK == reg_write(0x96, pld, 4, TIMEOUT_MS)) { |
|
|
|
uint8_t pld[] = {0x00, 0x07, 0x00, 0x05}; |
|
|
|
ESP_LOGI(TAG, "CO2 init OK"); |
|
|
|
reg_write(0x96, pld, 4, TIMEOUT_MS); |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(50)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(250)); |
|
|
|
while (1) { |
|
|
|
while (1) { |
|
|
|
vTaskDelay(pdMS_TO_TICKS(7000)); |
|
|
|
vTaskDelay(pdMS_TO_TICKS(5000)); |
|
|
|
|
|
|
|
|
|
|
|
uint8_t data[4] = {}; |
|
|
|
uint8_t data[4] = {}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int retry = 0; retry < 3; retry++) { |
|
|
|
if (ESP_OK == reg_read(0x06, data, 4, TIMEOUT_MS)) { |
|
|
|
if (ESP_OK == reg_read(0x06, data, 4, TIMEOUT_MS)) { |
|
|
|
uint16_t filtered = (data[0] << 8) | data[1]; |
|
|
|
uint16_t filtered = (data[0] << 8) | data[1]; |
|
|
|
uint16_t unfiltered = (data[2] << 8) | data[3]; |
|
|
|
uint16_t unfiltered = (data[2] << 8) | data[3]; |
|
|
@ -123,11 +130,16 @@ void co2_read_task(void *param) { |
|
|
|
if (filtered > 400 && filtered < 5000) { |
|
|
|
if (filtered > 400 && filtered < 5000) { |
|
|
|
g_data_report.co2_ppm = (float) filtered; |
|
|
|
g_data_report.co2_ppm = (float) filtered; |
|
|
|
g_data_report.co2_ready = true; |
|
|
|
g_data_report.co2_ready = true; |
|
|
|
|
|
|
|
g_data_report.co2_timestamp = xTaskGetTickCount(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
g_data_report.co2_ready = false; |
|
|
|
g_data_report.co2_ready = false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
xSemaphoreGive(g_mux_data_report); |
|
|
|
xSemaphoreGive(g_mux_data_report); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(50)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|