11-01-2022 06:30 AM - edited 11-07-2022 02:16 AM
Dear guys,
I think I have successfully import the BSEC library and now can get the data from I2C bus.
Since I got the output value, but I am not sure if this is correct, so need your help to confirm.
another question is how can I calculate the ethanol? not clear after reading the datasheet(especially Table 5).
MCU chip is stm32g0b0ve, I use IAR IDE (version 9.20.1) to debug.
below is the code that I modify based on the sample code.
#include "target_config.h"
#include "bsec_integration.h"
#include "bsec_serialized_configurations_iaq.h"
#include "i2c.h"
#include "uart.h"
/**********************************************************************************************************************/
/* functions */
/**********************************************************************************************************************/
/*!
* @brief Write operation in either I2C or SPI
*
* param[in] dev_addr I2C or SPI device address
* param[in] reg_addr register address
* param[in] reg_data_ptr pointer to the data to be written
* param[in] data_len number of bytes to be written
*
* @return result of the bus communication function
*/
int8_t bus_write(uint8_t reg_addr, uint8_t *reg_data_ptr, uint32_t data_len, void *dev_addr)
{
// ...
// Please insert system specific function to write to the bus where BME680 is connected
// ...
uint8_t slaveaddr = *(uint8_t *) dev_addr;
//if((I2C_MasterSend(I2C_2,slaveaddr,reg_data_ptr,data_len,I2C_MEM_MUTEX_TIMEOUT))!= HAL_OK)
if(I2C_Reg_MasterSend(I2C_2, reg_addr, slaveaddr, reg_data_ptr ,data_len, I2C_MUTEX_TIMEOUT) != HAL_OK)
{
putstring("bus_write error for voc sensor.\r\n\0");
}
return 0;//useless return value
}
/*!
* @brief Read operation in either I2C or SPI
*
* param[in] dev_addr I2C or SPI device address
* param[in] reg_addr register address
* param[out] reg_data_ptr pointer to the memory to be used to store the read data
* param[in] data_len number of bytes to be read
*
* @return result of the bus communication function
*/
int8_t bus_read(uint8_t reg_addr, uint8_t *reg_data_ptr, uint32_t data_len, void *dev_addr)
{
// ...
// Please insert system specific function to read from bus where BME680 is connected
// ...
//uint8_t slaveaddr = (0x76 <<1);
uint8_t slaveaddr = *(uint8_t *) dev_addr;
int ret = I2C_Reg_MasterRead(I2C_2, reg_addr, slaveaddr, reg_data_ptr ,data_len, I2C_MUTEX_TIMEOUT);
//int ret = I2C_MasterRead(I2C_2,slaveaddr,reg_data_ptr,data_len, I2C_MEM_MUTEX_TIMEOUT);
if(ret != HAL_OK)
{
putstring("bus_read error for voc sensor.\r\n\0");
}
return 0;//useless return value
}
/*!
* @brief System specific implementation of sleep function
*
* @param[in] t_us Time in microseconds
* @param[in] intf_ptr Pointer to the interface descriptor
*
* @return none
*/
void sleep_n(uint32_t t_us, void *intf_ptr)
{
// ...
// Please insert system specific function sleep or delay for t_ms milliseconds
// ...
osDelay(t_us/1000);
}
/*!
* @brief Capture the system time in microseconds
*
* @return system_current_time current system timestamp in microseconds
*/
uint32_t get_timestamp_us()
{
uint32_t system_current_time = 0;
// ...
// Please insert system specific function to retrieve a timestamp (in microseconds)
// ...
system_current_time = xTaskGetTickCount() * 1000;
return system_current_time;
}
/*!
* @brief Handling of the ready outputs
*
* @param[in] timestamp time in milliseconds
* @param[in] iaq IAQ
* @param[in] iaq_accuracy IAQ accuracy
* @param[in] static_iaq static IAQ
* @param[in] temperature raw temperature
* @param[in] humidity raw humidity
* @param[in] temperature temperature
* @param[in] humidity humidity
* @param[in] pressure pressure
* @param[in] gas raw gas
* @param[in] gas_percentage gas percentage
* @param[in] co2_equivalent CO2 equivalent
* @param[in] breath_voc_equivalent breath VOC equivalent
* @param[in] stabStatus stabilization status
* @param[in] runInStatus run in status
* @param[in] bsec_status value returned by the bsec_do_steps() call
*
* @return none
*/
void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity,
float pressure, float raw_temperature, float raw_humidity, float gas, float gas_percentage, bsec_library_return_t bsec_status,
float static_iaq, float stabStatus, float runInStatus, float co2_equivalent, float breath_voc_equivalent)
{
// ...
// Please insert system specific code to further process or display the BSEC outputs
// ...
char str[50];
sprintf(str,"static_iaq===%f \r\n\0",breath_voc_equivalent);
putstring(str);
}
/*!
* @brief Load previous library state from non-volatile memory
*
* @param[in,out] state_buffer buffer to hold the loaded state string
* @param[in] n_buffer size of the allocated state buffer
*
* @return number of bytes copied to state_buffer
*/
uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer)
{
// ...
// Load a previous library state from non-volatile memory, if available.
//
// Return zero if loading was unsuccessful or no state was available,
// otherwise return length of loaded state string.
// ...
return 0;
}
/*!
* @brief Save library state to non-volatile memory
*
* @param[in] state_buffer buffer holding the state to be stored
* @param[in] length length of the state string to be stored
*
* @return none
*/
void state_save(const uint8_t *state_buffer, uint32_t length)
{
// ...
// Save the string some form of non-volatile memory, if possible.
// ...
}
/*!
* @brief Load library config from non-volatile memory
*
* @param[in,out] config_buffer buffer to hold the loaded state string
* @param[in] n_buffer size of the allocated state buffer
*
* @return number of bytes copied to config_buffer
*/
uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer)
{
// ...
// Load a library config from non-volatile memory, if available.
//
// Return zero if loading was unsuccessful or no config was available,
// otherwise return length of loaded config string.
// ...
memcpy(config_buffer,bsec_config_iaq,sizeof(bsec_config_iaq));
return sizeof(bsec_config_iaq);
}
/*!
* @brief Main function which configures BSEC library and then reads and processes the data from sensor based
* on timer ticks
*
* @return result of the processing
*/
int start_voc(void)
{
return_values_init ret;
/* Call to the function which initializes the BSEC library
* Switch on low-power mode and provide no temperature offset */
ret = bsec_iot_init(BSEC_SAMPLE_RATE_CONT, 0.0f, bus_write, bus_read, sleep_n, state_load, config_load);
if (ret.bme68x_status)
{
/* Could not intialize BME68x */
return (int)ret.bme68x_status;
}
else if (ret.bsec_status)
{
/* Could not intialize BSEC library */
return (int)ret.bsec_status;
}
/* Call to endless loop function which reads and processes data based on sensor settings */
/* State is saved every 10.000 samples, which means every 10.000 * 3 secs = 500 minutes */
bsec_iot_loop(sleep_n, get_timestamp_us, output_ready, state_save, 1);
return 0;
}
and here is the output value in output_ready().
Solved! Go to Solution.
11-07-2022 07:36 AM
Hi chakey,
You could print output value with following reference code on STM32.
void output_ready(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)
{
PDEBUG("timestamp=%lld, iaq=%f, iaq_accuracy=%d, temperature=%f, humity=%f, pressure=%f, \
raw_temperature=%f, raw_humity=%f, gas=%f, bsec_status=%d, static_iaq=%f, co2_equivalent=%f, \
breath_voc_equivalent=%f\r\n", timestamp, iaq, iaq_accuracy, temperature, humidity, pressure, \
raw_temperature, raw_humidity, gas, bsec_status, static_iaq, co2_equivalent, breath_voc_equivalent);
}
BSEC does not output calculations of ethanol, you could refer the supported BSEC output value from integration guide.
The calibration status value iaq accuracy must reach 3 to obtain a high-precision output value.
11-07-2022 08:04 AM - edited 11-07-2022 08:04 AM
Hi BSTRobin
Thanks for the update!
Regarding to calculations of ethanol, is there any formula I can refer to calculate ethanol value?
Regarding to calibration status value iaq accuracy, how can I configure to get a high-precision output value? or just wait some time(if yes, how long)?
Thanks again.
11-07-2022 08:18 AM
Hi chakey,
BME680 is a metal-oxide based chemical sensor. The sensor output is created by interaction of volatile organic compounds (VOCs) with the sensitive layer of BME680. Unlike a physical sensor (e.g. pressure sensor like BMP), chemical sensors are thus influenced by a plethora of parameters and their response is very complex. On the one hand, this implies that quantification of VOCs is not possible in a random VOC mixture like the one the sensor faces in a real world environment.
Take LP mode as an example:
The IAQ value obtained within 8 hours is not credible, and it can be obtained after more than 8 hours.
After 7 days, the output value of different sensors under the same environment should be within the scope of the specification, ± 15+± 15%.
11-07-2022 08:29 AM
Thanks BSTRobin for the clarification!