BME680 BSEC function implementation for ESP-IDF

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(&GTXBuffer[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, &reg_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);
    
}

/*! @}*/

 

 

1 reply