Приветствую всех, кто интересуется качеством воздуха в помещении и хочет это контролировать и управлять.
Я сам заинтересовался этим вопросом недавно и решил пощупать датчик CO2 MH-Z19B своими руками. Меня вдохновило много статей, например Тёмная сторона MH-Z19.
Однако нигде (даже в инструкции) я не нашел как работать с пином Vo…
Я обратил внимание вот на что: в статье Обзор инфракрасного датчика CO2 MH-Z19 упоминается такой пункт:
- Vo — выходное напряжение 3.3В, не более 10мА
На некоторых интернет-магазинах, например, "Датчик углекислого газа CO2 MH-Z19B" указывается подобная информация:
- Vo — выходное напряжение 3.3В, не более 10мА
(как под копирку)
Но в инструкции (тут) указано чуть подробнее:
- Vo Analog output (0.4~2 V)or (0~2.5V)
А если копнуть еще, то в инструкции (тут) указано еще подробнее:
- Vo (Pin2) — Analog output (0.4~2 V) (0~3V range could be customized)
Я быстро погуглил и… ничего не нашел про этот выход! Странно, подумал Штирлиц, быстро подключил этот выход на аналоговый вход ESP8266 (для Arduino это тоже актуально) и начал исследовать.
Выводы:
- Напряжение на аналоговом выходе изменяется от 0,4xx до 2,002в.
- Аналоговый выход повторяет напряжением цифрового сигнала ppm.
- При изменении командами UART диапазона ppm 2k, 5k, 10k соотвественно изменяется диапазон преобразования Vo.
- Максимальное значение Vo=2,001в не изменяется в зависимости от диапазона, в качестве диапазона преобразования нужно устанавливать максимальное значение в ppm (2/5/10к).
- Минимальное значение Vo изменяется в зависимости от диапазона (?), а сам диапазон начинается от 400ppm.
- Если подобрать фактическое значение АЦП контроллера, то можно получить достойное соотвествие между напряжением и уровнем ppm. В диапазоне до 2k погрешность между цифровым сигналом UART и аналоговым преобразованием Vo не превышает нескольких единиц ppm.
- Можно или с помощью преобразователя USB-TTL или с помощью Arduino+ первично настроить датчик (отключить автокалибровку и перевести в «домашний» диапазон 400...2000ppm) и далее работать с ним как с аналоговым сигналом.
Как я преобразовывал:
[...]
const word cADC00v = 3; // ADC = 3 уе. при 0.0v
const word cADC04v2k = 235; // ADC = 235 уе. при 400ppm @2k
const word cADC04v5k = 174; // ADC = 174 уе. при 400ppm @5k
const word cADC04v1k = 153; // ADC = 153 уе. при 400ppm @10k
const word cADC20v = 646; // ADC = 646 6уе. при 2.0v
word ADC = analogRead(A0); // Чтение 10 бит ADC 0...1023
long Vin = map(ADC, cADC00v, cADC20v, 0, 2001); // Напряжение 0..3,3v по даташиту, фактически до 2,001v
long ppm_2k_04_2 = map(ADC, cADC04v2k,cADC20v, 400, 2000); // Преобразование Vo в ppm в диапазоне 2k
long ppm_5k_04_2 = map(ADC, cADC04v5k,cADC20v, 400, 5000); // Преобразование Vo в ppm в диапазоне 5k
long ppm_10k_04_2 = map(ADC, cADC04v1k,cADC20v, 400,10000); // Преобразование Vo в ppm в диапазоне 10k
[...]
«Магические» числа подобрал экспериментально. Так получилось и быстрее и точнее. При попытке посчитать очень точно, математически, фактически получилась большая погрешность.
Почему у меня так работает (0,4...2,0в а не 0...2,5в) я не знаю. Датчик куплен пару дней назад, производство 26 сентября 2019г. На корпусе выбит диапазон до 5к ppm.
Зачем это мне нужно? (ответ на «вот я бы сделал не так...»)
Ну… есть люди, которые любят держать паяльник в руках, а вот с контроллерами не дружат. Для них аналоговый выход это как минимум включить/выключить вентилятор, как максимум — плавное управление скоростью вытяжки/приточки/рекуператора.
А конкретно у меня: в соседней комнате уже 2 года работает система вентиляции, которую я сделал на свободно-программируемом промышленном контроллере. Т.к. контроллер промышленный, то и система программирования специфическая, не уверен, что на нем можно написать свой протокол обмена по UART. Да, там есть последовательный порт RS484, который прекрасно работает по ModBus, но этот порт занят системой диспетчеризации.
А вот что есть — свободный аналоговый вход, который можно настроить на 0-10в. И так имея всего около 30$ можно проапгрейдить систему вентиляции на интеллектуальное энергосбережение (вентилировать только тогда, когда нужно, и ровно на столько, на сколько нужно).
P.S.: код SoftSerial.readBytes(mhzBuffer, 9); на моем ESP8266 отказался работать. Убил на это около пяти часов жизни. Здесь это обсуждали, но прочитал я уже позже. Писал свою функцию в стиле if (SoftSerial.available() { x=SoftSerial.read(); }
.
Автор: veoramid