In this tutorial, the main control device used is Core2 v1.1, paired with Unit MQ. This current and voltage detection unit communicates via I2C. Modify the pin definitions in the program according to your actual circuit connections. After the device is connected, the corresponding I2C pins are G33 (SCL)
and G32 (SDA)
.
concentration
, the higher the voltage
feedback from Unit MQ. For information on voltage and concentration (ppm), please refer to the MQ-5 Datasheet.HEAT_MODE_CONTINUOUS
) and Pin Switch Heating Mode (HEAT_MODE_PIN_SWITCH
). It can retrieve data such as sensor voltage, ADC reference voltage, device temperature, etc., which can be selected as needed. getValidTags() // Data Valid Tag
getReferenceVoltage() // Reference Voltage
getNTCADC12bit() // NTC ADC
getNTCVoltage() // NTC Voltage
getNTCResistance() // NTC Resistance
getNTCTemperature(uint16_t ntcResistance) // NTC Temperature
getMQADC12bit() // Sensor ADC
getMQVoltage() // Sensor Voltage
#include <M5Unified.h>
#include <M5GFX.h>
#include "m5_unit_mq.hpp"
#define I2C_SDA (32) /**< I2C SDA pin number */
#define I2C_SCL (33) /**< I2C SCL pin number */
#define I2C_SPEED (400000) /**< I2C bus speed in Hz */
M5UnitMQ unitMQ; /**< Instance of the Unit MQ gas sensor */
/* Sensor status and data variables */
static led_status_t ledStatus = LED_WORK_STATUS_OFF; /**< Current LED state */
static heat_mode_t heatMode = HEAT_MODE_CONTINUOUS; /**< Current heating mode */
static mq_adc_valid_tags_t validTags = VALID_TAG_INVALID; /**< MQ ADC data validity flag */
static uint8_t highLevelTime = 0; /**< High-level heating time (not used here) */
static uint8_t lowLevelTime = 0; /**< Low-level heating time (not used here) */
static uint16_t mqADC12bit = 0; /**< MQ sensor raw ADC value (12-bit) */
static uint16_t ntcADC12bit = 0; /**< NTC sensor raw ADC value (12-bit) */
static uint16_t ntcResistance = 0; /**< Calculated NTC resistance in Ohms */
static uint16_t referenceVoltage = 0; /**< Reference voltage in millivolts */
static uint16_t mqVoltage = 0; /**< Calculated MQ sensor voltage in millivolts */
static uint16_t ntcVoltage = 0; /**< Calculated NTC sensor voltage in millivolts */
float temperature = 0.0f; /**< Calculated temperature in degrees Celsius */
static uint8_t firmwareVersion = 0; /**< Sensor firmware version */
/**
* @brief Arduino setup function, runs once at startup.
*
* Initializes the M5 hardware and Unit MQ sensor with I2C configuration.
* Retries sensor initialization until successful.
* Sets sensor heating mode and turns on the sensor LED.
*/
void setup()
{
M5.begin();
M5.Display.setRotation(1);
M5.Display.clear(TFT_WHITE);
M5.Display.setFont(&fonts::FreeMonoBold9pt7b);
M5.Display.setTextColor(TFT_BLACK);
Serial.begin(115200);
Serial.println("========== Unit MQ Initialization ==========");
// Initialize Unit MQ sensor on I2C bus, retry until success
while (!unitMQ.begin(&Wire, UNIT_MQ_I2C_BASE_ADDR, I2C_SDA, I2C_SCL, I2C_SPEED)) {
Serial.println("[ERROR] Unit MQ initialization failed! Retrying...");
delay(1000);
}
Serial.println("[INFO] Unit MQ initialization succeeded.");
// Set the heating mode to continuous heating
unitMQ.setHeatMode(HEAT_MODE_CONTINUOUS);
Serial.println("[INFO] Heating mode set to CONTINUOUS.");
// Turn on the sensor's LED indicator
unitMQ.setLEDState(LED_WORK_STATUS_ON);
Serial.println("[INFO] LED status set to ON.");
}
/**
* @brief Arduino main loop function, runs repeatedly.
*
* Reads sensor data including LED status, valid tags, firmware version,
* NTC sensor ADC and temperature, and MQ sensor ADC and voltage if valid.
* Prints all the relevant data to Serial for monitoring.
*/
void loop()
{
// Get the current heating mode
heatMode = unitMQ.getHeatMode();
// Retrieve current LED state
ledStatus = unitMQ.getLEDState();
// Retrieve validity tag for MQ sensor data
validTags = unitMQ.getValidTags();
// Retrieve sensor firmware version
firmwareVersion = unitMQ.getFirmwareVersion();
// Always read NTC sensor data and calculate temperature
ntcADC12bit = unitMQ.getNTCADC12bit();
referenceVoltage = unitMQ.getReferenceVoltage();
ntcVoltage = unitMQ.getNTCVoltage();
ntcResistance = unitMQ.getNTCResistance();
temperature = unitMQ.getNTCTemperature(ntcResistance);
// Print sensor status and readings
Serial.println("======== Unit MQ Status ========");
Serial.printf("Firmware Version : %d\n", firmwareVersion);
Serial.printf("Heating Mode : %s\n", heatMode == HEAT_MODE_CONTINUOUS ? "CONTINUOUS" : "SWITCH");
Serial.printf("LED Status : %s\n", ledStatus == LED_WORK_STATUS_ON ? "ON" : "OFF");
Serial.printf("NTC ADC (12-bit) : %u\n", ntcADC12bit);
Serial.printf("Reference Voltage : %u mV\n", referenceVoltage);
Serial.printf("NTC Voltage : %u mV\n", ntcVoltage);
Serial.printf("NTC Resistance : %u Ohm\n", ntcResistance);
Serial.printf("Temperature : %.2f °C\n", temperature);
M5.Display.clear(TFT_WHITE);
M5.Display.drawCenterString("Unit MQ Status", M5.Display.width()/2, 0);
M5.Display.setCursor(0, 20);
M5.Display.printf("Firmware Version : %d\n", firmwareVersion);
M5.Display.printf("Heating Mode : %s\n", heatMode == HEAT_MODE_CONTINUOUS ? "CONTINUOUS" : "SWITCH");
M5.Display.printf("LED Status : %s\n", ledStatus == LED_WORK_STATUS_ON ? "ON" : "OFF");
M5.Display.printf("NTC ADC (12-bit) : %u\n", ntcADC12bit);
M5.Display.printf("Reference Voltage: %u mV\n", referenceVoltage);
M5.Display.printf("NTC Voltage : %u mV\n", ntcVoltage);
M5.Display.printf("NTC Resistance : %u Ohm\n", ntcResistance);
M5.Display.printf("Temperature : %.2f C\n", temperature);
// Print MQ sensor readings only if data is valid
if (validTags == VALID_TAG_VALID) {
mqADC12bit = unitMQ.getMQADC12bit();
mqVoltage = unitMQ.getMQVoltage();
Serial.printf("Valid Tags : 0x%02X (MQ data valid)\n", validTags);
Serial.printf("MQ ADC (12-bit) : %u\n", mqADC12bit);
Serial.printf("MQ Voltage : %u mV\n", mqVoltage);
M5.Display.printf("Valid Tags : 0x%02X (valid)\n", validTags);
M5.Display.printf("MQ ADC (12-bit) : %u\n", mqADC12bit);
M5.Display.printf("MQ Voltage : %u mV\n", mqVoltage);
} else {
Serial.printf("Valid Tags : 0x%02X (MQ data invalid)\n", validTags);
Serial.println("[WARNING] MQ data invalid. Skipping MQ readings.");
M5.Display.printf("Valid Tags : 0x%02X (invalid)\n", validTags);
M5.Display.println("[WARNING] MQ data invalid. Skipping MQ readings.");
}
Serial.println("================================\n");
delay(1000); // Delay 1 second before next reading
}
#include <M5Unified.h>
#include <M5GFX.H>
#include "m5_unit_mq.hpp"
#define I2C_SDA (32) /**< I2C SDA pin number */
#define I2C_SCL (33) /**< I2C SCL pin number */
#define I2C_SPEED (400000) /**< I2C bus speed in Hz */
#define HIGH_LEVEL_TIME (30) /**< High level duration for pin switch mode in seconds */
#define LOW_LEVEL_TIME (10) /**< Low level duration for pin switch mode in seconds */
M5UnitMQ unitMQ; /**< Instance of the Unit MQ gas sensor class */
/* Sensor and system state variables */
static led_status_t ledStatus = LED_WORK_STATUS_OFF; /**< Current LED status */
static heat_mode_t heatMode = HEAT_MODE_PIN_SWITCH; /**< Heating mode of the sensor */
static mq_adc_valid_tags_t validTags = VALID_TAG_INVALID; /**< Validity tag for MQ sensor ADC data */
static uint8_t highLevelTime = 0; /**< High-level time setting for pin switch heating */
static uint8_t lowLevelTime = 0; /**< Low-level time setting for pin switch heating */
static uint16_t mqAdc12bit = 0; /**< Raw 12-bit ADC reading from MQ sensor */
static uint16_t ntcAdc12bit = 0; /**< Raw 12-bit ADC reading from NTC temperature sensor */
static uint16_t ntcResistance = 0; /**< Calculated resistance of NTC sensor (Ohms) */
static uint16_t referenceVoltage = 0; /**< Reference voltage value (mV) */
static uint16_t mqVoltage = 0; /**< Calculated voltage of MQ sensor output (mV) */
static uint16_t ntcVoltage = 0; /**< Calculated voltage of NTC sensor output (mV) */
float temperature = 0.0f; /**< Calculated temperature in Celsius */
static uint8_t firmwareVersion = 0; /**< Firmware version of the Unit MQ sensor */
void setup()
{
M5.begin();
M5.Display.setRotation(1);
M5.Display.clear(TFT_WHITE);
M5.Display.setFont(&fonts::FreeMonoBold9pt7b);
M5.Display.setTextColor(TFT_BLACK);
Serial.begin(115200);
Serial.println("========== Unit MQ Initialization ==========");
// Initialize the Unit MQ sensor with I2C settings.
// Retry initialization until successful.
while (!unitMQ.begin(&Wire, UNIT_MQ_I2C_BASE_ADDR, I2C_SDA, I2C_SCL, I2C_SPEED)) {
Serial.println("[ERROR] Unit MQ initialization failed! Retrying...");
delay(1000);
}
Serial.println("[INFO] Unit MQ initialization succeeded.");
// Set heating mode to PIN SWITCH mode, which alternates heating between HIGH and LOW levels.
unitMQ.setHeatMode(HEAT_MODE_PIN_SWITCH);
Serial.println("[INFO] Heating mode set to PIN SWITCH mode.");
// Configure the durations for high and low heating levels in PIN SWITCH mode.
unitMQ.setPulseTime(HIGH_LEVEL_TIME, LOW_LEVEL_TIME);
Serial.println("[INFO] Pin level switch time set to 30s HIGH and 5s LOW.");
// Turn on the sensor LED indicator.
unitMQ.setLEDState(LED_WORK_STATUS_ON);
Serial.println("[INFO] LED status set to ON.");
}
void loop()
{
// Get the current heating mode
heatMode = unitMQ.getHeatMode();
// Read the current LED status from the sensor.
ledStatus = unitMQ.getLEDState();
// Retrieve validity tag indicating whether MQ sensor data is reliable.
validTags = unitMQ.getValidTags();
// Get the firmware version from the sensor.
firmwareVersion = unitMQ.getFirmwareVersion();
// Always read NTC-related sensor data regardless of MQ data validity.
ntcAdc12bit = unitMQ.getNTCADC12bit(); // Raw ADC for NTC sensor
referenceVoltage = unitMQ.getReferenceVoltage(); // Reference voltage for ADC
ntcVoltage = unitMQ.getNTCVoltage(); // Calculated voltage across NTC
ntcResistance = unitMQ.getNTCResistance(); // Calculated resistance of NTC thermistor
temperature = unitMQ.getNTCTemperature(ntcResistance); // Convert resistance to temperature
Serial.println("======== Unit MQ Status ========");
Serial.printf("Firmware Version : %d\n", firmwareVersion);
Serial.printf("Heating Mode : %s\n", heatMode == HEAT_MODE_CONTINUOUS ? "CONTINUOUS" : "SWITCH");
Serial.printf("LED Status : %s\n", ledStatus == LED_WORK_STATUS_ON ? "ON" : "OFF");
// Print detailed NTC sensor parameters
Serial.printf("NTC ADC (12-bit) : %u\n", ntcAdc12bit);
Serial.printf("Reference Voltage : %u mV\n", referenceVoltage);
Serial.printf("NTC Voltage : %u mV\n", ntcVoltage);
Serial.printf("NTC Resistance : %u Ohm\n", ntcResistance);
Serial.printf("Temperature : %.2f °C\n", temperature);
M5.Display.clear(TFT_WHITE);
M5.Display.drawCenterString("Unit MQ Status", M5.Display.width()/2, 0);
M5.Display.setCursor(0, 20);
M5.Display.printf("Firmware Version : %d\n", firmwareVersion);
M5.Display.printf("Heating Mode : %s\n", heatMode == HEAT_MODE_CONTINUOUS ? "CONTINUOUS" : "SWITCH");
M5.Display.printf("LED Status : %s\n", ledStatus == LED_WORK_STATUS_ON ? "ON" : "OFF");
M5.Display.printf("NTC ADC (12-bit) : %u\n", ntcAdc12bit);
M5.Display.printf("Reference Voltage: %u mV\n", referenceVoltage);
M5.Display.printf("NTC Voltage : %u mV\n", ntcVoltage);
M5.Display.printf("NTC Resistance : %u Ohm\n", ntcResistance);
M5.Display.printf("Temperature : %.2f C\n", temperature);
// If MQ sensor data is valid, read and print MQ ADC and voltage values.
if (validTags == VALID_TAG_VALID) {
mqAdc12bit = unitMQ.getMQADC12bit();
mqVoltage = unitMQ.getMQVoltage();
Serial.printf("Valid Tags : 0x%02X (MQ data valid)\n", validTags);
Serial.printf("MQ ADC (12-bit) : %u\n", mqAdc12bit);
Serial.printf("MQ Voltage : %u mV\n", mqVoltage);
M5.Display.printf("Valid Tags : 0x%02X (valid)\n", validTags);
M5.Display.printf("MQ ADC (12-bit) : %u\n", mqAdc12bit);
M5.Display.printf("MQ Voltage : %u mV\n", mqVoltage);
} else {
// If MQ data is invalid, log a warning and skip readings.
Serial.printf("Valid Tags : 0x%02X (MQ data invalid)\n", validTags);
Serial.println("[WARNING] MQ data invalid. Skipping MQ readings.");
M5.Display.printf("Valid Tags : 0x%02X (invalid)\n", validTags);
M5.Display.println("[WARNING] MQ data invalid.\nSkipping MQ readings.");
}
Serial.println("================================\n");
delay(1000); // Wait for 1 second before next update
}
The effects of the two Unit MQ modes are as follows:
Continuous Heating Mode
Pin Switch Heating Mode