Fundamentos do Sensor de Gás MQ-4: Funcionamento e Estrutura Elétrica
Sensores de gás da família MQ, como o MQ-4, são amplamente utilizados em aplicações embarcadas para detecção de gases inflamáveis e tóxicos no ambiente. Esses sensores funcionam com base em uma resistência interna sensível à presença de gases, que varia conforme a concentração do composto alvo — neste caso, gases como metano (CH₄), propano (C₃H₈), hidrogênio (H₂), monóxido de carbono (CO) e vapores de álcool. Essa resistência variável é o coração do sensor, responsável por fornecer uma leitura elétrica proporcional à concentração de gás.

O MQ-4 possui um elemento de aquecimento interno e dois conjuntos de terminais: os pares A e B, responsáveis pela medição da resistência sensora (RS), e os pares H, conectados ao aquecedor (heater). O aquecimento é essencial para garantir que a superfície do semicondutor sensível atinja a temperatura correta de operação, geralmente entre 300°C e 400°C, condição necessária para que as reações de oxidação dos gases ocorram de forma eficiente, alterando a condutividade do material sensível (tipicamente dióxido de estanho, SnO₂).
Para realizar a medição de concentração de gás, um resistor de carga externo (denominado RL) é conectado em série com o sensor. A tensão de saída (VRL), medida entre o ponto médio entre RS e RL, varia conforme a proporção da resistência do sensor, permitindo a leitura indireta da concentração de gás. A escolha do valor de RL (típico entre 2kΩ e 47kΩ) influencia a sensibilidade do circuito. Quanto maior RL, maior será a tensão de saída para pequenas variações de RS, o que aumenta a sensibilidade, porém pode comprometer a linearidade em concentrações mais elevadas.

O comportamento da resistência RS em relação à concentração de gás é não linear e geralmente é modelado com gráficos log-log fornecidos em folhas de dados (datasheets). Neles, é comum apresentar a razão RS/R₀, onde R₀ é a resistência medida em ar limpo. Essa razão é usada para estimar a concentração de gás em partes por milhão (ppm), por meio de interpolação logarítmica entre os dados experimentais fornecidos pelo fabricante.

A seguir, nas próximas seções, descreveremos como derivar as fórmulas para calcular RS, como calibrar o sensor e como implementar a leitura e cálculo da concentração usando o ESP32 com o framework ESP-IDF, substituindo o uso do Arduino tradicional.
Derivação Matemática da Resistência do Sensor (RS) e Leitura de Tensão com o ESP32
A resistência RS do sensor de gás MQ-4 representa o ponto central para se calcular a concentração de gás presente no ambiente. Para encontrá-la, partimos de um circuito onde o sensor funciona como um divisor de tensão com um resistor de carga RL. A tensão de alimentação (VC) é aplicada aos terminais e a tensão de saída (VRL) é lida no ponto entre RS e RL.
Sabemos pela Lei de Ohm que: \(V = I \cdot R\)
No circuito da figura abaixo, temos:

Como RS e RL estão em série, a corrente total é dada por: \(I = \frac{V_C}{RS + RL}\)
E a tensão sobre RL (isto é, a tensão de saída lida pelo ADC do ESP32): \[V_{RL} = I \cdot RL = \frac{V_C \cdot RL}{RS + RL}\]
Reorganizando a fórmula para isolar RS: \[RS = \left( \frac{V_C \cdot RL}{V_{RL}} \right) – RL\]
Essa fórmula nos permite calcular RS com base na leitura de tensão obtida pelo conversor analógico-digital (ADC) do ESP32. No ESP-IDF, essa leitura é feita por meio da função adc1_get_raw
, que retorna um valor inteiro de 0 a 4095 (resolução de 12 bits por padrão), o qual deve ser convertido para tensão utilizando: VRL=raw⋅Vref4095V_{RL} = \frac{\text{raw} \cdot V_{ref}}{4095}
Onde Vref geralmente é de 3.3V no ESP32, mas pode variar conforme a calibração.
Exemplo em C com ESP-IDF: Leitura e cálculo de RS
#include "driver/adc.h"
#include "esp_log.h"
#define RL_VALUE 10000.0 // 10k Ohms
#define VC 3.3 // Tensão de alimentação do sensor (Vref)
#define TAG "MQ4"
void app_main() {
adc1_config_width(ADC_WIDTH_BIT_12); // Resolução 12 bits
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11); // GPIO36, range até ~3.3V
while (1) {
int raw = adc1_get_raw(ADC1_CHANNEL_0); // Leitura ADC
float vrl = (raw * VC) / 4095.0; // Conversão para tensão
float rs = ((VC * RL_VALUE) / vrl) - RL_VALUE;
ESP_LOGI(TAG, "ADC: %d | VRL: %.2f V | RS: %.2f Ohms", raw, vrl, rs);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
Esse código realiza a leitura do canal ADC1 (GPIO36) e calcula a resistência RS em tempo real, exibindo os valores no terminal. A escolha de RL (10kΩ no exemplo) deve ser mantida constante, pois será necessária na próxima etapa para cálculo de R₀ (calibração em ar limpo) e, posteriormente, da concentração em ppm.
Cálculo de R₀ e Calibração Inicial do Sensor em Ar Limpo
Antes de podermos estimar a concentração de gás no ambiente, é necessário determinar uma referência chamada R₀, que representa a resistência RS medida em ar limpo, isto é, na ausência de gases-alvo como metano, GLP ou CO. Essa resistência é usada como base de comparação para calcular a razão RS/R₀, que por sua vez será aplicada em uma curva de calibração logarítmica, normalmente fornecida pelo fabricante, para determinar a concentração de gás em partes por milhão (ppm).
Segundo o datasheet do sensor MQ-4, a razão típica RS/R₀ em ar limpo é de 4.4, o que significa que: R0=RSair4.4R₀ = \frac{RS_{air}}{4.4}
O processo de calibração consiste em realizar múltiplas leituras da resistência RS enquanto o sensor estiver exposto ao ar ambiente por vários minutos, até que sua resposta estabilize. Essa resistência é então usada para calcular o valor de R₀.
Código de Calibração em C para ESP-IDF
#include "driver/adc.h"
#include "esp_log.h"
#define RL_VALUE 10000.0 // Resistor de carga em ohms
#define VC 3.3 // Tensão de alimentação do sensor
#define AIR_RS_RO_RATIO 4.4 // Valor típico RS/R0 em ar limpo
#define TAG "CALIBRACAO"
void app_main() {
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
float rs_total = 0;
int samples = 500;
for (int i = 0; i < samples; i++) {
int raw = adc1_get_raw(ADC1_CHANNEL_0);
float vrl = (raw * VC) / 4095.0;
float rs = ((VC * RL_VALUE) / vrl) - RL_VALUE;
rs_total += rs;
vTaskDelay(pdMS_TO_TICKS(10));
}
float rs_avg = rs_total / samples;
float r0 = rs_avg / AIR_RS_RO_RATIO;
ESP_LOGI(TAG, "RS médio em ar limpo: %.2f Ohms", rs_avg);
ESP_LOGI(TAG, "R0 estimado: %.2f Ohms", r0);
}
Neste exemplo, o sistema coleta 500 amostras da resistência RS, espaçadas em 10 milissegundos, calcula a média e então aplica a fórmula para obter R₀. Esse valor será utilizado posteriormente para determinar a concentração de gás a partir da razão RS/R₀.
⚠️ Importante: Durante o processo de calibração, o ambiente deve estar livre de gases como metano, propano ou vapores de álcool. Isso assegura que o valor de R₀ represente corretamente a condição de referência do sensor.
Após essa etapa, recomenda-se salvar R₀ em memória flash ou EEPROM, caso seu projeto requeira desligamento/reinicialização frequente, evitando nova calibração sempre que o sistema for energizado.
Ótimo! Agora que já temos o valor de referência R₀, podemos prosseguir com o cálculo da concentração de gás em ppm a partir da razão RS/R₀, utilizando a equação logarítmica derivada da curva de sensibilidade do sensor MQ-4.
Seção 4 – Cálculo da Concentração de Gás (ppm) com Base em Curva Logarítmica
O comportamento da resistência do sensor em função da concentração de gás não é linear. Por isso, os fabricantes fornecem curvas de calibração em escalas logarítmicas (log-log), nas quais a relação entre a razão RS/R₀ e a concentração em ppm segue uma equação da forma: log10(y)=m⋅log10(x)+b\log_{10}(y) = m \cdot \log_{10}(x) + b
Onde:
- y=RS/R0y = RS/R_0 (razão de resistência),
- xx é a concentração de gás em ppm,
- mm é a inclinação (slope),
- bb é o coeficiente linear (intercepto).
Derivando a concentração de gás (x):
Isolando xx: log10(x)=log10(y)−bm\log_{10}(x) = \frac{\log_{10}(y) – b}{m}
E então: x=10(log10(y)−bm)x = 10^{\left(\frac{\log_{10}(y) – b}{m}\right)}
No caso do MQ-4, baseado em um exemplo extraído da curva para GLP (propano), foram utilizados os seguintes pontos para cálculo:
- Ponto 1: (200 ppm, 2.6 RS/R₀)
- Ponto 2: (10.000 ppm, 0.75 RS/R₀)
O cálculo da inclinação é feito por: m=log10(0.75/2.6)log10(10000/200)≈−0.318m = \frac{\log_{10}(0.75 / 2.6)}{\log_{10}(10000 / 200)} \approx -0.318
E o intercepto usando o ponto (5000 ppm, 0.9 RS/R₀): \[b = \log_{10}(0.9) – m \cdot \log_{10}(5000) \approx 1.133\]
Portanto, temos a equação para concentração de gás: \[ppm = 10^{\left(\frac{\log_{10}(RS/R_0) – 1.133}{-0.318}\right)}\]
Exemplo de Código ESP-IDF para Cálculo de ppm
#include <math.h>
#include "driver/adc.h"
#include "esp_log.h"
#define RL_VALUE 10000.0
#define VC 3.3
#define R0 11.82 // Valor obtido da calibração anterior
#define SLOPE -0.318
#define INTERCEPT 1.133
#define TAG "MQ4_PPM"
void app_main() {
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
while (1) {
int raw = adc1_get_raw(ADC1_CHANNEL_0);
float vrl = (raw * VC) / 4095.0;
float rs = ((VC * RL_VALUE) / vrl) - RL_VALUE;
float ratio = rs / R0;
float ppm_log = (log10f(ratio) - INTERCEPT) / SLOPE;
float ppm = powf(10, ppm_log);
ESP_LOGI(TAG, "RS: %.2f Ω | RS/R0: %.2f | ppm: %.2f", rs, ratio, ppm);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
Esse código realiza o cálculo em tempo real da concentração de gás em ppm, aplicando diretamente a fórmula logarítmica ajustada com os coeficientes da curva de sensibilidade. Note que o valor de R₀ deve ser previamente calibrado como mostrado na seção anterior.
💡 Dica prática: os sensores MQ precisam de um tempo de “aquecimento” (burn-in) de alguns minutos após energização para fornecer leituras estáveis.
Projeto Prático com ESP32: Alerta Visual e Exibição em Display OLED
Com os valores de RS, R₀ e a curva logarítmica corretamente implementados, podemos agora desenvolver um sistema embarcado funcional capaz de exibir, em tempo real, a concentração de gás detectada e emitir alertas visuais e sonoros quando os níveis ultrapassarem um limiar de segurança.
Este projeto utiliza os seguintes componentes:
- ESP32 DevKit
- Sensor de gás MQ-4
- Display OLED 0.96” (I2C, SSD1306)
- LED vermelho (alerta visual)
- Buzzer piezoelétrico (alerta sonoro)
- Resistores: 10kΩ (RL), 330Ω (LED)
- Protoboard e jumpers
Esquema de ligação
- MQ-4:
- A → VCC (3V3)
- B → GPIO36 (ADC1_CHANNEL_0)
- H → VCC e GND (alimentação do aquecedor)
- RL entre GPIO36 e GND
- Display OLED (SSD1306, I2C):
- SDA → GPIO21
- SCL → GPIO22
- VCC → 3V3
- GND → GND
- LED:
- Anodo → GPIO25
- Catodo → resistor de 330Ω → GND
- Buzzer:
- Positivo → GPIO26
- Negativo → GND
Código completo com alertas e display
#include <math.h>
#include "driver/adc.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "ssd1306.h" // biblioteca externa para OLED I2C
#define RL_VALUE 10000.0
#define VC 3.3
#define R0 11.82
#define SLOPE -0.318
#define INTERCEPT 1.133
#define ALERT_THRESHOLD_PPM 2000
#define TAG "MQ4_APP"
// Pinos
#define PIN_ADC ADC1_CHANNEL_0 // GPIO36
#define PIN_LED GPIO_NUM_25
#define PIN_BUZZER GPIO_NUM_26
#define I2C_SDA GPIO_NUM_21
#define I2C_SCL GPIO_NUM_22
void app_main() {
// Inicializa ADC
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(PIN_ADC, ADC_ATTEN_DB_11);
// Inicializa GPIOs
gpio_set_direction(PIN_LED, GPIO_MODE_OUTPUT);
gpio_set_direction(PIN_BUZZER, GPIO_MODE_OUTPUT);
// Inicializa OLED
ssd1306_init(I2C_NUM_0, I2C_SDA, I2C_SCL);
ssd1306_clear_screen();
ssd1306_contrast(0xFF);
while (1) {
int raw = adc1_get_raw(PIN_ADC);
float vrl = (raw * VC) / 4095.0;
float rs = ((VC * RL_VALUE) / vrl) - RL_VALUE;
float ratio = rs / R0;
float ppm_log = (log10f(ratio) - INTERCEPT) / SLOPE;
float ppm = powf(10, ppm_log);
float pct = ppm / 10000.0 * 100;
// Exibe no OLED
ssd1306_clear_screen();
char buffer[32];
snprintf(buffer, sizeof(buffer), "Gas: %.0f ppm", ppm);
ssd1306_display_text(buffer, 0, 0);
snprintf(buffer, sizeof(buffer), "%.1f%%", pct);
ssd1306_display_text(buffer, 0, 2);
// Alertas
if (ppm > ALERT_THRESHOLD_PPM) {
gpio_set_level(PIN_LED, 1);
gpio_set_level(PIN_BUZZER, 1);
} else {
gpio_set_level(PIN_LED, 0);
gpio_set_level(PIN_BUZZER, 0);
}
ESP_LOGI(TAG, "RS=%.2f Ω | Ratio=%.2f | ppm=%.1f", rs, ratio, ppm);
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
🛠️ Observação: Para compilar este projeto, será necessário integrar uma biblioteca SSD1306 compatível com o ESP-IDF. Sugiro utilizar uma baseada em I2C, como esp-idf-ssd1306 ou adaptar conforme necessário.
Esse projeto cria uma estação de monitoramento de gás que:
- Calcula a concentração de gás a cada 2 segundos,
- Exibe a leitura no display OLED,
- Dispara um alerta visual (LED) e sonoro (buzzer) se o valor ultrapassar 2000 ppm.
Esse tipo de aplicação pode ser adaptado para uso residencial, industrial, ou em sistemas embarcados conectados à nuvem (via MQTT, por exemplo).
Considerações Finais, Limitações do Sensor MQ-4 e Integração com IoT
Embora os sensores da família MQ, como o MQ-4, sejam acessíveis e fáceis de integrar com microcontroladores como o ESP32, é importante compreender suas limitações e características técnicas para não comprometer a confiabilidade do projeto.
Sensibilidade e Ruído
Sensores MQ operam com um aquecedor interno e possuem tempo de estabilização prolongado — podem levar entre 3 a 5 minutos para fornecer leituras confiáveis após energização. Além disso, são sensíveis a umidade, temperatura ambiente e gases interferentes, o que pode afetar significativamente os resultados.
Como utilizam um princípio de detecção baseado em variação de condutividade, são fortemente influenciados por ruído elétrico e flutuações de tensão de alimentação. Portanto, recomenda-se:
- Usar reguladores de tensão dedicados de 5V ou 3.3V com baixo ripple;
- Realizar média de múltiplas amostras (como mostrado nas seções anteriores);
- Implementar calibração periódica, especialmente em ambientes expostos a variações de gases não monitorados.
Faixa de Medição e Curvas Logarítmicas
A faixa útil do MQ-4 para detecção de gás metano, por exemplo, varia entre 200 ppm e 10.000 ppm. Fora dessa faixa, a curva log-log se torna extrapolada, podendo gerar leituras distorcidas. Para aplicações críticas (como detecção de vazamentos em indústrias ou motores a gás), recomenda-se o uso de sensores com saída linear calibrada ou sensores de referência certificados, como:
- NDIR (Infravermelho não dispersivo)
- MOS (Metal-Oxide Semiconductor de precisão)
- sensores eletroquímicos
Integração com IoT e Expansão do Projeto
Graças à capacidade do ESP32 de operar com Wi-Fi e Bluetooth, esse projeto pode ser facilmente expandido para aplicações de monitoramento remoto e alerta em tempo real, utilizando protocolos como:
- MQTT para envio de dados a um broker (como Mosquitto, HiveMQ ou AWS IoT);
- HTTP/REST para integração com dashboards web;
- Bluetooth LE (BLE) para comunicação local com apps mobile.
Além disso, é possível:
- Armazenar leituras em cartão SD ou SPIFFS;
- Registrar eventos críticos (como detecção acima do limiar) com timestamp e localização GPS;
- Enviar notificações por Telegram, e-mail ou WhatsApp em tempo real.
Essas possibilidades tornam o sistema ideal para aplicações de monitoramento ambiental, automação residencial, sistemas de segurança, cidades inteligentes, usinas de biogás, e muito mais.