Итак, вчера я собрал простенькое устройство на Arduino Uno для получения данных о концентрации CO2 в помещении. Устройство заработало и даже передавало какие-то данные в COM-порт. Однако нас интересует не просто какое-то абстрактное число, которое поступает в COM-порт, а именно значение концентрации CO2 в помещении. И сегодня будем разбираться с тем, как интерпретировать значения, передаваемые датчиком MQ135.
Первое, с чем необходимо разобраться — это то, что за «магические» числа попадают в COM-порт? Например, у меня сейчас монитор порта показывает вот такие числа:
Analog value: 93.00 Digital Value: 1 Analog value: 103.00 Digital Value: 1 Analog value: 103.00 Digital Value: 1 Analog value: 101.00 Digital Value: 1 Analog value: 98.00 Digital Value: 1 Analog value: 97.00
В скетче, для получения значения «Analog value» использовалась функция analogRead(). Посмотрим, что это за функция.
analogRead() — считывает значение с указанного аналогового входа. Напряжение поданное на аналоговый вход (от 0 до 5 вольт) преобразуется в значение от 0 до 1023 (1024 шага с разрешением 0.0049 Вольт).
То есть, получается, что значение 93, полученное с аналогового входа — это примерно 0,4557 вольт.
С напряжением разобрались. Теперь посмотрим как это напряжение преобразовать в значение концентрации. Вчера я вкратце описывал суть работы датчика MQ135 — чувствительный слой датчика нагревается до определенной температуры и начинает реагировать на определенный газ. Соответственно, по изменению напряжения, которое выдается на аналоговый выход можно оценить то на сколько больше/меньше становится концентрация газа. Звучит, вроде бы, относительно просто, но на деле — сплошной мрак.
На просторах Интернета можно найти спецификацию (datasheet) по датчику MQ135 и схему его подключения, например, вот такой datasheet.
Спецификация гласит следующее:
вот так выглядят характеристики чувствительности MQ-135 для нескольких газов при температура 20 градусов Цельсия, относительной влажности 65%, концентрации кислорода 21% и концентрации аммиака 100 ppm в чистом воздухе
R0 — это сопротивление датчика при 100 ppm NH3 в чистом воздухе.
RS — это сопротивление датчика при различных концентрациях газов.
При этом для датчика использовалось нагрузочное сопротивление (RL) в 20 кОм. Следуя всё той же спецификации, нагрузочное сопротивление может быть абсолютно различным, однако рекомендуется использовать нагрузочное сопротивление от 20 до 47 кОм. Хорошо, до сопротивления RL мы ещё доберемся, а пока разберемся с тем, как воспользоваться приведенным выше графиком, чтобы просчитать концентрацию CO2.
Первый и самый легкий путь — это воспользоваться готовой библиотекой для MQ135 и переложить все расчёты концентрации на Arduino. Таких библиотек в Сети можно найти массу, например, есть вот такая. Порядок установки библиотек в Arduino IDE следующий:
- Скачиваем архив с библиотекой в любое удобное место на жестком диске
- В меню выбираем «Скетч — Подключить библиотеку — Добавить .ZIP библиотеку» и указываем загруженный архив
После того, как библиотека будет добавлена, она появится в списке:
Выбираем библиотеку в списке и она подключается к нашему скетчу. В коде это будет выглядеть вот так:
#include
Чтобы воспользоваться библиотекой нам необходимо как минимум:
- Узнать значение нагрузочного сопротивление (RL) установленного на плате нашего датчика
- Внести изменения в библиотеку
- Откалибровать наш датчик (получить значение R0)
Начнем по порядку.
Узнаем значение нагрузочного сопротивления
Учитывая, что датчики MQ135 и аналогичные им могут устанавливаться на различные платы с разными нагрузочными сопротивлениями, RL нам придётся узнавать опытным путем. На плате моего датчика стоит резистор с маркировкой «102», что означает 1 кОм.
Вносим изменения в библиотеку
Библиотеки Arduino IDE по умолчанию находятся в директории c:\Users\%UserName%\Documents\Arduino\libraries\.
Ищем в этой директории папку с названием библиотеки (она будет называться «MQ135-master») и в этой папке открываем файл MQ135.h
В этом файле меняем значение обозначенное как RLOAD (по умолчанию там стоит значение 10) на то значение, которое мы узнали на предыдущем шаге, т.е. на единицу.
Сохраняем файл и двигаемся далее.
Калибруем датчик
Для калибровки датчика нам придётся написать вот такой скетч:
#include #define analogPin A0 // аналоговый выход MQ135 подключен к пину A0 Arduino MQ135 gasSensor = MQ135(analogPin); void setup() { Serial.begin(9600); // инициализация последовательного порта pinMode(analogPin, INPUT); // режим работы аналогового пина delay(5000); // даём датчику небольшое время на разогрев } void loop() { float rzero = gasSensor.getRZero(); // чтение калибровочных данных Serial.println(rzero); // выдача в последовательный порт delay(1000); // задержка перед выводом следующего значения }
Теперь, по логике вещей, мы должны сейчас найти чистый воздух, где содержание кислорода составляет ровно 21%, температура воздуха 20 градусов Цельсия и относительная влажность 65%. Оставить на таком воздухе наш датчик минут на 20-30, потом все полученные значение осреднить и получить наше итоговое значение R0.
Однако, учитывая то, что мне такого чистого помещения вряд ли удастся найти, я просто проветрил комнату в которой нахожусь, накрыл всю конструкцию небольшой коробкой и оставил так на 20 минут. В итоге я получил значение RO = 70.83. Это значение я также внёс в MQ135.h.
Получаем значение концентрации CO2 в помещении
Осталось теперь получить значение концентрации CO2 в помещении. Для этого заменяем скетче строку
float rzero = gasSensor.getRZero(); // чтение калибровочных данных
на такую
float CO2ppm = gasSensor.getPPM(); // чтение концентрации в PPM
Загружаем скетч в память и через несколько секунд в мониторе порта видим следующие значения:
439.39 439.39 439.39 428.56 428.56 428.56 428.56 428.56 428.56 428.56 428.56 417.91 417.91 417.91 417.91
Много это или мало — 428 ppm CO2? Судя по данным википедии концентрация CO2 в атмосфере составляет порядка 400 ppm. Если быть точнее, то (цитата): 11 мая 2019 года, зафиксирован новый рекорд концентрации CO2 в атмосфере: 415,28 ppm (или 0,041528 % углекислого газа в воздухе). При этом, нормой в помещении, судя по этим данным, считается концентрация в 800 — 1000 ppm. Если подуть на датчик, то он ожидаемо выдаст значение CO2 выше (у меня доходило значение до 800 ppm).
И на этом моменте (получение концентрации CO2) я бы и хотел остановиться по-подробнее. Насколько то значение, которое мы получаем с датчика является правдивым?
Первое, где большинство любителей поиграться с Arduino спотыкается — это калибровка датчика. Согласитесь, что найти в обычных условиях чистое помещение с заданными условиями микроклимата — практически не реально.
Второе, исходя из особенностей работы датчика мы здесь не учитываем, как минимум два важных параметра: температуру и влажность в помещении, которые явно влияют на сопротивление.
И третье, тот самый чувствительный слой оксида олова реагирует ведь не только на CO2, но может среагировать и вообще на всё подряд. В той же спецификации указано, что датчик реагирует не CO2, бензол, аммиак и etc. Соответственно, погрешность может возникнуть, если в воздухе одновременно будут находиться, например, аммиак, СО2 и бензол. Или показание датчика может быть вообще неверно интерпретировано, например, когда в чистом помещении мы вдруг захотим определить концентрацию бензола (которого фактически нет) — на аналоговый пин просто подастся какое-то напряжение и всё, а мы, следуя графикам из спецификации интерпретируем его, например, как 100 ppm бензола.
Таким образом, из всего вышесказанного можно сделать вывод — чтобы можно было получить от датчика более менее корректные значения и правильно их интерпретировать — придётся серьезно «попотеть». Но, у меня ещё пять дней вынужденных выходных, поэтому в следующий раз (завтра) я попытаюсь соединить воедино устройство Arduino и программку на Delphi, чтобы проанализировать работу MQ135 и попытаться вытащить из его работы хоть какие-то полезные данные.