Two sensors on one bus
What this example shows
The library's twoSensors example reads two boards on the same I2C bus. It creates one sensor object per board, starts both, and prints one reading in ppm and the other in ppb every 2.5 seconds.
The example creates sensorCO with SENSOR_CO on address 0x4A with GPIO 25 as its configuration pin, and sensorNO2 with SENSOR_NO2 on address 0x49 with GPIO 32. SENSOR_NH3 is the library's preset for this board's ammonia cell, and the ppm conversion uses the preset's sensitivity. As shipped, the example's readings are therefore not ammonia values. To read ammonia, change SENSOR_CO and SENSOR_NO2 to SENSOR_NH3 in the two lines that create the sensors.
The library talks to the board's ATtiny404 bridge when the address is from 0x30 to 0x37; with any other address, 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, SDA to SDA2 and SCL 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 example's comments say to set the addresses with jumpers on the back of the breakout and to connect each board's LMPEN to a GPIO pin. On this board the address is set with the ADDRESS switch, and LMPEN stays unconnected: a 10 kΩ resistor already pulls LMPEN to GND, and the ATtiny404 is connected to it too.
The example code
/**
**************************************************
*
* @file twoSensors.ino
* @brief See how to init two sensors and make two readings of PPM of gas.
*
* To successfully run the sketch:
* - Set different addresses using the jumpers on the back of the breakout
* - Connect LMPEN pins to a GPIO pin so the breakouts can be configured
* - Run the sketch and open serial monitor at 115200 baud!
*
* @authors Robert @ soldered.com
***************************************************/
// Include the required library
#include "Electrochemical-Gas-Sensor-SOLDERED.h"
// Create two different sensor objects
ElectrochemicalGasSensor sensorCO(SENSOR_CO, 0x4A, 25);
ElectrochemicalGasSensor sensorNO2(SENSOR_NO2, 0x49, 32);
// To see how the custom addresses are determined, check customAddress.ino
void setup()
{
Serial.begin(115200); // For debugging
// Init breakout #1
if (!sensorCO.begin())
{
// Can't init? Notify the user and go to infinite loop
Serial.println("ERROR: Can't init the sensor! Check connections!");
while (true)
delay(100);
}
Serial.println("CO sensor initialized successfully!");
// Init breakout #2
if (!sensorNO2.begin())
{
// Can't init? Notify the user and go to infinite loop
Serial.println("ERROR: Can't init the sensor! Check connections!");
while (true)
delay(100);
}
Serial.println("NO2 sensor initialized successfully!");
}
void loop()
{
// Make the reading of CO and print it
double COreading = sensorCO.getPPM();
// Print the reading with 5 digits of precision
Serial.print("CO sensor reading: ");
Serial.print(COreading, 5);
Serial.println(" PPM");
// Make the reading of NO2 and print it
double NO2reading = sensorNO2.getPPB();
// Print the reading with 5 digits of precision
Serial.print("NO2 sensor reading: ");
Serial.print(NO2reading, 5);
Serial.println(" PPB");
// Wait a bit before reading again
delay(2500);
}
The Serial Monitor shows:
CO sensor initialized successfully!
NO2 sensor initialized successfully!
Then every 2.5 seconds two lines follow: CO sensor reading: in ppm and NO2 sensor reading: in ppb, each to five decimals.
If a begin() call returns false, the example prints ERROR: Can't init the sensor! Check connections! instead and stops.
Functions used
ElectrochemicalGasSensor(sensorType _t, uint8_t _adcAddr = DEFAULT_ADC_ADDR, int _configPin = -1)returns noneCreates one sensor object. Create one per board, each with its own address. begin() picks how to talk to the board from the address: from 0x30 to 0x37 it uses the ATtiny404 bridge; any other address is used as the ADS1115's own I2C address.
ReturnsConstructor.
Parameters
| Parameter | Type | Description |
|---|---|---|
_t | sensorType | The cell preset, here SENSOR_CO and SENSOR_NO2. SENSOR_NH3 is the preset for this board's cell. |
_adcAddr | uint8_t | A bridge address from 0x30 to 0x37, or otherwise an ADS1115 address; here the ADS1115 addresses 0x4A and 0x49. This board's own address is its bridge address, set with the ADDRESS switch from 0x30 to 0x37. |
_configPin | int | A GPIO the library sets low while it configures that board's LMP91000 when the address is outside 0x30 to 0x37, here 25 and 32. Not used from 0x30 to 0x37. |
bool begin()returns boolStarts I2C. With an address from 0x30 to 0x37 it checks that the bridge answers and sends it the ADC settings from the preset; with any other address it starts the ADS1115 on that address directly. Then it configures the LMP91000 analog front end. 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.
double getPPM()returns doubleTakes one reading from that sensor and converts it to ppm with the sensor's preset. A result below zero is returned as 0.
ReturnsThe gas concentration in ppm.
double getPPB()returns doubleThe same reading as getPPM(), in parts per billion.
ReturnsgetPPM() multiplied by 1000.
Putting it together
Give each board its own address, create one sensor object per board, and call begin() on each. If either begin() returns false, the example prints an error and stops.