02-11-2022 11:44 AM
Hi. I am trying to implement BSEC for my BME680 sensor on chip ESP32 using ESP-IDF framework. I am successfully imported all libraries and I am able to build (compile) my project but I cant read data from my sensor. I wrote functions for bus write and read, also sleep_time, get_timestamp_us, output_ready and config_load. I am not sure if they are right but I didnt wrote functions state_load and state_save where I am not sure how they should work because there is no guidance in BSEC implementation document. I am getting terminal output as you can see in the picture where I cant inicialize BME680 and there is core error. I think possible solution is to write functions state_load and state_save. If there is anyone who can somehow help with code or code snippets I would be grateful (I am beginner 🙂 ). I am attaching my code and terminal output. Thanks.
/*!
* @file bsec_iot_example.c
*
* @brief
* Example for using of BSEC library in a fixed configuration with the BME680 sensor.
* This works by running an endless loop in the bsec_iot_loop() function.
*/
/*!
* @addtogroup bsec_examples BSEC Examples
* @brief BSEC usage examples
* @{*/
/**********************************************************************************************************************/
/* header files */
/**********************************************************************************************************************/
#include "bsec_integration.h"
#include "bme680.h"
#include "string.h"
#include "driver/i2c.h"
#include <esp_log.h>
#include <universal_node_msokol_10_2019.h>
#include "time.h"
#include "esp_timer.h"
#include "esp_sleep.h"
const uint8_t bsec_config_iaq[454] =
{0,8,4,1,61,0,0,0,0,0,0,0,174,1,0,0,48,0,1,0,0,192,168,71,64,49,119,76,0,0,225,68,137,65,0,191,205,204,204,190,0,0,64,191,225,122,148,190,0,0,0,0,216,
85,0,100,0,0,0,0,0,0,0,0,28,0,2,0,0,244,1,225,0,25,0,0,128,64,0,0,32,65,144,1,0,0,112,65,0,0,0,63,16,0,3,0,10,215,163,60,10,215,35,59,10,215,35,59,9,0,5,
0,0,0,0,0,1,88,0,9,0,229,208,34,62,0,0,0,0,0,0,0,0,218,27,156,62,225,11,67,64,0,0,160,64,0,0,0,0,0,0,0,0,94,75,72,189,93,254,159,64,66,62,160,191,0,0,0,0,
0,0,0,0,33,31,180,190,138,176,97,64,65,241,99,190,0,0,0,0,0,0,0,0,167,121,71,61,165,189,41,192,184,30,189,64,12,0,10,0,0,0,0,0,0,0,0,0,229,0,254,0,2,1,5,48,
117,100,0,44,1,112,23,151,7,132,3,197,0,92,4,144,1,64,1,64,1,144,1,48,117,48,117,48,117,48,117,100,0,100,0,100,0,48,117,48,117,48,117,100,0,100,0,48,117,48,117,
100,0,100,0,100,0,100,0,48,117,48,117,48,117,100,0,100,0,100,0,48,117,48,117,100,0,100,0,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,8,
7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,8,7,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,112,23,255,255,255,
255,255,255,255,255,220,5,220,5,220,5,255,255,255,255,255,255,220,5,220,5,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,44,1,0,0,0,0,237,52,0,0};
static const char* BSECTAG = "BSECbme680";
/**********************************************************************************************************************/
/* functions */
/**********************************************************************************************************************/
uint8_t GTXBuffer[512], GRXBuffer[2048];
int8_t sensorAPI_i2c_write(uint8_t slave_addr7, uint8_t sub_addr, uint8_t *ptrBuffer, uint16_t write_num)
{
uint16_t dev_addr = slave_addr7 << 1;
ESP_LOGI(BSECTAG, "sensorAPI_i2c_write slave_addr7: 0x%X", slave_addr7);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_write sub_addr: 0x%X", sub_addr);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_write dev_addr: 0x%X", dev_addr);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_write write_num: %u", write_num);
GTXBuffer[0] = sub_addr;
memcpy(>XBuffer[1], ptrBuffer, write_num);
// send register addr
ESP_LOGI(BSECTAG, "sensorAPI_i2c_write: Ready to write to device");
i2c_master_write_to_device(1, 0x77, GTXBuffer, write_num+1, 100 / portTICK_RATE_MS);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_write: Done writing to device");
return 0;
}
/*!
* @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 dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len)
{
sensorAPI_i2c_write(0x77, reg_addr, reg_data_ptr, data_len);
// uint8_t write_buf[2] = {reg_addr, *reg_data_ptr};
// i2c_master_write_to_device(I2C_MASTER_NUM, dev_addr, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return 0;
}
int8_t sensorAPI_i2c_read(uint8_t slave_addr7, uint8_t sub_addr, uint8_t *ptrBuffer, uint16_t read_num)
{
uint16_t dev_addr = slave_addr7 << 1;
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read slave_addr7: 0x%X", slave_addr7);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read sub_addr: 0x%X", sub_addr);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read dev_addr: 0x%X", dev_addr);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read read_num: %u", read_num);
//send register addr
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read: Ready to write to device");
i2c_master_write_to_device(1, 0x77, &sub_addr, 1, 100 / portTICK_RATE_MS);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read: Done write to device");
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read: Ready to read from device");
i2c_master_read_from_device(1, 0x77, ptrBuffer, read_num, 100 / portTICK_RATE_MS);
ESP_LOGI(BSECTAG, "sensorAPI_i2c_read: Done read from device");
return 0;
}
/*!
* @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 dev_addr, uint8_t reg_addr, uint8_t *reg_data_ptr, uint16_t data_len)
{
sensorAPI_i2c_read(0x77, reg_addr, reg_data_ptr, data_len);
// i2c_master_write_read_device(I2C_MASTER_NUM, dev_addr, ®_addr, 1, reg_data_ptr, (size_t) data_len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return 0;
}
/*!
* @brief System specific implementation of sleep function
*
* @param[in] t_ms time in milliseconds
*
* @return none
*/
void sleep_time(uint32_t t_ms) // zmena nazvu zo sleep na sleep_time kvoli tomu ze sme mali koliziu s time.c inicializaciou tejto funkcie (boli 2 rovnake)
{
vTaskDelay(t_ms);
}
/*!
* @brief Capture the system time in microseconds
*
* @return system_current_time current system timestamp in microseconds
*/
int64_t get_timestamp_us()
{
return esp_timer_get_time();
}
/*!
* @brief Handling of the ready outputs
*
* @param[in] timestamp time in nanoseconds
* @param[in] iaq IAQ signal
* @param[in] iaq_accuracy accuracy of IAQ signal
* @param[in] temperature temperature signal
* @param[in] humidity humidity signal
* @param[in] pressure pressure signal
* @param[in] raw_temperature raw temperature signal
* @param[in] raw_humidity raw humidity signal
* @param[in] gas raw gas sensor signal
* @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, bsec_library_return_t bsec_status,
float static_iaq, float co2_equivalent, float breath_voc_equivalent)
{
printf("output ready\n");
printf("%f\n",iaq);
}
/*!
* @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)
{
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
*/
void app_main()
{
i2c_driver_install(1,I2C_MODE_MASTER,0,0,0);
i2c_set_pin(1,21,22,1,1,I2C_MODE_MASTER);
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_LP, 0.0f, bus_write, bus_read, sleep_time, state_load, config_load);
if (ret.bme680_status)
{
printf("Could not intialize BME680\n");
}
else if (ret.bsec_status)
{
printf("Could not intialize BSEC library\n");
}
/* 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_time, get_timestamp_us, output_ready, state_save, 10000);
}
/*! @}*/
02-23-2022 03:15 AM
Hello domko99,
There was reference code I uploaded in previous topic: https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/NRF52840-with-BME680/td-p/49665/highligh...
You could refer this example code and correct you code on your platform.
For your error, it doesn't matter with functions state_load() and state_save().
You could refer to the code comments of the two functions:
/*!
* @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.
// ...
}