Bosch Sensortec Community

    cancel
    Showing results for 
    Search instead for 
    Did you mean: 

    BME680: Gas sensor heater unstable

    BME680: Gas sensor heater unstable

    GArndt_vacos
    Member

    Dear members,  I am evaluating the BME680 for smoldering fire detection in a dirty environment, which means that I am looking for a way to discriminate easily and heavily oxidizable gas species. For that purpose, I have forked from Bosch's BME680 driver to make use of the sensor's ability to configure and query 10 different heater configurations (temperature and duration). You can find the modified code here: https://github.com/guarndt/BME680_driver 

    I use all possible ten heater configurations; each step has a duration of 50 ms. That is more then the 20-30 ms which, according to the documentation, are required to achieve a stable heater temperature. The temperatures are 400°C down to 130°C in decrements of 30 K.

    Here comes my problem: Normally, that configuration works fine. I have tested it with a BME680 on a Joy-It breakout board connected directly to a Raspi 3 via I²C at 3.3 V, and it runs flawlessly for days. I have recorded a communication cycle with an oscilloscope; see Scope_regular.png

    In my lab setup driven by a Odroid C2, however, there are three of those BME680 boards connected to the I²C via a TCA9548A multiplexer and P82B96 line buffers with a supply voltage of 3.6 V. They may run equally flawlessly for up to a day, but after some (possibly shorter) time any one of them can get into an error state in which it is unable to achieve a stable heater temperature. Once it occurs, that always affects all ten temperature steps, whereas that sensor's other measurements (ambient temperature, pressure, humidity) continue to work fine. I have captured a communication cycle in the error state as well; see Scope_long.png

    How to stabilize the heater? Do I have to use longer cycles? It does not seem to depend on ambient temperature, as it usually happens at room temperature.

    The sensor is initialized like this:

     

    			dev_id = BME680_I2C_ADDR_PRIMARY;
    			intf = BME680_I2C_INTF;
    			/* amb_temp can be set to 25 prior to configuring the gas sensor
    			 * or by performing a few temperature readings without operating the gas sensor.
    			 */
    			amb_temp = 25;
    			if (bme680_init() != BME680_OK) {
    				throw new std::domain_error("Could not initialize BME680.");
    			}
    
    			/* Set the temperature, pressure and humidity settings */
    			tph_sett.os_hum = BME680_OS_2X;
    			tph_sett.os_pres = BME680_OS_4X;
    			tph_sett.os_temp = BME680_OS_8X;
    			tph_sett.filter = BME680_FILTER_SIZE_3;
    			/* Set the remaining gas sensor settings and link the heating profile */
    			gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
    			gas_sett.nb_conv = 0;
    			/* Select the power mode */
    			/* Must be set before writing the sensor configuration */
    			power_mode = BME680_FORCED_MODE;
    			/* Set the required sensor settings needed */
    			uint8_t const set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL;
    			/* Set the desired sensor configuration */
    			if (bme680_set_sensor_settings(set_required_settings) != BME680_OK) {
    				throw new std::domain_error("Could not configure BME680.");
    			}
    			/* Set the power mode */
    			if (bme680_set_sensor_mode() != BME680_OK) {
    				throw new std::domain_error("Could not set BME680's power mode.");
    			}

     

    Here is the code that is run in a loop to query the sensor:

     

    for (size_t i{0}; i < gasResistance.size(); ++i) {
    				if (_measurementEnd) {
    					std::this_thread::sleep_until(*_measurementEnd);
    					struct bme680_field_data data;
    					if (bme680_get_sensor_data(&data) == BME680_OK) {
    						averageTemperature += celsius_t{data.temperature / 100.0f};
    						averagePressure += hectopascal_t{data.pressure / 100.0f};
    						averageHumidity += data.humidity / 1000.0f;
    						/* Avoid using measurements from an unstable heating setup */
    						if (dayta.status & BME680_GASM_VALID_MSK) {
    							gasResistance[data.gas_index]->notifyObservers(ohm_t(data.gas_resistance));
    							/* Select the next gas sensor heater profile. */
    							this->gas_sett.nb_conv = overflowingNext<uint8_t, BME680_HEATER_SET_COUNT-1>(data.gas_index);
    							if (bme680_set_sensor_settings(BME680_NBCONV_SEL) != BME680_OK) {
    								ErrorObservable::notifyObservers("Next heater profile could not be selected."s);
    							}
    						} else {
                            // This is the error that keeps occurring:
    							ErrorObservable::notifyObservers("Measurement from unstable heating setup rejected."s);
    						}
    					} else {
    						ErrorObservable::notifyObservers("Data could not be acquired from device."s);
    					}
    				} else {
    					ErrorObservable::notifyObservers("Measurement had not been started."s);
    				}
    				/* Trigger the next measurement if you would like to read data out continuously */
    				if (power_mode == BME680_FORCED_MODE) {
    					if (bme680_set_sensor_mode() == BME680_OK) {
    						auto const measurementStart(std::chrono::steady_clock::now());
    						/* Calculate the total measurement duration (which takes time). */
    						uint16_t meas_period;
    						bme680_get_profile_dur(&meas_period);
    						_measurementEnd = measurementStart + std::chrono::milliseconds{meas_period};
    					} else {
    						_measurementEnd.reset();
    						ErrorObservable::notifyObservers("Could not set sensor mode after measurement."s);
    					}
    				}
    			}

     

     

    16 REPLIES 16

    Sorry for the long delay until I reported back. I have done more bughunting, fixing, and testing, with the following results:

    • The driver now resets the sensor once a heater stability error occurs more than 30 seconds after the most recent reset.
    • That has the effect that not all ten configurations are affected by the error, but typically only one of them: 370°C (or sometimes 310°C) in case of the sensor that is affected most often, normally 250°C in case of another one. The third one seems to be OK now - but it is used as a reference outside the experimental setup.
    • The issue shows up spontaneously, persists for minutes or hours across many resets, but eventually disappears again during long measurements in fresh air.
    • A different, more important case: All 10 heater configurations (400°C~130°C) become unstable when the sensors are suddenly exposed to a high concentration of VOCs or CO, e.g. vaporized gasoline or alcohol, or burning plastic. They are beyond a 0.5µm particle filter, so soot should not be an issue. Reset has no effect - the issue only disappears when the concentration gets lower again.

    Is there any known reason why a high VOC concentration (or sudden rise in concentration) might make the heater unstable? As I understand it, heater resistance regulation and gas sensor resistance measurement should be two distinct things, although the two parts are of course in close proximity.

    Do you think the problem can be addressed by increasing the heater time above 50ms? Are there better suggestions? I'd be glad to hear them. Thank you in advance.

    Vincent
    Community Moderator
    Community Moderator

    Can you try with latest BME68x API on the Github to see if this issue is still there or not? 

    The original driver reads the heater stability status in bme680.c:1233, but does not seem to evaluate it. It is only returned to the caller and must be checked separately. I'll see what I can do, but I remember that I had to modify the driver anyway because it could not be integrated on my platform as-is.

    Vincent, I tried with the original driver on a Raspi 3.

    You can find the code in original_BME680_driver.cpp

    I basically copied the example code from the github repo and modified the device's I²C address and the heater settings (to 370°C/50ms).

    The log is in original_BME680_driver.log

    When I suddenly place a small bottle of alcoholic desinfectant beneath the sensor, I can usually reproduce the issue - see line 830.

    It seems to be less likely when I increase the heater period to 150ms, which is too long for my application - and even longer than 20~30ms required in the manual.

     

    Vincent
    Community Moderator
    Community Moderator

    After discussing with the engineer team, we had the following suggestion: 

    1.  please use the "sequential mode" in latest BME68x API not the force mode. 

    2.  the minimal heat duration should be 140ms.  And 140ms should be kept as unit means if you need longer duration,  it should be (n*140) ms.   

    Can you try again with those suggestion? 

    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