first commit

This commit is contained in:
stuce-bot 2025-06-30 20:47:33 +02:00
commit 5893b00dd2
1669 changed files with 1982740 additions and 0 deletions

View file

@ -0,0 +1,12 @@
The generic_examples are provided only for a single sensor implementation.
If multiple sensors are used kindly refer to x8_board_examples where support for 8 sensors are demonstrated.
basic_config_state.ino example supports regression as well as classification outputs.
However BSEC supports only one mode at any given point of time.
Ensure to define the output mode required in the example code before compilation.
Set the OUTPUT_MODE macro to CLASSIFICATION for the classification output of the BSEC algorithm (default).
#define OUTPUT_MODE CLASSIFICATION
Set the OUTPUT_MODE macro to REGRESSION for the regression output of the BSEC algorithm.
#define OUTPUT_MODE REGRESSION

View file

@ -0,0 +1,223 @@
/**
* Copyright (C) 2021 Bosch Sensortec GmbH
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
/* If compiling this examples leads to an 'undefined reference error', refer to the README
* at https://github.com/BoschSensortec/Bosch-BSEC2-Library
*/
/* The new sensor needs to be conditioned before the example can work reliably. You may run this
* example for 24hrs to let the sensor stabilize.
*/
/**
* basic.ino sketch :
* This is an example for illustrating the BSEC virtual outputs and
* which has been designed to work with Adafruit ESP8266 Board
*/
#include <bsec2.h>
/* Macros used */
#define PANIC_LED LED_BUILTIN
#define ERROR_DUR 1000
#define SAMPLE_RATE BSEC_SAMPLE_RATE_ULP
/* Helper functions declarations */
/**
* @brief : This function toggles the led when a fault was detected
*/
void errLeds(void);
/**
* @brief : This function checks the BSEC status, prints the respective error code. Halts in case of error
* @param[in] bsec : Bsec2 class object
*/
void checkBsecStatus(Bsec2 bsec);
/**
* @brief : This function is called by the BSEC library when a new output is available
* @param[in] input : BME68X sensor data before processing
* @param[in] outputs : Processed BSEC BSEC output data
* @param[in] bsec : Instance of BSEC2 calling the callback
*/
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec);
/* Create an object of the class Bsec2 */
Bsec2 envSensor;
/* Entry point for the example */
void setup(void)
{
/* Desired subscription list of BSEC2 outputs */
bsecSensor sensorList[] = {
BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_STABILIZATION_STATUS,
BSEC_OUTPUT_RUN_IN_STATUS,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
BSEC_OUTPUT_STATIC_IAQ,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_GAS_PERCENTAGE,
BSEC_OUTPUT_COMPENSATED_GAS
};
/* Initialize the communication interfaces */
Serial.begin(115200);
Wire.begin();
pinMode(PANIC_LED, OUTPUT);
/* Valid for boards with USB-COM. Wait until the port is open */
while(!Serial) delay(10);
/* Initialize the library and interfaces */
if (!envSensor.begin(BME68X_I2C_ADDR_LOW, Wire))
{
checkBsecStatus(envSensor);
}
/*
* The default offset provided has been determined by testing the sensor in LP and ULP mode on application board 3.0
* Please update the offset value after testing this on your product
*/
if (SAMPLE_RATE == BSEC_SAMPLE_RATE_ULP)
{
envSensor.setTemperatureOffset(TEMP_OFFSET_ULP);
}
else if (SAMPLE_RATE == BSEC_SAMPLE_RATE_LP)
{
envSensor.setTemperatureOffset(TEMP_OFFSET_LP);
}
/* Subsribe to the desired BSEC2 outputs */
if (!envSensor.updateSubscription(sensorList, ARRAY_LEN(sensorList), SAMPLE_RATE))
{
checkBsecStatus(envSensor);
}
/* Whenever new data is available call the newDataCallback function */
envSensor.attachCallback(newDataCallback);
Serial.println("BSEC library version " + \
String(envSensor.version.major) + "." \
+ String(envSensor.version.minor) + "." \
+ String(envSensor.version.major_bugfix) + "." \
+ String(envSensor.version.minor_bugfix));
}
/* Function that is looped forever */
void loop(void)
{
/* Call the run function often so that the library can
* check if it is time to read new data from the sensor
* and process it.
*/
if (!envSensor.run())
{
checkBsecStatus(envSensor);
}
}
void errLeds(void)
{
while(1)
{
digitalWrite(PANIC_LED, HIGH);
delay(ERROR_DUR);
digitalWrite(PANIC_LED, LOW);
delay(ERROR_DUR);
}
}
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec)
{
if (!outputs.nOutputs)
{
return;
}
Serial.println("BSEC outputs:\n\tTime stamp = " + String((int) (outputs.output[0].time_stamp / INT64_C(1000000))));
for (uint8_t i = 0; i < outputs.nOutputs; i++)
{
const bsecData output = outputs.output[i];
switch (output.sensor_id)
{
case BSEC_OUTPUT_IAQ:
Serial.println("\tIAQ = " + String(output.signal));
Serial.println("\tIAQ accuracy = " + String((int) output.accuracy));
break;
case BSEC_OUTPUT_RAW_TEMPERATURE:
Serial.println("\tTemperature = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_PRESSURE:
Serial.println("\tPressure = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_HUMIDITY:
Serial.println("\tHumidity = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_GAS:
Serial.println("\tGas resistance = " + String(output.signal));
break;
case BSEC_OUTPUT_STABILIZATION_STATUS:
Serial.println("\tStabilization status = " + String(output.signal));
break;
case BSEC_OUTPUT_RUN_IN_STATUS:
Serial.println("\tRun in status = " + String(output.signal));
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
Serial.println("\tCompensated temperature = " + String(output.signal));
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
Serial.println("\tCompensated humidity = " + String(output.signal));
break;
case BSEC_OUTPUT_STATIC_IAQ:
Serial.println("\tStatic IAQ = " + String(output.signal));
break;
case BSEC_OUTPUT_CO2_EQUIVALENT:
Serial.println("\tCO2 Equivalent = " + String(output.signal));
break;
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
Serial.println("\tbVOC equivalent = " + String(output.signal));
break;
case BSEC_OUTPUT_GAS_PERCENTAGE:
Serial.println("\tGas percentage = " + String(output.signal));
break;
case BSEC_OUTPUT_COMPENSATED_GAS:
Serial.println("\tCompensated gas = " + String(output.signal));
break;
default:
break;
}
}
}
void checkBsecStatus(Bsec2 bsec)
{
if (bsec.status < BSEC_OK)
{
Serial.println("BSEC error code : " + String(bsec.status));
errLeds(); /* Halt in case of failure */
}
else if (bsec.status > BSEC_OK)
{
Serial.println("BSEC warning code : " + String(bsec.status));
}
if (bsec.sensor.status < BME68X_OK)
{
Serial.println("BME68X error code : " + String(bsec.sensor.status));
errLeds(); /* Halt in case of failure */
}
else if (bsec.sensor.status > BME68X_OK)
{
Serial.println("BME68X warning code : " + String(bsec.sensor.status));
}
}

View file

@ -0,0 +1,360 @@
/**
* Copyright (C) 2021 Bosch Sensortec GmbH
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
/* If compiling this examples leads to an 'undefined reference error', refer to the README
* at https://github.com/BoschSensortec/Bosch-BSEC2-Library
*/
/* The new sensor needs to be conditioned before the example can work reliably. You may run this
* example for 24hrs to let the sensor stabilize.
*/
/**
* basic_config_state.ino sketch :
* This is an example for integration of BSEC2x library using configuration setting and has been
* tested with Adafruit ESP8266 Board
*
* For quick integration test, example code can be used with configuration file under folder
* Bosch_BSEC2_Library/src/config/FieldAir_HandSanitizer (Configuration file added as simple
* code example for integration but not optimized on classification performance)
* Config string for H2S and NonH2S target classes is also kept for reference (Suitable for
* lab-based characterization of the sensor)
*/
/* Use the Espressif EEPROM library. Skip otherwise */
#if defined(ARDUINO_ARCH_ESP32) || (ARDUINO_ARCH_ESP8266)
#include <EEPROM.h>
#define USE_EEPROM
#endif
#include <bsec2.h>
#define CLASSIFICATION 1
#define REGRESSION 2
/* Configuration for two class classification used here
* For four class classification please use configuration under config/FieldAir_HandSanitizer_Onion_Cinnamon
*/
/* Note :
For the classification output from BSEC algorithm set OUTPUT_MODE macro to CLASSIFICATION.
For the regression output from BSEC algorithm set OUTPUT_MODE macro to REGRESSION.
*/
#define OUTPUT_MODE CLASSIFICATION
#if (OUTPUT_MODE == CLASSIFICATION)
const uint8_t bsec_config[] = {
#include "config/FieldAir_HandSanitizer/bsec_selectivity.txt"
};
#elif (OUTPUT_MODE == REGRESSION)
const uint8_t bsec_config[] = {
#include "config/bme688/bme688_reg_18v_300s_4d/bsec_selectivity.txt"
};
#endif
/* Macros used */
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) /* 360 minutes - 4 times a day */
#define PANIC_LED LED_BUILTIN
#define ERROR_DUR 1000
/* Helper functions declarations */
/**
* @brief : This function toggles the led continuously with one second delay
*/
void errLeds(void);
/**
* @brief : This function checks the BSEC status, prints the respective error code. Halts in case of error
* @param[in] bsec : Bsec2 class object
*/
void checkBsecStatus(Bsec2 bsec);
/**
* @brief : This function updates/saves BSEC state
* @param[in] bsec : Bsec2 class object
*/
void updateBsecState(Bsec2 bsec);
/**
* @brief : This function is called by the BSEC library when a new output is available
* @param[in] input : BME68X sensor data before processing
* @param[in] outputs : Processed BSEC BSEC output data
* @param[in] bsec : Instance of BSEC2 calling the callback
*/
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec);
/**
* @brief : This function retrieves the existing state
* @param : Bsec2 class object
*/
bool loadState(Bsec2 bsec);
/**
* @brief : This function writes the state into EEPROM
* @param : Bsec2 class object
*/
bool saveState(Bsec2 bsec);
/* Create an object of the class Bsec2 */
Bsec2 envSensor;
#ifdef USE_EEPROM
static uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE];
#endif
/* Gas estimate names will be according to the configuration classes used */
const String gasName[] = { "Field Air", "Hand sanitizer", "Undefined 3", "Undefined 4"};
/* Entry point for the example */
void setup(void)
{
#if (OUTPUT_MODE == CLASSIFICATION)
/* Desired subscription list of BSEC2 outputs */
bsecSensor sensorList[] = {
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_RAW_GAS_INDEX,
BSEC_OUTPUT_GAS_ESTIMATE_1,
BSEC_OUTPUT_GAS_ESTIMATE_2,
BSEC_OUTPUT_GAS_ESTIMATE_3,
BSEC_OUTPUT_GAS_ESTIMATE_4
};
#elif (OUTPUT_MODE == REGRESSION)
/* Desired subscription list of BSEC2 outputs */
bsecSensor sensorList[] = {
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_RAW_GAS_INDEX,
BSEC_OUTPUT_REGRESSION_ESTIMATE_1,
BSEC_OUTPUT_REGRESSION_ESTIMATE_2,
BSEC_OUTPUT_REGRESSION_ESTIMATE_3,
BSEC_OUTPUT_REGRESSION_ESTIMATE_4
};
#endif
Serial.begin(115200);
#ifdef USE_EEPROM
EEPROM.begin(BSEC_MAX_STATE_BLOB_SIZE + 1);
#endif
Wire.begin();
pinMode(PANIC_LED, OUTPUT);
/* Valid for boards with USB-COM. Wait until the port is open */
while (!Serial) delay(10);
/* Initialize the library and interfaces */
if (!envSensor.begin(BME68X_I2C_ADDR_LOW, Wire))
{
checkBsecStatus(envSensor);
}
/* Load the configuration string that stores information on how to classify the detected gas */
if (!envSensor.setConfig(bsec_config))
{
checkBsecStatus (envSensor);
}
/* Copy state from the EEPROM to the algorithm */
if (!loadState(envSensor))
{
checkBsecStatus (envSensor);
}
/* Subscribe for the desired BSEC2 outputs */
if (!envSensor.updateSubscription(sensorList, ARRAY_LEN(sensorList), BSEC_SAMPLE_RATE_SCAN))
{
checkBsecStatus (envSensor);
}
/* Whenever new data is available call the newDataCallback function */
envSensor.attachCallback(newDataCallback);
Serial.println("\nBSEC library version " + \
String(envSensor.version.major) + "." \
+ String(envSensor.version.minor) + "." \
+ String(envSensor.version.major_bugfix) + "." \
+ String(envSensor.version.minor_bugfix));
}
/* Function that is looped forever */
void loop(void)
{
/* Call the run function often so that the library can
* check if it is time to read new data from the sensor
* and process it.
*/
if (!envSensor.run()) {
checkBsecStatus (envSensor);
}
}
void errLeds(void)
{
while(1)
{
digitalWrite(PANIC_LED, HIGH);
delay(ERROR_DUR);
digitalWrite(PANIC_LED, LOW);
delay(ERROR_DUR);
}
}
void updateBsecState(Bsec2 bsec)
{
static uint16_t stateUpdateCounter = 0;
bool update = false;
if (!stateUpdateCounter || (stateUpdateCounter * STATE_SAVE_PERIOD) < millis())
{
/* Update every STATE_SAVE_PERIOD minutes */
update = true;
stateUpdateCounter++;
}
if (update && !saveState(bsec))
checkBsecStatus(bsec);
}
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec)
{
if (!outputs.nOutputs)
return;
Serial.println("BSEC outputs:\n\tTime stamp = " + String((int) (outputs.output[0].time_stamp / INT64_C(1000000))));
uint8_t index = 0;
for (uint8_t i = 0; i < outputs.nOutputs; i++)
{
const bsecData output = outputs.output[i];
switch (output.sensor_id)
{
case BSEC_OUTPUT_RAW_TEMPERATURE:
Serial.println("\tTemperature = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_PRESSURE:
Serial.println("\tPressure = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_HUMIDITY:
Serial.println("\tHumidity = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_GAS:
Serial.println("\tGas resistance = " + String(output.signal));
break;
case BSEC_OUTPUT_RAW_GAS_INDEX:
Serial.println("\tGas index = " + String(output.signal));
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
Serial.println("\tCompensated temperature = " + String(output.signal));
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
Serial.println("\tCompensated humidity = " + String(output.signal));
break;
case BSEC_OUTPUT_GAS_ESTIMATE_1:
case BSEC_OUTPUT_GAS_ESTIMATE_2:
case BSEC_OUTPUT_GAS_ESTIMATE_3:
case BSEC_OUTPUT_GAS_ESTIMATE_4:
index = (output.sensor_id - BSEC_OUTPUT_GAS_ESTIMATE_1);
if (index == 0) // The four classes are updated from BSEC with same accuracy, thus printing is done just once.
{
Serial.println("\tAccuracy = " + String(output.accuracy));
}
Serial.println("\tClass " + String(index + 1) + " probability = " + String(output.signal * 100) + "%");
break;
case BSEC_OUTPUT_REGRESSION_ESTIMATE_1:
case BSEC_OUTPUT_REGRESSION_ESTIMATE_2:
case BSEC_OUTPUT_REGRESSION_ESTIMATE_3:
case BSEC_OUTPUT_REGRESSION_ESTIMATE_4:
index = (output.sensor_id - BSEC_OUTPUT_REGRESSION_ESTIMATE_1);
if (index == 0) // The four targets are updated from BSEC with same accuracy, thus printing is done just once.
{
Serial.println("\tAccuracy = " + String(output.accuracy));
}
Serial.println("\tTarget " + String(index + 1) + " = " + String(output.signal * 100));
break;
default:
break;
}
}
updateBsecState(envSensor);
}
void checkBsecStatus(Bsec2 bsec)
{
if (bsec.status < BSEC_OK)
{
Serial.println("BSEC error code : " + String(bsec.status));
errLeds(); /* Halt in case of failure */
} else if (bsec.status > BSEC_OK)
{
Serial.println("BSEC warning code : " + String(bsec.status));
}
if (bsec.sensor.status < BME68X_OK)
{
Serial.println("BME68X error code : " + String(bsec.sensor.status));
errLeds(); /* Halt in case of failure */
} else if (bsec.sensor.status > BME68X_OK)
{
Serial.println("BME68X warning code : " + String(bsec.sensor.status));
}
}
bool loadState(Bsec2 bsec)
{
#ifdef USE_EEPROM
if (EEPROM.read(0) == BSEC_MAX_STATE_BLOB_SIZE)
{
/* Existing state in EEPROM */
Serial.println("Reading state from EEPROM");
Serial.print("State file: ");
for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++)
{
bsecState[i] = EEPROM.read(i + 1);
Serial.print(String(bsecState[i], HEX) + ", ");
}
Serial.println();
if (!bsec.setState(bsecState))
return false;
} else
{
/* Erase the EEPROM with zeroes */
Serial.println("Erasing EEPROM");
for (uint8_t i = 0; i <= BSEC_MAX_STATE_BLOB_SIZE; i++)
EEPROM.write(i, 0);
EEPROM.commit();
}
#endif
return true;
}
bool saveState(Bsec2 bsec)
{
#ifdef USE_EEPROM
if (!bsec.getState(bsecState))
return false;
Serial.println("Writing state to EEPROM");
Serial.print("State file: ");
for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++)
{
EEPROM.write(i + 1, bsecState[i]);
Serial.print(String(bsecState[i], HEX) + ", ");
}
Serial.println();
EEPROM.write(0, BSEC_MAX_STATE_BLOB_SIZE);
EEPROM.commit();
#endif
return true;
}

View file

@ -0,0 +1,21 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32@6.6.0
board = esp32dev
framework = espidf
platform_packages =
platformio/framework-espidf@~3.50201.0
lib_deps =
../../../
BME68x Sensor library=https://github.com/luar123/Bosch-BME68x-Library.git
https://github.com/natanaeljr/esp32-I2Cbus
monitor_speed = 115200

View file

@ -0,0 +1,274 @@
/**
* Copyright (C) 2021 Bosch Sensortec GmbH
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
/* If compiling this examples leads to an 'undefined reference error', refer to the README
* at https://github.com/BoschSensortec/Bosch-BSEC2-Library
*/
/* The new sensor needs to be conditioned before the example can work reliably. You may run this
* example for 24hrs to let the sensor stabilize.
*/
/**
* basic.ino sketch :
* This is an example for illustrating the BSEC virtual outputs and
* which has been designed to work with Adafruit ESP8266 Board
*/
#include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "I2Cbus.hpp"
#define BME688_ADD 0x77
static const char* TAG = "main";
#include <bsec2.h>
/* Macros used */
#define PANIC_LED GPIO_NUM_5
#define ERROR_DUR 1000
#define SAMPLE_RATE BSEC_SAMPLE_RATE_LP
/* Helper functions declarations */
/**
* @brief : This function toggles the led when a fault was detected
*/
void errLeds(void);
/**
* @brief : This function checks the BSEC status, prints the respective error code. Halts in case of error
* @param[in] bsec : Bsec2 class object
*/
void checkBsecStatus(Bsec2 bsec);
/**
* @brief : This function is called by the BSEC library when a new output is available
* @param[in] input : BME68X sensor data before processing
* @param[in] outputs : Processed BSEC BSEC output data
* @param[in] bsec : Instance of BSEC2 calling the callback
*/
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec);
/* Create an object of the class Bsec2 */
Bsec2 envSensor;
/* Function wrappers */
int8_t read_bytes_wrapper(uint8_t a_register, uint8_t *data, uint32_t len, void *intfPtr) {
return static_cast<I2C_t *>(intfPtr)->readBytes(BME688_ADD, a_register, len, data)==ESP_OK ? 0 : -1;
}
int8_t write_bytes_wrapper(uint8_t a_register, const uint8_t *data, uint32_t len,
void *intfPtr) {
return static_cast<I2C_t *>(intfPtr)->writeBytes(BME688_ADD, a_register, len, data)==ESP_OK ? 0 : -1;
}
uint32_t IRAM_ATTR millis() { return (uint32_t) (esp_timer_get_time() / 1000ULL); }
void IRAM_ATTR delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); }
uint32_t IRAM_ATTR micros() { return (uint32_t) esp_timer_get_time(); }
void delay_microseconds_safe(uint32_t us) { // avoids CPU locks that could trigger WDT or affect WiFi/BT stability
uint32_t start = micros();
const uint32_t lag = 5000; // microseconds, specifies the maximum time for a CPU busy-loop.
// it must be larger than the worst-case duration of a delay(1) call (hardware tasks)
// 5ms is conservative, it could be reduced when exact BT/WiFi stack delays are known
if (us > lag) {
delay((us - lag) / 1000UL); // note: in disabled-interrupt contexts delay() won't actually sleep
while (micros() - start < us - lag)
delay(1); // in those cases, this loop allows to yield for BT/WiFi stack tasks
}
while (micros() - start < us) // fine delay the remaining usecs
;
}
void delay_us(uint32_t period, void *intfPtr) {
delay_microseconds_safe(period);
}
/* Entry point for the example */
void setup(void)
{
/* Desired subscription list of BSEC2 outputs */
bsecSensor sensorList[] = {
BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_STABILIZATION_STATUS,
BSEC_OUTPUT_RUN_IN_STATUS,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
BSEC_OUTPUT_STATIC_IAQ,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_GAS_PERCENTAGE,
BSEC_OUTPUT_COMPENSATED_GAS
};
/* Initialize the communication interfaces */
i2c0.begin(GPIO_NUM_3,GPIO_NUM_0);
gpio_set_direction(PANIC_LED, GPIO_MODE_OUTPUT);
/* Initialize the library and interfaces */
if (!envSensor.begin(BME68X_I2C_INTF, read_bytes_wrapper, write_bytes_wrapper, delay_us, (void *) &i2c0, millis))
{
checkBsecStatus(envSensor);
}
/*
* The default offset provided has been determined by testing the sensor in LP and ULP mode on application board 3.0
* Please update the offset value after testing this on your product
*/
if (SAMPLE_RATE == BSEC_SAMPLE_RATE_ULP)
{
envSensor.setTemperatureOffset(TEMP_OFFSET_ULP);
}
else if (SAMPLE_RATE == BSEC_SAMPLE_RATE_LP)
{
envSensor.setTemperatureOffset(TEMP_OFFSET_LP);
}
/* Subsribe to the desired BSEC2 outputs */
if (!envSensor.updateSubscription(sensorList, ARRAY_LEN(sensorList), SAMPLE_RATE))
{
checkBsecStatus(envSensor);
}
/* Whenever new data is available call the newDataCallback function */
envSensor.attachCallback(newDataCallback);
ESP_LOGI(TAG, "BSEC library version %u.%u.%u.%u", envSensor.version.major, envSensor.version.minor, envSensor.version.major_bugfix, envSensor.version.minor_bugfix);
}
/* Function that is looped forever */
void loop(void)
{
/* Call the run function often so that the library can
* check if it is time to read new data from the sensor
* and process it.
*/
if (!envSensor.run())
{
checkBsecStatus(envSensor);
}
}
void errLeds(void)
{
while(1)
{
gpio_set_level(PANIC_LED, 1);
vTaskDelay(ERROR_DUR / portTICK_PERIOD_MS);
gpio_set_level(PANIC_LED, 0);
vTaskDelay(ERROR_DUR / portTICK_PERIOD_MS);
}
}
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec)
{
if (!outputs.nOutputs)
{
return;
}
ESP_LOGI(TAG, "BSEC outputs:\n\tTime stamp = %d", (int) (outputs.output[0].time_stamp / INT64_C(1000000)));
for (uint8_t i = 0; i < outputs.nOutputs; i++)
{
const bsecData output = outputs.output[i];
switch (output.sensor_id)
{
case BSEC_OUTPUT_IAQ:
ESP_LOGI(TAG, "\tIAQ = %f", output.signal);
ESP_LOGI(TAG, "\tIAQ accuracy = %d", (int) output.accuracy);
break;
case BSEC_OUTPUT_RAW_TEMPERATURE:
ESP_LOGI(TAG, "\tTemperature = %f", output.signal);
break;
case BSEC_OUTPUT_RAW_PRESSURE:
ESP_LOGI(TAG, "\tPressure = %f", output.signal);
break;
case BSEC_OUTPUT_RAW_HUMIDITY:
ESP_LOGI(TAG, "\tHumidity = %f", output.signal);
break;
case BSEC_OUTPUT_RAW_GAS:
ESP_LOGI(TAG, "\tGas resistance = %f", output.signal);
break;
case BSEC_OUTPUT_STABILIZATION_STATUS:
ESP_LOGI(TAG, "\tStabilization status = %f", output.signal);
break;
case BSEC_OUTPUT_RUN_IN_STATUS:
ESP_LOGI(TAG, "\tRun in status = %f", output.signal);
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
ESP_LOGI(TAG, "\tCompensated temperature = %f", output.signal);
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
ESP_LOGI(TAG, "\tCompensated humidity = %f", output.signal);
break;
case BSEC_OUTPUT_STATIC_IAQ:
ESP_LOGI(TAG, "\tStatic IAQ = %f", output.signal);
break;
case BSEC_OUTPUT_CO2_EQUIVALENT:
ESP_LOGI(TAG, "\tCO2 Equivalent = %f", output.signal);
break;
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
ESP_LOGI(TAG, "\tbVOC equivalent = %f", output.signal);
break;
case BSEC_OUTPUT_GAS_PERCENTAGE:
ESP_LOGI(TAG, "\tGas percentage = %f", output.signal);
break;
case BSEC_OUTPUT_COMPENSATED_GAS:
ESP_LOGI(TAG, "\tCompensated gas = %f", output.signal);
break;
default:
break;
}
}
}
void checkBsecStatus(Bsec2 bsec)
{
if (bsec.status < BSEC_OK)
{
ESP_LOGI(TAG, "BSEC error code : %d", bsec.status);
errLeds(); /* Halt in case of failure */
}
else if (bsec.status > BSEC_OK)
{
ESP_LOGI(TAG, "BSEC warning code : %d", bsec.status);
}
if (bsec.sensor.status < BME68X_OK)
{
ESP_LOGI(TAG, "BME68X error code : %d", bsec.sensor.status);
errLeds(); /* Halt in case of failure */
}
else if (bsec.sensor.status > BME68X_OK)
{
ESP_LOGI(TAG, "BME68X warning code : %d", bsec.sensor.status);
}
}
void loop_task(void *pv_params) {
setup();
while (true) {
loop();
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
extern "C" void app_main()
{
ESP_LOGI(TAG, "starting");
xTaskCreate(loop_task, "loopTask", 8192, nullptr, 1, NULL);
}