Skip to main content

Zero calibration

What this example shows​

The library's calibrateSensor example adds a fixed offset voltage to every reading with setCustomZeroCalibration(). In air with none of the target gas, adjust the offset until the voltage after calibration is roughly 0, as the example's comment says.

The example creates the sensor with SENSOR_NH3, the ammonia preset. The library calculates ppm from the preset's sensitivity and gain settings; the preset for this board's chlorine cell is SENSOR_CL2.

To see the voltages while you adjust the offset, open src/Electrochemical-Gas-Sensor-SOLDERED.h in the installed library and remove the // in front of #define ELECTROCHEMICAL_SENSOR_DEBUG. Every getPPM() call then also prints the raw voltage, the voltage without the reference value and the voltage after calibration.

The example code​

Select Board
calibrateSensor.ino
/**
**************************************************
*
* @file calibrateSensor.ino
* @brief See how to calibrate an electrochemical sensor
*
* To successfully run the sketch:
* - Uncomment the #define in the library header file
* - 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"

// This is the custom value we set for the calibration voltage
// This value is added to the voltage read from the ADC
// In an environment with 0 of the target gas, the voltage after calibration should be
// roughly 0, adjust customCalibration to get it to that value.
const double customCalibration = 0.05;


// Create the sensor object with the according type
ElectrochemicalGasSensor sensor(SENSOR_NH3, 0x49, 32);



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

// Initialize 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);
}

//Set the custom calibration value
sensor.setCustomZeroCalibration(customCalibration);

Serial.println("Sensor initialized successfully!");
}

void loop()
{
// Make the reading
double reading = sensor.getPPM();
// This function will also print debug messages if the #define in
// the header file of the library is uncommented
// It will print:
// - The raw voltage measurement
// - Voltage without reference value
// - Voltage after calibration
// These values can help you adjust the internal zero calibration



// 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 header comment asks for LMPEN to be connected. On this board a 10 kΩ resistor holds LMPEN low and it is wired to the ATtiny404, so you leave it unconnected (see the pin table on Hardware details).

Expected result:

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

Then a Sensor reading: line every 2.5 s, as in the Quick Start. With the debug define enabled, each reading is preceded by Electrochemical gas sensor readings: and three lines, Raw voltage measurement:, Voltage without reference value: and Voltage after calibration:, each with the value in volts to ten decimals. If begin() fails, the sketch prints ERROR: Can't init the sensor! Check connections! and stops.

Functions used​

ElectrochemicalGasSensor(sensorType _t, uint8_t _adcAddr = DEFAULT_ADC_ADDR, int _configPin = -1)returns ElectrochemicalGasSensor

Creates the sensor object. It stores the settings only; nothing is sent to the board until begin().

ReturnsThe sensor object.

Parameters

TypeNameDescription
sensorType_tThe cell preset. The example passes SENSOR_NH3; this board's SGX-4CL2 cell has the preset SENSOR_CL2.
uint8_t_adcAddrThe I2C address, DEFAULT_ADC_ADDR (0x49) when left out; the example passes 0x49. For an address from 0x30 to 0x37, the range of this board's ADDRESS switch, begin() talks to the board's ATtiny404; for any other address it looks for an ADS1115 at that address and the LMP91000 directly on the bus.
int_configPinA GPIO that begin() drives low while it configures the LMP91000 directly; the example passes 32. -1 (none) when left out. Unused for addresses 0x30 to 0x37.
bool begin()returns bool

Starts Wire, checks that the board answers, sets the preset's ADC gain and data rate, and configures the LMP91000 with the preset's settings. Call it once in setup() before reading.

Returnstrue when the board answered and both configuration steps succeeded, false otherwise.

void setCustomZeroCalibration(double calibration)returns void

Sets the voltage that getPPM() adds to every reading after it subtracts the internal zero voltage. It replaces the preset's zero calibration, which is 0 in SENSOR_CL2.

ReturnsNothing.

Parameters

TypeNameDescription
doublecalibrationThe offset in volts. The example uses customCalibration (0.05).
double getPPM()returns double

Takes one reading and converts it to ppm: it subtracts the internal zero voltage (the 2.5 V reference times the preset's internal zero percentage), adds the zero calibration, divides by the amplifier gain and by the preset's sensitivity in nA per ppm. A result below zero is returned as 0.

ReturnsThe gas concentration in ppm.

The example also uses Serial and delay(), which come with the Arduino core, not with this library.

Putting it together​

Run the sketch in air with none of the target gas, read Voltage after calibration:, and change customCalibration until that voltage is roughly 0. Keep the value you found and call setCustomZeroCalibration() with it in your own sketch, after begin().