Two sensors on one bus
What this example shows
The module's electrochemical-twoSensors.py example reads two boards on the same I2C bus. It creates one sensor object per board, starts both, and prints both readings in ppb every 2.5 seconds.
The example creates sensor1 with adc_addr=0x4A and config_pin=25, and sensor2 with adc_addr=0x49 and config_pin=32, both with the module's ozone preset, SENSOR_O3. SENSOR_NH3 is the preset for this board's cell, and the ppm conversion uses the preset's sensitivity (-1000 nA/ppm for SENSOR_O3, 40 nA/ppm for SENSOR_NH3). As shipped, the example's readings are therefore not ammonia values. To read ammonia, change SENSOR_O3 to SENSOR_NH3 in the import line and in the two lines that create the sensors. The example opens I2C bus 0 on pin 22 (SCL) and pin 21 (SDA).
The module talks to the board's ATtiny404 bridge when adc_addr is from 0x30 to 0x37; with any other value, such as the example's 0x4A and 0x49, it talks to an ADS1115 at that address directly. On this board the ADS1115 sits on the header's SDA2/SCL2 pins, which the Qwiic connectors do not reach, so this example does not run over Qwiic cables. Wire the controller to each board's header instead: 3.3 V to 3V3, GND to GND, the example's SDA pin (21) to SDA2 and its SCL pin (22) to SCL2. JP2 to JP4 set each board's ADS1115 address, as Hardware Details describes. The example then runs as written, with no change to the addresses.
The connecting diagram in the example's comments wires each board's LMPEN to a GPIO pin (25 and 32), because two LMP91000 chips on one bus share one address. On this board, leave LMPEN unconnected: a 10 kΩ resistor already pulls LMPEN to GND, and the ATtiny404 is connected to it too.
The example code
# FILE: electrochemical-twoSensors.py
# AUTHOR: Fran Fodor @ Soldered
# BRIEF: Two O3 sensor PPB reading example using two breakouts on one I2C bus.
# LAST UPDATED: 2026-05-21
# Connecting diagram:
#
# Qwiic------------------------>Qwiic
# LMPEN------------------------>25 (GPIO pin, required for I2C configuration)
#
# Qwiic------------------------>Qwiic (same bus)
# LMPEN------------------------>32 (GPIO pin, required for I2C configuration)
#
# Set different ADC I2C addresses on each breakout using the address jumpers.
# Both LMP91000 chips share address 0x48 — the LMPEN pin selects which one
# is active during configuration, so a GPIO pin is required for each sensor.
from machine import I2C, Pin
import time
from ElectrochemicalGasSensor import ElectrochemicalGasSensor, SENSOR_O3
# Initialize shared I2C bus
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
# Sensor 1: ADC address 0x4A, LMPEN on pin 25
sensor1 = ElectrochemicalGasSensor(SENSOR_O3, i2c, adc_addr=0x4A, config_pin=25)
# Sensor 2: ADC address 0x49, LMPEN on pin 32
sensor2 = ElectrochemicalGasSensor(SENSOR_O3, i2c, adc_addr=0x49, config_pin=32)
# -------------------------------------------------------------------------
# Setup
# -------------------------------------------------------------------------
print("Electrochemical Gas Sensor - Two Sensors Example")
if not sensor1.begin():
print("ERROR: Can't init sensor 1! Check connections!")
while True:
time.sleep_ms(100)
print("Sensor 1 initialized successfully!")
if not sensor2.begin():
print("ERROR: Can't init sensor 2! Check connections!")
while True:
time.sleep_ms(100)
print("Sensor 2 initialized successfully!")
# -------------------------------------------------------------------------
# Main loop
# -------------------------------------------------------------------------
while True:
reading1 = sensor1.getPPB()
reading2 = sensor2.getPPB()
print("Sensor 1 reading: {:.5f} PPB".format(reading1))
print("Sensor 2 reading: {:.5f} PPB".format(reading2))
time.sleep_ms(2500)
🔗Open the complete example
electrochemical-twoSensors.py at commit 623e1e6
The Thonny shell shows:
Electrochemical Gas Sensor - Two Sensors Example
Sensor 1 initialized successfully!
Sensor 2 initialized successfully!
Then two lines, Sensor 1 reading: and Sensor 2 reading:, follow every 2.5 seconds, each in ppb to five decimals.
If a begin() call returns False, the example prints ERROR: Can't init sensor 1! Check connections! (or sensor 2) instead and stops.
Functions used
ElectrochemicalGasSensor(sensor_type, i2c=None, adc_addr=0x49, config_pin=None)returns ElectrochemicalGasSensorCreates one sensor object. Create one per board, each with its own adc_addr. adc_addr decides how begin() talks to the board: from 0x30 to 0x37 it uses the ATtiny bridge protocol; any other value is used as the ADC's own I2C address.
ReturnsThe sensor object.
Parameters
| Parameter | Type | Description |
|---|---|---|
sensor_type | SensorConfig | The cell preset. SENSOR_NH3 is the preset for this board's cell. |
i2c | I2C | Your I2C object. Both sensors share the same one. |
adc_addr | int | The address the module talks to for that board: a bridge address from 0x30 to 0x37, or otherwise an ADS1115 address. Default 0x49. The example passes the ADS1115 addresses 0x4A for sensor 1 and 0x49 for sensor 2. This board's own address is its bridge address, set with the ADDRESS switch from 0x30 to 0x37. |
config_pin | int or None | A GPIO pin number the module sets low while it configures that board's LMP91000 and high afterwards, when adc_addr is outside 0x30 to 0x37. The example passes 25 and 32. Default None. Not used from 0x30 to 0x37. |
begin()returns boolWith an address from 0x30 to 0x37, checks that that board's bridge answers and sends it the ADC and analog front end settings from the preset. With any other address, starts the ADS1115 on that address directly and configures the LMP91000. Call it once for each sensor before any reading.
ReturnsTrue when every step succeeded. False when the bridge did not answer OK within 500 ms or reported an error, when starting the ADS1115 failed, or when configuring the analog front end failed.
getPPB()returns floatTakes one reading from that sensor and returns it in parts per billion. A result below zero is returned as 0.
ReturnsgetPPM() multiplied by 1000.
Putting it together
Give each board its own address, create one sensor object per board on the shared I2C object, and call begin() on each. If one begin() returns False, the example names that sensor and stops.