Skip to main content

Averaged measurement

What this example shows​

The library's averagedMeasurement example takes several readings, waits between them, and prints their average. Averaging smooths out the noise of a single reading.

The example creates the sensor with SENSOR_CO, the library's carbon monoxide preset, and no address, so the library's default address is used. SENSOR_NH3 is the library's preset for the SGX-4NH3 cell on this board, and the ppm conversion uses the preset's sensitivity: 70 nA/ppm for SENSOR_CO, 40 nA/ppm for SENSOR_NH3. As shipped, the example's readings are therefore not ammonia ppm. To read ammonia, change SENSOR_CO to SENSOR_NH3 in the line that creates the sensor.

The library talks to the board's ATtiny404 bridge when the address is from 0x30 to 0x37, and to an ADS1115 at that address directly for any other address, such as the default 0x49 this example uses. 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 the Qwiic cable. Wire the controller to the header instead: 3.3 V to 3V3, GND to GND, SDA to SDA2 and SCL to SCL2. The example then runs as written, with no change to the address.

The example's comments connect LMPEN to GND or a GPIO pin. On this board, leave LMPEN unconnected: a 10 kΩ resistor already pulls it to GND, and the ATtiny404 is connected to it too.

The example code​

Select Board
averagedMeasurement.ino
/**
**************************************************
*
* @file averagedMeasurement.ino
* @brief See how to use a built-in function to make an averaged measurement
*
* To successfully run the sketch:
* - Connect LMPEN pin to GND or a GPIO pin so the breakout 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"

// How many readings to average from and how long to wait between them
#define NUM_READINGS 5
#define SECS_BETWEEN_READINGS 3

// Configurations for each of the sensor types are in sensorConfigData.h in the library's 'src' folder
// Create the sensor object with the according type
ElectrochemicalGasSensor sensor(SENSOR_CO);

// If you are using a custom I2C address (for multiple sensors) use:
// ElectrochemicalGasSensor sensor(SENSOR_CO, 0x4A, 25);
// For more details on this, see customAddress.ino

void setup()
{
Serial.begin(115200); // For debugging

// Init the breakout
if (!sensor.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("Sensor initialized successfully!");
}

void loop()
{
// Make the averaged reading
// This is a blocking function, so it will take a while before code continues
double reading = sensor.getAveragedPPM(NUM_READINGS, SECS_BETWEEN_READINGS);

// If PPB is more relevant for your sensor, you can use:
// double reading = sensor.getAveragedPPB(NUM_READINGS, SECS_BETWEEN_READINGS);

// Print the reading with 5 digits of precision
Serial.print("Sensor reading: ");
Serial.print(reading, 5);
Serial.println(" PPM");

// Wait a bit before reading again
delay(2500);
}

The Serial Monitor shows:

Serial MonitorAutoscrollShow timestampNewline115200 baud
Message (Enter to send message to the board)
Sensor initialized successfully!

Then a line starting with Sensor reading: appears with the average in ppm. Five readings with 3 seconds after each take 15 seconds, plus the 2.5 second pause, so a new line arrives about every 17.5 seconds.

If begin() 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 none

Creates the sensor object. 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. Leaving the address out, as this example does, uses DEFAULT_ADC_ADDR, 0x49.

ReturnsConstructor.

Parameters

ParameterTypeDescription
_tsensorTypeThe cell preset. SENSOR_NH3 is the preset for this board's cell.
_adcAddruint8_tThe address. Default DEFAULT_ADC_ADDR (0x49). On this board the ADDRESS switch sets the bridge's address from 0x30 to 0x37.
_configPinintA GPIO the library sets low while it configures the LMP91000 when the address is outside 0x30 to 0x37. Not used from 0x30 to 0x37. Default -1, no pin.
bool begin()returns bool

Starts 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.

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 getAveragedPPM(uint8_t _numMeasurements = 5, uint8_t _secondsDelay = 2)returns double

Takes _numMeasurements readings with getPPM(), waits _secondsDelay seconds after each one, and returns their average. It blocks until all readings are done.

ReturnsThe averaged concentration in ppm.

Parameters

ParameterTypeDescription
_numMeasurementsuint8_tHow many readings to average. Default 5.
_secondsDelayuint8_tSeconds to wait after each reading. Default 2.
double getAveragedPPB(uint8_t _numMeasurements = 5, uint8_t _secondsDelay = 2)returns double

The same average as getAveragedPPM(), in parts per billion. The example shows it in a comment as an alternative.

ReturnsgetAveragedPPM() multiplied by 1000.

Parameters

ParameterTypeDescription
_numMeasurementsuint8_tHow many readings to average. Default 5.
_secondsDelayuint8_tSeconds to wait after each reading. Default 2.

Putting it together​

Use the averaged functions when a steady value matters more than a fast one. Because they block, nothing else in loop() runs while they wait, so keep NUM_READINGS × SECS_BETWEEN_READINGS short if your sketch has other work to do.