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

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

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

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

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

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

На свежем воздухе концентрация углекислого газа составляет примерно 400ppm, но может зависеть от множества факторов.

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

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

Прототип

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

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

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

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

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

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

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

Программа

Программировалось на Ардуино, благо там есть гора уже готовых библиотек, но при помощи PlatformIO - среда разработки гораздо удобнее.

Первым делом в скетч был добавлена возможность загрузки микропрограммы через 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 адрес, а если можно - то и имя прописать в DNS.

После этого малинка готова к приему циферок от датчика. Надо только установить библиотеку 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 для различных цветовых и световых эффектов. Показания датчика сохраняются в массив, по которому высчитывается среднее за последние пару минут значение - это позволяет сглаживать небольшие колебания концентрации.

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

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

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

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

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