first commit
This commit is contained in:
commit
5893b00dd2
1669 changed files with 1982740 additions and 0 deletions
12
libraries/bsec2/examples/generic_examples/Readme.md
Normal file
12
libraries/bsec2/examples/generic_examples/Readme.md
Normal 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
|
||||
223
libraries/bsec2/examples/generic_examples/basic/basic.ino
Normal file
223
libraries/bsec2/examples/generic_examples/basic/basic.ino
Normal 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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
274
libraries/bsec2/examples/generic_examples/basic_idf/src/main.cpp
Normal file
274
libraries/bsec2/examples/generic_examples/basic_idf/src/main.cpp
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue