Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BME680 BSEC function implementation for ESP-IDF

    BME680 BSEC function implementation for ESP-IDF

    domko99
    Member

    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);
        
    }
    
    /*! @}*/

     bsec_terminal.png

     

    1 REPLY 1

    BSTRobin
    Community Moderator
    Community Moderator

    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.
    // ...
    }

    Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist