Датчик углекислого газа 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.