maybe fix the bug

modbus
Ondřej Hruška 1 year 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 "bsec2.h"
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <esp_log.h>
#include <inttypes.h>
static const char *TAG = "bsec";
/* Private funcs - prototypes */
/**
@ -70,7 +76,10 @@ bool bsec2_updateSubscription(struct bsec2 *self, const bsecSensor *sensorList,
}
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;
@ -78,6 +87,8 @@ bool bsec2_run(struct bsec2 *self) {
self->opMode = self->bmeConf.op_mode;
if (currTimeNs >= self->bmeConf.next_call) {
ESP_LOGD(TAG, "bsec runs");
/* Provides the information about the current sensor configuration that is
necessary to fulfill the input requirements, eg: operation mode, timestamp
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
*/
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 */
{
self->lastMillis = timeMs;
self->ovfCounter++;
}
return timeMs + (self->ovfCounter * INT64_C(0xFFFFFFFF));
self->lastMillis = timeMs;
return (int64_t) timeMs + (self->ovfCounter * INT64_C(0xFFFFFFFF));
}
/* Private funcs impl */

@ -57,6 +57,8 @@ void app_main(void) {
periph_init();
vTaskDelay(pdMS_TO_TICKS(1000));
xTaskCreatePinnedToCore(voc_read_task, "VOC", 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_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) {
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_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));
/*esp_err_t ret = */ i2c_master_cmd_begin(CO2_I2C_NUM, chain, pdMS_TO_TICKS(TIMEOUT_MS));
i2c_cmd_link_delete(chain);
// if (ret == ESP_OK) {
vTaskDelay(pdMS_TO_TICKS(14));
// ets_delay_us(5000);
ets_delay_us(12000);
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) {
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) {
ESP_LOGE(TAG, "Sema fail");
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);
xSemaphoreGive(g_mux_i2c);
ets_delay_us(12000);
vTaskDelay(pdMS_TO_TICKS(12));
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) {
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) {
ESP_LOGE(TAG, "Sema fail");
return ESP_ERR_TIMEOUT;
@ -102,32 +104,42 @@ void co2_read_task(void *param) {
// continuous is the default
vTaskDelay(pdMS_TO_TICKS(35));
{
uint8_t pld[] = {0x00, 0x07, 0x00, 0x05};
reg_write(0x96, pld, 4, TIMEOUT_MS);
for (int retry = 1; retry <= 10; retry++) {
uint8_t pld[] = {0x00, 0x05, 0x00, 0x05};
if (ESP_OK == reg_write(0x96, pld, 4, TIMEOUT_MS)) {
ESP_LOGI(TAG, "CO2 init OK");
break;
}
vTaskDelay(pdMS_TO_TICKS(50));
}
vTaskDelay(pdMS_TO_TICKS(250));
while (1) {
vTaskDelay(pdMS_TO_TICKS(7000));
vTaskDelay(pdMS_TO_TICKS(5000));
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;
for (int retry = 0; retry < 3; retry++) {
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;
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 <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
struct data_report {
bool iaq_ready;
uint32_t iaq_timestamp;
float iaq;
float iaq_static;
float iaq_co2_ppm_equiv;
float iaq_voc_ppm_equiv;
bool thpg_ready;
uint32_t thpg_timestamp;
float temperature;
float pressure;
float humidity;
float gasr;
bool co2_ready;
uint32_t co2_timestamp;
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 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_TO_MS 1000
#define VOC_SEMA_TO_MS 2000
// Config overrides for BSEC
#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) {
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) {
ESP_LOGE(TAG, "Sema fail");
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) {
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) {
ESP_LOGE(TAG, "Sema fail");
return -1;
@ -120,8 +121,8 @@ static esp_err_t voc_init(void) {
gas_sensor.write = user_i2c_write;
gas_sensor.delay_us = user_delay_us;
for (int retry = 0; retry < 3; retry++) {
ESP_LOGD(TAG, "BME680 initializing");
for (int retry = 1; retry <= 3; retry++) {
ESP_LOGD(TAG, "BME680 initializing (try %d)", retry);
rslt = bme68x_init(&gas_sensor);
if (rslt == BME68X_OK) {
break;
@ -131,6 +132,7 @@ static esp_err_t voc_init(void) {
ESP_LOGE(TAG, "Error from bme680_init: %d", rslt);
return ESP_FAIL;
}
ESP_LOGI(TAG, "BME680 init 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 (my_report.thpg_ready) {
g_data_report.thpg_ready = true;
g_data_report.thpg_timestamp = xTaskGetTickCount();
g_data_report.humidity = my_report.humidity;
g_data_report.temperature = my_report.temperature;
g_data_report.pressure = my_report.pressure;
@ -213,6 +216,7 @@ static void new_data_callback(
if (my_report.iaq_ready) {
g_data_report.iaq_ready = true;
g_data_report.iaq_timestamp = xTaskGetTickCount();
g_data_report.iaq = my_report.iaq;
g_data_report.iaq_static = my_report.iaq_static;
g_data_report.iaq_co2_ppm_equiv = my_report.iaq_co2_ppm_equiv;
@ -285,5 +289,6 @@ void voc_read_task(void *param) {
}
abort:
ESP_LOGE(TAG, "VOC task ends");
vTaskDelete(NULL);
}

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

Loading…
Cancel
Save