Измеряем концентрацию CO2 в квартире с помощью MH-Z19. Рассказ о том как маленький датчик углекислого газа(co2) MH-Z19, расширил мое понимание об окружающем мире

Практически любая метеостанция, включая дешевые китайские модели за несколько долларов, умеет измерять основные параметры воздуха - температуру и влажность. С углекислым газом все сложнее: бытовых приборов, способных его измерять, практически нет в продаже. Усложняет ситуацию и то, что CO2 - газ без цвета и запаха, так что «носом» ощутить его концентрацию практически невозможно.

Подробности и измерения под катом.

Сам датчик MH-Z19 уже описывался здесь на сайте. За основу была взята статья "Обзор инфракрасного датчика CO2 ", а данный материал является его логическим продолжением. Про измерение концентрации CO2 на улице , однако данных о концентрации в квартире там не приводилось. Восполним этот пробел.

Железо

Первым делом на eBay были заказаны следующие компоненты:
- Arduino Micro ATmega32U4 3.3V (цена вопроса 5$). Т.к. датчик имеет 3-вольтовую логику, обычные Arduino лучше не использовать.
- OLED LCD-дисплей I2C 0.91«128x32 (цена вопроса 7$). Дисплей подключается к стандартным i2c-пинам Arduino.
- Собственно датчик MH-Z19 (цена вопроса 28$).
- Набор проводов с разъемами для штыревых контактов (цена вопроса 1-2$)
Таким образом, общая стоимость составила ~40$, или 2600р. Фирменный прибор от известной компании стоит примерно вдвое дороже, хотя здесь скорее вопрос не экономии, а технического интереса.

Код для Arduino был позаимствован из вышеприведенной статьи , в него был добавлен вывод данных на дисплей, а для более удобного анализа данных вывод был переделан в формат простой строки с разделителем. Также были добавлены метки времени, каждая соответствует 10 секундам.

Исходный код

#include #include // I2C OLED #include "SSD1306Ascii.h" #include "SSD1306AsciiWire.h" #define I2C_ADDRESS 0x3C SSD1306AsciiWire oled; // CO2 sensor: SoftwareSerial mySerial(8,9); // RX,TX byte cmd = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; unsigned char response; void setup() { // Serial Serial.begin(9600); mySerial.begin(9600); // OLED Wire.begin(); oled.begin(&Adafruit128x32, I2C_ADDRESS); oled.set400kHz(); oled.setFont(ZevvPeep8x16); oled.clear(); oled.println("setup::init()"); } long t = 0; 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++; oled.clear(); if (!(response == 0xFF && response == 0x86 && response == crc)) { Serial.println("CRC error: " + String(crc) + " / "+ String(response)); oled.println("Sensor CRC error"); } else { unsigned int responseHigh = (unsigned int) response; unsigned int responseLow = (unsigned int) response; unsigned int ppm = (256*responseHigh) + responseLow; Serial.print(String(t)); Serial.print(","); Serial.print(ppm); Serial.println(";"); if (ppm <= 400 || ppm > 4900) { oled.println("CO2: no data"); } else { oled.println("CO2: " + String(ppm) + " ppm"); if (ppm < 450) { oled.println("Very good"); } else if (ppm < 600) { oled.println("Good"); } else if (ppm < 1000) { oled.println("Acceptable"); } else if (ppm < 2500) { oled.println("Bad"); } else { oled.println("Health risk"); } } } delay(10000); t += 10; }


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

Конечно это не верх промышленного дизайна (в планах подыскать какой-то корпус), но для задачи показометра, способного работать как автономно, так и передавать данные по USB, устройство вполне справляется. Для получения данных по USB достаточно открыть в Arduino IDE монитор порта, в нем будут выводиться данные. Текст оттуда можно скопировать и открыть в любой программе, например в Excel.

Измерения

Следующий вопрос: что мы собственно измеряем? Устройство выдает данные в ppm (parts per million, частей на миллион). 1000 ppm = 0,1% содержания СО2. В интернете можно найти следующую таблицу допустимых концентраций:
- 350 - 450 ppm : Нормальный уровень на открытом воздухе.
- < 600 ppm : Приемлемые уровни. Уровень. рекомендованный для спален, детских садов и школ.
- 600 - 1000 ppm : Жалобы на несвежий воздух, возможно снижение концентрации внимания.
- 1000 ppm : Максимальный уровень стандартов ASHRAE (American Society of Heating, Refrigerating and Air-Conditioning Engineers) и OSHA (Occupational Safety & Health Administration).
- 1000 - 2500 ppm : Общая вялость, снижение концентрации внимания, возможна головная боль.
- 2500 - 5000 ppm : Возможны нежелательные эффекты на здоровье.

И наконец, результаты. Датчик был поставлен на кухне, окна металлопластиковые, время измерения около 8 часов.


Результаты оказались довольно-таки интересными. По горизонтали время в секундах, 3600 секунд соответствуют 1 часу.

Кривые на графике расшифровываются так:
0ч: показания около 420ppm (соответствуют уличным), дома никого не было, я пришел с работы и заодно включил датчик.
0-2 часа: я нахожусь на кухне, видно как в присутствии человека концентрация co2 медленно растет где-то до 900ppm.
2-4 часа: я ушел из помещения, видно как концентрация медленно спадает.
4-6 часов: я вернулся обратно, концентрация снова стала расти.
6й час: на плиту поставлена кастрюля с пельменями. Интересно видеть, как концентрация практически моментально увеличилась до 1700ppm, затем стала медленно спадать. Хотя газ горел недолго (минут 10-15) высокие уровни >1000 ppm держатся не менее часа.
Конец графика: было открыто окно, и уровень co2 упал практически сразу же.

Выводы

Устройство оказалось довольно-таки интересным, и особенно актуальным для работающих дома за компьютером. Так например, за время написания этой статьи уровень co2 вырос в помещении с 500 до 770ppm. Поглядывание на экран заставляет либо чаще открывать окно, либо наконец-таки задуматься об устройстве в доме нормальной вентиляции (наверное режим микропроветривания в окне был бы не лишним, а лучше какая-то вытяжка). Если бы я сейчас покупал новые окна, наверно задумался бы о более-менее качественной модели с нормальным проветриванием.

Также важно отметить актуальность хорошей вентиляции на кухне: как показывает график, даже за 10 минут одна газовая горелка может „выжечь“ весь запас кислорода, доведя концентрацию CO2 до весьма высокой. Измерения в спальне показали, что в плане вентиляции тоже все не очень хорошо: к утру концентрация co2 составляет более 1000ppm, а для умственного труда хороший сон это весьма актуально.

В общем, это нехитрое и недорогое устройство позволяет весьма эффективно проверить качество воздуха в квартире или офисе.
Автор желает всем хорошего здоровья и хорошего настроения. Ну и хорошего воздуха разумеется, тоже.

Вы когда-нибудь задавались вопросом, почему люди очень часто чувствуют себя сонными по утрам, вялыми в течении дня и такими уставшими и измотанными к вечеру? А ведь причина – вот она, под ногами! А точнее – в воздухе, которым мы дышим!

Что такое углекислый газ (CO 2) и каковы пределы его концентрации в помещении для хорошего самочувствия человека? CO 2 – бесцветный газ, без запаха, содержится в воздухе и выдыхается животными. Это нетоксичный газ, но превышение его концентрации в воздухе оказывает негативное влияние на здоровье человека . Измеряется в ppm (parts per million).

Качество воздуха в помещении описывается следующими факторами:

  • температура
  • влажность
  • запах
  • уровни концентрации различных газов

Поскольку люди выделяют углекислый газ в процессе дыхания, то концентрация CO 2 является одним из основных факторов, влияющих на качество воздуха.

Уровни концентрации CO 2 и их влияние на человека

Один из способов измерить уровень углекислого газа в воздухе – использовать arduino uno с инфракрасным датчиком MH-Z14.


Данный экземпляр детектирует CO 2 в диапазоне от 0 до 5000 ppm и соединяется с arduino по serial-интерфейсу (Tx и Rx). Напряжение питания 4-6V, максимальный ток достигает 100mA, но обычно держится в пределах <50mA. Желательно питать датчик не от самой arduino, а от отдельного источника питания, но для сборки прототипа этим можно пренебречь. Хочу заметить одно очень важное отличие в уровнях сигнала датчика и платы arduino:

  • arduino TX, RX – 5V
  • MH-Z14 TX, RX – 3.3V

Чтобы согласовать их сигналы, нам придется использовать конвертер логических уровней ().


Красная плата – конвертер логических уровней

Еще одно замечание: при некотором простое, датчику нужно время, чтобы “разогреться”. И это время составляет примерно 1 минуту; до этих пор датчик выдает 0 или какие-то нереальные значения.

Подключение


Примечание: HV – high voltage (5V), LV – low voltage (3.3V).



Что интересно, один человек, сидящий в комнате 3 часа с закрытыми окнами и дверью – повышает уровень CO2 с 450 ppm до 1800-1900 ppm (плохо!). Но если откинуть верхнюю часть одного окна стеклопакета, то через час концентрация снижается до <500 ppm (это супер) и держится на этом уровне (что и видно на фото с терминалом). 2 человека, проводящие ночь в одной комнате с закрытой дверью и окном, под утро повышают значение CO2 в комнате до >5000 ppm!

Вот и видео того, что получилось.

Заключение

Безусловно, полезная вещь, правда? Единственное, что дорогая… Хочу еще измерить уровень CO2 в маршрутке по пути на работу: иногда она так забивается, что реально нечем дышать, лицо краснеет и хочется вдохнуть глубже, потому что по ощущениям – не хватает воздуха. Как думаете, какая там набирается концентрация этого газа? =)

И до готового устройства ко всему выше неплохо было бы добавить:

  • DHT-11 (DHT-22) – датчик температуры и влажности, тоже показатель качества воздуха
  • MQ-2 – датчик взрывоопасных газов бутана и метана, а также дыма, вместе с какой-то пищалкой, чтобы не пропустить момент утечки газа или возгорание
  • дисплей LCD1602 или 2.4″ TFT экран, чтобы видеть результаты на экране, без подключения к компьютеру
  • блок питания, чтобы не зависеть от USB порта компьютера
  • корпус, что само собой красота и юзабилити
  • можно добавить модуль для работы с SD-карточками и часы реального времени и писать туда статистику, а потом перенести на компьютер и в excel построить графики; а можно приделать wifi / ethernet модуль и настроить на компьютере какой-нибудь веб сервер xampp , и записывать статистику туда
  • и, повторюсь, сделать питание датчика напрямую от блока питания (мимо платы arduino) – надежнее так…

Еще можно много чего прикрутить: реле, которое включит камин, если в комнате холодно; вытяжку/приток воздуха, когда в комнате становится душно; и так далее… но это уже тянет в области умных домов и выходит за рамки статьи! А мне остается пожелать…

Удачных вам экспериментов!

Все началось с того что я работаю в офисе, где как водится нет нормальной вентиляции, зато есть много народу половине которого все время жарко, а второй половине отчаянно дует.
Понятно что одного термометра для контроля воздуха в помещении недостаточно. Даже с кондиционером часто бывает прохладно, но душно. Спертый воздух. Оказалось на это больше всего влияет концентрация со2. Когда я узнал стоимость готовых приборов хотел от этой идеи отказаться. Но случайно попал на обзор оптического датчика концентрации со2. Цена конечно тоже не маленькая, но все-таки близко к разумным пределам. И руки давно чесались по паяльнику. В качестве контролера использовать решил ESP8266. Во первых дешево, во вторых что бы передавать информацию на компьютер, свой и любого желающего в комнате. После того как собрал и оттестировал первый вариант, решил добавить экран. Во первых это красиво:) Во вторых во многих случаях удобно.

Устройство построено на модуле ESP8266 NodeMcu Lua wi-fi

Сперва я подключил датчики температуры, в комнате и на улице. ds18b20

Затем собственно датчик углекислого газа. MH-Z19

И под конец дисплей



написал вот такую программу под винды

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

А теперь собственно впечатления.
Прибор оказался намного полезней и интереснее чем я ожидал. Во первых больше нет проблем с проветриванием, никто не возмущается, так как у всех выскакивает предупреждение и они довольно хорошо согласуются с личными ощущениями.
Ну и просто наблюдения показали что в солнечный день уровень со2 значительно ниже чем в пасмурный и дождливый, утром загрязненность воздуха выше чем днем. С первого взгляда можно понять что делать, проветривать, если зашкаливает со2, или включить кондиционер, если повышенная температура. Датчик температуры на улице хорошо показывает получится ли охладить проветриванием, или только кондиционер. Стало очевидным и понятным, что творится в комнате и как в этом жить. И дома прибор оказался очень полезным, особенно в детской комнате, тем более что за показаниями можно следить удаленно через WiFi.

В результате получилось что-то вроде:


Тут видно сам прибор с экраном и программа на компьютере которая принимает информацию через WIFI.

Дополнение про датчик.
Почему именно такой датчик?
Есть дешевый MQ-135. Но я не встретил в откликах ни одного доброго слова об этом датчике. Он реагирует на все подряд, температуру, влажность, питание. Напротив датчики аналогичной конструкции какой применил я используются везе в том числе в профессиональной аппаратуре.

Тут описан принцип работы датчика. Называется «инфракрасный оптический анализ»

Что касается ШИМ и UART. Я изначально решил использовать ШИМ так как это было удобнее в данной конструкции, решил попробовать, и если бы результат был не удовлетворительный, переделал бы на UART. По факту оказалось что ШИМ ничем не уступает. Точный надежный, ни каких плясок и сбоев. Так и оставил.

Есть идея заказать в Китае плату

Вот думаю заказать в Китае плату с разъемами.
Что бы даже ничего паять не надо было.
В готовую плату втыкаешь ESP8266, датчик со2, дисплей, датчик температуры ds18b20, отдельно разъем будет на внешний датчик.
Прошиваешь и все работает.
Как относитесь к такой идее?

Идеи и технологии описанные в данном материале, а так же все программное обеспечение. Может быть использовано без согласия автора только для личных целей.
Любое, другое коммерческое, или не коммерческое изготовление, или распространение данных материалов и устройств, возможно только по согласованию с автором.
[email protected]

Таким получается готовое изделие



Последняя реинкарнация данного прибора

В проекте по подсчету и публикации в сети показаний газового счетчика, я уже упоминал, что хорошо бы иметь возможность измерять не только температуру, но и содержание различных газов в воздухе. Тогда, в проекте, я пытался использоваться электрохимические датчики серии MQ. Один для измерения содержания природного газа в воздухе, второй для отслеживания концентрации CO. И если бы не полное фиаско с сенсорами MQ, вполне возможно, что данный проект и не появился бы.

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

Итак, цель настоящего мини-проекта в том, чтобы опробовать связку из Arduino-совместимой платы WeMos D1 Mini Pro, датчика содержания углекислого газа в воздухе и сервиса по хранению показаний ThingSpeak. На самом деле, данный мини-проект - проба пера, технологии определения содержания CO2 в воздухе, перед началом другого, немного более крупного проекта. Хотя результатами проекта можно пользоваться без каких-либо ограничений. Собранное устройство делает именно то, что от него требуется.

Почему я использую WeMos D1 Mini Pro для этого проекта? Плата мною уже изучена, подводные камни понятны. Кроме того, чип ESP8266 имеет встроенный Wi-Fi, а на самой плате распаяно, ни много ни мало, а целых 16 мегабайт памяти. Поэтому можно как угодно изгаляться, места для вашего скетча будет достаточно, нет необходимости экономить память.

640 килобайт хватит надолго!

Уильям Гейтс, 1981

Плата D1 Mini Pro поставляется вместе с набором шпыньков, включая сквозные, позволяющие не только устанавливать ее на макетную плату, но и одновременно использовать различные шишлды. Но, кроме неоспоримых достоинств у D1 Mini Pro есть и некоторый недостаток. На плате использована керамическая антенна, которая вроде бы должна обеспечивать вполне уверенное соединение с Wi-Fi. Однако, на практике связь хуже, чем у той же D1 R2 с антенной разведенной на плате. Видимо, по этой причине производитель добавил гнездо для подключения внешней антенных. Впрочем, разница все равно не слишком существенная.

Почему я использую сервис ThingSpeak? Да все по той же причине. Он бесплатен, позволяет передавать, агрегировать, хранить и обрабатывать данные со всех моих устройств. Что, согласитесь, удобно. Более того, доступность мощнейшего аппарата MatLab прямо онлайн, делает сервис ThingSpeak очень привлекательной средой для любых домашних проектов.

А вот на датчике MHZ-19 остановится подробнее.

MH-Z19

Датчики серии MH-Z выпускаются китайской компанией Winsen . Сама компания специализируется именно на разработке и производстве датчиков для определения газов. В активе компании имеются как электрохимические, так и датчики, выполненные по другим технологиям. Собственно, датчики MH-Z, а среди них MH-Z14A, MH-Z19B, MH-Z14 и MH-Z19, как раз и относятся к группе сенсоров, выполненных по другим технологиям.

В основе процесса измерения в сенсорах MH-Z лежит принцип оптического измерения содержания определенного газа. В английском языке подобная технология называется Nondispersive infrared, что на русский язык переводится примерно как «недисперсионная инфракрасная технология» или сокращенно NDIR. Наличие IR и то, что сам сенсор используется инфракрасное излучение для анализа воздуха наводит некоторых «специалистов» на то, что в датчике используется PIR (Passive Infrared) технология. Да, в PIR, как и в NDIR, используется инфракрасный свет, а в остальном это две отличных технологий.

В NDIR используется две камеры, одна заполнена азотом, а такой газ содержится и в атмосфере нашей планеты. Более того, азота в воздухе, которым мы дышим аж 78%. Кислорода 21%, а углекислого газа всего 1%. Так вот, одна из камер содержит азот, а вторая тот воздух, который подвергается исследованию. Через обе камеры, одновременно пропускается пучок инфракрасного света. Его источником может быть, все что угодно. В подобных устройствах обычно используется полупроводниковый диод, обеспечивающий требуемую длину волны. Если же источник инфракрасного света недостаточно стабилизирован по спектральной характеристике, то применяется оптический фильтр, отсекающий все остальные длины волн.

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

Несмотря на то что измерения сенсорами с технологией NDIR точны, могут наблюдаться и некоторые погрешности, особенно при малых концентрациях искомого газа, связанные с наличием в воздухе других газов. Так, у датчиков, используемых для определения CO2 есть некоторые, совсем небольшие, проблемы с H2O (паром), SO2 и NO2. В бытовом применении эти погрешности можно с легкостью скинуть со счетов, но для промышленного применения, где требуется высокая точность, видимо надо изобретать какие-то дополнительные механизмы. И да, когда вы дышите на датчик, стараясь проверить насколько он здорово работает, учтите, что в выдыхаемом вами воздухе содержится изрядное количество водяного пара, который так же окажет влияние на показания.

Как отметил выше, в настоящее время Winsen выпускает два вида датчиков, серию Z14 и Z19. Отличаются одна серия от другой внешним видом. Z19 это параллелепипед с двумя фильтрами, а Z14 - усеченный цилиндр на плате с одним фильтром. Есть различия между моделями и внутри серий связанные с дополнительными настройками по диапазонам работы. В целом же обе серии можно считать идентичными, а различия несущественными.

Калибровка

Датчик Z19 имеет возможность калибровки. Причем возможна калибровка двумя способами. Первый и самый точный способ: калибровка абсолютного нуля. Для этого датчик необходимо поместить в атмосферу из чистого азота, подождать пока азот не вытеснит все остальные газы из корпуса датчика, примерно пять минут, и запустить калибровку командой. Результаты будут записаны в память микроконтроллера сенсора, и они будут использоваться для последующих определений значений измерений. Азот, кстати, можно приобрести на предприятиях занимающимися реализацией газов. Правда, самый маленький баллон будет стоить как два, а то и четыре датчика MH-Z19, но искусство требует жертв.

Второй способ, так называемый span calibration применяется для калибровки в бытовых условиях. Выполняется он точно так же, как и в первом способе, но датчик нет необходимости помещать в атмосферу азота. Достаточно вынести его на чистый и свежий воздух и произвести калибровку. Тут делается упор на то, что в атмосферном воздухе содержится порядка 400 ppm CO2. И значение это постоянно на протяжении длительного времени и более-менее однородно по всему земному шару. Но при подобной калибровке следует учитывать, что значение в 400 ppm весьма условно, поскольку концентрация углекислого газа колеблется, и в весьма ощутимых пределах, в зависимости от внешних факторов. В крупном городе концентрация будет выше, чем на селе. Летней ночью в лесу углекислого газа будет больше, чем в том же лесу, тем же летом, но в солнечную погоду днем.

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

Чем плох CO2?

Чем же плохо повышенное содержание углекислого газа в воздухе? А тем, что углекислый газ есть не что иное, как естественный результат нашей с вами жизнедеятельности. И не только нашей, кстати. Вдыхаем мы воздух, в котором преобладает азот и кислород, а выдыхаем все тот же азот, мало кислорода и много углекислого газа. Процесс миграции углекислого газа из крови, через альвеолы в легких происходит из-за парциального давления газов по разные стороны мембраны альвеолы. Суть парциального давления в том, что при одинаковом атмосферном давлении, если различается состав газов по разную сторону мембраны, то тот газ, которого больше с одной стороны и меньше с другой, будет пытаться проникнуть на другую сторону и уравновесить свою концентрацию. По такому же принципу работает и наполнение газом датчика MH-Z, где нет никакой принудительной вентиляции. Поэтому результаты он показывает с некоторой задержкой. Пока парциальное давление газов уравновесится.

Ну так вот, при дыхании, давление углекислого газа в капиллярах альвеолы, читай его процентное соотношение к другим газам, выше, чем во вдыхаемом воздухе, а содержание кислорода, наоборот, ниже. Углекислый газ старается выбраться из тела в атмосферу, а кислород наоборот, проникнуть в него. Для успешной работы этой системы обмена, во вдыхаемом воздухе должно быть много кислорода и мало углекислого газа. Иначе, вывод отработки из организма работать не будет. Собственно, этим и плохо высокое содержание CO2 в воздухе. Чем выше его содержание, тем хуже будет выводиться ненужный результат химических реакций наших тех. От переизбытка СО2 в воздухе и как следствие в самом теле, ухудшается самочувствие, страдает работоспособность, да и в целом идет интоксикация организма теми самыми шлаками. Именно по этой причине мамы стараются выгнать своих детей на улицу, подышать свежим воздухом, поиграть на морозце. Тем самым происходит очищение организма от ненужного ему СО2.

Во взрослом состоянии организма увещевание мам уже не действует и человек готов просидеть 12 часов в душном офисе имитируя бурную деятельность. Именно имитируя, ведь работать в атмосфере с повышенным содержанием углекислого газа нормально невозможно. Даже имитация работы будет жиденькой и вялой.

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

Подключение

Подключаются датчики серии MH-Z к микроконтроллерам двумя способами. Доступно либо использование PWM (ШИМ), либо подключение по UART (последовательному порту). Мы уже знаем, что чипы ESP8266 не очень дружат с PWM под средой Android, поэтому для подключения будем использовать только и исключительно UART. Более того, подключение по последовательному порту еще и предпочтительнее, поскольку не только снижает нагрузку на сам микроконтроллер, но и позволяет использовать команды калибровки. Да и разве не здорово получать значения содержания CO2 сразу в ppm прямо с датчика, а не заниматься длительными и мучительными вычислениями? Вот именно, что стоит.

Во избежание ненужной гибели человеческих жертв, хочу обратить внимание воспитанного читателя на то, что для питания датчика MH-Z19 требуется напряжение от 4.5 и до 5.5 вольт, а для обмена данными по последовательному порту (равно как и для PWM) требуется 3.3 вольтовая логика. Поэтому при подключении датчика к оригинальным Arduino потребуется согласование уровней логики, иначе возможно повреждение устройства. Все эти параметры указаны в официальной спецификации на устройство, поэтому пренебрегать ими не стоит. Итак, подключаем питание, благо на плате WeMos есть выводы как для 5 вольт, так и для 3.3 вольт, а заодно подключаем линии передачи и приема на пины D1 и D2. И собственно после этого все должно заработать, в аппаратном понимании понятно.

Теперь, что касается программной стороны. Для того чтобы WeMos начал работать с UART необходимо использовать библиотеку для программного последовательного порта (SoftwareSerial). Библиотека позволяет организовывать UART порт на любых пинах устройства. В стандартной Arduino поставке уже есть такая библиотека, но для чипов ESP8266 нужна своя, особая библиотека (возможно, что в более свежих версиях Espressif SDK данная библиотека уже присутствует в поставке). Ее необходимо будет скачать и установить в систему, если ранее подобная операция не была произведена. Правда, после этого возможны коллизии с обычными Arduino скетчами. Нужно просто помнить по SoftwareSerial и отключать ее в случае проблем.

Для работы с MH-Z19 не требуется какая-то отдельная библиотека, весь требуемый код весьма и весьма компактен, и доступен для написания программистом самостоятельно.

Небольшое замечание по частоте опроса датчика. В спецификации не указывается максимальная частота опроса, но в некоторых обзорах упоминается, что дескать, не стоит дергать датчик чаще, чем раз в 10 секунд. Мол помрет раньше времени. Не могу согласиться с таким утверждением. Если в темноте присмотреться к датчику, то будут заметны световые импульсы, примерно каждые 3 секунды. Это сенсор проводит измерения уровня газа. Обработка показаний занимает тоже не космические величины, поэтому лично я не вижу никакой проблемы по считыванию значений не чаще чем 4-5 секунд. Тут важно попасть между вспышками, дабы получать каждый раз новый результат, а не копию старого. Хотя в моем скетче показания считываются вообще раз в 10 минут, мне важна статистика и динамика, а не моментальный результат.

В скетче, помимо всего прочего, осуществляется отправка показаний измерения CO2 и температуры на сервер ThingSpeak. Да-да, вы не должны не доверять своим глазам. Датчик MH-Z19 измеряет еще и температуру. Для получения более точного результата измерений содержания углекислого газа нужно проводить корректировку измерений по температуре самого датчика. Именно отсюда измеряемая температура слегка выше температуры окружающего воздуха и, пожалуй, может быть использована только в академических целях. Но как же получить измерения температуры? В официальной спецификации, полученной с сайта Winsen и многих других, действительно нет никакого упоминания по поводу температуры. А вот в спецификации на датчик MH-Z14 температура есть и передается она в ответе от сенсора вместе с остальными данными (байт 4).

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

#include #include #include #include #include #include #include const char* ssid = "YourWiFiNetWork"; const char* password = "YourWiFiPasswird"; WiFiClient client; // All fucntions https://www.arduino.cc/en/Reference/WiFi & http://esp8266.github.io/Arduino/versions/2.0.0/doc/libraries.html#wifi-esp8266wifi-library #define ledPin D4 // the onboard LED unsigned long CO2Channel = ThingSpeakChannelNumber; const char * CO2WriteAPIKey = "ThingSpeakWriteAPIKey"; unsigned long CO2Millis = 600000; unsigned long MillisLast = 0; ESP8266WebServer server(80); // Simple web server String webArray; // Keeps messages // CO2 sensor: SoftwareSerial mySerial(D1, D2); // RX,TX byte cmd = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; unsigned char response; void setup() { pinMode(ledPin, OUTPUT); Serial.begin(115200); Serial.println(""); mySerial.begin(9600); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(5000); ESP.restart(); } Serial.println("WiFi is ready..."); int lo = WiFi.RSSI(); Serial.print("WiFi signal: "); Serial.println(lo); { // Ota ArduinoOTA.onStart(() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else // U_SPIFFS type = "filesystem"; // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Serial.println("Start updating " + type); }); ArduinoOTA.onEnd(() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress((unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError((ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); Serial.println("OTA is ready"); } { // Web-server init server.on ("/", EhternetWebServer); server.begin(); // Starts Web-Server Serial.println("Web-server is Ready..."); } digitalWrite(ledPin, HIGH); Serial.println("Let us go...."); delay(3000); } void getCO2Data() { mySerial.write(cmd, 9); memset(response, 0, 9); mySerial.readBytes(response, 9); // CRC check int i; byte crc = 0; for (i = 1; i < 8; i++) crc += response[i]; crc = 255 - crc; crc++; // End of CRC check if (!(response == 0xFF && response == 0x86 && response == crc)) { //Serial.println("CRC error: " + String(crc) + " / " + String(response)); char raw; sprintf(raw, "RAW: %02X %02X %02X %02X %02X %02X %02X %02X %02X", response, response, response, response, response, response, response, response, response); //Serial.println(raw); printWeb(raw); printWeb("CRC error: " + String(crc) + " / " + String(response)); MillisLast = CO2Millis-10000; } else { unsigned int responseHigh = (unsigned int) response; unsigned int responseLow = (unsigned int) response; int ppm = (256 * responseHigh) + responseLow; int temp = response - 20; Serial.println(String("-=-")); char raw; sprintf(raw, "RAW: %02X %02X %02X %02X %02X %02X %02X %02X %02X", response, response, response, response, response, response, response, response, response); printWeb(raw); if (ppm <= 400 || ppm > 4900) { //Serial.println("CO2: no valid data"); printWeb("CO2: no valid data"); MillisLast = CO2Millis; } else { printWeb("CO2 PPM:" + String(ppm) + "; Temp:" + String(temp)); digitalWrite(ledPin, LOW); String sURL = "http://api.thingspeak.com/update?api_key="; sURL += CO2WriteAPIKey; sURL += "&field1=" + String(ppm) + "&field2=" + String(temp); printWeb(sURL); HTTPClient http; http.begin(sURL); int httpCode = http.GET(); if (httpCode == HTTP_CODE_OK) { //Serial.printf("ThingSpeak responce code: %d\n", httpCode); printWeb("ThingSpeak responce code: " + String(httpCode)); } else { printWeb("ThingSpeak failed, error: " + String(http.errorToString(httpCode).c_str())); MillisLast = CO2Millis-10000; } digitalWrite(ledPin, HIGH); } } } void loop() { unsigned long CurrentMillis = millis(); if (CurrentMillis - MillisLast > CO2Millis || MillisLast == 0) { MillisLast = CurrentMillis; getCO2Data(); } server.handleClient(); // Check Web-Server requests ArduinoOTA.handle(); // Handle Over The Air update delay(1000); } void EhternetWebServer() { Serial.println("WebServer responce request"); String responce = ""; responce += ""; for (int i = 0; i < 100; i++) { responce += i + 1; responce += ". "; responce += webArray[i]; responce += " "; } responce += "


"; server.send (200, "text/html", responce); } void printWeb(String s) { Serial.println(s); for (int i = 99; i > 0; i--) { webArray[i] = webArray; } String sS = "" + String(MillisLast) + ": " + s; webArray = sS; }

Помимо чтения значений датчика и отправки их в сеть к ThingSpeak, в скетче реализован механизм обновления прошивки по воздуху (OTA), и веб-сервер выводящий 100 последних сообщений, в целях отладки, разумеется.

ThingSpeak

Как видно из приведенного ниже графика, содержание диоксида углерода плавает в течение 12 часов. Датчик установлен в комнате с одним окном. В комнате периодически обитает двое взрослых и два мелких хищника. Окно постоянно приоткрыто для проветривания. Данные подаются на сервер каждые 10 минут, а затем происходит усреднение по 10 значениям. В какие-то периоды времени отправка данных невозможна, и линия графика выглядит как просто сплайн.

По графику хорошо видно, что в ночное время содержание CO2 колеблется на приемлемом уровне в районе 500 ppm, а около 8 утра наблюдается небольшой всплеск до 600. Ночью, когда любая активность минимальна, проветривания оказалось достаточно для поддержания оптимального уровня свежести воздуха. А вот в тот момент, когда все люди и звери становятся активными, содержание диоксида увеличивается. Хотя и в такой момент оно находится на вполне неплохом уровне. Затем же идет плавное снижение содержания вплоть до его номинального значения. Мелкие хищники днем спят, а их мощности метаболизма недостаточно для поддержания высокого уровня содержания CO2 в атмосфере комнаты.

Графики на ThingSpeak хороши, но не гибки. Но я не поленился и выгрузил данные сразу за несколько дней для анализа в Excel. Благо подобная функция, функция выгрузки, присутствует в ThingSpeak. Несколько несложных манипуляций и готов весьма подробный график готов. Поскольку значений выгружено много, то без дополнительных манипуляций провести усреднение непросто, но, с другой стороны, так даже интереснее. При анализе графика следует учитывать временный сдвиг в 3 часа из-за выгруженных данных в часовом поясе UTC+0.

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

Выводы

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

Update . Все течет, все меняется. И вот производитель данного сенсора, переехал на новый сайт и как оказалось в его ассортименте присутствует сразу три датчика MH-Z19: MH-Z19, MH-Z14A, MH-Z19B. Разнообразие датчиков меня удивило и я решил слегка разобраться в чем, собственно, разница между ними.

Практически любая метеостанция, включая дешевые китайские модели за несколько долларов, умеет измерять основные параметры воздуха - температуру и влажность. С углекислым газом все сложнее: бытовых приборов, способных его измерять, практически нет в продаже. Усложняет ситуацию и то, что CO2 - газ без цвета и запаха, так что «носом» ощутить его концентрацию практически невозможно.

Подробности и измерения под катом.

Сам датчик MH-Z19 уже описывался здесь на сайте. За основу была взята статья "Обзор инфракрасного датчика CO2 ", а данный материал является его логическим продолжением. Про измерение концентрации CO2 на улице , однако данных о концентрации в квартире там не приводилось. Восполним этот пробел.

Железо

Первым делом на eBay были заказаны следующие компоненты:
- Arduino Micro ATmega32U4 3.3V (цена вопроса 5$). Т.к. датчик имеет 3-вольтовую логику, обычные Arduino лучше не использовать.
- OLED LCD-дисплей I2C 0.91«128x32 (цена вопроса 7$). Дисплей подключается к стандартным i2c-пинам Arduino.
- Собственно датчик MH-Z19 (цена вопроса 28$).
- Набор проводов с разъемами для штыревых контактов (цена вопроса 1-2$)
Таким образом, общая стоимость составила ~40$, или 2600р. Фирменный прибор от известной компании стоит примерно вдвое дороже, хотя здесь скорее вопрос не экономии, а технического интереса.

Код для Arduino был позаимствован из вышеприведенной статьи , в него был добавлен вывод данных на дисплей, а для более удобного анализа данных вывод был переделан в формат простой строки с разделителем. Также были добавлены метки времени, каждая соответствует 10 секундам.

Исходный код

#include #include // I2C OLED #include "SSD1306Ascii.h" #include "SSD1306AsciiWire.h" #define I2C_ADDRESS 0x3C SSD1306AsciiWire oled; // CO2 sensor: SoftwareSerial mySerial(8,9); // RX,TX byte cmd = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; unsigned char response; void setup() { // Serial Serial.begin(9600); mySerial.begin(9600); // OLED Wire.begin(); oled.begin(&Adafruit128x32, I2C_ADDRESS); oled.set400kHz(); oled.setFont(ZevvPeep8x16); oled.clear(); oled.println("setup::init()"); } long t = 0; 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++; oled.clear(); if (!(response == 0xFF && response == 0x86 && response == crc)) { Serial.println("CRC error: " + String(crc) + " / "+ String(response)); oled.println("Sensor CRC error"); } else { unsigned int responseHigh = (unsigned int) response; unsigned int responseLow = (unsigned int) response; unsigned int ppm = (256*responseHigh) + responseLow; Serial.print(String(t)); Serial.print(","); Serial.print(ppm); Serial.println(";"); if (ppm <= 400 || ppm > 4900) { oled.println("CO2: no data"); } else { oled.println("CO2: " + String(ppm) + " ppm"); if (ppm < 450) { oled.println("Very good"); } else if (ppm < 600) { oled.println("Good"); } else if (ppm < 1000) { oled.println("Acceptable"); } else if (ppm < 2500) { oled.println("Bad"); } else { oled.println("Health risk"); } } } delay(10000); t += 10; }

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

Конечно это не верх промышленного дизайна (в планах подыскать какой-то корпус), но для задачи показометра, способного работать как автономно, так и передавать данные по USB, устройство вполне справляется. Для получения данных по USB достаточно открыть в Arduino IDE монитор порта, в нем будут выводиться данные. Текст оттуда можно скопировать и открыть в любой программе, например в Excel.

Измерения

Следующий вопрос: что мы собственно измеряем? Устройство выдает данные в ppm (parts per million, частей на миллион). 1000 ppm = 0,1% содержания СО2. В интернете можно найти следующую таблицу допустимых концентраций:
- 350 - 450 ppm : Нормальный уровень на открытом воздухе.
- < 600 ppm : Приемлемые уровни. Уровень. рекомендованный для спален, детских садов и школ.
- 600 - 1000 ppm : Жалобы на несвежий воздух, возможно снижение концентрации внимания.
- 1000 ppm : Максимальный уровень стандартов ASHRAE (American Society of Heating, Refrigerating and Air-Conditioning Engineers) и OSHA (Occupational Safety & Health Administration).
- 1000 - 2500 ppm : Общая вялость, снижение концентрации внимания, возможна головная боль.
- 2500 - 5000 ppm : Возможны нежелательные эффекты на здоровье.

И наконец, результаты. Датчик был поставлен на кухне, окна металлопластиковые, время измерения около 8 часов.


Результаты оказались довольно-таки интересными. По горизонтали время в секундах, 3600 секунд соответствуют 1 часу.

Кривые на графике расшифровываются так:
0ч: показания около 420ppm (соответствуют уличным), дома никого не было, я пришел с работы и заодно включил датчик.
0-2 часа: я нахожусь на кухне, видно как в присутствии человека концентрация co2 медленно растет где-то до 900ppm.
2-4 часа: я ушел из помещения, видно как концентрация медленно спадает.
4-6 часов: я вернулся обратно, концентрация снова стала расти.
6й час: на плиту поставлена кастрюля с пельменями. Интересно видеть, как концентрация практически моментально увеличилась до 1700ppm, затем стала медленно спадать. Хотя газ горел недолго (минут 10-15) высокие уровни >1000 ppm держатся не менее часа.
Конец графика: было открыто окно, и уровень co2 упал практически сразу же.

Выводы

Устройство оказалось довольно-таки интересным, и особенно актуальным для работающих дома за компьютером. Так например, за время написания этой статьи уровень co2 вырос в помещении с 500 до 770ppm. Поглядывание на экран заставляет либо чаще открывать окно, либо наконец-таки задуматься об устройстве в доме нормальной вентиляции (наверное режим микропроветривания в окне был бы не лишним, а лучше какая-то вытяжка). Если бы я сейчас покупал новые окна, наверно задумался бы о более-менее качественной модели с нормальным проветриванием.

Также важно отметить актуальность хорошей вентиляции на кухне: как показывает график, даже за 10 минут одна газовая горелка может „выжечь“ весь запас кислорода, доведя концентрацию CO2 до весьма высокой. Измерения в спальне показали, что в плане вентиляции тоже все не очень хорошо: к утру концентрация co2 составляет более 1000ppm, а для умственного труда хороший сон это весьма актуально.

В общем, это нехитрое и недорогое устройство позволяет весьма эффективно проверить качество воздуха в квартире или офисе.
Автор желает всем хорошего здоровья и хорошего настроения. Ну и хорошего воздуха разумеется, тоже.