Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 
    SOLVED

    How to use BSEC_IOT exemple for the BME680

    How to use BSEC_IOT exemple for the BME680

    hamady
    Established Member

    Hello 

    I'm using the BME680 in STMCubeIDE with a STM32WLE,

    I succed in importing all the files for the bsec algo with the 'bme680_iaq_33v_300s_4d' settings. 

    And i used the GCC cortex M4 libalgobsec.a file 

    I want the library to be called by my own sleep callback function that will be triggered every 120 sec (or semething close to BSEC requirement), to read IAQ data.

    So i used the files in 'BSEC_Integration_Examples'

     

    void sleep_n(uint32_t t_us, void *intf_ptr)
    {
    	//HAL_LPTIM_Counter_Start_IT(&hlptim1,(32768/ 128) * t_us);     //20sec timer
    	//Delay_us(t_us);
    }
    
    int64_t get_timestamp_us()
    {
    
    	int64_t system_current_time = 0;
    	// ...
    	// Please insert system specific function to retrieve a timestamp (in microseconds)
    	// ...
    	system_current_time =((int64_t)(HAL_GetTick())*1000);
    	return system_current_time;
    
    
    }
    
    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.
        // ...
    	//SPI_Flash_Erase_4K(SECTOR_STATE_BSEC);
    	//SPI_Flash_Write_Bytes(SECTOR_STATE_BSEC,length+1,state_buffer);
    	//SPI_Flash_Sleep();
    }
    
    
    uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer)
    {
        /*memcpy(config_buffer, Selectivity_config, n_buffer);
        return n_buffer;*/
    	return 0;
    }
    
    
    
    void output_ready(int64_t timestamp, float gas_estimate_1, float gas_estimate_2, float gas_estimate_3, float gas_estimate_4,
         float raw_pressure, float raw_temp, float raw_humidity, float raw_gas, uint8_t raw_gas_index, bsec_library_return_t bsec_status)
    {
        int64_t timestamp_int = (int64_t)timestamp;
        int32_t gas_estimate_1_int = (int32_t)gas_estimate_1;
        int32_t gas_estimate_2_int = (int32_t)gas_estimate_2;
        int32_t gas_estimate_3_int = (int32_t)gas_estimate_3;
        int32_t gas_estimate_4_int = (int32_t)gas_estimate_4;
        int32_t raw_pressure_int = (int32_t)raw_pressure;
        int32_t raw_temp_int = (int32_t)raw_temp;
        int32_t raw_humidity_int = (int32_t)raw_humidity;
        int32_t raw_gas_int = (int32_t)raw_gas;
        int32_t raw_gas_index_int = (int32_t)raw_gas_index;
        int32_t bsec_status_int = (int32_t)bsec_status;
    
        APP_LOG(TS_ON, VLEVEL_L, "Timestamp: %lld, Gas Estimate 1: %d, Gas Estimate 2: %d, Gas Estimate 3: %d, Gas Estimate 4: %d, Raw Pressure: %d, Raw Temperature: %d, Raw Humidity: %d, Raw Gas: %d, Raw Gas Index: %d, BSEC Status: %d\r\n",
                timestamp_int, gas_estimate_1_int, gas_estimate_2_int, gas_estimate_3_int, gas_estimate_4_int, raw_pressure_int, raw_temp_int, raw_humidity_int, raw_gas_int, raw_gas_index_int, bsec_status_int);
    }
    	Enable_sensor_BME680();
    	return_values_init ret;
    	struct bme68x_dev bme_dev;
    	memset(&bme_dev,0,sizeof(bme_dev));
    	bme_dev.intf = BME68X_SPI_INTF;
    	bme_dev.read = bme68x_spi_read;
    	bme_dev.write = bme68x_spi_write;
    	bme_dev.delay_us = bme68x_delay_us;
    	//bme_dev.intf_ptr = &communicationSetup;
    	bme_dev.amb_temp = 25;
    
    	ret = bsec_iot_init(BSEC_SAMPLE_RATE_ULP, 0.0f, bme68x_spi_write, bme68x_spi_read, sleep_n, state_load, config_load, bme_dev);
    	if (ret.bme68x_status)
    		{
    			/* Could not initialize BME68x */
    			APP_LOG(TS_ON, VLEVEL_L,"Error while initializing BME68x: %d",ret.bme68x_status);
    			return;
    		}
    		else if (ret.bsec_status)
    		{
    			/* Could not initialize BSEC library */
    			APP_LOG(TS_ON, VLEVEL_L,"Error while initializing BSEC library: %d",ret.bsec_status);
    			return;
    		}

     

    Here i can see that the BME680 is initalised but when the code come to the bsec init the MCU stop working.

    Also what is the code to be called when i trigger my sleep callback function (LPTIM)

     

    Thanks

    9 REPLIES 9

    hamady
    Established Member

    And also do you have any exemple for only IAQ with usage of sleep.

    Thanks

    hamady
    Established Member

    Hello,

    @BSTRobin Any update about my issue ?

    Thanks

    BSTRobin
    Community Moderator
    Community Moderator

    Hi hamady,

    If you use BSEC2.4.0.0, you can refer attached example code on STM32, enable macro definition in the file user_define.h.
    //#define BME68X_OUTPUT_GAS_ESTIMATE
    #define BME68X_OUTPUT_GAS_IAQ

    hamady
    Established Member

    Hello,

    Thanks for the response it works like a charm in LP mode i can get my IAQ readings

    But in ULP mode i can't get the data

    Here my function modified for my sleep mode usage 

    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;
    	uint32_t tick_before, tick_after;
        
        /* BSEC sensor settings struct */
        bsec_bme_settings_t sensor_settings;
    	memset(&sensor_settings, 0, sizeof(sensor_settings));
    	
    	/* BSEC sensor data */
    	struct bme68x_data data;
        
    	uint8_t nFieldsLeft = 0;
        uint32_t bsec_state_len = 0;
        uint32_t n_samples = 0;
    	int8_t ret_val;
    	
        opMode = sensor_settings.op_mode;
    	
        bsec_library_return_t bsec_status = BSEC_OK;
    	sensor_settings.next_call = 0;
    	
       // while (1)
        //{
        	tick_before = HAL_GetTick();
            /* get the timestamp in nanoseconds before calling bsec_sensor_control() */
            time_stamp = get_timestamp_us() * 1000;
    		if (time_stamp >= sensor_settings.next_call)
    		{
    			/* Retrieve sensor settings to be used in this time instant by calling bsec_sensor_control */
    			bsec_status = bsec_sensor_control(time_stamp, &sensor_settings);
    			if (bsec_status != BSEC_OK)
    			{
    				if (bsec_status < BSEC_OK)
    				{
    					APP_LOG(TS_ON, VLEVEL_L,"ERROR: bsec_sensor_control: %d\n", bsec_status);
    					//break;
    				}
    				else
    				{
    					APP_LOG(TS_ON, VLEVEL_L,"WARNING: bsec_sensor_control: %d\n", bsec_status);
    				}
    			}
    			switch (sensor_settings.op_mode)
    			{
    			case BME68X_FORCED_MODE:
    				setBme68xConfigForced(&sensor_settings);
    				break;
    			case BME68X_PARALLEL_MODE:
    				if (opMode != sensor_settings.op_mode)
    				{
    					setBme68xConfigParallel(&sensor_settings);
    				}
    				break;
    			case BME68X_SLEEP_MODE:
    				if (opMode != sensor_settings.op_mode)
    				{
    					ret_val = bme68x_set_op_mode(BME68X_SLEEP_MODE, &bme68x_g);
    					if ((ret_val == BME68X_OK) && (opMode != BME68X_SLEEP_MODE))
    					{
    						opMode = BME68X_SLEEP_MODE;
    					}
    				}
    				break;
    			}
    			
    			if (sensor_settings.trigger_measurement && sensor_settings.op_mode != BME68X_SLEEP_MODE)
    			{
    				nFields = 0;
    				bme68x_get_data(lastOpMode, &sensor_data[0], &nFields, &bme68x_g);
    				iFields = 0;
    				if(nFields)
    				{
    					do
    					{
    						nFieldsLeft = getData(&data);
    						/* check for valid gas data */
    						if (data.status & BME68X_GASM_VALID_MSK)
    						{
    							if (!processData(time_stamp, data, sensor_settings.process_data, output_ready))
    							{
    								return;
    							}
    						}
    					}while(nFieldsLeft);
    				}
    			}
    			
    			/* 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;
    			}
    		}
    		else{
    			APP_LOG(TS_ON, VLEVEL_L,"ERROR: time stamp: %d\n\r", sensor_settings.next_call);
    		}
    		tick_after = HAL_GetTick();
    		//PDEBUG("cost %u ms\r\n", tick_after - tick_before);
    	//}
    }

    hamady
    Established Member

     

    @BSTRobin 

    So for the moment i'm running the sensor in LP mode with the 300s_4d config and the iaq_accuracy is changing and IAQ behave normally.

    Is my utilisation of the lib is good knowing that the ULP config isn't working

     

    Thanks

     

    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