Calibrate the zero point
What this example shows
The calibrateSensor example applies a zero-point offset and prints the gas
concentration in PPM every 2.5 seconds. It creates the sensor with address
0x49 and configuration pin 32.
customCalibration is a voltage the library adds to the ADC voltage before it
converts it. The example's comment gives the method: in an environment with
none of the target gas, adjust the value until the voltage after calibration is
roughly 0.
To see that voltage, the example asks you to uncomment one line in the library's
header file, Electrochemical-Gas-Sensor-SOLDERED.h:
//#define ELECTROCHEMICAL_SENSOR_DEBUG
With it defined, every getPPM() call also prints the raw voltage measurement,
the voltage without the reference value, and the voltage after calibration.
The example is written with SENSOR_NH3, the library's ammonia preset, so its
PPM values are not H2S values. Do not switch it to the library's SENSOR_H2S
preset unchanged: that preset is written for the SGX-4H2S-100 cell, with a
sensitivity of 1200 nA per ppm, while this board carries the SGX-4H2S-300 cell,
whose
datasheet
gives an output signal of 460 ± 140 nA per ppm. With SENSOR_H2S the
reading comes out about 2.6 times too low. Pass a custom sensor type with the
SENSOR_H2S settings and 460 nA per ppm instead, as
Quick Start
shows.
The example code
// 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);
}
Expected result:
Sensor initialized successfully!
Then a line starting with Sensor reading: follows every 2.5 seconds, with the
concentration in PPM to five decimals. The library never reports a value below
zero: it returns 0 instead, so 0.00000 is a normal reading. With
ELECTROCHEMICAL_SENSOR_DEBUG defined, each reading is preceded by the lines
Electrochemical gas sensor readings:, Raw voltage measurement:,
Voltage without reference value: and Voltage after calibration:, each
voltage in volts to ten decimals. If the sensor does not answer, 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 noneCreates the sensor object. The sensor type holds the front-end and conversion settings for one gas cell. The address decides how begin() talks to the board: an address from 0x30 to 0x37 goes through the board's ATtiny404; any other address, such as the default 0x49, goes to an ADS1115 at that address and to the LMP91000 directly.
ReturnsConstructor.
Parameters
| Name | Type | Description |
|---|---|---|
_t | sensorType | Preset from the library (SENSOR_CO, SENSOR_NO2, SENSOR_SO2, SENSOR_O3, SENSOR_NO, SENSOR_H2S, SENSOR_NH3, SENSOR_CL2) or a custom sensorType. For this board's cell, pass a custom one with 460 nA per ppm. |
_adcAddr | uint8_t | The address begin() talks to. This example passes 0x49. |
_configPin | int | A GPIO the library holds high and pulls low while it configures the LMP91000 directly. Ignored at addresses from 0x30 to 0x37. This example passes 32. |
bool begin()returns boolStarts I2C and picks how to talk to the board from the address. With an address from 0x30 to 0x37 it checks that the board's ATtiny404 answers and sends it the ADC gain from the sensor type with the slowest data rate; each command waits up to 500 ms for an answer. With any other address it starts an ADS1115 at that address with the same gain and data rate, sets the configuration pin as an output held high, and pulls it low while it configures the LMP91000. Call it once before reading.
Returnstrue when every step succeeded, false otherwise.
void setCustomZeroCalibration(double calibration)returns voidSets the zero-point offset: a voltage that getPPM() adds after subtracting the front end's internal zero and before converting to PPM. It replaces the sensor type's internal zero calibration for this object.
ReturnsNothing.
Parameters
| Name | Type | Description |
|---|---|---|
calibration | double | Offset in volts. The example passes customCalibration (0.05). |
double getPPM()returns doubleReads the ADC, subtracts the front end's internal zero (2.5 V times its percentage), adds the zero calibration, then divides by the amplifier gain and by the cell sensitivity in nA per ppm from the sensor type. A result below 0 is returned as 0. With ELECTROCHEMICAL_SENSOR_DEBUG defined it also prints the three voltages.
ReturnsGas concentration in PPM.
Putting it together
Create the sensor, call begin(), then call setCustomZeroCalibration() with
your offset before you take readings. Run the sketch where there is none of the
target gas, change customCalibration, and upload it again until the voltage
after calibration is roughly 0.