- PVSM.RU - https://www.pvsm.ru -

Практический опыт использования Blynk для датчика СО2. Часть 1

Всем привет. Это еще одна статья из разряда ESP8266 + Blynk = . Прошу не воспринимать как рекламу, а только как дань уважения разработчикам платформы Blynk и личный опыт, который может быть полезен кому то еще, кроме меня.

Начало

Идея проекта родилась несколько лет назад, когда в порыве DYI-энтузиазма на Ali был куплен датчик качества воздуха MQ-135. По спецификации этот датчик реагирует на наличие в воздухе таких веществ как: NH3, NOx, спирт, бензин, дым и CO2 и выдает свою абстрактную оценку качества воздуха на аналоговом выходе [да я знаю, что существуют подстроечные резисторы и способы калибровки, но как то это слишком сложно].
Испытания показали, что на всякие вредные и «вонючие» соединения датчик реагирует отлично, показывая достаточно резкое изменение выходного уровня. Хуже дело обстояло с определением невидимого врага, а именно углекислого газа СО2. Про вред и очевидную повсеместность этого диоксида сказано немало, повторяться не будем.
Практический опыт использования Blynk для датчика СО2. Часть 1 - 1

Поэтому для меня, датчик MQ-135 оказался бесполезным, поскольку не мог «заметить» существенную разницу в качестве воздуха в переполненном людьми помещении и на свежем воздухе. Но вызов был уже принят, поэтому несколько итераций спустя родилась последняя (текущая) версия платы OpenWindAir с ИК-датчиком MH-Z19 [да не идеальный, да китайский]. Подробнее про получившуюся железку и ее аппаратные возможности написано в статье Система сбора данных на ESP. Часть I [1].
Для задачи измерения уровня углекислого газа в жилом помещении датчик оказался идеальным и оптимальным по цене (1200 рублей на Ali с доставкой) решением.

Blynk — помогает соединить железо, облако и телефон

Про платформу Blynk уже много хорошего сказано, например тут [2]. Возможности платформы просто удивляют своей продуманностью и удобством использования. Поэтому когда пришло время выбирать среду разработки для ESP8266 и писать программу, выбор сразу пал на Arduino IDE и библиотеку Blynk.
Запуск тестового скетча BlynkSimpleEsp8266, не вызвал никаких проблем. Однако по мере усложнения и наращивания функционала — пришлось столкнуться с некоторыми трудностями, о которых и хочется рассказать подробнее.
Практический опыт использования Blynk для датчика СО2. Часть 1 - 2

Архитектура ПО

Главный плюс разработки ПО под ESP8266 в среде Arduino IDE – что можно совместить в одном скетче совершенно разные библиотеки и вам за это почти ничего не будет.
Перед началом разработки ТЗ было сформулировано тезисно и включало следующие пункты:

1. Необходимо с определенным интервалом считывать показания датчика CO2 (MH-Z19) и отображать результаты с помощью трех (зеленый, желтый, красный) светодиодов. Пределы были выбраны почти с учетом ГОСТ 30494-2011 (Здания жилые и общественные. Параметры микроклимата в помещениях.): до 900 PPM – зеленый, от 901 до 1400 PPM — желтый, выше 1401 PPM — красный. Также у нас есть бипер, порог бибикания которого задан на уровне 1100 PPM, но его можно настроить или вообще отключить через Blynk. Во время отладки выяснилось, что иногда MH-Z19 может глюкануть и выдать свое максимальное значение (в зависимости от установленного предела: 1000, 2000, 3000 или 5000 PPM), вместо фактически измеренного. Это немного осложнило обработку результатов и могло привести к ложным сообщениям пользователю, а нервы пользователя надо беречь. И поскольку нет абсолютно верного (кроме многократных измерений) способа отличить неверно измеренные 2000 PPM (дикое значение для жилого помещения) от ситуации, когда пользователь сидит и специально дышит в датчик. То было принято две меры по маскировке данной проблемы: установлен предел измерения в 2000 PPM (предполагается использование прибора в жилых помещениях и все что больше 1400 для нас уже красная зона) и добавлено усреднение результатов последних 10 измерений. Как итог — единичные ложные срабатывания (на 2000 PPM) не дают больших всплесков на усредненном графике. Но при желании через Blynk можно настроить предел измерения датчика и посмотреть фактическое (не усредненное значение CO2).

2. Для работы с датчиком температурывлажности (AM2302) была использована библиотека DHT Sensor Library от Adafruit. Было сделано два небольших изменения: добавил повторное считывание AM2302 (иногда считывается не с первого раза) и введены поправочные коэффициенты для значений температуры и влажности. Если используется встроенный датчик, то опытным путем установлено, что воздух внутри прибора «суше» на 15% и теплее на 2 градуса C (1 градус F) чем снаружи, при использовании выносного датчика (выбирается джампером) — поправку в измеренные результаты вносить не надо и можно отключить.

3. Пользователь должен иметь возможность настроить устройство (подключиться к WiFi, указать auth token и тд) без дополнительного софта или перепрошивки. Наиболее оптимальным решением стало использование библиотеки WiFiManager, которая переводит ESP в режим точки доступа и позволяет через Captive портал сохранить во флешку настройки WiFi сети и другие параметры.
Практический опыт использования Blynk для датчика СО2. Часть 1 - 3
В дальнейшем при старте библиотека пытается подключится к сохраненной WiFi точке и в случае неудачи снова переходит в режим точки доступа и Captive портала. А если пользователь вдруг не захочет использовать Blynk или у него не окажется WiFi-роутера, то в этом случае OpenWindAir никогда на загрузится и будет только стартовать в AP-режиме и перезагружаться по таймауту. Выход из этой безвыходной ситуации был найден следующий, если у нас сохранены ненулевые параметры подключения к Blynk или MQTT серверу, значит при старте будем пытаться подключиться и перезагружаться, в противном случае — можем и не подключаться к WiFi, а работать оффлайн.

if (!wifiManager.autoConnect("OpenWind - tap to config")){
if (mqtt_server[0] != '' || blynk_token[0] != ''){
Serial.println("Failed to go online for Blynk and MQTT, restarting..");
ESP.restart();
}
else{
Serial.println("Failed to go online, offline mode activated");
online = false;
}

4. Blynk требует подключения к Интернету (если сервер не локальный) и поэтому необходимо контролировать наличие подключения к WiFi. Библиотека WiFiManager на данный момент не умеет восстанавливать соединение с WiFi и если в квартире «моргнет» свет и роутер перезагрузится, то восстановить подключение ESP8266 к WiFi поможет только перезагрузка. Поэтому пришлось добавить простой таймер, который через 60 непрерывных секунд отсутствия коннекта перезагрузит устройство.

if (WiFi.status() != WL_CONNECTED && online){
if (!wifilost_flag){
wifilost_timer_start = uptime;
wifilost_flag = true;
}
if (((uptime - wifilost_timer_start) > wifilost_timer_max) && wifilost_flag){
Serial.print("nrWiFi connection lost, restarting..");
wifilost_flag = false;
ESP.restart();
}
}

5. В качестве альтернативы использования Blynk пользователь может выбрать отправку показаний по протоколу MQTT на сервер Народного мониторинга [3] или любого другого подобного сервиса. Для этих целей была выбрана библиотека PubSubClient, которая написана на наиболее понятном мне языке Си и единственная (из представленных в каталоге Arduino IDE), которая имела понятные примеры.

6. Перепрошивка устройства дело хоть и не частое и не очень сложное (особенно при наличии встроенного CP2102), но все равно захотелось максимально упростить этот процесс. Библиотека ArduinoOTA позволяет легко загрузить новый бинарник и прошить его. Активировать ОТА можно как кнопкой на устройстве, так и удаленно через телефон. Однако без сюрпризов не обошлось, оказывается мной были куплены модули ESP8266-12E с разным размером файловой системы (SPIFFS).

Примерное распределение Flash
Практический опыт использования Blynk для датчика СО2. Часть 1

Внешне не отличимые модули ESP8266-12E могут иметь файловую систему размером 1 или 3 Мб и требовать разные прошивки (опции сборки в Arduino IDE). Поэтому, чтобы избежать возможных проблем, при загрузке надо проверять фактический размер памяти и при ОТА апгрейде запрашивать на сервере соответствующий бинарник (пока не сделано). Или можно пойти чуть более простым путем и собирать все прошивки под SPIFFS c меньшим номиналом 1 Мб, т. к. они вполне работают на ESP8266-12E c большим объемом памяти.
Для таких проверок в SDK есть удобные функции позволяющие определить размер фактической и выбранной в IDE памяти.

String realSize = String(ESP.getFlashChipRealSize());
String ideSize = String(ESP.getFlashChipSize());
bool flashCorrectlyConfigured = realSize.equals(ideSize);

if(flashCorrectlyConfigured){
Serial.println("flash correctly configured, SPIFFS starts, IDE size: " + ideSize + ", match real size: " + realSize);
}
else{
Serial.println("flash incorrectly configured, SPIFFS cannot start, IDE size: " + ideSize + ", real size: " + realSize);
}

7. Чтобы самому не путаться в разных версиях ПО и отличать их друг от друга, был немного переписан файл arduino-1.8.5hardwareplatform.txt от Arduino IDE так, чтобы во время компиляции запускался bat файл, который делает копию текущего скетча и полученного бинарника, а также автоматически инкрементирует номер версии.

recipe.hooks.sketch.prebuild.0.pattern=D:arduino-1.8.5hardwareincrement.bat {build.path} {build.source.path} {build.project_name}

Таким образом, после каждой сборкипрошивки имеем зашитый в бинарнике номер версии и копию скетча с таким же номером. А если папку со скетчем положить в Dropbox — то получится самодельная система контроля версий.

Инструкция по настройке автоинкремента версии для Arduino IDE и bat-файл выложены на гитхабе.

8. Ну а раз есть встроенный USB-UART переходник (с драйвером для CP2102 нет никаких проблем в Windows и Linux), то нельзя было не добавить вывод результатов измерений через Терминал (на скорости 9600). Раз в двадцать секунд выводятся результаты измерений и сообщения об ошибках.

Reading MHZ19 sensor: ok
Reading DHT22 sensor: ok
===================================================

Humidity: 36.20%
Temperature: 27.20C 83.56F
C02: 1153 ppm
C02 average: 462 ppm
ADC: 99
UpTime: 0 days, 0 hours, 3 minutes, 45 seconds.
Time: 16:25:56 20/3/2018
===================================================

А по нажатию кнопки Enter можно получить сообщение с системной информацией.
======SYSTEM-STATUS================================
Device name: OpenWindAir
Software version: 0.1.235
FreeHeap: 33824
ChipId: 13704617
FlashChipId: 1405167
FlashChipSize: 4194304
FlashChipSpeed: 40000000
CycleCount: 2204474679
Time: 16:27:6 20/3/2018
UpTime: 295
======BLYNK-STATUS=================================
Blynk token: 65a99f9e363a421c8b22d5b0162cce27
Blynk connected: 1
Notify level: 1100
Beep: 1
CO2 limit: 2000
Temperature correction: 1
======NETWORK-STATUS===============================
WiFi network: adakta2
WiFi status: 3
RSSI: -70
MAC: 18FE34D11DA9
IP: 192.168.0.152
Online: 1
======MQTT-STATUS==================================
MQTT server:narodmon.ru
MQTT port:1883
MQTT login:login
MQTT key:key
MQTT topics:
/OpenWindAir/h
/OpenWindAir/t
/OpenWindAir/f
/OpenWindAir/ppm
/OpenWindAir/status
======END-of-STATUS================================

Самая неприятная проблема

Самое неприятное с чем пришлось столкнуться при разработке, это когда при одновременной отправке результатов измерений на сервер MQTT и в Blynk, часть данных может начать теряться и не доходить до сервера. Как оказалось, на то, чтобы подключиться к серверу MQTT и отправить данные — может понадобиться несколько секунд и за это время библиотека Blynk успевает потерять соединение со своим сервером и в результате если вручную не инициировать переподключение к серверу — может пройти достаточно много времени и часть результатов измерений потеряется. Пришлось добавить проверку состояния WiFi клиента _blynkWifiClient и случае отсутствия коннекта делать принудительный стоп _blynkWifiClient.stop(), а потом подключаться к серверу Blynk заново.

if (WiFi.status() == WL_CONNECTED){
wifilost_flag = false;
if (blynk_token[0] != ''){
if (Blynk.connected() && _blynkWifiClient.connected()){
Blynk.run();
}
else{
Serial.print("nrReconnecting to blynk.. ");
Serial.print(Blynk.connected());
if (!_blynkWifiClient.connected()){
 _blynkWifiClient.stop();
 Return _blynkWifiClient.connect(BLYNK_DEFAULT_DOMAIN, BLYNK_DEFAULT_PORT);
}
Blynk.connect(4000);
Serial.print(Blynk.connected());
}
}

Заключение

Это моя первая статья, хотя с момента регистрации на Хабре прошло уже 7 лет. Прошу не судить очень строго и не обращать внимание на говнокод, который пока является единственным языком программирования, которым я владею.
Ознакомиться с проектом целиком можно в репозитории на гитхабе [4].
Наличие датчика CO2 не дает мне (и моей семье) лишний раз засиживаться в душной комнате. Но самое главное он прекратил вечную войну между лагерями тех кому жарко и тех кому дует (это был я), в пользу первых.

Далее будет QR код, просканировав который приложением Blynk (AppSore [5], Android [6]) можно узнать, какой микроклимат был у меня дома последние 3 месяца.
Практический опыт использования Blynk для датчика СО2. Часть 1 - 4
Проект работает, прошу ничего не ломать.

Автор: Захаренков Алексей

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/programmirovanie/275817

Ссылки в тексте:

[1] Система сбора данных на ESP. Часть I: https://geektimes.ru/post/298211/

[2] тут: https://geektimes.ru/post/268482/

[3] Народного мониторинга: http://narodmon.ru

[4] в репозитории на гитхабе: https://github.com/zaharenkov/openwindair

[5] AppSore : https://itunes.apple.com/us/app/blynk-control-arduino-raspberry/id808760481?ls=1&mt=8

[6] Android: https://play.google.com/store/apps/details?id=cc.blynk

[7] Источник: https://geektimes.ru/post/122601/?utm_campaign=122601