Skip to main content

Sweep the heater in parallel mode

What this example shows​

In parallel mode the gas sensor sweeps through a heater profile while temperature, pressure and humidity are measured continuously. The example uses a ten-step profile (heater temperatures from 100 to 320 °C) where each step lasts a multiple of one shared heating duration. It prints only the fields that hold a valid gas measurement taken with a stable heater.

The example creates the sensor with BME690(), so on the esp32 and esp8266 ports it uses I2C(0) with SDA on pin 21 and SCL on pin 22, at address 0x76.

The example code​

# FILE: bme690-parallelMode.py
# AUTHOR: Josip Simun Kuci @ Soldered
# BRIEF: Run the BME690 in parallel mode, where the gas sensor sweeps through
# a heater profile while temperature, pressure and humidity are
# measured continuously
# WORKS WITH: BME690 breakout board: solde.red/333411
# LAST UPDATED: 2026-09-16

from bme690 import (
BME690,
BME69X_ERROR,
BME69X_GASM_VALID_MSK,
BME69X_HEAT_STAB_MSK,
BME69X_NEW_DATA_MSK,
BME69X_PARALLEL_MODE,
)
import time

# New data, gas measurement valid and heater stable, all at once.
BME690_VALID_DATA = (
BME69X_NEW_DATA_MSK | BME69X_GASM_VALID_MSK | BME69X_HEAT_STAB_MSK
)

# Heater temperature profile in degrees Celsius.
HEATER_TEMP = [320, 100, 100, 100, 200, 200, 200, 320, 320, 320]

# Multipliers of the shared heater duration, one per profile step.
HEATER_MUL = [5, 2, 10, 30, 5, 5, 5, 5, 5, 5]

sensor = BME690()

sensor.set_tph()

# The shared heating duration is the total measurement duration minus the
# time needed for the temperature, pressure and humidity measurement.
shared_heatr_dur = 140 - sensor.get_meas_dur(BME69X_PARALLEL_MODE) // 1000

sensor.set_heater_prof(HEATER_TEMP, HEATER_MUL, shared_heatr_dur)
sensor.set_op_mode(BME69X_PARALLEL_MODE)

if sensor.check_status() == BME69X_ERROR:
raise Exception("BME690 setup failed: " + sensor.status_string())

print(
"Timestamp(ms), Temperature(C), Pressure(Pa), Humidity(%), "
"Gas resistance(Ohm), Status, Gas index, Meas index"
)

while True:
if sensor.fetch_data():
fields_left = 1

while fields_left:
data, fields_left = sensor.get_data()

# Skip the fields which hold no valid measurement.
if data.status != BME690_VALID_DATA:
continue

print(
"{}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, 0x{:02x}, {}, "
"{}".format(
time.ticks_ms(),
data.temperature,
data.pressure,
data.humidity,
data.gas_resistance,
data.status,
data.gas_index,
data.meas_index,
)
)

🔗Open the complete example

Examples/bme690-parallelMode.py at commit 91a07b5

→

Expected result:

ShellMicroPython
Timestamp(ms), Temperature(C), Pressure(Pa), Humidity(%), Gas resistance(Ohm), Status, Gas index, Meas index

Each valid field then prints one row: the millisecond counter, temperature in °C, pressure in Pa, humidity in % r.H. and gas resistance in Ω (each to two decimals), the status byte, the heater profile step and the measurement index. Only fields whose status is exactly new data, valid gas and stable heater are printed, so the status column always reads 0xb0.

Functions used​

BME690(i2c=None, address=BME69X_I2C_ADDR_LOW, amb_temp=25)returns BME690

Creates the sensor object. It soft-resets the sensor, checks its chip ID (0x61) and reads the calibration data. It raises an exception when the sensor does not answer or another chip is at the address; every other function records its result in the status instead of raising.

ReturnsThe sensor object.

Parameters

TypeNameDescription
I2Ci2cA ready machine.I2C object. Left out, the module opens I2C(0) with SCL on pin 22 and SDA on pin 21 on the esp32 and esp8266 ports and one Soldered board firmware, and raises an exception on any other port.
intaddressThe I2C address: BME69X_I2C_ADDR_LOW (0x76, the default) or BME69X_I2C_ADDR_HIGH (0x77).
intamb_tempAmbient temperature in °C, used to work out the heater setting. 25 by default.
sensor.set_tph(os_temp=BME69X_OS_2X, os_pres=BME69X_OS_16X, os_hum=BME69X_OS_1X)returns None

Sets the oversampling for temperature, pressure and humidity. Called without arguments, as here, it sets the defaults of the Arduino library.

ReturnsNothing. The result is in the status.

Parameters

TypeNameDescription
intos_tempTemperature oversampling, BME69X_OS_NONE to BME69X_OS_16X.
intos_presPressure oversampling, BME69X_OS_NONE to BME69X_OS_16X.
intos_humHumidity oversampling, BME69X_OS_NONE to BME69X_OS_16X.
sensor.get_meas_dur(op_mode=BME69X_SLEEP_MODE)returns int

Works out how long one temperature, pressure and humidity measurement takes, from the oversampling set with set_tph(), so call set_tph() first. In parallel mode no wake-up time is added. With the set_tph() defaults it returns 41590 µs here, so the example's shared heating duration is 140 - 41 = 99 ms.

ReturnsThe measurement duration in microseconds.

Parameters

TypeNameDescription
intop_modeThe mode to calculate for. The example passes BME69X_PARALLEL_MODE, because the mode is not set yet.
sensor.set_heater_prof(temp, dur, shared_heatr_dur=None)returns None

Sets the gas heater profile and switches the heater on. With a list of temperatures, a list of multipliers and a shared heating duration, as here, it writes a parallel-mode profile: each step lasts its multiplier times the shared duration. Temperatures above 400 °C are capped at 400 °C. A shared duration of 0 leaves the warning Set the shared heater duration.

ReturnsNothing. The result is in the status.

Parameters

TypeNameDescription
listtempHeater temperature of each step in °C. The example uses HEATER_TEMP.
listdurIn parallel mode, the multiplier of the shared duration for each step. The example uses HEATER_MUL.
intshared_heatr_durThe shared heating duration in ms. Passing it selects parallel mode.
sensor.set_op_mode(op_mode)returns None

Puts the sensor to sleep, then sets the requested mode. With BME69X_PARALLEL_MODE the sensor keeps measuring and sweeping the heater on its own. The mode is remembered for fetch_data() and get_data().

ReturnsNothing. The result is in the status.

Parameters

TypeNameDescription
intop_modeBME69X_SLEEP_MODE, BME69X_FORCED_MODE, BME69X_PARALLEL_MODE or BME69X_SEQUENTIAL_MODE.
sensor.check_status()returns int

Sums up the status the last function left behind.

ReturnsBME69X_ERROR (-1) after an error, BME69X_WARNING (1) after a warning, BME69X_OK (0) otherwise.

sensor.status_string()returns str

Describes the current status code in a few words, such as Communication failure or No new data.

ReturnsThe description, an empty string when the status is OK.

sensor.fetch_data()returns int

Reads the sensor's three result fields into the module's buffer and sorts them so the oldest new sample comes first. When nothing new is there, the status reads No new data.

ReturnsThe number of new data fields, 0 when there are none.

sensor.get_data()returns tuple

Hands out the next new field from the buffer as a BME690Data object with temperature (°C), pressure (Pa), humidity (% r.H.), gas_resistance (Ω), status, gas_index (the profile step) and meas_index.

Returns(data, fields_left): the BME690Data, or None when there is no new data, and how many new fields are left after this one.

Putting it together​

The example first works out the shared heating duration from get_meas_dur(), so that one profile time base is 140 ms in total. set_heater_prof() then writes the ten steps and set_op_mode(BME69X_PARALLEL_MODE) starts the sensor. The loop collects every new field with fetch_data() and get_data() and compares its status with BME690_VALID_DATA, the three status bits combined, so only complete gas measurements are printed.