Обзор инфракрасного датчика CO2 MH-Z19

от автора

В последнее время популярны гаджеты, показывающие уровень CO2, равно как и статьи, рассказывающие как монитор CO2 можно превратить в подключенный к компьютеру датчик. Я хочу показать решение задачи с другой стороны.

В отличие от старых датчиков CO2, MH-Z19 не требует специфического напряжения или высокой мощности и умеет передавать данные через UART и PWM.


  • Hd — калибровка нуля начнется, если на Hd более 7 секунд подается LOW. Калибровку проводить не нужно.
  • SR — не используется
  • Tx — уровень сигнала — 3.3В
  • Rx — тоже 3.3В (работает и с 5В, но я бы не рекомендовал)
  • Vo — выходное напряжение 3.3В, не более 10мА

  • PWM, данные снимаются так — длина цикла 1004мс. Первые 2мс всегда HIGH, последние — всегда LOW, а «середина» пропорциональна концентрации CO2 в пределах 0 — 5000ppm (а не 2000ppm как в документации).
    Cppm = 2000 * (Thigh — 2ms)/(Thigh + Tlow — 4ms)
    Отмечу, что PWM — штука очень капризная, требующая аккуратной пайки и 3.3В.
  • AOT — не используется
  • Gnd — земля
  • Vin — напряжение питания 3.6 — 5.5В (сенсор работает и выдает те же значения при питании 3.3В, но производитель настоятельно рекомендует придерживаться рамок)

Не то, чтобы я не доверял PWM, но лучше получать данные в цифре и с контрольной суммой. UART позволяет запрашивать уровень концентрации CO2 и заниматься двумя видами калибровки. Оставим калибровку Гаррусу и рассмотрим запрос данных. Для этого на скорости 9600 (8 bit, stop — 1, parity — none) нужно отправить следующие девять байт:
• 0xFF — начало любой команды
• 0x01 — первый сенсор (он всего один)
• 0x86 — команда
• 0x00 0x00 0x00 0x00 0x00 — данные
• 0x79 — контрольная сумма.

В ответ придет что-то такое:
• 0xFF — начало любого ответа
• 0x86 — команда
• 0x01, 0xC1 — старшее и младшее значение (256 * 0x01 + 0xC1 = 449)
• 0x3C, 0x04, 0x3C, 0xC1 — в документации сказано, что должно приходить что-то типа 0x47, 0x00, 0x00, 0x00, но на деле приходит непонятно что.
• 0x7B — контрольная сумма.

Контрольная сумма считается следующим образом: берутся 7 байт ответа (все кроме первого и последнего), складываются, инвертируются, увеличиваются на 1: 0x86 + 0x01… + 0xC1 = 0x85, 0x85 xor 0xFF = 0x7A, 0x7A + 1 = 0x7B.

Согласно документации сенсору требуется около трех минут, чтобы выйти на рабочий режим. Первое время после включения он будет выдавать или 5000ppm, или 400ppm. После особо усердной пайки может приходить в себя несколько часов.

Сенсор реагирует на изменение концентрации CO2 с задержкой около минуты. При превышении концентрации в 5000ppm (например, вы минуту интенсивно на него дышали), он некоторое время будет выдавать ложные данные, занижая уровень CO2 — я так получал даже 80ppm.

В документации это не отражено, но не стоит запрашивать данные по UART чаще раза в 10 секунд, иначе сенсор начинает выдавать что-то странное.

Пришло время картинок. Подключим сенсор к Arduino Uno через Software Serial, RX/TX в A0/A1, питание в 5В, землю — в Gnd:

Позаимствованный скетч, в который я добавил проверку контрольной суммы

#include <SoftwareSerial.h>;  SoftwareSerial mySerial(A0, A1); // A0 - к TX сенсора, A1 - к RX  byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};  unsigned char response[9];  void setup() {   Serial.begin(9600);   mySerial.begin(9600); }  void loop()  {   mySerial.write(cmd, 9);   memset(response, 0, 9);   mySerial.readBytes(response, 9);   int i;   byte crc = 0;   for (i = 1; i < 8; i++) crc+=response[i];   crc = 255 - crc;   crc++;    if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) {     Serial.println("CRC error: " + String(crc) + " / "+ String(response[8]));   } else {     unsigned int responseHigh = (unsigned int) response[2];     unsigned int responseLow = (unsigned int) response[3];     unsigned int ppm = (256*responseHigh) + responseLow;     Serial.println(ppm);   }   delay(10000); } 

Каждое измерение идет с интервалом 10 секунд. Значения перестали прыгать когда я отошел от сенсора.

Теперь сделаем датчик мобильным. Для этого потребуется устройство с OTG и приложение типа DroidTerm.
Тут есть тонкость: чтобы связь установилась — нужно перезагрузить Arduino.

Убедившись, что все работает, уберем Arduino, заменив его на FTDI FT232RL.

Питание на датчик стоит подавать уже после подключения чтобы не было проблем с соединением.
Для отправки бинарных данные через COM-порт я использую RealTerm:

Возможно, стоит добавить управление питанием через DTR, чтобы можно было перезапускать датчик.

Полезные ссылки:
Мануал по датчику MH-Z19
Схема подключения и код для PWM

У меня всего один датчик и я очень не люблю разбирать то, что однажды сделал, поэтому предлагаю выбрать вам.

Что сделать с датчиком?

Никто ещё не голосовал. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

ссылка на оригинал статьи https://geektimes.ru/post/272090/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *