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 saw your code and question. It seems like you want to use BSEC, correct? 

    If yes, you shouldn't touch BME68x API since all things are controllbed by BSEC library. 

    If you're not going to use BSEC2 library, why you choose parallel not forced mode? 

    Please give me your information more and I will guide you accordingly. 

    Thank you. 

    Sorry I didn't notice your answer.

    I'm using the BSEC 2 and one of my mistakes was that I wanted to take a State, which will be loaded at the initalizaiton, from one sensor for all the others. So the sensor could get faster to the best accurancy. I have understand that each BME688 need his own configuration and this will only saved when the accurancy reaches 3.

    _bme68x_status |= setConfig(bsec_config_selectivity);  <-- from IAQ selectiv 2277 values (bsec_sel_iaq_3v3_4d )
    _bme68x_status |= loadState();                                                 <-- 197 numbers will be set in the initialization

    Is this correct?

    My other problem is that during the 5 cycles of measurement the first value is much higher than the last one. Is it correct that last one is the most significant value or should I take the average?

    Minhwan
    Community Moderator
    Community Moderator

    Could you share the test log and elaborate what you mean? 

    Thank you. 

    Hi,

    I have eliminate the code, which searches for the smallest CO2 value. So you can see the movement of this value. The sensor do the gas scan mode. After the break of 108s the five scans generate five different values. Do I have calculate the average or do I have to take the last value?

    In the xlsx is the log file. The question stays the same. How to deal with the five different values?

    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