Introduction
The Gravity: Laser CH4(methane) sensor is based on Tunable Diode Laser Absorption Spectroscopy (TDLAS) technology for methane gas detection. It adopts a dual-pass optical path structure, offering excellent gas selectivity, no oxygen dependence, and long service life. An integrated temperature sensor allows direct output of methane gas data (%LEL, Lower Explosive Limit) with temperature compensation. Compared with catalytic bead methane sensors, the laser detection principle ensures higher safety.
The onboard Gravity interface supports I2C/UART data output, and the standoff mounting design makes it easy to fix the sensor onto any flat surface.
Product Feature
- High measurement accuracy with pre-delivery factory calibration
- Low cross-sensitivity, exclusively sensitive to methane
- Extended service life (>10 years)
Product Specification
- Supply Voltage: 3.3–5 V
- Operating Temperature: -13 to 58 °C
- Operating Humidity: 0–95% R.H. (non-condensing)
- Operating Current: <300 mA
- Warm-up Time: 15 s
- Response Time: T90 <15 s
Pinout

Pin | Description |
---|---|
VCC | DC 3.3V-5.5V Input |
GND | GND |
SCL/TX | I2C Clock/ UART Transmit |
SDA/RX | I2C Data /UART Receive |
Toturial
Prepare
Hardware
- DFRduino UNO+IO Expansion board (SKU:DFR0216-2) * 1
- Gravity: Laser CH4 Sensor(SKU:SEN0654) * 1
Software
- Download Arduino IDE: Click to download Arduino IDE
- Download DFRobot_MHZ9041A library and install .zip library manully:DFRobot MHZ9041A Github
- Or Search and install "DFRobot_MHZ9041A" library in the library manager
Hookup diagram
Sample code
- Ensure the dip switch on CH4 sensor is on the I2C side
- Upload following code and check the serial monitor
/*!
* @file get conncentration.ino
* @brief get ch4 conncentration
* @copyright Copyright (c) 2025 DFRobot Co.Ltd (http://www.dfrobot.com)
* @license The MIT License (MIT)
* @author ZhixinLiu([email protected])
* @version V1.0.0
* @date 2025-04-24
* @url https://github.com/DFRobot/DFRobot_MHZ9041A
*/
#include "DFRobot_MHZ9041A.h"
#define I2C_COMMUNICATION //use I2C for communication, but use the serial port for communication if the line of codes were masked
#ifdef I2C_COMMUNICATION
DFRobot_MHZ9041A_I2C ch4(&Wire ,0x34);
#else
/* -----------------------------------------------------------------------------------------------------
* | Sensor | Connect line | Leonardo/Mega2560/M0 | UNO | ESP8266 | ESP32 | microbit | m0 |
* | VCC |=============>| VCC | VCC | VCC | VCC | X | vcc |
* | GND |=============>| GND | GND | GND | GND | X | gnd |
* | RX |=============>| Serial1 TX1 | 5 | 5/D6 | D2 | X | tx1 |
* | TX |=============>| Serial1 RX1 | 4 | 4/D7 | D3 | X | rx1 |
* ----------------------------------------------------------------------------------------------------*/
/* Baud rate cannot be changed */
#if defined(ARDUINO_AVR_UNO) || defined(ESP8266)
SoftwareSerial mySerial(4, 5);
DFRobot_MHZ9041A_UART ch4(&mySerial, 115200);
#elif defined(ESP32)
DFRobot_MHZ9041A_UART ch4(&Serial1, 115200 ,/*rx*/D2 ,/*tx*/D3);
#else
DFRobot_MHZ9041A_UART ch4(&Serial1, 115200);
#endif
#endif
void setup()
{
Serial.begin(115200);
while(!ch4.begin()){
Serial.println("NO Deivces !");
delay(1000);
} Serial.println("Device connected !");
//ch4.reset();
ch4.setMode(ePassivityMode); // set Passivity mode
}
void loop()
{
float ch4Concentration = ch4.getCH4Concentration(); // get CH4 concentration
float temperature = ch4.getTemperature(); // get temperature
eFaultCode_t errorCode = ch4.getErrorMsg(); // get error code
String sourceData = ch4.getSourceData(); // get source data
Serial.print("CH4 Concentration: ");
Serial.print(ch4Concentration, 2); // print CH4 concentration
Serial.println("%LEL");
Serial.print("Temperature: ");
Serial.print(temperature, 2); // print temperature
Serial.println("C");
Serial.print("Error Code: ");
Serial.println(errorCode); // print error code
Serial.print("Source Data: ");
Serial.println(sourceData); // print source data
Serial.println("===================================");
delay(20);
}
Result
Open the serial monitor, methane concentration, module temperature, and related data would show up.
Toturial with Gravity SCI DAQ
The Gravity SCI DAQ offers a code-free solution for sensor monitoring and data logging. It allows users to view real-time sensor data directly or record time-stamped measurements into a .csv file without any programming effort.
Hardware
- Gravity: SCI DAQ (SKU:DFR0999) * 1
- Gravity: Laser CH4 Sensor (SKU: SEN0654) * 1
- Double-headed PH2.0-4P Cable(Come with Gravity: SCI DAQ) * 1
Tutorial
According to this Firmware update tutorial, upgrade the Gravity: SCI module firmware to version V1.0.5 or above. Once upgraded, the Gravity: Laser Methane Sensor can be directly connected to the SCI module to view methane concentration, enabling programming-free scientific experiments and exploration.
Result

API list
/**
* @enum eFaultCode_t
* @brief Types of sensor fault codes
*/
typedef enum {
eSensorNormal = 0x00, // 00 Sensor operating normally
eTempControlError = 0x01, // 01 Temperature control error
eAmbientTempError = 0x02, // 02 Ambient temperature error
eAmbientAndTempControlError = 0x03, // 03 Ambient temperature error & temperature control error
eLaserSignalWeak = 0x04, // 04 Weak laser signal
eAmbientAndSignalWeakError = 0x06, // 06 Ambient temperature error & weak laser signal
eLaserSignalError = 0x10, // 16 Laser signal error
eAmbientAndSignalError = 0x12, // 18 Ambient temperature error & laser signal error
} eFaultCode_t;
/**
* @enum eModuleMode_t
* @brief sensor work mode
*/
typedef enum {
ePassivityMode = 0x00,
eActiveMode = 0x01,
} eWorkMode_t;
/**
* @fn setMode
* @brief Set the working mode
* @param mode Working mode
* @note 0x00: Active mode, 0x01: Passive mode
* @return null
*/
void setMode(eWorkMode_t mode);
/**
* @fn getSourceData
* @brief Get raw sensor data
* @return Raw data string, up to 43 bytes in length
*/
String getSourceData(void);
/**
* @fn getCH4Concentration
* @brief Get methane (CH4) concentration
* @return CH4 concentration value, two decimal places, the second digit is always 0, unit: %LEL
*/
float getCH4Concentration(void);
/**
* @fn getTemperature
* @brief Get ambient temperature
* @return Temperature in degrees Celsius
*/
float getTemperature(void);
/**
* @fn getErrorMsg
* @brief Get error code information
* @return Error code
*/
eFaultCode_t getErrorMsg(void);
/**
* @fn getActiveData
* @brief Get raw data in active reporting mode
* @return Raw data string in active mode
*/
String getActiveData(void);
/**
* @fn reset
* @brief Reset the onboard methane sensor; hold the reset pin low for 2 seconds to complete the reset
* @return null
*/
void reset(void);
/**
* @fn setDeviceID
* @brief Set the module address,range 0x03~0x7F
* @return Returns 1 if successful, otherwise returns 0
*/
bool setDeviceID(uint8_t id);
/**
* @fn getDeviceID
* @brief Get the module address
* @return Module address
*/
uint8_t getDeviceID(void);
UART protocol
UART config: 115200bps 8-N-1
Note: The UART output is an ACSII string that is uploaded every 1S, totaling 44 bytes.
Function Code | Frame Head | Concentration | Space | Temperature | Space | Reserve | Space | Reserve |
---|---|---|---|---|---|---|---|---|
Byte Index | 0 | 1~7 | 8 | 9~13 | 14 | 15~21 | 22 | 23~27 |
Byte Length | 1 | 7 | 1 | 5 | 1 | 7 | 1 | 5 |
Unit | / | %LEL | / | ℃ | / | ℃ | / | / |
Example | A | +000.00 | < SP > | +23.7 | < SP > | 0666.22 | < SP > | +16.1 |
Space | Reserve | Space | Space | Error Code | Space | XOR CheckSum | CR | LF |
---|---|---|---|---|---|---|---|---|
Byte Index | 28 | 29~35 | 36 | 37~38 | 39 | 40~41 | 42 | 43 |
Byte Length | 1 | 7 | 1 | 2 | 1 | 2 | 1 | 1 |
Unit | / | V | / | / | / | / | < CR > | < LF > |
Example | < SP > | B+066.0 | < SP > | 00 | < SP > | 3B | < CR > | < LF > |
Output String Parsing Guide:
Example: A+000.00 +24.0 0665.38 +16.1 B+066.0 00
A: Frame header
+000.00: Methane concentration value, with two decimal places; the second decimal digit is always 0. Unit: %LEL
+24.0: Ambient temperature. Unit: °C
0665.38: Reserved
+16.1: Reserved
B+066.0: Reserved
00: Error code value — 0: normal; 1: abnormal
BIT7~5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0 |
---|---|---|---|---|---|
Reserve | Laser signal abnormal | Weak laser signal | Reserve | Ambient temperature abnormal | Temperature control status abnormal |
More
WIKI modify history
Doc version | Time | Editor | Content |
---|---|---|---|
V1.0 | 2025.4.27 | YeezB | First release |
Product modify histroy
Product Version | Time | Editor | Content |
---|---|---|---|
V1.0 | 2025.4.27 | YeezB | First release |