maybe fix the bug

modbus
Ondřej Hruška 2 years ago
parent 557b074527
commit 30b322fba5
  1. 19
      components/bme680/src/bsec2.c
  2. 2
      main/app_main.c
  3. 62
      main/co2_sensor.c
  4. 10
      main/data_report.h
  5. 13
      main/voc_sensor.c
  6. 32
      main/web/websrv.c

@ -1,6 +1,12 @@
#include <string.h> #include <string.h>
#include "bsec2.h" #include "bsec2.h"
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <esp_log.h>
#include <inttypes.h>
static const char *TAG = "bsec";
/* Private funcs - prototypes */ /* Private funcs - prototypes */
/** /**
@ -70,7 +76,10 @@ bool bsec2_updateSubscription(struct bsec2 *self, const bsecSensor *sensorList,
} }
bool bsec2_run(struct bsec2 *self) { bool bsec2_run(struct bsec2 *self) {
int64_t currTimeNs = bsec2_getTimeMs(self) * INT64_C(1000000); int64_t ms = bsec2_getTimeMs(self);
int64_t currTimeNs = ms * INT64_C(1000000);
//ESP_LOGD(TAG, "%"PRIi64" ms = %"PRIi64" ns, nextcall %"PRIi64, ms, currTimeNs, self->bmeConf.next_call);
uint8_t lastOpMode = self->opMode; uint8_t lastOpMode = self->opMode;
@ -78,6 +87,8 @@ bool bsec2_run(struct bsec2 *self) {
self->opMode = self->bmeConf.op_mode; self->opMode = self->bmeConf.op_mode;
if (currTimeNs >= self->bmeConf.next_call) { if (currTimeNs >= self->bmeConf.next_call) {
ESP_LOGD(TAG, "bsec runs");
/* Provides the information about the current sensor configuration that is /* Provides the information about the current sensor configuration that is
necessary to fulfill the input requirements, eg: operation mode, timestamp necessary to fulfill the input requirements, eg: operation mode, timestamp
at which the sensor data shall be fetched etc */ at which the sensor data shall be fetched etc */
@ -221,14 +232,14 @@ bool bsec2_setConfig(struct bsec2 *self, const uint8_t *config) {
* @brief Function to calculate an int64_t timestamp in milliseconds * @brief Function to calculate an int64_t timestamp in milliseconds
*/ */
int64_t bsec2_getTimeMs(struct bsec2 *self) { int64_t bsec2_getTimeMs(struct bsec2 *self) {
int64_t timeMs = bsec2_timestamp_millis(); uint64_t timeMs = bsec2_timestamp_millis();
if (self->lastMillis > timeMs) /* An overflow occurred */ if (self->lastMillis > timeMs) /* An overflow occurred */
{ {
self->lastMillis = timeMs; self->lastMillis = timeMs;
self->ovfCounter++; self->ovfCounter++;
} }
return timeMs + (self->ovfCounter * INT64_C(0xFFFFFFFF)); self->lastMillis = timeMs;
return (int64_t) timeMs + (self->ovfCounter * INT64_C(0xFFFFFFFF));
} }
/* Private funcs impl */ /* Private funcs impl */

@ -57,6 +57,8 @@ void app_main(void) {
periph_init(); periph_init();
vTaskDelay(pdMS_TO_TICKS(1000));
xTaskCreatePinnedToCore(voc_read_task, "VOC", 4096, NULL, PRIO_NORMAL, NULL, 1); xTaskCreatePinnedToCore(voc_read_task, "VOC", 4096, NULL, PRIO_NORMAL, NULL, 1);
xTaskCreatePinnedToCore(co2_read_task, "CO2", 4096, NULL, PRIO_NORMAL, NULL, 1); xTaskCreatePinnedToCore(co2_read_task, "CO2", 4096, NULL, PRIO_NORMAL, NULL, 1);

@ -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,32 +104,42 @@ 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] = {};
if (ESP_OK == reg_read(0x06, data, 4, TIMEOUT_MS)) {
uint16_t filtered = (data[0] << 8) | data[1]; for (int retry = 0; retry < 3; retry++) {
uint16_t unfiltered = (data[2] << 8) | data[3]; if (ESP_OK == reg_read(0x06, data, 4, TIMEOUT_MS)) {
uint16_t filtered = (data[0] << 8) | data[1];
ESP_LOGI(TAG, "CO2 ppm %d, raw %d", filtered, unfiltered); uint16_t unfiltered = (data[2] << 8) | data[3];
if (pdPASS == xSemaphoreTake(g_mux_data_report, pdMS_TO_TICKS(1000))) { ESP_LOGI(TAG, "CO2 ppm %d, raw %d", filtered, unfiltered);
if (filtered > 400 && filtered < 5000) {
g_data_report.co2_ppm = (float) filtered; if (pdPASS == xSemaphoreTake(g_mux_data_report, pdMS_TO_TICKS(1000))) {
g_data_report.co2_ready = true; if (filtered > 400 && filtered < 5000) {
} else { g_data_report.co2_ppm = (float) filtered;
g_data_report.co2_ready = false; g_data_report.co2_ready = true;
g_data_report.co2_timestamp = xTaskGetTickCount();
} else {
g_data_report.co2_ready = false;
}
} }
xSemaphoreGive(g_mux_data_report);
break;
} }
xSemaphoreGive(g_mux_data_report);
vTaskDelay(pdMS_TO_TICKS(50));
} }
} }
} }

@ -11,24 +11,34 @@
#include <stdbool.h> #include <stdbool.h>
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
#include <freertos/task.h>
struct data_report { struct data_report {
bool iaq_ready; bool iaq_ready;
uint32_t iaq_timestamp;
float iaq; float iaq;
float iaq_static; float iaq_static;
float iaq_co2_ppm_equiv; float iaq_co2_ppm_equiv;
float iaq_voc_ppm_equiv; float iaq_voc_ppm_equiv;
bool thpg_ready; bool thpg_ready;
uint32_t thpg_timestamp;
float temperature; float temperature;
float pressure; float pressure;
float humidity; float humidity;
float gasr; float gasr;
bool co2_ready; bool co2_ready;
uint32_t co2_timestamp;
float co2_ppm; float co2_ppm;
}; };
static inline uint32_t timestamp_age(uint32_t ticks) {
return xTaskGetTickCount() - ticks;
}
#define DATA_MAX_AGE (pdMS_TO_TICKS(60000))
extern SemaphoreHandle_t g_mux_data_report; extern SemaphoreHandle_t g_mux_data_report;
extern struct data_report g_data_report; extern struct data_report g_data_report;

@ -14,6 +14,7 @@ static const char *TAG = "voc";
#define VOC_I2C_NUM I2C_NUM_0 #define VOC_I2C_NUM I2C_NUM_0
#define VOC_I2C_TO_MS 1000 #define VOC_I2C_TO_MS 1000
#define VOC_SEMA_TO_MS 2000
// Config overrides for BSEC // Config overrides for BSEC
#define BME68X_PERIOD_POLL UINT32_C(5000) #define BME68X_PERIOD_POLL UINT32_C(5000)
@ -70,7 +71,7 @@ static BME68X_INTF_RET_TYPE user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, u
if (length == 0) { if (length == 0) {
return BME68X_OK; return BME68X_OK;
} }
BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(500)); BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(VOC_SEMA_TO_MS));
if (suc != pdPASS) { if (suc != pdPASS) {
ESP_LOGE(TAG, "Sema fail"); ESP_LOGE(TAG, "Sema fail");
return -1; return -1;
@ -93,7 +94,7 @@ static BME68X_INTF_RET_TYPE user_i2c_write(uint8_t reg_addr, const uint8_t *reg_
if (length == 0) { if (length == 0) {
return BME68X_OK; return BME68X_OK;
} }
BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(500)); BaseType_t suc = xSemaphoreTake(g_mux_i2c, pdMS_TO_TICKS(VOC_SEMA_TO_MS));
if (suc != pdPASS) { if (suc != pdPASS) {
ESP_LOGE(TAG, "Sema fail"); ESP_LOGE(TAG, "Sema fail");
return -1; return -1;
@ -120,8 +121,8 @@ static esp_err_t voc_init(void) {
gas_sensor.write = user_i2c_write; gas_sensor.write = user_i2c_write;
gas_sensor.delay_us = user_delay_us; gas_sensor.delay_us = user_delay_us;
for (int retry = 0; retry < 3; retry++) { for (int retry = 1; retry <= 3; retry++) {
ESP_LOGD(TAG, "BME680 initializing"); ESP_LOGD(TAG, "BME680 initializing (try %d)", retry);
rslt = bme68x_init(&gas_sensor); rslt = bme68x_init(&gas_sensor);
if (rslt == BME68X_OK) { if (rslt == BME68X_OK) {
break; break;
@ -131,6 +132,7 @@ static esp_err_t voc_init(void) {
ESP_LOGE(TAG, "Error from bme680_init: %d", rslt); ESP_LOGE(TAG, "Error from bme680_init: %d", rslt);
return ESP_FAIL; return ESP_FAIL;
} }
ESP_LOGI(TAG, "BME680 init OK");
return ESP_OK; return ESP_OK;
} }
@ -203,6 +205,7 @@ static void new_data_callback(
if (pdPASS == xSemaphoreTake(g_mux_data_report, pdMS_TO_TICKS(1000))) { if (pdPASS == xSemaphoreTake(g_mux_data_report, pdMS_TO_TICKS(1000))) {
if (my_report.thpg_ready) { if (my_report.thpg_ready) {
g_data_report.thpg_ready = true; g_data_report.thpg_ready = true;
g_data_report.thpg_timestamp = xTaskGetTickCount();
g_data_report.humidity = my_report.humidity; g_data_report.humidity = my_report.humidity;
g_data_report.temperature = my_report.temperature; g_data_report.temperature = my_report.temperature;
g_data_report.pressure = my_report.pressure; g_data_report.pressure = my_report.pressure;
@ -213,6 +216,7 @@ static void new_data_callback(
if (my_report.iaq_ready) { if (my_report.iaq_ready) {
g_data_report.iaq_ready = true; g_data_report.iaq_ready = true;
g_data_report.iaq_timestamp = xTaskGetTickCount();
g_data_report.iaq = my_report.iaq; g_data_report.iaq = my_report.iaq;
g_data_report.iaq_static = my_report.iaq_static; g_data_report.iaq_static = my_report.iaq_static;
g_data_report.iaq_co2_ppm_equiv = my_report.iaq_co2_ppm_equiv; g_data_report.iaq_co2_ppm_equiv = my_report.iaq_co2_ppm_equiv;
@ -285,5 +289,6 @@ void voc_read_task(void *param) {
} }
abort: abort:
ESP_LOGE(TAG, "VOC task ends");
vTaskDelete(NULL); vTaskDelete(NULL);
} }

@ -93,22 +93,34 @@ static esp_err_t handler_sample(httpd_req_t *req) {
bool need_comma = false; bool need_comma = false;
if (g_data_report.iaq_ready) { if (g_data_report.iaq_ready) {
wp += sprintf(wp, "\"iaq\":%.2f,\"iaq_s\":%.2f,\"iaq_co2\":%.2f,\"iaq_voc\":%.2f", if (timestamp_age(g_data_report.iaq_timestamp) < DATA_MAX_AGE) {
g_data_report.iaq,g_data_report.iaq_static, g_data_report.iaq_co2_ppm_equiv, g_data_report.iaq_co2_ppm_equiv); wp += sprintf(wp, "\"iaq\":%.2f,\"iaq_s\":%.2f,\"iaq_co2\":%.2f,\"iaq_voc\":%.2f",
need_comma = true; g_data_report.iaq, g_data_report.iaq_static, g_data_report.iaq_co2_ppm_equiv, g_data_report.iaq_co2_ppm_equiv);
need_comma = true;
} else {
g_data_report.iaq_ready = false;
}
} }
if (g_data_report.thpg_ready) { if (g_data_report.thpg_ready) {
wp += sprintf(wp, "%s\"temp\":%.2f,\"hum\":%.2f,\"pres\":%.1f,\"gasr\":%.1f", if (timestamp_age(g_data_report.thpg_timestamp) < DATA_MAX_AGE) {
need_comma?",":"", wp += sprintf(wp, "%s\"temp\":%.2f,\"hum\":%.2f,\"pres\":%.1f,\"gasr\":%.1f",
g_data_report.temperature,g_data_report.humidity, g_data_report.pressure, g_data_report.gasr); need_comma ? "," : "",
need_comma = true; g_data_report.temperature, g_data_report.humidity, g_data_report.pressure, g_data_report.gasr);
need_comma = true;
} else {
g_data_report.thpg_ready = false;
}
} }
if (g_data_report.co2_ready) { if (g_data_report.co2_ready) {
wp += sprintf(wp, "%s\"co2\":%.2f", if (timestamp_age(g_data_report.co2_timestamp) < DATA_MAX_AGE) {
need_comma?",":"", wp += sprintf(wp, "%s\"co2\":%.2f",
g_data_report.co2_ppm); need_comma ? "," : "",
g_data_report.co2_ppm);
} else {
g_data_report.co2_ready = false;
}
} }
sprintf(wp, "}"); sprintf(wp, "}");

Loading…
Cancel
Save