habrahabr

Белый Куб на страже чистоты воздуха, часть 1

  • суббота, 22 ноября 2014 г. в 02:11:44
http://habrahabr.ru/post/243669/

Устройство для мониторинга параметров домашней среды с передачей данных по Wi-Fi.

image

В статье описывается устройство для измерения, индикации на встроенном дисплее и передачи в сеть по Wi-Fi параметров окружающей среды:

• уровень СО2 (углекислый газ)
• уровень СО (угарный газ)
• содержание паров этилового спирта (С2Н5ОН)
• уровень горючих газов (LPG)
• уровень аммиака (NH3)
• содержание водорода(H2)
• значения атмосферного давления
• влажности и температуры воздуха
• уровня освещенности
• уровня магнитного поля по трем осям
• уровня гравитации по трем осям
• уровня ускорений по трем осям
• температуры произвольного количества цифровых датчиков температуры типа DS18B20.

Изюминкой БК является способ смены экранов по двойному постукиванию по корпусу. Видео как это происходит:

Подробное описание этого способа управления ниже.

Белый Куб внешне представляет собой корпус белого цвета с ребром 10 см, купленный в Чипе и Дипе.

При обдумывании реализации прибора я решил, что прибор должен все собранные данные выдавать в сеть. Данные интересны не одномоментно, а своими долговременными тенденциями. Очень интересно иметь большие архивы данных для последующей обработки. Таким образом, разумно данные от датчиков передавать на «большую машину», обрабатывать там, хранить, извлекать, считать статистику, рисовать графики, строить разнообразные корреляции и пр. Все это имеет смысл делать только на большой машине с мощным процессором, большой памятью, большим дисплеем и низкой трудоемкостью обработки данных, используя все богатство наработанного матобеспечения для отображения и разнообразной обработки данных.

В качестве центрального процессора БК я применил Ардуино Нано. Для меня удобство разработки и программирования перевесили недостатки. Учитывая также заметное энергопотребление датчиков газов, датчика СО2 и модуля Wi-Fi не имеет смысла бороться за низкое потребление ЦП. Плюс надо учесть и то, что БК – единичный прибор, не предназначенный для массового производства.

Для передачи данных по Wi-Fi я использовал замечательное устройство «HI-LINK HLK-RM04 Serial Port-Ethernet-Wi-Fi Adapter Module» (http://dx.com/p/hi-link-hlk-rm04-serial-port-ethernet-wi-fi-adapter-module-blue-black-214540), которое представляет собой по сути мини-рутер с большими возможностями.

image

И с обратной стороны:

image

Я использовал режим прозрачной передачи данных Serial – Wi-Fi. Я не буду подробно останавливаться на этом устройстве – в сети достаточно описаний, опыта применения и форумов по этому мини-рутеру.

Из любопытного следует упомянуть библиотеку github.com/chunlinhan/WiFiRM04

В процессе отладки выяснились некоторые особенности передачи данных по Wi-Fi по сравнению с кабелем. Так, если по кабелю строка данных из например 130 байт из Ардуино так и приходит строкой в 130 байт, то при передаче этой же строки по Wi-Fi данные оказываются разбитыми на 4-5 частей и на приемном конце эти части требуется собрать и только потом передать строку на обработку. Углубленно с этим я не разбирался, учел при написании программы приема данных от Белого Куба. Возможно, эти особенности передачи по радиоканалу связаны с уже большой загруженностью диапазона 2.4 ГГц и конкурентным доступом устройств, работающих на одном частотном канале.
Следует обратить внимание, что с DX модули приходят без внутренней антенны:

image

Я докупил внешние антенны в DESSY.RU и потребовал от продавца возмещения расходов.

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

Датчик CO2 типа K-30:



Куплен отдельно у производителя на сайте. Это самый дорогой из примененных датчиков, но он стоит своих денег, поскольку очень долговечен и стабилен. Принцип действия заключается в измерении поглощения инфракрасного излучения в калиброванном тракте. Данные с этого датчика можно снимать как в аналоговом виде, так и двумя цифровыми интерфейсами – последовательным и I2C. Также этот датчик содержит механизм автокалибровки, который учитывает данные за прошедшие две недели (интервал времени программируется) и минимальный уровень в течение этого времени считает за 400 ррм. Таким образом учитывается долговременное смещение калибровки датчика. На сайте производителя имеется как подробная документация, так и примеры программы считывания данных, которыми я и воспользовался. Я купил два датчика, один через преобразователь сериал – USB на FT232 подключен к домашней управляющей машине, второй использован в БК. Датчик питается от 5 вольт, но уровни на сериал порту должны быть 3.3 в. Это для случая подключения по сериал порту. Если используется порт I2C – то преобразователь уровней не требуется.

Остальные датчики – аналоговые:

Пары этилового спирта (C2H5OH) – MQ5
Угарный газ СО –MQ7
Водород H2 – MQ8
Сжиженный газ (LPG) – MQ6
Аммиак (NH3)– MQ135
Дым — MQ2

Выглядят датчики вот так:

image

image

image

Несмотря на некоторое внешнее отличие, устроены датчики одинаково, содержат чувствительный элемент, меняющий проводимость под действием того или иного газа и компаратор на половинке LM393. Датчики имеют 4 внешних вывода – два для питания модуля (+5 и земля) и два выхода – один аналоговый и один цифровой с выхода компаратора.
Чувствительные элементы нуждаются в подогреве и поэтому ток потребления довольно большой – около 200 мА.

Рекомендуемая мануалом схема включения – последовательно с датчиком включается резистор и с него снимается полезный сигнал. По мануалу нагрузочный резистор можно ставить от 5 до 47 КОм, типичное значение – 10 КОм.
Любопытно отметить, что сами датчики обладают малой избирательностью и одинаково хорошо реагируют на весь спектр веществ и газов. Это, впрочем, выяснилось уже в процессе испытаний и отладки БК.

На печатной плате размещен собственно датчик, сдвоенный компаратор типа LM393, пара светодиодов и вспомогательная обвязка. Один светодиод – индикатор питания, второй – индикатор срабатывания компаратора. К счастью, на выходном разъеме имеется и вывод аналогового сигнала непосредственно от датчика, так что я смог использовать эти узлы без изменений, кроме датчика СО.
Датчик CO (MQ7) пришлось модернизировать. Этот датчик требует особого режима питания в соответствии с мануалом. 90 секунд на нагревательный элемент следует подавать полное напряжение 5 вольт, а затем 60 секунд – 1.4 вольта. На плате питание подогревателя организовано иначе – +5 вольт подаются на один вывод нагревателя, а второй вывод через резистор 5 ом присоединен к земле.

image

На фото красными стрелками показаны элементы:
1 – резистор 5 ом в цепи нагревателя
2 – вывод нагревателя
3 – компаратор LM393

Я демонтировал резистор (1) и проводом МГТФ соединил вывод нагревателя (2) к ноге разъема, на которую был заведен выход компаратора. Компаратор (3) я также демонтировал с платы. Второй провод восстанавливает ошибочно разрушенную цепь индикаторного светодиода. Индикаторный светодиод включен параллельно нагревательному элементу. Это позволило при отладке программы визуально наблюдать за текущим режимом – нагрев или измерение по изменению яркости светодиода.

image

фото переделанного датчика CO MQ7

Поскольку нагреватель датчика требует значительного тока (порядка 200 мА), то питать его напрямую от вывода Ардуино нельзя (максимум 40 мА). Я использовал промежуточный полевой транзистор в ключевом режиме. Транзистор вот такой: IRLU120NPBF, Nкан 100В 10А logic ТO251, куплен в Чипе и Дипе. Это транзистор Т1 на принципиальной схеме БК.

Электрическая принципиальная схем Белого Куба:

image

Изучив материалы в интернете я решил, что оптимальным будет импульсное питание датчика в режиме ШИМ нужной скважности. Другие методы – например, последовательное включение диодов или резисторов – требуют ручного подбора элементов. Недостатком этого метода является то, что импульсное питание нагревателя может приводить к помехам при измерении аналогового сигнала с датчика.

Внимательно прочитав даташит, я понял, что измерять уровень СО следует в самом конце цикла измерения непосредственно перед включением цикла нагрева. Поэтому я решил, что не буду принимать никаких специальных мер по подавлению импульсной помехи от ШИМ, а просто выключу ШИМ сигнал перед измерением, дам системе успокоиться несколько миллисекунд, измерю уровень СО и потом включу питание опять. Тепловая инерция датчика – десятки секунд, так что во время переключения температура чувствительного элемента не меняется и выходной сигнал тоже стабилен.

Вид выходного сигнала по каналу измерения СО показан на графике:

image

На этом графике зеленый меандр – переключение напряжения на нагревательном элементе, красная линия – сигнал с датчика СО, желтая – сигнал, зафиксированный непосредственно перед сменой режима нагрева.

Измерение сигнала от датчика СО производится непрерывно, в систему обработки поступают как текущий сигнал, измеряемый с периодом около 3-х секунд (период основного цикла скетча), так и измерение «по мануалу» с периодом 2.5 минуты (90+60 секунд). Из графиков видно, что сигнал внутри периода измерения также несет информацию о текущем уровне СО и скорости его изменения. Выделить и использовать ее можно путем сравнения (вычитания) запомненного массива значений на предыдущем такте измерений с текущими значениями. Разница с предыдущим циклом с возможно какой-то дополнительной обработкой (усреднением за 10-20 секунд) даст более-менее адекватную информацию о скорости увеличения вредного агента в воздухе. Это позволит увеличить скорость реакции на изменение СО с двух с половиной минут до нескольких секунд. Идею такой обработки я нашел тут.

Остальные аналоговые датчики особого питания не требуют. Все аналоговые датчики газов требуют прогрева в течение 48 часов после подачи питания.

Измерение давления воздуха.

Для измерения этого параметра я использовал модуль «L3G4200D ADXL345 HMC5883L BMP085 MWC Sensor Module for Arduino».

image

image

Модуль содержит 4 датчика, изначально предназначен для летательных аппаратов типа мультикоптера. Модуль куплен на DX.com из соображений «оптом дешевле». Оказалось впрочем, что и для датчика ADXL345 нашлось свое применение. Об этом несколько ниже.

BMP085 – цифровой датчик абсолютного давления воздуха с датчиком температуры.
ADXL345 – трехосевой датчик ускорения
HMC5883L – трехосевой датчик магнитного поля
L3G4200D – трехосевой цифровой гироскоп.

Все датчики подключены к шине I2C, для считывания показаний я применил готовые библиотеки.

Датчик ADXL345 предназначен для измерения ускорения по трем осям с выдачей результатов по шине I2C. Датчик этот умеет измерять в частности ускорение свободного падения.

А еще этот датчик умеет реагировать на воздействия “tap” и “double tap” – т.е. на одиночное и двойное постукивание. И это дает возможность оказывать на программу (скетч) БК управляющие воздействия. Я использовал этот механизм для переключения экранов на дисплее. Данных много и они на одном экране не помещаются. Поэтому я сгруппировал их по трем экранам и переключаю их по double tap по корпусу БК. Мне очень не хотелось делать какие-либо кнопки, я хотел оставить поверхность БК чистой, насколько это возможно.

ADXL345 умеет выставлять аппаратное прерывание по факту детектирования double tap, его я подключил к выводу D3 Ардуино.

К сожалению, из-за ограничений МК у меня не получилось организовать полноценную обработку аппаратных прерываний. Внутри прерывания я не могу опросить регистры ADXL345, так как если прерывание случилось внутри программы общения с другим устройством на той же шине I2C – я порушу этот обмен. Поэтому я сделал компромиссно – при обработке прерывания от ADXL345 я только ставлю флаг, что зарегистрирован double tap, а собственно опрос ADXL345 с целью сброса флага прерывания я делаю в подпрограмме вывода на экран. Решение не идеальное и иногда дающее артефакты на экране, но зато максимально быстрое. Если просто опрашивать в главном цикле ADXL345 на наличие события – то время реакции может быть около 3-х секунд при неудачном раскладе. Это раздражающе долго… Мой вариант дает максимальную задержку менее секунды и я счел его приемлемым.

Видео переключения экрана по дабл тапу:

Данные с датчиков магнитного поля и ускорений читаются, отображаются на дисплее (экран 2) и передаются по каналу связи без изменений. Их обработка – пока дело будущего.

image

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

Какую практическую пользу извлечь из этих показаний – я пока не решил. Может быть анализ изменений магнитного поля даст какую-то полезную информацию для метеочувствительных людей? Впрочем, как электронный компас устройство можно использовать уже сейчас.

Датчик освещенности.

У меня осталась пара свободных выводов на Ардуине, одна из них – с аппаратным прерыванием. Я решил использовать этот вывод для измерения освещенности. В сети я нашел упоминания о методе измерения освещенности путем измерения времени разрядки обратно-включенного p-n перехода светодиода. Суть метода в следующем – на вывод процессора присоединяется обратно включенный светодиод. Вывод включается в режим OUTPUT и на него подается высокий уровень (+5 в). Паразитная емкость светодиода плюс емкость монтажа заряжается до высокого уровня. Далее вывод переключается в режим INPUT и к нему прикрепляется прерывание по изменению уровня или по отрицательному фронту. Входной импеданс процессора ATMEL328P в таком режиме весьма велик – десятки мегаом, поэтому разряд паразитной емкости фототоком занимает достаточно большое время – от единиц миллисекунд до единиц секунд. По срабатыванию прерывания достаточно зафиксировать текущее время. Разность между временем начала цикла и временем окончания цикла даст время в миллисекундах, обратно пропорциональное освещенности. В моем случае для темноты ночью время составляет примерно 3500 миллисекунд, а днем на Солнце – единицы миллисекунд. Я поставил дополнительный конденсатор параллельно светодиоду емкостью в десяток пикофарад, иначе днем разрядка была очень быстрой (менее 1 мс). Я получил 3-10 мс ярким солнечным днем. Собственная емкость светодиода составляет около 8 пикофарад. Дополнительная емкость привела к заметному увеличению времени разряда в темноте – более 4-х секунд. Тут я столкнулся с определенной трудностью. Основной цикл программы длится примерно 3.6 секунды. В начале цикла я запускаю измерение освещенности, выполняю все остальные операции и к концу цикла я ожидаю, что в глобальной переменной лежит значение освещенности, положенная туда в прерывании. Сначала у меня была мысль организовать автономный цикл измерения освещенности, так чтобы в самом прерывании опять запускался цикл. Но тогда при высоких уровнях освещенности (т.е. малом времени цикла – несколько миллисекунд) процессор будет занят только измерением освещенности. Если же делать запуск один раз в начале основного цикла –то при низких уровнях освещенности срабатывания еще не будет и значения будет равно 0… Вышел я из положения так – запускаю измерение в начале цикла, но проверяю – было срабатывание или нет. Если было – запускаю штатным образом. Если нет – ничего не делаю. Минус такого решения – при низких уровнях освещенности вдвое падает скорость измерения. Впрочем – меня все равно интересуют данные с характерным временем изменения в десятки секунд, так что этот минус неважен. Получился преобразователь освещенности в длину импульса с некоторыми особенностями и ценой в 20 рублей.

Выбор светодиодов. Поскольку к моменту подключения датчика освещенности Белый Куб уже имел отверстия диаметром 8 мм – то я решил, что будет красиво использовать диод такого же диаметра. Я купил в Чипе и Дипе по паре штук светодиодов каждого имевшегося там цвета (красного, зеленого, желтого, белого и синего) диаметром 8 мм и поставил эксперимент с целью определения оптимального светодиода. Для исследования светодиодов я соорудил простейший стенд. Стенд состоит из Ардуино Нано, модуля Wi-Fi – serial и исследуемого светодиода на винтовых зажимах. Питание системы осуществлялось от литиевой батареи (power pack).

Немного теории – освещенность в комнате меняется примерно в 1000 раз и более. Ночью освещенность составляет единицы и доли люмена, солнечным днем около внутри комнаты освещенность будет около 1000 люмен, а у окна — около 10 000 люмен.

Для каждого светодиода искал максимум освещенности – наводил систему мелкими шагами на самое яркое пятно на улице и на самое темное в комнате и затем уносил систему в темное помещение.

Результаты обработки измерений приведены в таблице.
(цифры в таблице – время разрядки в миллисекундах)
LED окно комната в темноте диапазон, раз
зеленый 4 440 4524 1131
белый 16 1028 10161 635
красный 2 49 883 442
желтый 4 25 287 72
синий 5 53 53 11

Получилось, что зеленый светодиод обладает максимальной шириной диапазона – более 1000 раз (от единиц мс до 4 секунд), за ним идет белый (635 раз), затем красный (442) и желтый (72) и замыкает список синий с диапазоном 11. Белый светодиод отличился еще и меньшей чувствительностью к свету.
Подробная интерпретация полученных результатов лежит за рамками данной статьи, но ясно, что оптимально использовать в БК зеленый светодиод.

Преобразование показаний датчика освещенности в люксы.

Нормы на освещенность легко находятся в интернете (Санитарные правила и нормы СанПиН 2.2.1/2.1.1.1278-03). Из изучения этого документа следует, что освещенность нормируется в диапазоне 20 – 750 люкс (от кладовой до рабочего места для точных работ). Иначе говоря, калибровать датчик освещенности БК имеет практический смысл в диапазоне от единиц люкс до тысячи люкс.

Для решения этой задачи я применил готовый калиброванный датчик BH1750. Датчик был подключен к отдельной Ардуино, подключенной к Wi-Fi модулю. Скетч читал показания датчика и транслировал их в сеть, откуда они забирались программой, усреднялись на интервале 1 минуты и записывались в лог файл. После нескольких дней я обработал эти первичные данные, сопоставив данные от БК и калиброванного датчика. В результате обработки данных я получил таблицу преобразования, по которой можно пересчитать время разрядки диода в люксы. Из таблицы можно вывести формулу, но я это оставил на When I'm sixty four.

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



Напряжение питания меняется из-за циклов нагрева и измерения датчика CO MQ7. В цикле измерения на него подается 1.4В, а в цикле нагрева — 5в, ток потребления меняется, меняется напряжение питания и уплывает порог срабатывания входа D3. По измерениям получилось, что из-за фактора нестабильности питания изменение времени составляет от 10% при высоких уровнях освещенности до более 30% при низких.

Это изменение можно скорректировать программно.

Учитывая, что точность измерений получилась весьма невысокой (ошибки порядка 30%), я решил ограничиться простейшим способом преобразования измеренного времени разряда в люксы в виде таблицы. Микропроцессор Ардуино Нано обладает весьма скромными ресурсами для серьезной обработки таких данных и я принял решение перенести более серьезную обработку в программу на Visual Basic. В такой программе можно и провести фильтрацию данных, усреднение на большом интервале времени. На текущий момент график освещенности за сутки выглядит так:



Черная стрелка — момент выключения телевизора. Красная — восход Солнца (на сегодня 20 ноября 2014 это 8:13 по данным Гисметео).

Датчик в виде диода сохраняет отзывчивость и на малые уровни освещенности в районе единиц и десятых долей люкса. Датчик BH1750 имеет минимальную чувствительность в 1 люкс. Так например BH1750 не реагирует на телевизор или настольную лампу мощностью в единицы ватт (светодиодную), а датчик в БК – уверенно реагирует. Есть впрочем и другие датчики освещенности с существенно большим диапазоном, например MAX44009 c заявленным диапазоном 0,045 — 188000 люкс, интерфейсом I2C, но и ценой порядка 200 р (в Чипе и Дипе — 250р). Впрочем, может быть в следующей версии БК я заменю датчик освещенности. Использование готовых модулей конечно правильнее с точки зрения качества оконечного изделия, но делать что-то своими руками интереснее на порядок.

Использование светодиода и метода измерения длительности разряда в таком простейшем виде не обеспечивает достаточной точности, но может быть использовано например для выполнения подстройки яркости дисплея или каких-то еще задач, которым нужно знание освещенности грубо, с точностью до 30-40%. Скажем возможно уверенное различение дня и ночи.

Дисплей

В БК я использовал дисплей от Нокии 3510i. Единственным его плюсом является очень низкая цена в магазинах запчастей для сотовых. Я купил этот дисплей за 46 р. Минус – нет светодиодов подсветки, надо делать свои, небольшой размер, маленькая цветность – 4096 цветов и замороченное программирование обмена в режиме 4096 цветов. На текущий момент оптимальным видится использование готовых модулей типа такого. Этот модуль несколько дороже (около 300 р), но полный цвет, встроенная подсветка, простое программирование перевешивают незначительное увеличение цены. Я использовал этот модуль в радиометре и вполне доволен его качеством. О радиометре с Wi-Fi и Глонасс\GPS см. статью тут.

Подсветку в дисплее Нокия 3510i я сделал в виде планки из двухстороннего фольгированного стеклотекстолита с равномерно размещенными тремя светодиодами. Высота планки около 3-х мм, ширина – соответствует ширине торца дисплея. На планке сделаны прорези в фольге и по месту напаяны светодиоды. Последовательно с каждым диодом включен резистор 20 ом, все секции соединены параллельно и последовательно включен еще один резистор для управления яркостью подсветки. Планка припаяна двумя медными проводами в торце дисплея. Подвеска подсветки на гибких медных проводах позволяют подобрать положение планки для достижения оптимальной яркости дисплея.

Использованы светодиоды «BL-LS3014A0S1UW2C, Светодиод SMD 3014, Warm White, 120˚ 2300мКд», купленные в Чипе и Дипе по 26 р. С учетом светодиодов (3 использовал + 1 спалил) цена дисплея получается уже около 150 рублей, что всего лишь вдвое меньше готового.
Дисплейный модуль смонтирован в крышке Куба и присоединен к основному модулю плоским шлейфом. Дополнительный провод – для подсоединения динамика, который есть на дисплее. Я его использовал в последний момент, когда остались и свободная нога на Ардуине и место в памяти для кода, генерирующего звуковые сигналы.

image

Странная форма дисплейного модуля получилась из-за ошибок проектирования. Я решил что отверстий по бокам Куба хватит для отвода тепла, но практически оказалось, что не хватает и необходимо сверху тоже сделать отверстия. Поскольку дисплейный модуль закрывал всю верхнюю крышку – пришлось удалить все возможное, чтобы дать максимальный проход для теплого воздуха. Ножницы по металлу и дремель прекрасно справились с задачей удаления ненужного :) Дополнительный провод МГТФ, обмотанный вокруг плоского шлейфа, добавлен в последний момент для подачи сигнала на пищалку.

Встроенный дисплей БК, экран 1:

image

Слева направо, по строкам:
Влажность, температура воздуха
Уровень CO2, ppm, давление воздуха в миллиметрах рт ст, температура внутри БК
Уровень CO текущий, измеренный, статус (N – нагрев, I – измерение)
Уровень дыма, уровень горючих газов
Уровень аммиака, паров этилового спирта

Экран 2:

image

Слева направо, по строкам:
Показания датчика магнитного поля по трем осям – X, Y, Z
Показания датчика гравитации по трем осям – X, Y, Z
Показания датчика ускорений поля по трем осям – X, Y, Z
Уровень водорода, освещенность.

Последнее значение в первой строке – фактически отклонение от направления на северный магнитный полюс 
Вот любопытная фотография:

image

Как можно заметить – стрелка компаса и грань куба практически параллельны друг другу и направлению на магнитный север.
Нуль оси Z – потому что датчик установлен вертикально и ось Z горизонтальна, ось Y вертикальна.

Экран 3, температурные датчики:

image

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

Продолжение следует.