Датчик углекислого газа CO₂ MH-Z19 (NDIR)

Полное руководство по датчику CO₂ MH-Z19: технические характеристики, распиновка, схемы подключения к ESP32, документация и примеры кода для Arduino, ESP-IDF, ESPHome.

Окружающая среда UART PWM

Обзор

MH-Z19 — это высокоточный датчик концентрации углекислого газа (CO₂), использующий технологию недисперсионного инфракрасного излучения (NDIR). Он идеально подходит для мониторинга качества воздуха в помещениях, системах вентиляции (HVAC) и теплицах. Датчик отличается высокой избирательностью, стабильностью и длительным сроком службы.

MH-Z19 — это инфракрасный датчик для измерения уровня CO₂. Он поддерживает интерфейсы UART и PWM, имеет встроенную температурную компенсацию и позволяет обнаруживать концентрацию газа до 2000 ppm (опционально до 5000 ppm).

Датчик MH-Z19

О датчике CO₂ MH-Z19 (NDIR)

MH-Z19 — это инфракрасный (NDIR) датчик, разработанный для точного измерения концентрации углекислого газа. Благодаря технологии NDIR датчик обладает высокой чувствительностью, длительным сроком службы и устойчивостью к влиянию других газов.

Ключевые особенности

  • Технология NDIR – Обеспечивает точное обнаружение CO₂ с минимальными помехами.
  • Гибкие интерфейсы – Поддержка UART и PWM для связи с микроконтроллерами.
  • Стабильность и долговечность – Надежное решение для систем непрерывного мониторинга.
  • Идеально для умных систем – Широко применяется в HVAC, теплицах и бытовых мониторах воздуха.

Для обнаружения летучих органических соединений (VOC) рассмотрите также датчик CCS811, который измеряет TVOC и eCO₂. 🚀

Где купить

Приобретите MH-Z19

Технические характеристики

Характеристики MH-Z19

Основные технические параметры датчика MH-Z19 для мониторинга CO₂.

Интерфейсы
UART, PWM
Точность
±50 ppm + 5% от показаний
Диапазон
0 – 2000 ppm (до 5000)
Питание
3.6В – 5.5В (макс 18 мА)
Скачать полный даташит
Конфигурация пинов

Распиновка MH-Z19

Интерфейс MH-Z19 обычно состоит из 9 выводов, поддерживающих связь по UART и опциональный выход PWM.

Визуальная диаграмма распиновки
Основное вид сверху
Распиновка MH-Z19
Всего выводов
9
Типы
UART + PWM
Быстрые советы
  • Технология NDIR — Высокая точность для CO₂.
  • Компенсация — Встроенная температурная компенсация.
  • Калибровка — Пин HD предназначен для установки «нуля» (400ppm).
Описание выводов
Название Тип Описание Примечания
1 Vout Питание Выход 3.3В (макс 10мА) Не для питания ESP32!
2 RXD UART Вход приема UART (3.3В) К пину TX микроконтроллера
3 TXD UART Выход передачи UART (3.3В) К пину RX микроконтроллера
4 SR Зарезервировано Заводской пин Не подключать
5 HD Калибровка Калибровка нуля Заземлить на >7с в свежем воздухе
6 Vin Питание Вход питания (3.6В–5.5В) Рекомендуется 5В
7 GND Земля Подключение земли Общая земля
8 AOT Зарезервировано Заводской пин Не подключать
9 PWM PWM Выход ШИМ сигнала Альтернатива UART
Руководство по подключению

Подключение MH-Z19 к ESP32

Для обмена данными через UART подключите Vin к 5V, GND к земле, TXD датчика к RX2 ESP32 (GPIO16), а RXD датчика к TX2 ESP32 (GPIO17).

Схема подключения
Рекомендуемая (UART)
Схема подключения MH-Z19 к ESP32
Подключений
5
Статус
4 обязательных
Протокол
UART
Соединения выводов
Вывод MH-Z19 Связь Вывод ESP32 Описание
Pin 6 (Vin) ОБЯЗАТЕЛЬНО 5V Питание 5В для лучшей стабильности
Pin 7 (GND) ОБЯЗАТЕЛЬНО GND Общая земля
Pin 3 (TXD) ОБЯЗАТЕЛЬНО GPIO 16 (RX2) Датчик передает данные CO₂
Pin 2 (RXD) ОБЯЗАТЕЛЬНО GPIO 17 (TX2) Датчик получает команды
Pin 5 (HD) ОПЦИОНАЛЬНО Любой GPIO Только для ручной калибровки нуля
🕒 Прогрев: 3+ минуты после включения 📍 Калибровка: свежий воздух (~400ppm) ⚡ Логика: 3.3В (совместимо с ESP32) 🔌 Питание: требуется стабильное 5В
Помощь и поддержка

Устранение неполадок MH-Z19

Распространенные проблемы при работе с датчиком и способы их решения.

Ошибка инициализации датчика
Invalid preamble from MHZ19

Проблема: Микроконтроллер не получает корректных данных от датчика.

Решение: Проверьте правильность подключения пинов TX и RX (они должны быть перекрещены: TX датчика к RX контроллера). Убедитесь, что датчик получает стабильное питание 5В (не 3.3В). Проверьте скорость UART (обычно 9600).

Постоянные высокие показания (5000 ppm)
Датчик застыл на максимуме

Проблема: Сенсор выдает 5000 ppm даже при проветривании.

Решение: Проведите «нулевую» калибровку. Оставьте датчик включенным на чистом воздухе не менее чем на 20 минут, затем кратковременно (на 7+ секунд) замкните пин HD на землю. Либо отправьте команду калибровки через UART.

Медленное обновление данных
Показания меняются неохотно

Замечание: Датчик имеет физическую инерцию, так как газ должен диффундировать в камеру.

Совет: Не опрашивайте датчик чаще чем раз в 2–5 секунд. Время отклика T90 составляет менее 120 секунд.

Примеры программирования

Примеры кода для MH-Z19

Готовые примеры реализации для различных платформ.

Arduino
Arduino IDE
Базовый пример UART (SoftwareSerial)
C++
```cpp #include

// Создаем объект для работы с UART на пинах 10 (RX) и 11 (TX) SoftwareSerial mySerial(10, 11);

void setup() { Serial.begin(9600); mySerial.begin(9600); }

void loop() { // Команда для чтения данных: заголовок, номер команды (0x86), пустые байты и чексумма byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; mySerial.write(cmd, 9); delay(500);

if (mySerial.available()) {
    byte response[9];
    mySerial.readBytes(response, 9);
    // Проверяем преамбулу и команду
    if (response[0] == 0xFF && response[1] == 0x86) {
        // Расчет концентрации: (High_Byte * 256) + Low_Byte
        int CO2 = (response[2] << 8) + response[3];
        Serial.print("Концентрация CO2: ");
        Serial.print(CO2);
        Serial.println(" ppm");
    }
}
delay(2000);

}

      <p class="mt-4 text-sm text-slate-600 dark:text-slate-400 leading-relaxed !mb-0">
        Этот скетч отправляет команду запроса данных через SoftwareSerial. Концентрация CO₂ рассчитывается на основе байтов ответа и выводится в монитор порта каждые 2.5 секунды.
      </p>
    </div>
  </details>

  <div id="esp-idf"></div>
  <details class="group border border-slate-200 dark:border-slate-800 rounded-2xl bg-white dark:bg-slate-900 overflow-hidden [&_summary::-webkit-details-marker]:hidden">
    <summary class="flex items-center gap-4 p-4 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors w-full outline-none">
      <img src="/img/32WN7tz--V-40.png" alt="ESP-IDF" class="w-10 h-10 object-contain shrink-0" loading="lazy" />
      <div class="flex-1 text-left min-w-0">
        <div class="font-bold text-slate-900 dark:text-slate-100 text-base leading-tight">ESP-IDF</div>
        <div class="text-xs text-slate-500 dark:text-slate-400 leading-tight">Нативный фреймворк Espressif</div>
      </div>
      <div class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-bold bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300">C</div>
      <div class="ml-2 p-1 rounded-xl bg-slate-100 dark:bg-slate-800">
        <svg class="w-5 h-5 text-slate-400 transition transform group-open:rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" /></svg>
      </div>
    </summary>
    <div class="p-4 border-t border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-900/50">
```c
#include <stdio.h>
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define UART_NUM UART_NUM_1
#define TXD_PIN (GPIO_NUM_17)
#define RXD_PIN (GPIO_NUM_16)

void app_main(void) {
    const uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_param_config(UART_NUM, &uart_config);
    uart_set_pin(UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
    uart_driver_install(UART_NUM, 256, 0, 0, NULL, 0);

    uint8_t cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
    uint8_t response[9];

    while (1) {
        uart_write_bytes(UART_NUM, (const char *)cmd, 9);
        vTaskDelay(pdMS_TO_TICKS(500));
        int len = uart_read_bytes(UART_NUM, response, 9, pdMS_TO_TICKS(1000));
        if (len == 9 && response[0] == 0xFF && response[1] == 0x86) {
            int CO2 = (response[2] << 8) | response[3];
            printf("CO2: %d ppm\n", CO2);
        }
        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}
  <p class="mt-4 text-sm text-slate-600 dark:text-slate-400 leading-relaxed !mb-0">
    Пример конфигурации UART для ESP-IDF. Код опрашивает MH-Z19 и выводит результат в консоль каждую итерацию цикла.
  </p>
</div>
ESPHome
ESPHome
Конфигурация для Home Assistant
YAML
```yaml uart: tx_pin: GPIO17 rx_pin: GPIO16 baud_rate: 9600

sensor:

  • platform: mhz19 co2: name: “MH-Z19 CO2” temperature: name: “MH-Z19 Температура” update_interval: 60s
      <p class="mt-4 text-sm text-slate-600 dark:text-slate-400 leading-relaxed !mb-0">
        Простая интеграция MH-Z19 в ESPHome. Поддерживает чтение уровня CO₂ и приблизительной температуры сенсора.
      </p>
    </div>
  </details>

  <div id="micropython"></div>
  <details class="group border border-slate-200 dark:border-slate-800 rounded-2xl bg-white dark:bg-slate-900 overflow-hidden [&_summary::-webkit-details-marker]:hidden">
    <summary class="flex items-center gap-4 p-4 cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800/50 transition-colors w-full outline-none">
      <img src="/img/U_FT8ja_jJ-40.png" alt="MicroPython" class="w-10 h-10 object-contain shrink-0" loading="lazy" />
      <div class="flex-1 text-left min-w-0">
        <div class="font-bold text-slate-900 dark:text-slate-100 text-base leading-tight">MicroPython</div>
        <div class="text-xs text-slate-500 dark:text-slate-400 leading-tight">Удобство Python на микроконтроллерах</div>
      </div>
      <div class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-bold bg-indigo-100 text-indigo-700 dark:bg-indigo-900/40 dark:text-indigo-300">Python</div>
      <div class="ml-2 p-1 rounded-xl bg-slate-100 dark:bg-slate-800">
        <svg class="w-5 h-5 text-slate-400 transition transform group-open:rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" /></svg>
      </div>
    </summary>
    <div class="p-4 border-t border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-900/50">
```python
from machine import UART, Pin
import time

# Настройка UART порта
uart = UART(2, baudrate=9600, tx=Pin(17), rx=Pin(16))
# Байты команды запроса данных
cmd = bytearray([0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79])

def read_co2():
    uart.write(cmd)
    time.sleep(0.1)
    if uart.any():
        response = uart.read(9)
        if len(response) == 9 and response[0] == 0xFF and response[1] == 0x86:
            # Превращаем два байта в число ppm
            co2 = (response[2] << 8) | response[3]
            return co2
    return None

while True:
    val = read_co2()
    if val is not None:
        print(f"CO2 Concentration: {val} ppm")
    else:
        print("Ошибка чтения")
    time.sleep(2)
  <p class="mt-4 text-sm text-slate-600 dark:text-slate-400 leading-relaxed !mb-0">
    Python скрипт для циклического опроса MH-Z19 через аппаратный UART ESP32.
  </p>
</div>

Итоги

MH-Z19 — это отличный выбор для тех, кому нужны надежные и точные показания уровня СО₂ без ложных срабатываний на другие газы. Использование технологии NDIR делает его заметно надежнее дешевых полупроводниковых аналогов.

Рекомендации
  • Используйте 5В для стабильной работы инфракрасной лампы.
  • Не забывайте о времени прогрева (мин. 3 минуты).
  • Проводите калибровку раз в несколько месяцев для высокой точности.
Безопасность
  • Не допускайте попадания влаги и конденсата.
  • Избегайте сильных механических вибраций.
  • Не подключайте пины калибровки к питанию.

Готовы собрать свой монитор воздуха?

Интегрируйте MH-Z19 в свой проект на ESP32 и узнайте точно, когда пора проветрить комнату!

Похожие варианты датчиков

Просмотрите другие популярные датчики качества воздуха и газа для ваших проектов.