Custom configuration
What this example shows
The library's customConfig example builds its own sensorType preset: the
cell's sensitivity, the zero offset, the ADC range and every LMP91000 setting.
begin() then sends that configuration to the board instead of a built-in
preset.
The values in the example are not this board's. To tune this board's cell,
start from the library's SENSOR_CL2 preset and change one value at a time:
| Field | SENSOR_CL2 value |
|---|---|
nanoAmperesPerPPM | 600.0F |
internalZeroCalibration | 0 |
adsGain | ADS_GAIN_4_096V |
TIA_GAIN_IN_KOHMS | TIA_GAIN_120_KOHM |
RLOAD | RLOAD_33_OHM |
REF_SOURCE | REF_EXTERNAL |
INTERNAL_ZERO | INTERNAL_ZERO_20_PERCENT |
BIAS_SIGN | BIAS_SIGN_POSITIVE |
BIAS | BIAS_0_PERCENT |
FET_SHORT | FET_SHORT_DISABLED |
OP_MODE | OP_MODE_3LEAD_AMP_CELL |
Keep REF_SOURCE at REF_EXTERNAL: the board has a 2.5 V reference for the
front end, and the library calculates ppm with 2.5 V.
The example code
/**
**************************************************
*
* @file customConfig.ino
* @brief Create a custom config for the LMP91000 and upload it to the device.
* This enables you to use this breakout with any electrochemical sensor.
*
* To successfully run the sketch:
* - Edit the custom configuration
* - Connect LMPEN to any GPIO pin
* - Run the sketch and open serial monitor at 115200 baud!
*
*
* @authors Robert @ soldered.com
***************************************************/
// Include the required library
#include "Electrochemical-Gas-Sensor-SOLDERED.h"
/**
* Here are parameters to configure for the custom sensor:
*
* nanoAmperesPerPPM: From the datasheet of the particular electrochemical
* sensor, used in the calculation of PPM/PPB
*
* internalZeroCalibration: A fixed value which is summed to the voltage
* measured by the ADS. The value here should make the reading be
* just barely 0 PPM when the sensor is in a place with none of the target gas
*
* adsGain: The gain of the ADS
* The voltage here represents the max range which it can measure
* ADS_GAIN_6_144V 6.144 V
* ADS_GAIN_4_096V 4.096 V
* ADS_GAIN_2_048V 2.048 V
* ADS_GAIN_1_024V 1.024 V
* ADS_GAIN_0_512V 0.512 V
* ADS_GAIN_0_256V 0.256 V
*
* TIA_GAIN_IN_KOHMS: The gain of the amplifier
* This increases the sensitivity of the measurement
* TIA_GAIN_EXTERNAL External resistance
* TIA_GAIN_2_75_KOHM 2.75 kOhm
* TIA_GAIN_3_5_KOHM 3.5 kOhm
* TIA_GAIN_7_KOHM 7 kOhm
* TIA_GAIN_14_KOHM 14 kOhm
* TIA_GAIN_35_KOHM 35 kOhm
* TIA_GAIN_120_KOHM 120 kOhm
* TIA_GAIN_350_KOHM 350 kOhm
*
* RLOAD: The load resistor in the LMP91000
* Specified in the electrochemical sensor's datasheet
* RLOAD_10_OHM 10 Ohm
* RLOAD_33_OHM 33 Ohm
* RLOAD_50_OHM 50 Ohm
* RLOAD_100_OHM 100 Ohm
*
* REF_SOURCE: Source of the control voltage reference
* For our breakout, use external, there's a 2.5V external
* reference voltage
* REF_INTERNAL Internal
* REF_EXTERNAL External
*
* INTERNAL_ZERO: Internal zero selection
* If the electrochemical sensor has a positive polarity, you
* would usually want to use 20% for the most headroom in the signal
* INTERNAL_ZERO_20_PERCENT 20%
* INTERNAL_ZERO_50_PERCENT 50%
* INTERNAL_ZERO_67_PERCENT 67%
* INTERNAL_ZERO_BYPASSED Internal zero bypassed
*
* BIAS_SIGN: The polarity of the bias voltage
* BIAS_SIGN_NEGATIVE Negative
* BIAS_SIGN_POSITIVE Positive
*
* BIAS: Added bias, percentage of the reference voltage
* Most sensors don't require this, check each sensor's datasheet
* BIAS_0_PERCENT 0%
* BIAS_1_PERCENT 1%
* BIAS_2_PERCENT 2%
* BIAS_4_PERCENT 4%
* BIAS_6_PERCENT 6%
* ...
* BIAS_22_PERCENT 22%
* BIAS_24_PERCENT 24%
*
* FET_SHORT: Short the FET
* Used to perserve the electrochemical sensor
* Has to be disabled for the sensor to be operable
* FET_SHORT_DISABLED Disabled
* FET_SHORT_ENABLED Enabled
*
* OP_MODE: Mode of operation
* OP_MODE_DEEP_SLEEP Deep Sleep (default)
* OP_MODE_2LEAD_GROUND_CELL 2-lead ground referred galvanic cell
* OP_MODE_STANDBY Standby
* OP_MODE_3LEAD_AMP_CELL 3-lead amperometric cell
* OP_MODE_TEMPERATURE_TIA_OFF Temperature measurement (TIA Off)
* OP_MODE_TEMPERATURE_TIA_ON Temperature measurement (TIA On)
*
* For more details, check thge LMP91000 datasheet, chapter 7.6
*/
// Here is an example of a custom configuration:
const sensorType SENSOR_CUSTOM = {
100.0F, // nanoAmperesPerPPM
0, // internalZeroCalibration
ADS_GAIN_4_096V, // adsGain
TIA_GAIN_120_KOHM, // TIA_GAIN_IN_KOHMS
RLOAD_10_OHM, // RLOAD
REF_EXTERNAL, // REF_SOURCE
INTERNAL_ZERO_20_PERCENT, // INTERNAL_ZERO
BIAS_SIGN_NEGATIVE, // BIAS_SIGN
BIAS_0_PERCENT, // BIAS
FET_SHORT_DISABLED, // FET_SHORT
OP_MODE_3LEAD_AMP_CELL, // OP_MODE
};
// Create the sensor object with the custom type
ElectrochemicalGasSensor sensor(SENSOR_CUSTOM);
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 reading
double reading = sensor.getPPM();
// Print the reading with 5 digits of precision
Serial.println("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 to a GPIO. 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:
Sensor initialized successfully!
Then, every 2.5 s, Sensor reading: on its own line, followed by a line with
the value in ppm with five decimals and PPM. 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 ElectrochemicalGasSensorCreates the sensor object. It stores the settings only; nothing is sent to the board until begin().
ReturnsThe sensor object.
Parameters
| Type | Name | Description |
|---|---|---|
sensorType | _t | The preset, here the example's own SENSOR_CUSTOM. Its fields are listed in the order the sensorType struct declares them. |
uint8_t | _adcAddr | The I2C address, DEFAULT_ADC_ADDR (0x49) when left out, as in the example. 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 | _configPin | A GPIO that begin() drives low while it configures the LMP91000 directly. -1 (none) when left out. Unused for addresses 0x30 to 0x37. |
bool begin()returns boolStarts Wire, checks that the board answers, sets the preset's ADC gain and data rate, and writes the preset's amplifier gain and load, reference, internal zero, bias and operating mode to the LMP91000. Call it once in setup() before reading.
Returnstrue when the board answered and both configuration steps succeeded, false otherwise.
double getPPM()returns doubleTakes one reading and converts it to ppm with the preset's values: it subtracts the internal zero voltage (2.5 V times the internal zero percentage), adds internalZeroCalibration, divides by the amplifier gain and by nanoAmperesPerPPM. 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
begin() writes the LMP91000 and ADC fields to the board, and getPPM() uses
nanoAmperesPerPPM, internalZeroCalibration, the amplifier gain and the
internal zero in its calculation. Upload the sketch again after each change. The constant
names for each field (TIA_GAIN_..., RLOAD_..., BIAS_..., OP_MODE_...)
are defined in the library's src/sensorConfigData.h.