Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BME688 evaluation

    BME688 evaluation

    doppio-R
    Member

    Hello

    I'm working with the BME688  and using the parallel mode. Is it normal, that after each measurement the device take 2 Minutes to rest? Could time between two measurements a bit shorter? In my point of view, the bsec calculate 5 times for each value during the measurement. Should I take the last value or the average (see picture humidity, x-scale time[s])?

    doppioR_0-1658218874691.png

     

     

    During this record I had compared the CO2 values, which were between 2425 and 2150ppm, and an alternative CO2 Sensor, which values were between 650 and 900. Why do I have such a difference between these values. Is this connected to the values which I load from the eeprom?

     Additonal I would like to say, that the temperature and humidity works almost correct.

    /*
     * BME688.c
     *
     *  Created on: Aug 25, 2021
     *      Author: Ruo
     */
    
    
    
    #include <ApplicationData.h>
    #include <string.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include "eeprom.h"
    
    #include <BME688_driver.h>
    #include "bsec_datatypes_hidden.h"
    
    
    
    #define BMETimestamp				1200000			//every 20 Minutes
    uint32_t LastSaveBMEState = 0;
    bool SaveState = false;
    float COtwo = 500;
    uint8_t n_fields;
    static uint32_t tick;
    static int64_t currTimeNs = 0;
    enum BsecStep _step;
    struct BsecOutput 	BME688_Output;
    
    
    struct bme68x_dev _bme68x;
    struct bme68x_conf _bme68x_conf;
    struct bme68x_heatr_conf _bme68x_heatr_conf;
    struct bme68x_data _bme68x_data[3]; // accessing bme68x data registers
    int8_t _bme68x_status;				// Placeholder for the BME68x driver's error codes
    #define BME68X_VALID_DATA  UINT8_C(0xB0)
    #define CHECK_BSEC_INPUT(x, shift)		(x & (1 << (shift-1)))
    #define ARRAY_LEN(array)				(sizeof(array)/sizeof(array[0]))
    struct BsecOutput {
    	bsec_output_t outputs[BSEC_NUMBER_OUTPUTS];
    	uint8_t len;
    }BsecOutput;
    typedef void (*BsecCallback)(const struct bme68x_data*, const struct BsecOutput*);
    bsec_version_t _bsec_version;		// Stores the version of the BSEC algorithm
    bsec_bme_settings_t _bsec_bme_settings;
    bsec_library_return_t _bsec_status;
    //
    struct BsecOutput _output;
    BsecCallback _proc;
    uint8_t _op_mode;					// operating mode of sensor
    uint8_t prev_gas_idx;
    bool check_meas_idx;                // check measurement index to track the order
    uint8_t last_meas_index;            // last measurement index received from sensor
    
    float _temp_offset;
    // Global variables to help create a millisecond timestamp that doesn't overflow every 51 days.
    // If it overflows, it will have a negative value. Something that should never happen.
    uint32_t _timer_overflow_counter;
    uint32_t _timer_last_value;
    
    extern float analogFilterValue(float filteredValue, float value, float filterDelta);
    
    enum BsecStep {
    	CONTROL_STEP,
    	MEASUREMENT_STEP,
    
    	LAST_STEP
    };
    
    
    bsec_virtual_sensor_t sensorList[] = {
        BSEC_OUTPUT_RAW_TEMPERATURE,						// ID = 6
        BSEC_OUTPUT_RAW_PRESSURE,							// ID = 7
        BSEC_OUTPUT_RAW_HUMIDITY,							// ID = 8
        BSEC_OUTPUT_RAW_GAS,								// ID = 9
        BSEC_OUTPUT_RAW_GAS_INDEX,							// ID = 26
        BSEC_OUTPUT_IAQ,									// ID = 1
        //BSEC_OUTPUT_STATIC_IAQ,                           /* ID = 	!< Unscaled indoor-air-quality estimate */
        BSEC_OUTPUT_CO2_EQUIVALENT,                         /* ID = 3	!< co2 equivalent estimate [ppm] */
        BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,                  /* ID = 4	!< breath VOC concentration estimate [ppm] */
        BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,	// ID = 14
        BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,		// ID = 15
        //	BSEC_OUTPUT_STABILIZATION_STATUS,					// ID = 12
        //BSEC_OUTPUT_GAS_ESTIMATE_1,							// ID = 22
        //BSEC_OUTPUT_GAS_ESTIMATE_2,							// ID = 23
        //BSEC_OUTPUT_GAS_ESTIMATE_3,							// ID = 24
        //BSEC_OUTPUT_GAS_ESTIMATE_4							// ID = 25
    };
    
    typedef struct structBME688_t
    {
    
      I2C_HandleTypeDef *phi2c; //!< handle to I2C Device
    } structBME688_t;
    structBME688_t BME688_MCU;
    
    
    bool loadState(void)
    {
      uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE];
    
      if (eepromReadPage((unsigned char*) &bsecState, EEPROM_DEVICE_BME_DATA_ADDRESS, sizeof(bsecState)) != false)
      	return false;
    
      if(bsecState[0] != 0xff && bsecState[0] != 0)
      {
      	if (!setState(bsecState))
          return false;
      }
      else																// Erase the EEPROM with zeroes
      {
      	if (!setState(bsec_fistState))
      	{
      		for (uint8_t i = 0; i < BSEC_MAX_STATE_BLOB_SIZE; i++)
      		{
      			bsecState[i] = 0;
      		}
      		eepromWritePage((unsigned char*) &bsecState, EEPROM_DEVICE_BME_DATA_ADDRESS, sizeof(bsecState));
      		return false;
      	}
    
      }
      return true;
    }
    
    bool saveState(void)
    {
      uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE];
      if (!getState(bsecState))
        return false;
    
      eepromWritePage((unsigned char*) &bsecState, EEPROM_DEVICE_BME_DATA_ADDRESS, sizeof(bsecState));
      return true;
    }
    
    #define ALength  5
    float array[ALength];
    /*!
     *
     */
    bool BME688_Init(I2C_HandleTypeDef *hi2c, uint8_t Slave_Address)
    {
      BME688_MCU.phi2c 	= hi2c;																//Data for the BME Driver & Communication
      _bme68x.intf_ptr 	= (void*)(intptr_t) Slave_Address;
      _bme68x.intf 		= BME68X_I2C_INTF;
      _bme68x.amb_temp 	= 25;
      _bme68x.delay_us	= delay_us;
      _bme68x.read 		= bme68x_i2c_read;
      _bme68x.write 		= bme68x_i2c_write;
    
      _timer_overflow_counter = 0;
      _timer_last_value = 0;
      _step = CONTROL_STEP;
      _bme68x_status = BME68X_OK;
      _bsec_status = BSEC_OK;
      _temp_offset = 5.0;
    
      _bme68x_status = bsec_init();																			// Bsec Library initialization
      _step = CONTROL_STEP;
      last_meas_index = 0;
      _bme68x_status |= setConfig(bsec_config_selectivity);									// BME688 vordefinierte Config wird geladen
      _bme68x_status |= loadState();
      _bme68x_status |= updateSubscription(BSEC_SAMPLE_RATE_HIGH_PERFORMANCE);				// BME688 samplerate definition
      _bme68x_status |= bme68x_init(&_bme68x);												// BME688 initialization
      if (_bsec_status < BSEC_OK)
        return false;
    
    
      //BME688 setting definition
      _bsec_bme_settings.op_mode 					= 	BME68X_PARALLEL_MODE;
      _bsec_bme_settings.humidity_oversampling	=	BME68X_OS_2X;
      _bsec_bme_settings.pressure_oversampling	=	BME68X_OS_16X;
      _bsec_bme_settings.temperature_oversampling	= 	BME68X_OS_2X;
      _bsec_bme_settings.run_gas = BME68X_ENABLE;
      uint16_t temp_prof[10] = { 250, 100, 100, 100, 100, 100, 100, 250, 250, 250 };		// Heater temperature in degree Celsius
      uint16_t mul_prof[10] = { 2, 0, 10, 15, 2, 2, 2, 2, 2, 2 };							// Multiplier to the shared heater duration
      for(uint8_t i=0; i<(ARRAY_LEN(temp_prof));i++)
        _bsec_bme_settings.heater_temperature_profile[i]=	temp_prof[i];
      for(uint8_t j=0; j<(ARRAY_LEN(mul_prof));j++)
        _bsec_bme_settings.heater_duration_profile[j]	=	mul_prof[j];
      _bsec_bme_settings.heater_profile_len		= 	10;
    
      setBme68xConfigParallel();
    
    	for(uint8_t i=0; i<ALength; i++)
    	{
    		array[i] = 500;
    	}
    
      return true;
    }
    
    float C02Value = 0;
    uint8_t Co2counter = 0;
    float CO2_Summe = 0;
    float smallestValue = 500;
    /*!
     * @brief Die Werte des Sensors werden abgerufen und zugewiesen.
     *
     * @return 1 = OK / 0 = nOK
     */
    bool BME688_Handle(void)												// kann im spaeteren Verlauf komplett durch run ersetzt werden. Benenung run soll genauer sein.
    {
    	if(run())																								// Command from BME688
    	{
    		if (!_output.len)
    			return false;
    		for (uint8_t i = 0; i < _output.len; i++)
    		{
    			const bsec_output_t DataOutput = _output.outputs[i];
    			switch(DataOutput.sensor_id)
    			{
    			case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:				// BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE = 14 | RAW_TEMPERATURE = 6
    				Pab.PabIn.s.SensorData.BME_temperature = DataOutput.signal;
    				break;
    			case BSEC_OUTPUT_RAW_PRESSURE:														//BSEC_OUTPUT_RAW_PRESSURE = 7
    				Pab.PabIn.s.SensorData.BME_pressure = analogFilterValue(Pab.PabIn.s.SensorData.BME_pressure, (float) DataOutput.signal, 25) - 30;				//-30 offset zum anderen Sensor
    				break;
    			case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:			// BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY = 15 | RAW_Hum = 8
    				Pab.PabIn.s.SensorData.BME_humidity = DataOutput.signal;
    				break;
    			case BSEC_OUTPUT_CO2_EQUIVALENT:											// BSEC_OUTPUT_CO2_EQUIVALENT = 3
    				if(DataOutput.accuracy > 0)
    				{
    					array[Co2counter] = DataOutput.signal;
    					Co2counter++;
    					if(Co2counter>= ALength)
    					{
    						Co2counter =0;
    						C02Value = array[0];
    						for(uint8_t i=0; i<ALength; i++)
    						{
    							if(C02Value>array[i])
    								C02Value = array[i];
    						}
    					}
    					Pab.PabIn.s.SensorData.BME_CO2 = C02Value; //smallestValue
    				}
    				break;
    			case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:										//BSEC_OUTPUT_BREATH_VOC_EQUIVALENT = 4
    				if(DataOutput.accuracy > 0)
    					Pab.PabIn.s.SensorData.BME_VOC = DataOutput.signal;
    				break;
    			case BSEC_OUTPUT_IAQ:																			//1
    				if(DataOutput.accuracy>=2)
    				{
    					Pab.PabIn.s.SensorData.BME_IAQ = DataOutput.signal;
    					SaveState = true;
    				}
    				break;
    			}
    		}
    
    		if(HAL_GetTick() - LastSaveBMEState > BMETimestamp && SaveState == true)
    		{
    			LastSaveBMEState = HAL_GetTick();
    			saveState();
    		}
    		_output.len = 0;
    	}
    	else
    	{
    		return false;
    	}
    
    	return true;
    }
    
    
    
    /**
     * @brief Function that sets the desired sensors and the sample rates (by subscription)
     */
    bool updateSubscription(float sampleRate)
    {
      uint8_t nSensors = ARRAY_LEN(sensorList);
      bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS], sensorSettings[BSEC_MAX_PHYSICAL_SENSOR];
      uint8_t nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR;
    
      for (uint8_t i = 0; i < nSensors; i++) {
          virtualSensors[i].sensor_id = sensorList[i];
          virtualSensors[i].sample_rate = sampleRate;
      }
    
      _bsec_status = bsec_update_subscription(virtualSensors, nSensors, sensorSettings, &nSensorSettings);
      if (_bsec_status < BSEC_OK)
        return false;
    
      return true;
    }
    
    
    
    
    /*!
     * @brief Die BME library (BSEC) kontrolliert den Sensor. Hier werden die Werte aus dem Sensor gelesen. Die Library berechnet die zusätzlichen Werte.
     *
     * @return 1 = OK / 0 = nOK
     */
    bool run(void)
    {
    	n_fields = 0;
    	tick = HAL_GetTick();
    	currTimeNs = 1000000 * (int64_t)tick;
    	_op_mode = _bsec_bme_settings.op_mode;
    
    	if (currTimeNs >=  _bsec_bme_settings.next_call)
    	{
    		_bsec_status = bsec_sensor_control(currTimeNs, &_bsec_bme_settings);
    		if (_bsec_status < BSEC_OK)
    			return false;
    
    		switch(_bsec_bme_settings.op_mode) {
    		case BME68X_FORCED_MODE:
    			setBme68xConfigForced();
    			break;
    		case BME68X_PARALLEL_MODE:
    			if (_op_mode != _bsec_bme_settings.op_mode)
    			{
    				setBme68xConfigParallel();
    			}
    			break;
    
    		case BME68X_SLEEP_MODE:
    			if (_op_mode != _bsec_bme_settings.op_mode)
    			{
    				setBme68xConfigSleep();
    			}
    			break;
    		}
    
    		if (_bme68x_status < BME68X_OK)
    			return false;
    
    
    
    		_bme68x_status = bme68x_get_data(_op_mode, _bme68x_data, &n_fields, &_bme68x);
    		for(uint8_t i = 0; i < n_fields; i++)
    		{
    			if (_bme68x_data[i].status & BME68X_GASM_VALID_MSK)
    			{
    				/* Measurement index check to track the first valid sample after operation mode change */
    				if(check_meas_idx == true )
    				{
    					/* After changing the operation mode, Measurement index expected to be zero
    					 * however with considering the data miss case as well, condition shall be checked less
    					 * than last received measurement index */
    					if(last_meas_index == 0 || _bme68x_data[i].meas_index == 0 ||  _bme68x_data[i].meas_index < last_meas_index)
    					{
    						check_meas_idx = false;
    					}
    					else
    					{
    						continue; // Skip the invalid data samples or  data from last duty cycle scan
    					}
    				}
    
    				last_meas_index = _bme68x_data[i].meas_index;
    
    				if(!processData(currTimeNs, &_bme68x_data[i]))
    				{
    					return false;
    				}
    
    			}
    		}
    
    	}
    	return true;
    }
    
    /**
     * @brief Function to get the state of the algorithm to save to non-volatile memory
     */
    bool getState(uint8_t *state)
    {
      uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE];
      uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE;
    
      _bsec_status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state);
      if (_bsec_status < BSEC_OK)
        return false;
      return true;
    }
    
    /**
     * @brief Function to set the state of the algorithm from non-volatile memory
     */
    bool setState(uint8_t *state)
    {
      uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE];
    
      _bsec_status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE);
      if (_bsec_status < BSEC_OK)
        return false;
    
      memset(&_bsec_bme_settings, 0, sizeof(_bsec_bme_settings));
      _step = CONTROL_STEP;
    
      return true;
    }
    
    /**
     * @brief Function to set the configuration of the algorithm from memory
     * Error through the
     */
    
    bool setConfig(const uint8_t *state)
    {
      uint8_t workBuffer[BSEC_MAX_WORKBUFFER_SIZE];
    
      _bsec_status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE, workBuffer, BSEC_MAX_PROPERTY_BLOB_SIZE);
      if (_bsec_status < BSEC_OK)
        return false;
    
      memset(&_bsec_bme_settings, 0, sizeof(_bsec_bme_settings));
      _step = CONTROL_STEP;
    
      return true;
    }
    
    
    /* Private functions */
    
    /**
     * @brief Read data from the BME68X and process it
     */
    bool processData(int64_t currTimeNs, struct bme68x_data *data)
    {
      bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas
      uint8_t nInputs = 0;
    
      if (CHECK_BSEC_INPUT(_bsec_bme_settings.process_data, BSEC_INPUT_HEATSOURCE)) {
          inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE;
          inputs[nInputs].signal = _temp_offset;
          inputs[nInputs].time_stamp = currTimeNs;
          nInputs++;
      }
      if (CHECK_BSEC_INPUT(_bsec_bme_settings.process_data, BSEC_INPUT_TEMPERATURE)) {
          inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE;
          inputs[nInputs].signal = data->temperature;
          inputs[nInputs].time_stamp = currTimeNs;
          nInputs++;
      }
      if (CHECK_BSEC_INPUT(_bsec_bme_settings.process_data, BSEC_INPUT_HUMIDITY)) {
          inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY;
          inputs[nInputs].signal = data->humidity;
          inputs[nInputs].time_stamp = currTimeNs;
          nInputs++;
      }
      if (CHECK_BSEC_INPUT(_bsec_bme_settings.process_data, BSEC_INPUT_PRESSURE)) {
          inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE;
          inputs[nInputs].signal = data->pressure;
          inputs[nInputs].time_stamp = currTimeNs;
          nInputs++;
      }
      if (CHECK_BSEC_INPUT(_bsec_bme_settings.process_data, BSEC_INPUT_GASRESISTOR)) {
          inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR;
          inputs[nInputs].signal = data->gas_resistance;
          inputs[nInputs].time_stamp = currTimeNs;
          nInputs++;
      }
      if (CHECK_BSEC_INPUT(_bsec_bme_settings.process_data, BSEC_INPUT_PROFILE_PART)) {
          inputs[nInputs].sensor_id = BSEC_INPUT_PROFILE_PART;
          inputs[nInputs].signal = (_op_mode == BME68X_FORCED_MODE) ? 0 : data->gas_index;
          inputs[nInputs].time_stamp = currTimeNs;
          nInputs++;
      }
      if (nInputs > 0) {
          _output.len = BSEC_NUMBER_OUTPUTS;
          memset(_output.outputs, 0, sizeof(_output.outputs));
    
          _bsec_status = bsec_do_steps(inputs, nInputs, _output.outputs, &_output.len);
    
          if (_bsec_status < BSEC_OK)
    	return false;
      }
    
      if (_proc != NULL)
        _proc(data, &_output);
      return true;
    
    }
    
    /**
     * @brief Set the BME68X sensor configuration to forced mode
     */
    void setBme68xConfigForced(void)
    {
    
      /* Set the filter, odr, temperature, pressure and humidity settings */
      _bme68x_conf.filter = BME68X_FILTER_OFF;
      _bme68x_conf.odr = BME68X_ODR_NONE;
      _bme68x_conf.os_hum = _bsec_bme_settings.humidity_oversampling;
      _bme68x_conf.os_pres = _bsec_bme_settings.pressure_oversampling;
      _bme68x_conf.os_temp = _bsec_bme_settings.temperature_oversampling;
    
      _bme68x_status = bme68x_set_conf(&_bme68x_conf, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      /* Set the gas sensor settings and link the heating profile */
      _bme68x_heatr_conf.enable = _bsec_bme_settings.run_gas;
      _bme68x_heatr_conf.shared_heatr_dur = 0;
      _bme68x_heatr_conf.heatr_temp = _bsec_bme_settings.heater_temperature;
      _bme68x_heatr_conf.heatr_dur = _bsec_bme_settings.heater_duration;
      _bme68x_heatr_conf.heatr_temp_prof = NULL;
      _bme68x_heatr_conf.heatr_dur_prof = NULL;
      _bme68x_heatr_conf.profile_len = 0;
    
      /* Select the power mode */
      _bme68x_status = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &_bme68x_heatr_conf, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      _bme68x_status = bme68x_set_op_mode(BME68X_FORCED_MODE, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      _op_mode = BME68X_FORCED_MODE;
    }
    
    /**
     * @brief Set the BME68X sensor configuration to sleep mode
     */
    void setBme68xConfigSleep(void)
    {
      _bme68x_status = bme68x_set_op_mode(BME68X_SLEEP_MODE, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      _op_mode = BME68X_SLEEP_MODE;
    }
    
    /**
     * @brief Set the BME68X sensor configuration to parallel mode
     */
    void setBme68xConfigParallel(void)
    {
      /* Set the filter, odr, temperature, pressure and humidity settings */
      _bme68x_conf.filter = BME68X_FILTER_OFF;
      _bme68x_conf.odr = BME68X_ODR_NONE;
      _bme68x_conf.os_hum = _bsec_bme_settings.humidity_oversampling;
      _bme68x_conf.os_pres = _bsec_bme_settings.pressure_oversampling;
      _bme68x_conf.os_temp = _bsec_bme_settings.temperature_oversampling;
    
      _bme68x_status = bme68x_set_conf(&_bme68x_conf, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      /* Set the gas sensor settings and link the heating profile */
      _bme68x_heatr_conf.enable = _bsec_bme_settings.run_gas;
      _bme68x_heatr_conf.shared_heatr_dur = GAS_WAIT_SHARED - (bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &_bme68x_conf, &_bme68x) / INT64_C(1000));
      _bme68x_heatr_conf.heatr_temp = 0;
      _bme68x_heatr_conf.heatr_dur = 0;
      _bme68x_heatr_conf.heatr_temp_prof = _bsec_bme_settings.heater_temperature_profile;
      _bme68x_heatr_conf.heatr_dur_prof = _bsec_bme_settings.heater_duration_profile;
      _bme68x_heatr_conf.profile_len = _bsec_bme_settings.heater_profile_len;
    
      /* Select the power mode */
      _bme68x_status = bme68x_set_heatr_conf(BME68X_PARALLEL_MODE, &_bme68x_heatr_conf, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      _bme68x_status = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &_bme68x);
      if (_bme68x_status < BME68X_OK)
        return;
    
      /* Enable measurement index check to track the first valid sample after operation mode change */
      check_meas_idx = true;
    
      _op_mode = BME68X_PARALLEL_MODE;
    }
    
    /**
     * @brief Function to calculate an int64_t timestamp in milliseconds
     */
    int64_t getTimeMs(void)
    {
      int64_t timeMs = HAL_GetTick();
    
      if (_timer_last_value > timeMs) { // An overflow occured
          _timer_last_value = timeMs;
          _timer_overflow_counter++;
      }
      return (timeMs + (_timer_overflow_counter * 0xFFFFFFFF));
    }
    
    int64_t getTimeUs(void)
    {
    	int64_t timeUs = (HAL_GetTick()/1000);
    
      if (_timer_last_value > timeUs) { // An overflow occured
          _timer_last_value = timeUs;
          _timer_overflow_counter++;
      }
      return (timeUs + (_timer_overflow_counter * 0xFFFFFFFF));
    }
    
    void delay_ms(uint32_t period)
    {
      HAL_Delay(period);
    }
    
    
    void delay_us(uint32_t period, void *intf_ptr)
    {
      (void) intf_ptr;
      HAL_Delay(period/1000);
    }
    
    int8_t bme68x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr)
    {
      intptr_t devID = (intptr_t)intf_ptr;
      HAL_I2C_Mem_Write(BME688_MCU.phi2c,devID,reg_addr,I2C_MEMADD_SIZE_8BIT,(uint8_t *) reg_data, length, 2000);
      return 0;
    }
    
    int8_t bme68x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr)
    {
      intptr_t devID = (intptr_t)intf_ptr;
      HAL_I2C_Mem_Read(BME688_MCU.phi2c,devID,reg_addr,I2C_MEMADD_SIZE_8BIT, reg_data, length, 2000);
      return 0;
    }
    
    
    
    

    Best regards

    11 REPLIES 11

    Minhwan
    Community Moderator
    Community Moderator

    Hi, 

     

    I checked your log, it's quite strange result. 

    Several questions I have. 

    1. Have you changed any code for BME68x API? If yes, please don't. Just modify BSEC source code is enough. 

    2. Which config file are you using it? If you are using config file which we provided, 5 cyclic result doesn't make sense. Are you using custom config file made yourself? Could you upload it config file? 

    Thanks, 

    Hi,

    I haven't changed any code in the API. The file, which I have uploaded is the only one. Many parts of the code are from Bosch as well. The config file belongs to an older bsec 2.X version. The array has the size of 2277 and is the bsec_sel_iaq_33v_3s_28d.

    In your datasheet is written, that the sensor has 5 measurement cycles during the gas sensor mode.

    Minhwan
    Community Moderator
    Community Moderator

    Hi doppio, 

     

    Yes, I'm talking about the code you uploaded. 

    It seems like you mixed BME68x API example code and BSEC example code. 

    For exampe, you don't need those kind of code for getting proper data. 

      uint16_t temp_prof[10] = { 250, 100, 100, 100, 100, 100, 100, 250, 250, 250 };		// Heater temperature in degree Celsius
      uint16_t mul_prof[10] = { 2, 0, 10, 15, 2, 2, 2, 2, 2, 2 };							// Multiplier to the shared heater duration

    There is latest BSEC2 in below url

    https://www.bosch-sensortec.com/software-tools/software/bme688-software/

    And there is integration guide in the bsec2 library zip file. 

    Please download and check the integration guide. 

    And feel free to ask me after you check the document. 

    Plus, in case of scan mode, you can make your own scan mode technically, but BSEC2 handles it. 

    Thank you. 

     

    Hi Minhwan,

    i downloaded the new software and renew my code. See below. I changed the power mode to LP, because I'm interested in the air quality and do not search for a specific gas. Additional I updated the associated files. When I'm using the newer libalgobsec.a the system seems more agile and realistic, but the CO2 value starts at 600 and do not go below. Why?   Even though I'm sitting next to an open window, I don't get the low value.

    Additional the values of temperature and humidity in both library version have a big difference. Which version should I use?

    I attach the log file, where both versions are included. During both measurement I have blow to the sensor.

    Thanks.

     

    Minhwan
    Community Moderator
    Community Moderator

    Hi, 

     

    I saw your result and it is pretty much okay so far. 

    You can get any CO2 value once you reach to IAQ accuracy level 1  although we recommend to wait up to 3. 

    Then, CO2 value changed in your log down to 460 when IAQ is going down, then CO2 level going up when IAQ level is going up. 

    And I recommend to use latest BSEC library and recommend to keep checking data for a long time. 

    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