Undo merge

This commit is contained in:
Oliver Brandmueller committed 2019-01-19 19:54:54 +01:00
1 parent d9404b1a32
commit 7bdff00161
60 files changed
+1911 -1679

No files matched your search

-559
View File
@@ -1,559 +0,0 @@
/*
* Copyright (C) 2017 Robert Bosch. All Rights Reserved.
*
* Disclaimer
*
* Common:
* Bosch Sensortec products are developed for the consumer goods industry. They may only be used
* within the parameters of the respective valid product data sheet. Bosch Sensortec products are
* provided with the express understanding that there is no warranty of fitness for a particular purpose.
* They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device
* that may lead to bodily harm or property damage if the system or device malfunctions. In addition,
* Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems.
* The resale and/or use of products are at the purchasers own risk and his own responsibility. The
* examination of fitness for the intended use is the sole responsibility of the Purchaser.
*
* The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for
* incidental, or consequential damages, arising from any product use not covered by the parameters of
* the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch
* Sensortec for all costs in connection with such claims.
*
* The purchaser must monitor the market for the purchased products, particularly with regard to
* product safety and inform Bosch Sensortec without delay of all security relevant incidents.
*
* Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid
* technical specifications of the product series. They are therefore not intended or fit for resale to third
* parties or for use in end products. Their sole purpose is internal client testing. The testing of an
* engineering sample may in no way replace the testing of a product series. Bosch Sensortec
* assumes no liability for the use of engineering samples. By accepting the engineering samples, the
* Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering
* samples.
*
* Special:
* This software module (hereinafter called "Software") and any information on application-sheets
* (hereinafter called "Information") is provided free of charge for the sole purpose to support your
* application work. The Software and Information is subject to the following terms and conditions:
*
* The Software is specifically designed for the exclusive use for Bosch Sensortec products by
* personnel who have special experience and training. Do not use this Software if you do not have the
* proper experience or training.
*
* This Software package is provided `` as is `` and without any expressed or implied warranties,
* including without limitation, the implied warranties of merchantability and fitness for a particular
* purpose.
*
* Bosch Sensortec and their representatives and agents deny any liability for the functional impairment
* of this Software in terms of fitness, performance and safety. Bosch Sensortec and their
* representatives and agents shall not be liable for any direct or indirect damages or injury, except as
* otherwise stipulated in mandatory applicable law.
*
* The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no
* responsibility for the consequences of use of such Information nor for any infringement of patents or
* other rights of third parties which may result from its use. No license is granted by implication or
* otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are
* subject to change without notice.
*
* It is not allowed to deliver the source code of the Software to any third party without permission of
* Bosch Sensortec.
*
*/
/*!
* @file bsec_integration.c
*
* @brief
* Private part of the example for using of BSEC library.
*/
/*!
* @addtogroup bsec_examples BSEC Examples
* @brief BSEC usage examples
* @{*/
/**********************************************************************************************************************/
/* header files */
/**********************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "bsec_integration.h"
/**********************************************************************************************************************/
/* local macro definitions */
/**********************************************************************************************************************/
#define NUM_USED_OUTPUTS 8
/**********************************************************************************************************************/
/* global variable declarations */
/**********************************************************************************************************************/
/* Global sensor APIs data structure */
static struct bme680_dev bme680_g;
/* Global temperature offset to be subtracted */
static float bme680_temperature_offset_g = 0.0f;
/**********************************************************************************************************************/
/* functions */
/**********************************************************************************************************************/
/*!
* @brief Virtual sensor subscription
* Please call this function before processing of data using bsec_do_steps function
*
* @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP)
*
* @return subscription result, zero when successful
*/
static bsec_library_return_t bme680_bsec_update_subscription(float sample_rate)
{
bsec_sensor_configuration_t requested_virtual_sensors[NUM_USED_OUTPUTS];
uint8_t n_requested_virtual_sensors = NUM_USED_OUTPUTS;
bsec_sensor_configuration_t required_sensor_settings[BSEC_MAX_PHYSICAL_SENSOR];
uint8_t n_required_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR;
bsec_library_return_t status = BSEC_OK;
/* note: Virtual sensors as desired to be added here */
requested_virtual_sensors[0].sensor_id = BSEC_OUTPUT_IAQ;
requested_virtual_sensors[0].sample_rate = sample_rate;
requested_virtual_sensors[1].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE;
requested_virtual_sensors[1].sample_rate = sample_rate;
requested_virtual_sensors[2].sensor_id = BSEC_OUTPUT_RAW_PRESSURE;
requested_virtual_sensors[2].sample_rate = sample_rate;
requested_virtual_sensors[3].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY;
requested_virtual_sensors[3].sample_rate = sample_rate;
requested_virtual_sensors[4].sensor_id = BSEC_OUTPUT_RAW_GAS;
requested_virtual_sensors[4].sample_rate = sample_rate;
requested_virtual_sensors[5].sensor_id = BSEC_OUTPUT_RAW_TEMPERATURE;
requested_virtual_sensors[5].sample_rate = sample_rate;
requested_virtual_sensors[6].sensor_id = BSEC_OUTPUT_RAW_HUMIDITY;
requested_virtual_sensors[6].sample_rate = sample_rate;
requested_virtual_sensors[7].sensor_id = BSEC_OUTPUT_STATIC_IAQ;
requested_virtual_sensors[7].sample_rate = sample_rate;
/* Call bsec_update_subscription() to enable/disable the requested virtual sensors */
status = bsec_update_subscription(requested_virtual_sensors, n_requested_virtual_sensors, required_sensor_settings,
&n_required_sensor_settings);
return status;
}
/*!
* @brief Initialize the BME680 sensor and the BSEC library
*
* @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP)
* @param[in] temperature_offset device-specific temperature offset (due to self-heating)
* @param[in] bus_write pointer to the bus writing function
* @param[in] bus_read pointer to the bus reading function
* @param[in] sleep pointer to the system specific sleep function
* @param[in] state_load pointer to the system-specific state load function
* @param[in] config_load pointer to the system-specific config load function
*
* @return zero if successful, negative otherwise
*/
return_values_init bsec_iot_init(float sample_rate, float temperature_offset, bme680_com_fptr_t bus_write,
bme680_com_fptr_t bus_read, sleep_fct sleep, state_load_fct state_load, config_load_fct config_load)
{
return_values_init ret = {BME680_OK, BSEC_OK};
bsec_library_return_t bsec_status = BSEC_OK;
uint8_t bsec_state[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0};
uint8_t bsec_config[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0};
uint8_t work_buffer[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0};
int bsec_state_len, bsec_config_len;
/* Fixed I2C configuration */
bme680_g.dev_id = BME680_I2C_ADDR_PRIMARY;
bme680_g.intf = BME680_I2C_INTF;
/* User configurable I2C configuration */
bme680_g.write = bus_write;
bme680_g.read = bus_read;
bme680_g.delay_ms = sleep;
/* Initialize BME680 API */
ret.bme680_status = bme680_init(&bme680_g);
if (ret.bme680_status != BME680_OK)
{
return ret;
}
/* Initialize BSEC library */
ret.bsec_status = bsec_init();
if (ret.bsec_status != BSEC_OK)
{
return ret;
}
/* Load library config, if available */
bsec_config_len = config_load(bsec_config, sizeof(bsec_config));
if (bsec_config_len != 0)
{
ret.bsec_status = bsec_set_configuration(bsec_config, bsec_config_len, work_buffer, sizeof(work_buffer));
if (ret.bsec_status != BSEC_OK)
{
return ret;
}
}
/* Load previous library state, if available */
bsec_state_len = state_load(bsec_state, sizeof(bsec_state));
if (bsec_state_len != 0)
{
ret.bsec_status = bsec_set_state(bsec_state, bsec_state_len, work_buffer, sizeof(work_buffer));
if (ret.bsec_status != BSEC_OK)
{
return ret;
}
}
/* Set temperature offset */
bme680_temperature_offset_g = temperature_offset;
/* Call to the function which sets the library with subscription information */
ret.bsec_status = bme680_bsec_update_subscription(sample_rate);
if (ret.bsec_status != BSEC_OK)
{
return ret;
}
return ret;
}
/*!
* @brief Trigger the measurement based on sensor settings
*
* @param[in] sensor_settings settings of the BME680 sensor adopted by sensor control function
* @param[in] sleep pointer to the system specific sleep function
*
* @return none
*/
static void bme680_bsec_trigger_measurement(bsec_bme_settings_t *sensor_settings, sleep_fct sleep)
{
uint16_t meas_period;
uint8_t set_required_settings;
int8_t bme680_status = BME680_OK;
/* Check if a forced-mode measurement should be triggered now */
if (sensor_settings->trigger_measurement)
{
/* Set sensor configuration */
bme680_g.tph_sett.os_hum = sensor_settings->humidity_oversampling;
bme680_g.tph_sett.os_pres = sensor_settings->pressure_oversampling;
bme680_g.tph_sett.os_temp = sensor_settings->temperature_oversampling;
bme680_g.gas_sett.run_gas = sensor_settings->run_gas;
bme680_g.gas_sett.heatr_temp = sensor_settings->heater_temperature; /* degree Celsius */
bme680_g.gas_sett.heatr_dur = sensor_settings->heating_duration; /* milliseconds */
/* Select the power mode */
/* Must be set before writing the sensor configuration */
bme680_g.power_mode = BME680_FORCED_MODE;
/* Set the required sensor settings needed */
set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL;
/* Set the desired sensor configuration */
bme680_status = bme680_set_sensor_settings(set_required_settings, &bme680_g);
/* Set power mode as forced mode and trigger forced mode measurement */
bme680_status = bme680_set_sensor_mode(&bme680_g);
/* Get the total measurement duration so as to sleep or wait till the measurement is complete */
bme680_get_profile_dur(&meas_period, &bme680_g);
/* Delay till the measurement is ready. Timestamp resolution in ms */
sleep((uint32_t)meas_period);
}
/* Call the API to get current operation mode of the sensor */
bme680_status = bme680_get_sensor_mode(&bme680_g);
/* When the measurement is completed and data is ready for reading, the sensor must be in BME680_SLEEP_MODE.
* Read operation mode to check whether measurement is completely done and wait until the sensor is no more
* in BME680_FORCED_MODE. */
while (bme680_g.power_mode == BME680_FORCED_MODE)
{
/* sleep for 5 ms */
sleep(5);
bme680_status = bme680_get_sensor_mode(&bme680_g);
}
}
/*!
* @brief Read the data from registers and populate the inputs structure to be passed to do_steps function
*
* @param[in] time_stamp_trigger settings of the sensor returned from sensor control function
* @param[in] inputs input structure containing the information on sensors to be passed to do_steps
* @param[in] num_bsec_inputs number of inputs to be passed to do_steps
* @param[in] bsec_process_data process data variable returned from sensor_control
*
* @return none
*/
static void bme680_bsec_read_data(int64_t time_stamp_trigger, bsec_input_t *inputs, uint8_t *num_bsec_inputs,
int32_t bsec_process_data)
{
static struct bme680_field_data data;
int8_t bme680_status = BME680_OK;
/* We only have to read data if the previous call the bsec_sensor_control() actually asked for it */
if (bsec_process_data)
{
bme680_status = bme680_get_sensor_data(&data, &bme680_g);
if (data.status & BME680_NEW_DATA_MSK)
{
/* Pressure to be processed by BSEC */
if (bsec_process_data & BSEC_PROCESS_PRESSURE)
{
/* Place presssure sample into input struct */
inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_PRESSURE;
inputs[*num_bsec_inputs].signal = data.pressure;
inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
(*num_bsec_inputs)++;
}
/* Temperature to be processed by BSEC */
if (bsec_process_data & BSEC_PROCESS_TEMPERATURE)
{
/* Place temperature sample into input struct */
inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
#ifdef BME680_FLOAT_POINT_COMPENSATION
inputs[*num_bsec_inputs].signal = data.temperature;
#else
inputs[*num_bsec_inputs].signal = data.temperature / 100.0f;
#endif
inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
(*num_bsec_inputs)++;
/* Also add optional heatsource input which will be subtracted from the temperature reading to
* compensate for device-specific self-heating (supported in BSEC IAQ solution)*/
inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
inputs[*num_bsec_inputs].signal = bme680_temperature_offset_g;
inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
(*num_bsec_inputs)++;
}
/* Humidity to be processed by BSEC */
if (bsec_process_data & BSEC_PROCESS_HUMIDITY)
{
/* Place humidity sample into input struct */
inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
#ifdef BME680_FLOAT_POINT_COMPENSATION
inputs[*num_bsec_inputs].signal = data.humidity;
#else
inputs[*num_bsec_inputs].signal = data.humidity / 1000.0f;
#endif
inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
(*num_bsec_inputs)++;
}
/* Gas to be processed by BSEC */
if (bsec_process_data & BSEC_PROCESS_GAS)
{
/* Check whether gas_valid flag is set */
if(data.status & BME680_GASM_VALID_MSK)
{
/* Place sample into input struct */
inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
inputs[*num_bsec_inputs].signal = data.gas_resistance;
inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
(*num_bsec_inputs)++;
}
}
}
}
}
/*!
* @brief This function is written to process the sensor data for the requested virtual sensors
*
* @param[in] bsec_inputs input structure containing the information on sensors to be passed to do_steps
* @param[in] num_bsec_inputs number of inputs to be passed to do_steps
* @param[in] output_ready pointer to the function processing obtained BSEC outputs
*
* @return none
*/
static void bme680_bsec_process_data(bsec_input_t *bsec_inputs, uint8_t num_bsec_inputs, output_ready_fct output_ready)
{
/* Output buffer set to the maximum virtual sensor outputs supported */
bsec_output_t bsec_outputs[BSEC_NUMBER_OUTPUTS];
uint8_t num_bsec_outputs = 0;
uint8_t index = 0;
bsec_library_return_t bsec_status = BSEC_OK;
int64_t timestamp = 0;
float iaq = 0.0f;
uint8_t iaq_accuracy = 0;
float temp = 0.0f;
float raw_temp = 0.0f;
float raw_pressure = 0.0f;
float humidity = 0.0f;
float raw_humidity = 0.0f;
float raw_gas = 0.0f;
float static_iaq = 0.0f;
uint8_t static_iaq_accuracy = 0;
float co2_equivalent = 0.0f;
uint8_t co2_accuracy = 0;
float breath_voc_equivalent = 0.0f;
uint8_t breath_voc_accuracy = 0;
float comp_gas_value = 0.0f;
uint8_t comp_gas_accuracy = 0;
float gas_percentage = 0.0f;
uint8_t gas_percentage_acccuracy = 0;
/* Check if something should be processed by BSEC */
if (num_bsec_inputs > 0)
{
/* Set number of outputs to the size of the allocated buffer */
/* BSEC_NUMBER_OUTPUTS to be defined */
num_bsec_outputs = BSEC_NUMBER_OUTPUTS;
/* Perform processing of the data by BSEC
Note:
* The number of outputs you get depends on what you asked for during bsec_update_subscription(). This is
handled under bme680_bsec_update_subscription() function in this example file.
* The number of actual outputs that are returned is written to num_bsec_outputs. */
bsec_status = bsec_do_steps(bsec_inputs, num_bsec_inputs, bsec_outputs, &num_bsec_outputs);
/* Iterate through the outputs and extract the relevant ones. */
for (index = 0; index < num_bsec_outputs; index++)
{
switch (bsec_outputs[index].sensor_id)
{
case BSEC_OUTPUT_IAQ:
iaq = bsec_outputs[index].signal;
iaq_accuracy = bsec_outputs[index].accuracy;
break;
case BSEC_OUTPUT_STATIC_IAQ:
static_iaq = bsec_outputs[index].signal;
static_iaq_accuracy = bsec_outputs[index].accuracy;
break;
case BSEC_OUTPUT_CO2_EQUIVALENT:
co2_equivalent = bsec_outputs[index].signal;
co2_accuracy = bsec_outputs[index].accuracy;
break;
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
breath_voc_equivalent = bsec_outputs[index].signal;
breath_voc_accuracy = bsec_outputs[index].accuracy;
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
temp = bsec_outputs[index].signal;
break;
case BSEC_OUTPUT_RAW_PRESSURE:
raw_pressure = bsec_outputs[index].signal;
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
humidity = bsec_outputs[index].signal;
break;
case BSEC_OUTPUT_RAW_GAS:
raw_gas = bsec_outputs[index].signal;
break;
case BSEC_OUTPUT_RAW_TEMPERATURE:
raw_temp = bsec_outputs[index].signal;
break;
case BSEC_OUTPUT_RAW_HUMIDITY:
raw_humidity = bsec_outputs[index].signal;
break;
case BSEC_OUTPUT_COMPENSATED_GAS:
comp_gas_value = bsec_outputs[index].signal;
comp_gas_accuracy = bsec_outputs[index].accuracy;
break;
case BSEC_OUTPUT_GAS_PERCENTAGE:
gas_percentage = bsec_outputs[index].signal;
gas_percentage_acccuracy = bsec_outputs[index].accuracy;
break;
default:
continue;
}
/* Assume that all the returned timestamps are the same */
timestamp = bsec_outputs[index].time_stamp;
}
/* Pass the extracted outputs to the user provided output_ready() function. */
output_ready(timestamp, iaq, iaq_accuracy, temp, humidity, raw_pressure, raw_temp,
raw_humidity, raw_gas, bsec_status, static_iaq, co2_equivalent, breath_voc_equivalent);
}
}
/*!
* @brief Runs the main (endless) loop that queries sensor settings, applies them, and processes the measured data
*
* @param[in] sleep pointer to the system specific sleep function
* @param[in] get_timestamp_us pointer to the system specific timestamp derivation function
* @param[in] output_ready pointer to the function processing obtained BSEC outputs
* @param[in] state_save pointer to the system-specific state save function
* @param[in] save_intvl interval at which BSEC state should be saved (in samples)
*
* @return none
*/
void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready,
state_save_fct state_save, uint32_t save_intvl)
{
/* Timestamp variables */
int64_t time_stamp = 0;
int64_t time_stamp_interval_ms = 0;
/* Allocate enough memory for up to BSEC_MAX_PHYSICAL_SENSOR physical inputs*/
bsec_input_t bsec_inputs[BSEC_MAX_PHYSICAL_SENSOR];
/* Number of inputs to BSEC */
uint8_t num_bsec_inputs = 0;
/* BSEC sensor settings struct */
bsec_bme_settings_t sensor_settings;
/* Save state variables */
uint8_t bsec_state[BSEC_MAX_STATE_BLOB_SIZE];
uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE];
uint32_t bsec_state_len = 0;
uint32_t n_samples = 0;
bsec_library_return_t bsec_status = BSEC_OK;
while (1)
{
/* get the timestamp in nanoseconds before calling bsec_sensor_control() */
time_stamp = get_timestamp_us() * 1000;
/* Retrieve sensor settings to be used in this time instant by calling bsec_sensor_control */
bsec_sensor_control(time_stamp, &sensor_settings);
/* Trigger a measurement if necessary */
bme680_bsec_trigger_measurement(&sensor_settings, sleep);
/* Read data from last measurement */
num_bsec_inputs = 0;
bme680_bsec_read_data(time_stamp, bsec_inputs, &num_bsec_inputs, sensor_settings.process_data);
/* Time to invoke BSEC to perform the actual processing */
bme680_bsec_process_data(bsec_inputs, num_bsec_inputs, output_ready);
/* Increment sample counter */
n_samples++;
/* Retrieve and store state if the passed save_intvl */
if (n_samples >= save_intvl)
{
bsec_status = bsec_get_state(0, bsec_state, sizeof(bsec_state), work_buffer, sizeof(work_buffer), &bsec_state_len);
if (bsec_status == BSEC_OK)
{
state_save(bsec_state, bsec_state_len);
}
n_samples = 0;
}
/* Compute how long we can sleep until we need to call bsec_sensor_control() next */
/* Time_stamp is converted from microseconds to nanoseconds first and then the difference to milliseconds */
time_stamp_interval_ms = (sensor_settings.next_call - get_timestamp_us() * 1000) / 1000000;
if (time_stamp_interval_ms > 0)
{
sleep((uint32_t)time_stamp_interval_ms);
}
}
}
/*! @}*/
-165
View File
@@ -1,165 +0,0 @@
/*
* Copyright (C) 2017 Robert Bosch. All Rights Reserved.
*
* Disclaimer
*
* Common:
* Bosch Sensortec products are developed for the consumer goods industry. They may only be used
* within the parameters of the respective valid product data sheet. Bosch Sensortec products are
* provided with the express understanding that there is no warranty of fitness for a particular purpose.
* They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device
* that may lead to bodily harm or property damage if the system or device malfunctions. In addition,
* Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems.
* The resale and/or use of products are at the purchasers own risk and his own responsibility. The
* examination of fitness for the intended use is the sole responsibility of the Purchaser.
*
* The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for
* incidental, or consequential damages, arising from any product use not covered by the parameters of
* the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch
* Sensortec for all costs in connection with such claims.
*
* The purchaser must monitor the market for the purchased products, particularly with regard to
* product safety and inform Bosch Sensortec without delay of all security relevant incidents.
*
* Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid
* technical specifications of the product series. They are therefore not intended or fit for resale to third
* parties or for use in end products. Their sole purpose is internal client testing. The testing of an
* engineering sample may in no way replace the testing of a product series. Bosch Sensortec
* assumes no liability for the use of engineering samples. By accepting the engineering samples, the
* Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering
* samples.
*
* Special:
* This software module (hereinafter called "Software") and any information on application-sheets
* (hereinafter called "Information") is provided free of charge for the sole purpose to support your
* application work. The Software and Information is subject to the following terms and conditions:
*
* The Software is specifically designed for the exclusive use for Bosch Sensortec products by
* personnel who have special experience and training. Do not use this Software if you do not have the
* proper experience or training.
*
* This Software package is provided `` as is `` and without any expressed or implied warranties,
* including without limitation, the implied warranties of merchantability and fitness for a particular
* purpose.
*
* Bosch Sensortec and their representatives and agents deny any liability for the functional impairment
* of this Software in terms of fitness, performance and safety. Bosch Sensortec and their
* representatives and agents shall not be liable for any direct or indirect damages or injury, except as
* otherwise stipulated in mandatory applicable law.
*
* The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no
* responsibility for the consequences of use of such Information nor for any infringement of patents or
* other rights of third parties which may result from its use. No license is granted by implication or
* otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are
* subject to change without notice.
*
* It is not allowed to deliver the source code of the Software to any third party without permission of
* Bosch Sensortec.
*
*/
/*!
* @file bsec_integration.h
*
* @brief
* Contains BSEC integration API
*/
/*!
* @addtogroup bsec_examples BSEC Examples
* @brief BSEC usage examples
* @{*/
#ifndef __BSEC_INTEGRATION_H__
#define __BSEC_INTEGRATION_H__
#ifdef __cplusplus
extern "C"
{
#endif
/**********************************************************************************************************************/
/* header files */
/**********************************************************************************************************************/
/* Use the following bme680 driver: https://github.com/BoschSensortec/BME680_driver/releases/tag/bme680_v3.5.1 */
#include "bme680.h"
/* BSEC header files are available in the inc/ folder of the release package */
#include "bsec_interface.h"
#include "bsec_datatypes.h"
/**********************************************************************************************************************/
/* type definitions */
/**********************************************************************************************************************/
/* function pointer to the system specific sleep function */
typedef void (*sleep_fct)(uint32_t t_ms);
/* function pointer to the system specific timestamp derivation function */
typedef int64_t (*get_timestamp_us_fct)();
/* function pointer to the function processing obtained BSEC outputs */
typedef void (*output_ready_fct)(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity,
float pressure, float raw_temperature, float raw_humidity, float gas, bsec_library_return_t bsec_status,
float static_iaq, float co2_equivalent, float breath_voc_equivalent);
/* function pointer to the function loading a previous BSEC state from NVM */
typedef uint32_t (*state_load_fct)(uint8_t *state_buffer, uint32_t n_buffer);
/* function pointer to the function saving BSEC state to NVM */
typedef void (*state_save_fct)(const uint8_t *state_buffer, uint32_t length);
/* function pointer to the function loading the BSEC configuration string from NVM */
typedef uint32_t (*config_load_fct)(uint8_t *state_buffer, uint32_t n_buffer);
/* structure definitions */
/* Structure with the return value from bsec_iot_init() */
typedef struct{
/*! Result of API execution status */
int8_t bme680_status;
/*! Result of BSEC library */
bsec_library_return_t bsec_status;
}return_values_init;
/**********************************************************************************************************************/
/* function declarations */
/**********************************************************************************************************************/
/*!
* @brief Initialize the BME680 sensor and the BSEC library
*
* @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP)
* @param[in] temperature_offset device-specific temperature offset (due to self-heating)
* @param[in] bus_write pointer to the bus writing function
* @param[in] bus_read pointer to the bus reading function
* @param[in] sleep pointer to the system-specific sleep function
* @param[in] state_load pointer to the system-specific state load function
*
* @return zero if successful, negative otherwise
*/
return_values_init bsec_iot_init(float sample_rate, float temperature_offset, bme680_com_fptr_t bus_write, bme680_com_fptr_t bus_read,
sleep_fct sleep, state_load_fct state_load, config_load_fct config_load);
/*!
* @brief Runs the main (endless) loop that queries sensor settings, applies them, and processes the measured data
*
* @param[in] sleep pointer to the system-specific sleep function
* @param[in] get_timestamp_us pointer to the system-specific timestamp derivation function
* @param[in] output_ready pointer to the function processing obtained BSEC outputs
* @param[in] state_save pointer to the system-specific state save function
* @param[in] save_intvl interval at which BSEC state should be saved (in samples)
*
* @return return_values_init struct with the result of the API and the BSEC library
*/
void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready,
state_save_fct state_save, uint32_t save_intvl);
#ifdef __cplusplus
}
#endif
#endif /* __BSEC_INTEGRATION_H__ */
/*! @}*/
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -103,7 +103,7 @@
/** BME680 configuration macros */
/** Enable or un-comment the macro to provide floating point data output */
#ifndef BME680_FLOAT_POINT_COMPENSATION
/* #define BME680_FLOAT_POINT_COMPENSATION */
//#define BME680_FLOAT_POINT_COMPENSATION
#endif
/** BME680 General config */
+498
View File
@@ -0,0 +1,498 @@
/**
* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
* The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility
* for the consequences of use
* of such information nor for any infringement of patents or
* other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder.
*
* @file bsec.cpp
* @date 31 Jan 2018
* @version 1.0
*
*/
#include "bsec.h"
TwoWire *Bsec::wireObj = NULL;
SPIClass *Bsec::spiObj = NULL;
/**
* @brief Constructor
*/
Bsec::Bsec() {
nextCall = 0;
version.major = 0;
version.minor = 0;
version.major_bugfix = 0;
version.minor_bugfix = 0;
millisOverflowCounter = 0;
lastTime = 0;
bme680Status = BME680_OK;
outputTimestamp = 0;
_tempOffset = 0.0f;
status = BSEC_OK;
zeroOutputs();
}
/**
* @brief Function to initialize the BSEC library and the BME680 sensor
*/
void Bsec::begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read,
bme680_com_fptr_t write, bme680_delay_fptr_t idleTask) {
_bme680.dev_id = devId;
_bme680.intf = intf;
_bme680.read = read;
_bme680.write = write;
_bme680.delay_ms = idleTask;
_bme680.amb_temp = 25;
_bme680.power_mode = BME680_FORCED_MODE;
beginCommon();
}
/**
* @brief Function to initialize the BSEC library and the BME680 sensor
*/
void Bsec::begin(uint8_t i2cAddr, TwoWire &i2c) {
_bme680.dev_id = i2cAddr;
_bme680.intf = BME680_I2C_INTF;
_bme680.read = Bsec::i2cRead;
_bme680.write = Bsec::i2cWrite;
_bme680.delay_ms = Bsec::delay_ms;
_bme680.amb_temp = 25;
_bme680.power_mode = BME680_FORCED_MODE;
Bsec::wireObj = &i2c;
Bsec::wireObj->begin();
beginCommon();
}
/**
* @brief Function to initialize the BSEC library and the BME680 sensor
*/
void Bsec::begin(uint8_t chipSelect, SPIClass &spi) {
_bme680.dev_id = chipSelect;
_bme680.intf = BME680_SPI_INTF;
_bme680.read = Bsec::spiTransfer;
_bme680.write = Bsec::spiTransfer;
_bme680.delay_ms = Bsec::delay_ms;
_bme680.amb_temp = 25;
_bme680.power_mode = BME680_FORCED_MODE;
pinMode(chipSelect, OUTPUT);
digitalWrite(chipSelect, HIGH);
Bsec::spiObj = &spi;
Bsec::spiObj->begin();
beginCommon();
}
/**
* @brief Common code for the begin function
*/
void Bsec::beginCommon(void) {
status = bsec_init();
getVersion();
bme680Status = bme680_init(&_bme680);
}
/**
* @brief Function that sets the desired sensors and the sample rates
*/
void Bsec::updateSubscription(bsec_virtual_sensor_t sensorList[],
uint8_t nSensors, float sampleRate) {
bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS],
sensorSettings[BSEC_MAX_PHYSICAL_SENSOR];
uint8_t nVirtualSensors = 0, nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR;
for (uint8_t i = 0; i < nSensors; i++) {
virtualSensors[nVirtualSensors].sensor_id = sensorList[i];
virtualSensors[nVirtualSensors].sample_rate = sampleRate;
nVirtualSensors++;
}
status = bsec_update_subscription(virtualSensors, nVirtualSensors,
sensorSettings, &nSensorSettings);
return;
}
/**
* @brief Callback from the user to trigger reading of data from the BME680,
* process and store outputs
*/
bool Bsec::run(void) {
bool newData = false;
/* Check if the time has arrived to call do_steps() */
int64_t callTimeMs = getTimeMs();
if (callTimeMs >= nextCall) {
bsec_bme_settings_t bme680Settings;
int64_t callTimeNs = callTimeMs * INT64_C(1000000);
status = bsec_sensor_control(callTimeNs, &bme680Settings);
if (status < BSEC_OK)
return false;
nextCall =
bme680Settings.next_call / INT64_C(1000000); // Convert from ns to ms
bme680Status = setBme680Config(bme680Settings);
if (bme680Status != BME680_OK) {
return false;
}
bme680Status = bme680_set_sensor_mode(&_bme680);
if (bme680Status != BME680_OK) {
return false;
}
/* Wait for measurement to complete */
uint16_t meas_dur = 0;
bme680_get_profile_dur(&meas_dur, &_bme680);
delay_ms(meas_dur);
newData = readProcessData(callTimeNs, bme680Settings);
}
return newData;
}
/**
* @brief Function to get the state of the algorithm to save to non-volatile
* memory
*/
void Bsec::getState(uint8_t *state) {
uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE];
uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE;
status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer,
BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state);
}
/**
* @brief Function to set the state of the algorithm from non-volatile memory
*/
void Bsec::setState(uint8_t *state) {
uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE];
status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer,
BSEC_MAX_STATE_BLOB_SIZE);
}
/**
* @brief Function to set the configuration of the algorithm from memory
*/
void Bsec::setConfig(const uint8_t *state) {
uint8_t workBuffer[BSEC_MAX_PROPERTY_BLOB_SIZE];
status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE,
workBuffer, sizeof(workBuffer));
}
/* Private functions */
/**
* @brief Get the version of the BSEC library
*/
void Bsec::getVersion(void) { bsec_get_version(&version); }
/**
* @brief Read data from the BME680 and process it
*/
bool Bsec::readProcessData(int64_t currTimeNs,
bsec_bme_settings_t bme680Settings) {
bme680Status = bme680_get_sensor_data(&_data, &_bme680);
if (bme680Status != BME680_OK) {
return false;
}
bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas
uint8_t nInputs = 0, nOutputs = 0;
if (_data.status & BME680_NEW_DATA_MSK) {
if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) {
inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE;
#ifdef BME680_FLOAT_POINT_COMPENSATION
inputs[nInputs].signal = _data.temperature;
#else
inputs[nInputs].signal = _data.temperature / 100.0f;
#endif
inputs[nInputs].time_stamp = currTimeNs;
nInputs++;
/* Temperature offset from the real temperature due to external heat
* sources */
inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE;
inputs[nInputs].signal = _tempOffset;
inputs[nInputs].time_stamp = currTimeNs;
nInputs++;
}
if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) {
inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY;
#ifdef BME680_FLOAT_POINT_COMPENSATION
inputs[nInputs].signal = _data.humidity;
#else
inputs[nInputs].signal = _data.humidity / 1000.0f;
#endif
inputs[nInputs].time_stamp = currTimeNs;
nInputs++;
}
if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) {
inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE;
inputs[nInputs].signal = _data.pressure;
inputs[nInputs].time_stamp = currTimeNs;
nInputs++;
}
if (bme680Settings.process_data & BSEC_PROCESS_GAS) {
inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR;
inputs[nInputs].signal = _data.gas_resistance;
inputs[nInputs].time_stamp = currTimeNs;
nInputs++;
}
}
if (nInputs > 0) {
nOutputs = BSEC_NUMBER_OUTPUTS;
bsec_output_t _outputs[BSEC_NUMBER_OUTPUTS];
status = bsec_do_steps(inputs, nInputs, _outputs, &nOutputs);
if (status != BSEC_OK)
return false;
zeroOutputs();
if (nOutputs > 0) {
outputTimestamp =
_outputs[0].time_stamp / 1000000; // Convert from ns to ms
for (uint8_t i = 0; i < nOutputs; i++) {
switch (_outputs[i].sensor_id) {
case BSEC_OUTPUT_IAQ:
iaqEstimate = _outputs[i].signal;
iaqAccuracy = _outputs[i].accuracy;
break;
case BSEC_OUTPUT_STATIC_IAQ:
staticIaq = _outputs[i].signal;
staticIaqAccuracy = _outputs[i].accuracy;
break;
case BSEC_OUTPUT_CO2_EQUIVALENT:
co2Equivalent = _outputs[i].signal;
co2Accuracy = _outputs[i].accuracy;
break;
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
breathVocEquivalent = _outputs[i].signal;
breathVocAccuracy = _outputs[i].accuracy;
break;
case BSEC_OUTPUT_RAW_TEMPERATURE:
rawTemperature = _outputs[i].signal;
break;
case BSEC_OUTPUT_RAW_PRESSURE:
pressure = _outputs[i].signal;
break;
case BSEC_OUTPUT_RAW_HUMIDITY:
rawHumidity = _outputs[i].signal;
break;
case BSEC_OUTPUT_RAW_GAS:
gasResistance = _outputs[i].signal;
break;
case BSEC_OUTPUT_STABILIZATION_STATUS:
stabStatus = _outputs[i].signal;
break;
case BSEC_OUTPUT_RUN_IN_STATUS:
runInStatus = _outputs[i].signal;
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
temperature = _outputs[i].signal;
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
humidity = _outputs[i].signal;
break;
case BSEC_OUTPUT_COMPENSATED_GAS:
compGasValue = _outputs[i].signal;
compGasAccuracy = _outputs[i].accuracy;
break;
case BSEC_OUTPUT_GAS_PERCENTAGE:
gasPercentage = _outputs[i].signal;
gasPercentageAcccuracy = _outputs[i].accuracy;
break;
default:
break;
}
}
return true;
}
}
return false;
}
/**
* @brief Set the BME680 sensor's configuration
*/
int8_t Bsec::setBme680Config(bsec_bme_settings_t bme680Settings) {
_bme680.gas_sett.run_gas = bme680Settings.run_gas;
_bme680.tph_sett.os_hum = bme680Settings.humidity_oversampling;
_bme680.tph_sett.os_temp = bme680Settings.temperature_oversampling;
_bme680.tph_sett.os_pres = bme680Settings.pressure_oversampling;
_bme680.gas_sett.heatr_temp = bme680Settings.heater_temperature;
_bme680.gas_sett.heatr_dur = bme680Settings.heating_duration;
uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL |
BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL;
return bme680_set_sensor_settings(desired_settings, &_bme680);
}
/**
* @brief Function to zero the outputs
*/
void Bsec::zeroOutputs(void) {
temperature = 0.0f;
pressure = 0.0f;
humidity = 0.0f;
gasResistance = 0.0f;
rawTemperature = 0.0f;
rawHumidity = 0.0f;
stabStatus = 0.0f;
runInStatus = 0.0f;
iaqEstimate = 0.0f;
iaqAccuracy = 0;
staticIaq = 0.0f;
staticIaqAccuracy = 0;
co2Equivalent = 0.0f;
co2Accuracy = 0;
breathVocEquivalent = 0.0f;
breathVocAccuracy = 0;
compGasValue = 0.0f;
compGasAccuracy = 0;
gasPercentage = 0.0f;
gasPercentageAcccuracy = 0;
}
/**
* @brief Function to calculate an int64_t timestamp in milliseconds
*/
int64_t Bsec::getTimeMs(void) {
int64_t timeMs = millis();
if (lastTime > timeMs) { // An overflow occured
lastTime = timeMs;
millisOverflowCounter++;
}
return timeMs + (millisOverflowCounter * 0xFFFFFFFF);
}
/**
@brief Task that delays for a ms period of time
*/
void Bsec::delay_ms(uint32_t period) {
// Wait for a period amount of ms
// The system may simply idle, sleep or even perform background tasks
delay(period);
}
/**
@brief Callback function for reading registers over I2C
*/
int8_t Bsec::i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData,
uint16_t length) {
uint16_t i;
int8_t rslt = 0;
if (Bsec::wireObj) {
Bsec::wireObj->beginTransmission(devId);
Bsec::wireObj->write(regAddr);
rslt = Bsec::wireObj->endTransmission();
Bsec::wireObj->requestFrom((int)devId, (int)length);
for (i = 0; (i < length) && Bsec::wireObj->available(); i++) {
regData[i] = Bsec::wireObj->read();
}
} else {
rslt = -1;
}
return rslt;
}
/**
* @brief Callback function for writing registers over I2C
*/
int8_t Bsec::i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData,
uint16_t length) {
uint16_t i;
int8_t rslt = 0;
if (Bsec::wireObj) {
Bsec::wireObj->beginTransmission(devId);
Bsec::wireObj->write(regAddr);
for (i = 0; i < length; i++) {
Bsec::wireObj->write(regData[i]);
}
rslt = Bsec::wireObj->endTransmission();
} else {
rslt = -1;
}
return rslt;
}
/**
* @brief Callback function for reading and writing registers over SPI
*/
int8_t Bsec::spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData,
uint16_t length) {
int8_t rslt = 0;
if (Bsec::spiObj) {
Bsec::spiObj->beginTransaction(
SPISettings(4000000, MSBFIRST, SPI_MODE0)); // Can be upto 10MHz
digitalWrite(devId, LOW);
Bsec::spiObj->transfer(
regAddr); // Write the register address, ignore the return
for (uint16_t i = 0; i < length; i++)
regData[i] = Bsec::spiObj->transfer(regData[i]);
digitalWrite(devId, HIGH);
Bsec::spiObj->endTransaction();
} else {
rslt = -1;
}
return rslt;
;
}
+230
View File
@@ -0,0 +1,230 @@
/**
* Copyright (C) 2017 - 2018 Bosch Sensortec GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the copyright holder nor the names of the
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
* The information provided is believed to be accurate and reliable.
* The copyright holder assumes no responsibility
* for the consequences of use
* of such information nor for any infringement of patents or
* other rights of third parties which may result from its use.
* No license is granted by implication or otherwise under any patent or
* patent rights of the copyright holder.
*
* @file bsec.h
* @date 31 Jan 2018
* @version 1.0
*
*/
#ifndef BSEC_CLASS_H
#define BSEC_CLASS_H
/* Includes */
#include "Arduino.h"
#include "Wire.h"
#include "SPI.h"
#include "inc/bsec_datatypes.h"
#include "inc/bsec_interface.h"
#include "bme680/bme680.h"
/* BSEC class definition */
class Bsec
{
public:
/* Public variables */
bsec_version_t version; // Stores the version of the BSEC algorithm
int64_t nextCall; // Stores the time when the algorithm has to be called next in ms
int8_t bme680Status; // Placeholder for the BME680 driver's error codes
bsec_library_return_t status;
float iaqEstimate, rawTemperature, pressure, rawHumidity, gasResistance, stabStatus, runInStatus, temperature, humidity,
staticIaq, co2Equivalent, breathVocEquivalent, compGasValue, gasPercentage;
uint8_t iaqAccuracy, staticIaqAccuracy, co2Accuracy, breathVocAccuracy, compGasAccuracy, gasPercentageAcccuracy;
int64_t outputTimestamp; // Timestamp in ms of the output
static TwoWire *wireObj;
static SPIClass *spiObj;
/* Public APIs */
/**
* @brief Constructor
*/
Bsec();
/**
* @brief Function to initialize the BSEC library and the BME680 sensor
* @param devId : Device identifier parameter for the read/write interface functions
* @param intf : Physical communication interface
* @param read : Pointer to the read function
* @param write : Pointer to the write function
* @param idleTask : Pointer to the idling task
*/
void begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask);
/**
* @brief Function to initialize the BSEC library and the BME680 sensor
* @param i2cAddr : I2C address
* @param i2c : Pointer to the TwoWire object
*/
void begin(uint8_t i2cAddr, TwoWire &i2c);
/**
* @brief Function to initialize the BSEC library and the BME680 sensor
* @param chipSelect : SPI chip select
* @param spi : Pointer to the SPIClass object
*/
void begin(uint8_t chipSelect, SPIClass &spi);
/**
* @brief Function that sets the desired sensors and the sample rates
* @param sensorList : The list of output sensors
* @param nSensors : Number of outputs requested
* @param sampleRate : The sample rate of requested sensors
*/
void updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate = BSEC_SAMPLE_RATE_ULP);
/**
* @brief Callback from the user to trigger reading of data from the BME680, process and store outputs
* @return true if there are new outputs. false otherwise
*/
bool run(void);
/**
* @brief Function to get the state of the algorithm to save to non-volatile memory
* @param state : Pointer to a memory location that contains the state
*/
void getState(uint8_t *state);
/**
* @brief Function to set the state of the algorithm from non-volatile memory
* @param state : Pointer to a memory location that contains the state
*/
void setState(uint8_t *state);
/**
* @brief Function to set the configuration of the algorithm from memory
* @param state : Pointer to a memory location that contains the configuration
*/
void setConfig(const uint8_t *config);
/**
* @brief Function to set the temperature offset
* @param tempOffset : Temperature offset in degree Celsius
*/
void setTemperatureOffset(float tempOffset)
{
_tempOffset = tempOffset;
}
/**
* @brief Function to calculate an int64_t timestamp in milliseconds
*/
int64_t getTimeMs(void);
/**
* @brief Task that delays for a ms period of time
* @param period : Period of time in ms
*/
static void delay_ms(uint32_t period);
/**
* @brief Callback function for reading registers over I2C
* @param devId : Library agnostic parameter to identify the device to communicate with
* @param regAddr : Register address
* @param regData : Pointer to the array containing the data to be read
* @param length : Length of the array of data
* @return Zero for success, non-zero otherwise
*/
static int8_t i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length);
/**
* @brief Callback function for writing registers over I2C
* @param devId : Library agnostic parameter to identify the device to communicate with
* @param regAddr : Register address
* @param regData : Pointer to the array containing the data to be written
* @param length : Length of the array of data
* @return Zero for success, non-zero otherwise
*/
static int8_t i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length);
/**
* @brief Callback function for reading and writing registers over SPI
* @param devId : Library agnostic parameter to identify the device to communicate with
* @param regAddr : Register address
* @param regData : Pointer to the array containing the data to be read or written
* @param length : Length of the array of data
* @return Zero for success, non-zero otherwise
*/
static int8_t spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length);
private:
/* Private variables */
struct bme680_dev _bme680;
struct bme680_field_data _data;
float _tempOffset;
// Global variables to help create a millisecond timestamp that doesn't overflow every 51 days.
// If it overflows, it will have a negative value. Something that should never happen.
uint32_t millisOverflowCounter;
uint32_t lastTime;
/* Private APIs */
/**
* @brief Get the version of the BSEC library
*/
void getVersion(void);
/**
* @brief Read data from the BME680 and process it
* @param currTimeNs: Current time in ns
* @param bme680Settings: BME680 sensor's settings
* @return true if there are new outputs. false otherwise
*/
bool readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings);
/**
* @brief Set the BME680 sensor's configuration
* @param bme680Settings: Settings to configure the BME680
* @return BME680 return code. BME680_OK for success, failure otherwise
*/
int8_t setBme680Config(bsec_bme_settings_t bme680Settings);
/**
* @brief Common code for the begin function
*/
void beginCommon(void);
/**
* @brief Function to zero the outputs
*/
void zeroOutputs(void);
};
#endif
File renamed without changes.
File renamed without changes.
File renamed without changes.