Андрей Овчаров

маленькое невинное хобби

Датчик углекислого газа MH-Z19b

Разбирая свои закрома радиодеталей наткнулся на любопытный модуль - MH-Z19b. Это простенький датчик уровня углекислого газа. Немножко поковырявшись в интернете, выяснил его возможности:

  • Питание +5в, можно кормить любой зарядкой для мобильного
  • Данные можно снимать через последовательный порт
  • Диапазон измерения - до 5000ppm

На свежем воздухе концентрация углекислого газа составляет примерно 400ppm, но может зависить от множества факторов. В помещении нормальным считается содержание углекислого газа до 800ppm. Если концентрация превышает 1000ppm, то появляется чувство усталости. При концентрации выше 1400ppm голова станет ощутимо ватной.

Попробую на базе этого датчика собрать простой сигнализатор качества воздуха.

Прототип

В качестве “мозга” устройства будет полюбившийся мне в последнее время ESP8266. Для подключения достаточно всего четырёх проводов, значит можно использовать самую простую версию - ESP-01. В качестве основы всей конструкции - макетная плата, несколько разъёмов и немного провода.

исходные модули

Разъёма питания на макетке не предусмотрено, но в закромах нашлась старая плата с припаянными Micro USB разъемом и регулятором напряжения на 3.3в. То, что надо. Отпилил всё лишнее и прикрутил к макетке двумя винтами М2.

Схема подключения тривиальная. Если нигде не напутать, то заработает сразу.

схема устройства

Резисторы по 10К, конденсаторы на питание я проигнорировал - прототип, все-таки.

собранный прототип

Программа

Программировалось всё на обычной Ардуине, благо там есть гора уже готовых библиотек. Первым делом в скетч был добавлена возможность загрузки микропрограммы через WiFi - чтобы не переключать постоянно модуль между программатором и датчиком, называется Arduino OTA. Кстати, обновляется так гораздо быстрее чем через UART.

Для получения данных с датчика библиотека тоже есть, но её я не использовал - там и так всего несколько строк:

SoftwareSerial co2(0, 2);

void setup() {
  // ...
  co2.begin(9600);
}

int co2ppm() {
  static byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  static byte response[9] = {0};

  co2.write(cmd, 9);
  co2.readBytes(response, 9);

  unsigned int responseHigh = (unsigned int) response[2];
  unsigned int responseLow = (unsigned int) response[3];

  return (256 * responseHigh) + responseLow;
}

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

Сбор данных

Для сбора данных у меня сейчас используется валявшийся ранее без дела микрокомпьютер Raspberry PI. На него был установлен брокер протокола MQTT mosquitto с конфигурацией по умолчанию. Внутри локальной домашней сети это достаточно безопасно, да и ничего приватного там все равно нет.

Установка элементарная:

sudo apt-get update
sudo apt-get install mosquitto

Все настройки - по умолчанию, этого достаточно для домашней сети. Единственный важный момент - надо настроить роутер так, чтобы у малинки был статический IP адрес.

После этого малинка готова к приему циферок от датчика. Надо только установить библиотеку PubSubClient.

В программу добавилось следующее:

#include <PubSubClient.h>

const char* mqtt_server = "192.168.178.29";

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  // ...
  client.setServer(mqtt_server, 1883);
}

void loop() {
  // ...
  static char msg[250];
  snprintf (msg, 250, "co2 ppm=%d", co2ppm());
  client.publish("sensor/co2", msg);
}

Данные отправляются в формате InfluxDB - это пригодится на следующем шаге.

Хранение истории для анализа

Хранятся данные в InfluxDB. Это специальная база данных для записей, упорядоченных по времени. Самое то для истории показаний разных датчиков.

Установка немножко более замороченная, потому что хочется последнюю версию от разработчиков:

curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
echo "deb https://repos.influxdata.com/debian stretch stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
sudo apt install influxdb telegraf

Все настройки тоже по умолчанию, только нужно добавить конфигурацию для импорта данных из mosquitto в InfluxDB:

Файл /etc/telegraf/telegraf.d/sensors.conf

[[inputs.mqtt_consumer]]
  servers = ["tcp://localhost:1883"]
  topics = [
    "sensor/co2"
  ]

[[outputs.influxdb]]
urls = ["http://127.0.0.1:8086"]
database = "sensors"

Получаем данные из mosquitto, отправляем в influxdb.

Таким образом в базе данных sensors появятся показания нашего датчика.

Визуализация

Красивые динамичные графики рисует пакет Grafana.

Установка, тоже последняя версия:

curl https://bintray.com/user/downloadSubjectPublicKey?username=bintray | sudo apt-key add -
echo "deb https://dl.bintray.com/fg2it/deb jessie main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt install grafana

После этого можно окрыть в браузере страницу http://<адрес малинки>:3000/ и настроить источник данных (InfluxDB) и панель с графиками. В результате можно сделать вот такую красоту:

график уровня углекислого газа

Результаты прототипирования

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

Где-то неделю я наблюдал за графиками. Показания, может и не точные, но представление о свежести воздуха дают. При закрытых окнах концентрация медленно растет и за несколько часов добирается до 1000ppm, что, действительно, субъективно ощущается как чувство усталости и потери внимания. Если проветрить - опять опускается до 400-500ppm и становится ощутимо легче.

Результаты работы прототипа мне понравились и я решил собрать устройство более качественно - на нормальной печатной плате.

Второй прототип

Плату развёл, как обычно, в Eagle CAD и заказал у JLCPCB. Десяток плат стоит всего $2, что вполне доступно. Изготовление и доставка заняли порядка трёх недель.

Для уменьшения габаритов датчик припаян “вверх ногами”. Под ним располагается преобразователь напряжения на 3.3V, с другой стороны платы - модуль ESP8266 ESP-12e и, по желанию, датчик температуры и влажности DHT22. На свободном месте - трёхцветный светодиодный модуль WS2812b для простой индикации. Для питания - разъем USB, можно воткнуть напрямую в любой блок питания с выходом USB. Получилось весьма просто и компактно.

собранное устройство
собранное устройство

Разъема для программирования на плате нет. Я подпаял провода напрямую к ESP8266 и залил туда минимальную прошивку, которая подключается к домашней сети WiFi и включает режим обновления прошивки по сети.

Индикация

На плате распаян трехцветный светодиодный модуль WS2812b, а в прошивку была добавлена библиотека WS2812FX для различных цветовых и световых эффектов. Показания датчика сохраняются в массив, по которому высчитывается среднее за последние пару минут значение - это позволяет сглаживать небольшие колебания концентрации CO2.

При нормальной концентрации устройство медленно и неярко “дышит” зелёным светом, когда концентрация начинает превышать 1000ppm, то начинает более ярко и настойчиво моргать жёлтым, а при концентрации более 1400ppm резко вспыхивает красным на полной яркости.

Вполне наглядно и удобно. А вот так устройство выглядит на рабочем столе в розетке со встроенным USB блоком питания:

собранное устройство

Исходные файлы проекта

Исходные файлы проекта - схема, файлы Gerber для производства печатных плат и исходные коды для Arduino лежат в репозитории на GitHub - https://github.com/snakeye/co2-sensor.