The analog front end is implemented using one LMP91000, a programmable AFE potentiostat designed for use in use in micro-power electrochemical sensing applications. This little thing supports gas sensitivities over a range of 0.5 nA/ppm and up to 9500 nA/ppm. Communication with the microcontroller is done via I2C, plus one analog line for the sensor readings.

The microcontroller used is a PIC24F16KM202, featuring a 12-bit A/D converter with threshold detect, which takes care of all the computations and sends data to the host application via UART interface (3.3V logic levels).

There’s also one IC that looks to me like a Si7021-A20 I2C temperature and humidity sensor. On the top side, there’s an IC marked “SPH3” which I haven’t been able to identify.

Anyway, that’s not even important; all one has to know is the communication protocol.

Performance and characteristics

This little hydrogen sulfide sensor has some pretty impressive specifications.

The measurement range is from 0 to 10ppm, with a resolution of 10 ppb (parts per billion).

Measurement accuracy is 15% of the reading

Measurement repeatability is below ±3% of reading

Very important, it has a low cross-sensitivity to other gases:

10ppm chlorine will be registered as -2.2ppm H2S

10ppm NO2 will be registered as -2.0ppm H2S

20ppm SO2 will be registered as 1.7ppm H2S

50ppm NO will be registered as 1.2ppm H2S

400ppm CO will be registered as 1.1ppm H2S

Other gases such as ozone (5ppm), methane (500ppm), ammonia (100ppm) will alter the H2S readings by less than 1ppm.

The sensor is designed to be powered from 3.3V, with a range of 2.6 to 3.3V power supply voltage

Power consumption is 1mW for 1 minute triggered samples and 12mW for continuous operation.

Its environmental characteristics allow it to operate outside

Temperature Range is 20 to 40 C (-30 to 55 C intermittent)

Humidity Range is 15 to 95% (0 to 100% non — condensing intermittent)

Sensor lifespan is over 5 years.

Arduino code for the H2S sensor

Here comes the fun part: using the sensor with an Arduino board. I used one Arduino Due, as that board works with 3.3V logic levels. The on;y thing to keep in mind is that the Due is a 32-bit board, and as such the int variable is 32 bit (ranges from -2,147,483,648 to 2,147,483,647). On 8-bit boards some readings will have to be recorded as floats.

Considering the sensor connected to UART1, UART0 being used by the serial monitor, the code I propose performs an EEPROM dump, showing all the settings of the sensor, and then triggers a measurement every 10 seconds. The results are sent to the PC using the Serial Monitor in Arduino IDE.

NOTE: The code below is for sensor firmware 14FEB17.

// SPEC H2S Sensor demo code

// This code works with sensor firmware 14FEB17



// Serial number of my sensor

// #define mysensor_serial_no 012017030207



// #define SERIAL1_RX_BUFFER_SIZE 256

// #define SERIAL1_TX_BUFFER_SIZE 256



// Sensor values

// The format of the output is: SN[XXXXXXXXXXXX], PPB [0 : 999999], TEMP [-99:99],

// RH[0:99], RawSensor[ADCCount], TempDigital, RHDigital, Day[0:99], Hour [0:23]

// Note that on Arduino Due integer variable (int) stores a 32-bit (4-byte) value.

// This yields a range of -2,147,483,648 to 2,147,483,647

// (minimum value of -2^31 and a maximum value of (2^31) - 1).

// On 8 bit boards some readings have to be recorded as floats



String SensorSerialNo;

int H2S;

int Temperature;

int RH;

int RawSensor;

int TempDigital;

int RHDigital;

int Days;

int Hours;

int Minutes;

int Seconds;



#define command_delay 500

#define start_delay 2500

String dataString = "";

String responseString = "";

boolean dataStringComplete = 0;

char inChar;



void setup() {

Serial.begin(9600);

Serial.println("H2S sensor demo code!");

Serial1.begin(9600);

// Normally, data is returned within one second

Serial1.setTimeout(1500);

// reserve 80 bytes for the dataString

dataString.reserve(80);

responseString.reserve(150);



// Wait for sensor

delay(500);

flush_serial1();



// EEPROM dump

SPEC_dump_EEPROM();

Serial.println(" ");

Serial.println("STARTING MEASUREMENTS");

Serial.println(" ");

}







void loop() {

// Do a readout every 10 seconds

SPEC_Data_read();

SPEC_parse_data();

SPEC_print_data();

delay(10000);

}



/* ********************************************************************************

* This function triggers one measurement and receives the data from the sensor

**********************************************************************************/

void SPEC_Data_read(){

// First, we do some initialization

// dataStringComplete is set as "false", as we don't have any valid data received

dataStringComplete = 0;

// Clear the data string

dataString = "";

// Now we trigger a measurement

Serial1.print(" ");

// We wait for the sensor to respond

dataString = Serial1.readStringUntil('

');

//Serial.println(dataString);

}



/* ********************************************************************************

* This function takes the received string and upodates sensor data

**********************************************************************************/

void SPEC_parse_data(){

// Parses the received dataString

// Data string is comma separated

// The format of the output is: SN[XXXXXXXXXXXX], PPB [0 : 999999], TEMP [-99:99],

// RH[0:99], RawSensor[ADCCount], TempDigital, RHDigital, Day[0:99], Hour [0:23],

// Minute[0:59], Second[0 : 59]\r



// Take a look also at

// https://stackoverflow.com/questions/11068450/arduino-c-language-parsing-string-with-delimiter-input-through-serial-interfa

// We look first for the SN

int idx1 = dataString.indexOf(',');

SensorSerialNo = dataString.substring(0, idx1);

int idx2 = dataString.indexOf(',', idx1 + 1);

// Hint: after comma there's a space - it should be ignored

String S_gas = dataString.substring(idx1 + 2, idx2);

H2S = S_gas.toInt();

int idx3 = dataString.indexOf(',', idx2 + 1);

String S_temp = dataString.substring(idx2 + 2, idx3);

Temperature = S_temp.toInt();

int idx4 = dataString.indexOf(',', idx3 + 1);

String S_humi = dataString.substring(idx3 + 2, idx4);

RH = S_humi.toInt();

int idx5 = dataString.indexOf(',', idx4 + 1);

String S_raw_gas = dataString.substring(idx4 + 2, idx5);

RawSensor = S_raw_gas.toInt();

int idx6 = dataString.indexOf(',', idx5 + 1);

String S_Tdigital = dataString.substring(idx5 + 2, idx6);

TempDigital = S_Tdigital.toInt();

int idx7 = dataString.indexOf(',', idx6 + 1);

String S_RHdigital = dataString.substring(idx6 + 2, idx7);

RHDigital = S_RHdigital.toInt();

int idx8 = dataString.indexOf(',', idx7 + 1);

String S_Days = dataString.substring(idx7 + 2, idx8);

Days = S_Days.toInt();

int idx9 = dataString.indexOf(',', idx8 + 1);

String S_Hours = dataString.substring(idx8 + 2, idx9);

Hours = S_Hours.toInt();

int idx10 = dataString.indexOf(',', idx9 + 1);

String S_Minutes = dataString.substring(idx9 + 2, idx10);

Minutes = S_Minutes.toInt();

int idx11 = dataString.indexOf('\r');

String S_Seconds = dataString.substring(idx10 + 2, idx11);

Seconds = S_Seconds.toInt();

}





/* ********************************************************************************

* This function prints the sensor data

**********************************************************************************/

void SPEC_print_data(){

Serial.println("********************************************************************");

Serial.print ("Sensor Serial No. is ");

Serial.println (SensorSerialNo);

Serial.print ("H2S level is ");

Serial.print (H2S);

Serial.println (" ppb");

Serial.print ("Temperature is ");

Serial.print (Temperature, DEC);

Serial.println (" deg C");

Serial.print ("Humidity is ");

Serial.print (RH, DEC);

Serial.println ("% RH");

Serial.print ("Sensor is online since: ");

Serial.print (Days, DEC);

Serial.print (" days, ");

Serial.print (Hours, DEC);

Serial.print (" hours, ");

Serial.print (Minutes, DEC);

Serial.print (" minutes, ");

Serial.print (Seconds, DEC);

Serial.println (" seconds");

Serial.println ("Raw Sensor Data");

Serial.print ("Raw gas level: ");

Serial.println (RawSensor);

Serial.print ("Temperature digital: ");

Serial.println (TempDigital);

Serial.print ("Humidity digital: ");

Serial.println (RHDigital);

Serial.println ("");

}





/* ********************************************************************************

* EEPROM dump

**********************************************************************************/

void SPEC_dump_EEPROM(){

// First we trigger a measurement

Serial1.print(" ");

// Within one second time we send the command "e"

delay(400);

Serial1.print("e");

dataString = Serial1.readStringUntil('

');

// You can uncomment this line if you wish

//Serial.println(dataString);

for (int i=0; i<20; i++){

responseString = Serial1.readStringUntil('

');

Serial.println(responseString);

}

}



void flush_serial1(){

// Do we have data in the serial buffer?

// If so, flush it

if (Serial1.available() > 0){

Serial.println ("Flushing serial buffer...");

while(1){

inChar = (char)Serial1.read();

delay(10);

Serial.print(inChar);

if (inChar == '

') break;

}

Serial.println (" ");

Serial.println ("Buffer flushed!");

}

}

Some comments regarding the code

The DGS-H2S 968–036 operating manual of the sensor (version March 2017) is a bit ambiguous regarding the UART communication protocol. On page 5 it states that a command is recognized if it’s received within 1-second from a TRIGGER event. On the next page, we find a 5-seconds interval for a command to be recognized.

I have found that the commands are recognized within an 800-milliseconds interval after the trigger event (before the sensor starts sending back the measured values). As a result, configuring the sensor with a terminal program such TeraTerm is next to impossible.

Also, the commands must NOT be terminated with \r

or with

, Just the command letter is enough.

Code examples for other commands will be published soon,

When starting for the first time, you will get some extreme readings. This is because the way this sensor works. In one of the technical documents, I have found a piece of information that compares this sensor with a capacitor, with bias placed across the working and reference electrodes being similar to the voltage across the plates of a capacitor. The high current observed at the sensor startup is like the charging current of a capacitor. As such, it is recommended to leave the sensor run for about one hour after power-up to get accurate readings.