- Почему измерение co2 важно во времена короны?
- Основные результаты использования arduino с mh-z14a
- Основные результаты использования esp8266 с mh-z14a
- Основные выводы при создании сигнализации co2 с помощью mh-z14a
- Основные результаты использования esp32 с mh-z14a
- Arduino и датчик mq-135: измерение концентрации углекислого газа в воздухе
- Аналоговый интерфейс mh-z14a
- Видео, демонстрирующее работу проекта
- Выбор режима питания нагревателя
- Выходные контакты
- Датчик co2 mh-z14a
- Датчик газа mq-135
- Датчик углекислого газа в воздухе (co2) "mh-z19b" – головоломка
- Интерфейс mh-z14a uart
- Исходный код программы (скетча)
- Как измерить концентрацию co2 в воздухе?
- Коммуникационные интерфейсы mh-z14a
- Коррекция базовой линии mh-z14a
- Модуль oled дисплея (0.96’ oled display module)
- Необходимые компоненты
- Подключение mh-z14a к разным микроконтроллерам
- Подключение и настройка
- Преобразователь логических уровней
- Программный код arduino для сигнализации co2 с mh-z14a
- Распиновка mh-z14a
- Регулятор напряжения 3v3
- Результаты использования arduino с mh-z14a после повторной калибровки
- Смена адреса модуля
- Создание сигнализации co2 с помощью mh-z14a
- Схема проекта
- Шим интерфейс mh-z14a
- Заключение по созданию сигнализации co2 с помощью mh-z14a
Почему измерение co2 важно во времена короны?
Основная причина, по которой люди заражаются SARS-CoV-2 (вирусом, вызывающимся COVID-19), – это контакт с респираторными каплями, переносящими инфекционный вирус.
Во время выдоха образуются дыхательные капли (дыхание, речь, пение, кашель, чихание и т.д.). Размер этих капель различается и в основном делится на две категории:
- Более крупные капли
- Более мелкие капли и частицы
Мы хотим сосредоточиться на этих более мелких каплях и частицах, которые передаются воздушно-капельным путем, когда инфекционный человек вырабатывает респираторные капли в течение длительного времени (от 30 минут до нескольких часов) в замкнутом пространстве, таком как офис.
Мы можем избежать передачи через вентиляцию, например, через открытые окна в офисах или классах. Цель состоит в том, чтобы избежать высокой концентрации респираторных капель и частиц в воздухе.
Но когда достигается концентрация, то я должен открыть окна в своем офисе? Концентрацию респираторных капель в воздухе измерить крайне сложно. Но мы можем измерить концентрацию углекислого газа (CO2) в выдыхаемом воздухе во время дыхания. Эта концентрация CO2 пропорциональна концентрации респираторных капель в воздухе.
Таким образом, целью данного руководства является создание измерителя CO2, который сообщит вам, когда будет достигнута концентрация респираторных капель, чтобы открыть окна, чтобы снизить риск заражения COVID-19, или просто когда следует проветрить помещение.
Основные результаты использования arduino с mh-z14a
На следующем рисунке показаны мои измерения с Arduino Uno, визуализированные с помощью последовательного плоттера Arduino IDE. Калибровка MH-Z14A во время этого измерения не производилась. Разница после повторной калибровки показана в следующем подразделе.
Использование аналогового интерфейса MH-Z14A с микроконтроллером Arduino (синяя линия)
Если вы видите аналоговые значения на последовательном плоттере, вы сразу замечаете более высокие выбросы, которые, кажется, возникают на регулярной основе. Для стабильного и достоверного измерения выбросы представляют собой большую проблему, потому что наша сигнализация сработает, когда выброс превысит предварительно определенное значение сигнализации.
Использование интерфейса UART MH-Z14A с микроконтроллером Arduino (красная линия)
Использование связи UART для получения значений CO2 от MH-Z14A вызывает те же проблемы, что и аналоговый интерфейс. Мы можем видеть, что значения датчика UART частично совпадают с ШИМ интерфейсом, но часто падают. Такое поведение кажется необычным и не позволяет использовать интерфейс UART для сигнализации CO2.
Использование интерфейса ШИМ MH-Z14A с микроконтроллером Arduino (зеленая линия)
Интерфейс ШИМ – единственный интерфейс, который не имеет выбросов и поэтому может использоваться для нашей сигнализации CO2. В большинстве случаев значения ШИМ также подтверждаются концентрацией CO2 из интерфейса UART.
Основные результаты использования esp8266 с mh-z14a
Ключевой вывод при использовании ESP8266 с MH-Z14A заключается в том, что эта комбинация у меня не заработала. Я попробовал взять другой микроконтроллер ESP8266 и пробовал каждый интерфейс измерения отдельно. Но у меня всегда был один и тот же код ошибки, который вы видите на следующем рисунке.
Основные выводы при создании сигнализации co2 с помощью mh-z14a
В последней главе этой статьи я хочу обсудить свои основные выводы, полученные при использовании разных микроконтроллеров и CO2 датчика MH-Z14A.
Основные результаты использования esp32 с mh-z14a
Когда я использовал ESP32 с MH-Z14A, у меня возникли проблемы с интерфейсом UART, что привело к постоянному перезапуску ESP32. По этой причине я использовал только аналоговый интерфейс и интерфейс ШИМ для получения концентрации CO2. Обратите внимание, что все значения датчика записываются перед повторной калибровкой.
Использование аналогового интерфейса MH-Z14A с микроконтроллером ESP32 (синяя линия)
Аналоговый интерфейс ESP32 демонстрирует то же поведение, что и Arduino. Мы регулярно получаем более высокие концентрации CO2.
Использование интерфейса ШИМ MH-Z14A с микроконтроллером ESP32 (красная линия)
Интерфейс ШИМ показывает действительные значения датчика без каких-либо выбросов. Поэтому я бы рекомендовал использовать интерфейс ШИМ MH-Z14A при использовании микроконтроллера ESP32.
Arduino и датчик mq-135: измерение концентрации углекислого газа в воздухе
Уровень углекислого газа (двуокись углерода или CO2) в атмосфере Земли повышается день ото дня. Среднее значение CO2 в атмосфере в 2022 году составило 409,8 частей на миллион, а в октябре 2020 года – 411,29. Двуокись углерода является ключевым парниковым газом, на который приходится около трех четвертей выбросов. Таким образом, мониторинг уровня CO2 также стал приобретать все большее значение.
В нашем предыдущем проекте мы использовали инфракрасный датчик CO2 для измерения концентрации CO2 в воздухе. В этом проекте мы собираемся использовать датчик MQ-135 с Arduino для измерения концентрации углекислого газа. Измеренные значения концентрации CO2 будут отображаться на OLED-модуле.
Датчик газа MQ-135 – это датчик качества воздуха для обнаружения широкого спектра газов, включая NH3, NOx, спирт, бензол, дым и CO2. Датчик MQ-135 можно приобрести как в виде модуля, так и просто как датчик. В этом проекте мы используем сенсорный модуль MQ-135 для измерения концентрации CO2 в PPM. Принципиальная схема платы модуля MQ-135 приведена далее.
Нагрузочный резистор RL играет очень важную роль в обеспечении работы датчика. Этот резистор изменяет свое значение сопротивления в зависимости от концентрации газа. Согласно документации на MQ-135, сопротивление нагрузочного резистора может находиться в диапазоне от 10 кОм до 47 кОм. В документации рекомендуется откалибровать детектор на концентрацию 100 ppm NH3 или 50 ppm спирта в воздухе и использовать значение сопротивления нагрузки (RL) около 20 кОм. По умолчанию на плате стоит значение этого резистора 1 кОм.
Таким образом, чтобы измерить соответствующие значения концентрации CO2, вам необходимо заменить резистор 1 кОм на резистор 22 кОм. Полная схема подключения датчика газа MQ-135 к Arduino приведена далее.
Схема очень проста, поскольку мы подключаем только датчик MQ-135 и модуль OLED-дисплея к Arduino Nano. Датчик газа MQ-135 и модуль OLED-дисплея питаются от 5 В. Вывод аналогового выхода датчика MQ-135 подключен к выводу A0 Arduino Nano. Поскольку модуль OLED-дисплея использует связь SPI, мы установили связь SPI между модулем OLED и Arduino Nano. После подключения оборудования в соответствии с принципиальной схемой оно должно выглядеть примерно так:
Теперь, когда мы знаем значение RL, давайте приступим к расчету значений Ro для чистого воздуха. Здесь мы собираемся использовать MQ135.h для измерения концентрации CO2 в воздухе. Поэтому сначала загрузите библиотеку MQ-135, затем предварительно нагрейте датчик в течение 24 часов, прежде чем считывать значения Ro. После процесса предварительного нагрева используйте приведенный ниже код, чтобы прочитать значения Ro.
#include "MQ135.h"
void setup (){
Serial.begin (9600);
}
void loop() {
MQ135 gasSensor = MQ135(A0); // Attach sensor to pin A0
float rzero = gasSensor.getRZero();
Serial.println (rzero);
delay(1000);
}
Теперь, когда вы получили значения Ro, перейдите в Документы – Arduino –libraries –MQ135-master, откройте файл MQ135.h и измените значения RLOAD и RZERO.
#define RLOAD 22.0
#define RZERO 5804.99
Теперь прокрутите вниз и замените значение ATMOCO2 текущим значением CO2 в атмосфере, равным 411,29.
#define ATMOCO2 397.13
Полный код для взаимодействия датчика MQ-135 с Arduino приведен далее.
#define RLOAD 22.0
#include "MQ135.h"
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_MOSI 9
#define OLED_CLK 10
#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
MQ135 gasSensor = MQ135(A0);
int val;
int sensorPin = A0;
int sensorValue = 0;
void setup() {
Serial.begin(9600);
pinMode(sensorPin, INPUT);
display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();
display.display();
}
void loop() {
val = analogRead(A0);
Serial.print ("raw = ");
Serial.println (val);
// float zero = gasSensor.getRZero();
// Serial.print ("rzero: ");
//Serial.println (zero);
float ppm = gasSensor.getPPM();
Serial.print ("ppm: ");
Serial.println (ppm);
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(18,43);
display.println("CO2");
display.setCursor(63,43);
display.println("(PPM)");
display.setTextSize(2);
display.setCursor(28,5);
display.println(ppm);
display.display();
display.clearDisplay();
delay(2000);
}
Как только оборудование и код будут готовы, следует проверить датчик. Для этого подключите Arduino к ноутбуку, выберите плату и порт и нажмите кнопку загрузки. Затем откройте монитор последовательного порта и подождите некоторое время (процесс предварительного нагрева), после чего вы увидите окончательные данные. Значения будут отображаться на OLED-дисплее, как показано на следующем изображении.
© anemometers.ru
Аналоговый интерфейс mh-z14a
Всего имеется два разных аналоговых выхода MH-Z14A, которые отличаются выходным напряжением аналогового выхода.
- Vout1 имеет расширение. выходное напряжение от 0 В до 2,5 В для диапазона выходного сигнала от 0 до 5000 частей на миллион.
- Vout2 имеет расширение. выходное напряжение от 0,4 В до 2 В для диапазона выходного сигнала от 0 до 5000 частей на миллион.
Поскольку диапазон напряжения Vout1 выше, мы можем получить более подробные измерения от Vout1, которые мы хотим использовать для нашей сигнализации CO2 в этой статье.
Чтобы рассчитать концентрацию CO2, мы должны сделать следующие шаги:
- Считайте аналоговое значение с помощью analogRead функции.
- Пересчитайте аналоговое напряжение на основе рабочего напряжения микроконтроллера и максимального значения аналого-цифрового преобразователя (АЦП) микроконтроллера.
- Рассчитайте концентрацию газа, используя следующий градиентный треугольник.
Теперь мы можем погрузиться в уравнения для расчета концентрации CO2 от MH-Z14A, когда вы используете вывод Vout1 или Vout2 на MH-Z14A.
Формулы, когда Vout1 используется для расчета концентрации газа.
Формулы, когда Vout2 используется для расчета концентрации газа.
Видео, демонстрирующее работу проекта
732 просмотров
Выбор режима питания нагревателя
В сенсоре предусмотрено два режима работы, переключаемых джампером.
Выходные контакты
Датчик подключается к управляющей электронике через выходной кабель с четырьмя проводниками:
Датчик co2 mh-z14a
Для нашего датчика Corona CO2 мы используем MH-Z14A с рабочим напряжением от 4,5 В до 5,5 В. Следовательно, датчик CO2 может работать на всех микроконтроллерах Arduino с рабочим напряжением 5 В. Для микроконтроллеров ESP8266 и ESP32 с рабочим напряжением 3,3 В мы должны использовать выход 5 В от USB-соединения.
Во время работы MH-Z14A потребление тока составляет около 100 мА и поэтому не подходит для проекта с батарейным питанием.
При первом запуске датчика CO2 ИК-лампе требуется около 3 минут для предварительного нагрева, чтобы создать оптимальное ИК-излучение через измеряемый газ. Мы можем использовать эту информацию о функции настройки позже в скрипте Arduino, где мы приостанавливаем весь скрипт на 3 минуты, прежде чем считать какие-либо значения датчиков.
Диапазон измерения CO2 составляет 0…5000 ppm с точностью измерения около ± 50 ppm. В соответствии с данными из Европейской ассоциации отопления и вентиляции(REHVA) в хорошо проветриваемом помещении концентрация CO2 ниже 800 частей на миллион (наш предупреждающий сигнал) и должна быть ниже 1000 частей на миллион (наш сигнал тревоги).
Датчик газа mq-135
Датчик MQ-135 относиться к полупроводниковым приборам. Принцип работы датчика основан на изменении сопротивления тонкопленочного слоя диоксида олова SnO2 при контакте с молекулами определяемого газа. Чувствительный элемент датчика состоит из керамической трубки с покрытием Al2O3 и нанесенного на неё чувствительного слоя диоксида олова.
Внутри трубки проходит нагревательный элемент, который нагревает чувствительный слой до температуры, при которой он начинает реагировать на определяемый газ. Чувствительность к разным газам достигается варьированием состава примесей в чувствительном слое.
Датчик углекислого газа в воздухе (co2) "mh-z19b" – головоломка
Чтобы окончательно решить исход вековечной вражды в офисе между «теми, кому дует» и «теми, кому душно» решил разориться на бюджетный датчик содержания CO2 в атмосферном воздухе
и прикрутить к нему сирену
. Поскольку цена на такие датчики — совсем негуманная, выбрал вариант «MH-Z19B», который оказался самым бюджетным.
К сожалению, датчик подарил головоломку. Подробности — под катом.
(Внимание — в обзоре много «программизма», ругани в адрес китайских даташитов, присутствует шестнадцатеричная математика — так что если тема DIY вам не близка, проходите мимо, иначе будете разочарованы).
Датчик «MH-Z19B» сделан китайской компанией «Winsen» (даташит, PDF) и неоднократноупоминался на Habrahabr и Geektimes. Это вторая ревизия, с буквой «b» в названии, по результатам китайской «работы над ошибками». Первую ревизию одним неверным движением можно было ввести в режим калибровки, для которой требовалась атмосфера с нулевым содержанием CO2. Бедолагам, которые в это влетали, приходилось искать баллон с чистым азотом или кислородом, чтобы её организовать. В ревизии «b» китайцы сделали так, что модуль «эталонной» считает смесь с 400ppm углекислоты — то есть его можно, теоретически, перекалибровать просто в лесу или в парке.
Модуль пришёл в паре с небольшим шлейфом, основная плата имеет надпил, позволяющий отломать кусок с разъёмом и вместо этого припаять гребёнки. Модуль работает в двух режимах — UART (передавая показания по последовательному порту на 9600 бод) и PWM, контакты слева и справа, соответственно:
Для удобства я обрезал шлейф и насадил на провода дюпоновские наконечники. Правда, выяснилось, что часть проводов вообще ни к чему не подключена. Напротив, PWM оказался не выведен на шлейф, к контакту пришлось дополнительно подпаиваться, завернув из предосторожности датчик в плёнку поплотнее:
Датчик работает по следующему принципу — он получает по UART девятибайтовые команды (последний байт — CRC) и отвечает также девятибайтовыми пакетами. Замер концентрации СО2 выполняется командой с байтом 0x86:
Также показания можно прочитать, померяв ширину PWM-сигнала:
Тут подстерегала первая проблема — как узнать текущую размерность измерений? Даташит упоминает, что датчик может мерять в диапазаонах от нуля как до 2000, так и от нуля до 5000ppm:
Запросить текущее значение у датчика нельзя, поэтому остаётся только явно задавать размерность при каждом старте. Даташит описывает формат команды, которая скажет модулю, в какой шкале работать:
Почему-то ни одна инструкция в интернете этого вопроса не касается — никто толком не интересовался настройками датчика и просто принимают их как данность. Кряхтим и пишем код для Ардуино, который пошлёт модулю нужную команду:
(CRC вычисляем по формуле из того же даташита, (NOT(Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7)) 1)
Пробуем и так, и эдак, но в результате получаем на выходе дикие неправдоподобные значения концентрации СО2, вылетающие за паспортные диапазоны показаний датчика в разы. Уже испугавшись, что запороли дорогой прибор, через какое-то время нагугливаем ссылку revspace.nl/MHZ19 со словами
According to the MH-Z19B datasheet, you can configure the measurement range by putting the desired range in byte 3 and 4. However, unlike what the MH-Z19B datasheet says, you can set the range using the following command (in this case 0x07d0 = 2000 ppm in byte 6 and 7)
Замечательные китайцы ухитрились ошибиться в даташите!
Материмся, и вместо третьего и четвёртого байта пишем в шестой и седьмой. Благодаря подсказке неизвестного голландца — модуль воскресает.
Поскольку теперь доверия модулю нет никакого, решил разобраться с его показаниями досконально и сравнить результаты по UART и PWM. Пишем код под Ардуино, который сначала, в блоке setup, даёт команду установки размерности, а потом в цикле loop делает замеры. Модуль располагаем на сквозняке у форточки.
Код (финальный, уже включающий все позднейшие *открытия*
#include <SoftwareSerial.h>
#define pwmPin 10
SoftwareSerial swSerial(A0, A1); // RX, TX
void setup() {
Serial.begin(9600);
swSerial.begin(9600);
pinMode(pwmPin, INPUT);
/*
Источник - https://revspace.nl/MHZ19
2000 ppm range: 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x8F
5000 ppm range: 0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB
*/
// Этот вариант ("A") с записью команды в 6й и 7й байт - работает
// bytes: 3 4 6 7
byte setrangeA_cmd[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB}; // задаёт диапазон 0 - 5000ppm
unsigned char setrangeA_response[9];
swSerial.write(setrangeA_cmd,9);
swSerial.readBytes(setrangeA_response, 9);
int setrangeA_i;
byte setrangeA_crc = 0;
for (setrangeA_i = 1; setrangeA_i < 8; setrangeA_i ) setrangeA_crc =setrangeA_response[setrangeA_i];
setrangeA_crc = 255 - setrangeA_crc;
setrangeA_crc = 1;
if ( !(setrangeA_response[0] == 0xFF && setrangeA_response[1] == 0x99 && setrangeA_response[8] == setrangeA_crc) ) {
Serial.println("Range CRC error: " String(setrangeA_crc) " / " String(setrangeA_response[8]) " (bytes 6 and 7)");
} else {
Serial.println("Range was set! (bytes 6 and 7)");
}
delay(1000);
/*
// Этот вариант ("B") с записью команды в 3й и 4й байт, согласно даташиту - НЕ работает и поэтому закомментирован
// bytes: 3 4 6 7
byte setrangeB_cmd[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB};
unsigned char setrangeB_response[9];
swSerial.write(setrangeB_cmd,9);
swSerial.readBytes(setrangeB_response, 9);
int setrangeB_i;
byte setrangeB_crc = 0;
for (setrangeB_i = 1; setrangeB_i < 8; setrangeB_i ) setrangeB_crc =setrangeB_response[setrangeB_i];
setrangeB_crc = 255 - setrangeB_crc;
setrangeB_crc = 1;
if ( !(setrangeB_response[0] == 0xFF && setrangeB_response[1] == 0x99 && setrangeB_response[8] == setrangeB_crc) ) {
Serial.println("Range CRC error: " String(setrangeB_crc) " / " String(setrangeB_response[8]) " (bytes 3 and 4)");
} else {
Serial.println("Range was set! (bytes 3 and 4)");
}
delay(1000);
*/
}
void loop() {
byte measure_cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
unsigned char measure_response[9];
unsigned long th, tl, ppm = 0, ppm2 = 0, ppm3 = 0;
// ***** узнаём концентрацию CO2 через UART: *****
swSerial.write(measure_cmd,9);
swSerial.readBytes(measure_response, 9);
int i;
byte crc = 0;
for (i = 1; i < 8; i ) crc =measure_response[i];
crc = 255 - crc;
crc = 1;
if ( !(measure_response[0] == 0xFF && measure_response[1] == 0x86 && measure_response[8] == crc) ) {
Serial.println("CRC error: " String(crc) " / " String(measure_response[8]));
}
unsigned int responseHigh = (unsigned int) measure_response[2];
unsigned int responseLow = (unsigned int) measure_response[3];
unsigned int ppm = (256*responseHigh) responseLow;
// ***** узнаём концентрацию CO2 через PWM: *****
do {
th = pulseIn(pwmPin, HIGH, 1004000) / 1000;
tl = 1004 - th;
ppm2 = 2000 * (th-2)/(th tl-4); // расчёт для диапазона от 0 до 2000ppm
ppm3 = 5000 * (th-2)/(th tl-4); // расчёт для диапазона от 0 до 5000ppm
} while (th == 0);
Serial.print(ppm);
Serial.print(" <- ppm (UART) ");
Serial.print((ppm/5)*2);
Serial.println(" <- two fifths of it"); // Потом пришло озарение
Serial.print(th);
Serial.println(" <- Milliseconds PWM is HIGH");
Serial.print(ppm2);
Serial.println(" <- ppm2 (PWM) with 2000ppm as limit");
Serial.print(ppm3);
Serial.println(" <- ppm3 (PWM) with 5000ppm as limit");
Serial.println("-----------");
delay(5000);
}
Все замеры проводим, подключив модуль к питанию от 5 вольт; при 3.3 вольтах он выдаёт очевидно некорректные значения по верху диапазона.
В режиме PWM при заданном диапазоне значений от 0 до 2000ppm получаем, в условиях центра города, заполночь у форточки во двор, 1208ppm, что, безусловно, завышено. UART выдаёт нам близкое значение 1227ppm — различия вполне объяснимы ошибками оцифровки PWM-показаний.
Для сравнения, вот примерные дапазоны концентраций СО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: Возможны нежелательные эффекты на здоровье.
Переключаем датчик в диапазон 0 — 5000ppm. В режиме PWM у той же форточки во двор получаем 478ppm, что гораздо больше похоже на правду. Но вот в режиме UART наш датчик снова выдаёт совершенно неправдоподобное значение 1213ppm.
Десять раз перепроверив формулы, по близости показаний начинаю догадываться, что датчик считает с ошибками в арифметике. Модифицирую код, чтобы формула расчёта концентрации CO2 по данным PWM рассчитывалась с подстановкой всех вариантов верхнего предела значений. В момент какого-то озарения также дополнительно модифицирую код, чтобы значение, полученное по UART, дополнительно выводилось домноженным на 2000/5000:
диапазон 0 — 2000ppm
Range was set! (bytes 6 and 7)
1227 <- ppm (UART) 490 <- two fifths of it
606 <- Milliseconds PWM is HIGH
1208 <- ppm2 (PWM) with 2000ppm as limit
3020 <- ppm3 (PWM) with 5000ppm as limit
диапазон 0 — 5000ppm
Range was set! (bytes 6 and 7)
1213 <- ppm (UART) 484 <- two fifths of it
241 <- Milliseconds PWM is HIGH
478 <- ppm2 (PWM) with 2000ppm as limit
1195 <- ppm3 (PWM) with 5000ppm as limit
Делаем выводы:
После этого расследования датчик поселится в приборе в офисе, в компании с барометром, датчиком влажности воздуха, содержания пыли и ESP8266 для управления всем этим добром. Хоть я и вдохновился изначально приборчиками в переговорках московского Google, мой вариант не будет иметь цифр и экрана, а вместо этого получит более простую цветовую индикацию, как светофор — а подробные логи будет выкладывать по WiFi на сервер. Впрочем, это уже отдельная история.
Интерфейс mh-z14a uart
Если вы не хотите рассчитывать концентрацию CO2, вы можете получить значение концентрации CO2 непосредственно через интерфейс UART. Настройки для связи UART являются стандартными и перечислены в следующей таблице.
Скорость передачи | 9600 |
Байт даты | 8 байт |
Остановить байт | 1 байт |
Байт калибровки | none |
Процесс связи по UART следующий:
- Микроконтроллер отправляет заранее определенный 9-байтовый массив через UART на MH-Z14A.
- MH-Z14A отвечает в зависимости от содержимого запроса ответов длинной 9-байт, который считывает микроконтроллер.
- Массив ответов содержит концентрацию высокого уровня (байт 2), а также концентрацию низкого уровня (байт 3).
- Концентрация газа: высокий уровень * 256 низкий уровень
Вы также можете запустить калибровку нулевой точки и точки диапазона с помощью интерфейса связи UART. Вы найдете содержимое всех массивов в MH-Z14A datasheet или ниже, в нашем примере программирования.
Исходный код программы (скетча)
intsensorIn=A4; #include <SPI.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // ширина OLED дисплея в пикселах #define SCREEN_HEIGHT 64 // высота OLED дисплея в пикселах // контакты, к которым подключен OLED дисплей по интерфейсу SPI (default case): #define OLED_MOSI 9 #define OLED_CLK 10 #define OLED_DC 11 #define OLED_CS 12 #define OLED_RESET 13 Adafruit_SSD1306display(SCREEN_WIDTH,SCREEN_HEIGHT, OLED_MOSI,OLED_CLK,OLED_DC,OLED_RESET,OLED_CS); voidsetup(){ Serial.begin(9600); // используем значение опорного напряжения по умолчанию analogReference(DEFAULT); display.begin(SSD1306_SWITCHCAPVCC); display.clearDisplay(); display.display(); } voidloop(){ //Read voltage intsensorValue=analogRead(sensorIn); // преобразуем считанное с выхода АЦП значение в напряжение floatvoltage=sensorValue*(5000/1024.0); if(voltage==0) { Serial.println(“Fault”); } elseif(voltage<400) { Serial.println(“preheating”); } else { intvoltage_diference=voltage–400; floatconcentration=voltage_diference*50.0/16.0; // Print Voltage Serial.print(“voltage: “); Serial.print(voltage); Serial.println(“mv”); //Print CO2 concentration Serial.print(“CO2 Concentration: “); Serial.print(concentration); Serial.println(“ppm”); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(18,43); display.println(“CO2”); display.setCursor(63,43); display.println(“(PPM)”); display.setTextSize(2); display.setCursor(28,5); display.println(concentration); display.display(); display.clearDisplay(); } delay(2000); } |
Как измерить концентрацию co2 в воздухе?
Концентрация углекислого газа может быть измерена с помощью детектора инфракрасного (ИК) излучения, поскольку ИК-излучение СО2 имеет уникальную характеристику, которая определяется длиной волны. На следующем рисунке показаны длины волн различных газов и их сила поглощения.
На длине волны около 4250 нм поглощение CO2 является самым высоким. Таким образом, ИК-детектор CO2 может измерять концентрацию CO2 в воздухе, если измерения других длин волн отсутствуют. На следующем рисунке показана схема ИК-детектора.
На картинке видно, что есть вход и выход для газа. Инфракрасная лампа создает инфракрасное излучение через измеряемый газ. Это ИК-излучение фильтруется интерференционным фильтром до нужного газа, который необходимо измерять, в нашем случае CO2. Фильтр предотвращает попадание на ИК-детектор волны другой длины, кроме CO2.
Как и у всех газов, концентрация зависит от температуры и давления. Стандартная температура окружающей среды составляет 25 ° C, а давление – 1013 кПа. Уравнение для расчета концентрации газа при различных температурах и давлениях: p = p (25 ° C, 1013 кПа) * p / 1013 * 298 / (273 t)
В этой части мы могли бы углубиться в теорию, но хорошо то, что датчик CO2, который мы используем, имеет встроенную температурную компенсацию.
Коммуникационные интерфейсы mh-z14a
Всего существует три варианта считывания значений датчика с MH-Z14A, которые подробно описаны в следующих разделах.
Коррекция базовой линии mh-z14a
MH-Z14A имеет встроенную температурную компенсацию, называемую автоматической коррекцией базовой линии (ABC), для измерения точных значений CO2 также после смены комнаты с разными температурами. Базовым показателем для датчика CO2 является то, что уровень CO2 должен составлять 400 частей на миллион, что соответствует уровню CO2 в уличном воздухе.
- Подключите контакт 8 к GND минимум на 7 секунд.
- Отправьте определенную комбинацию байтов через интерфейс UART, см. Программный код для сигнализации аэрозолей.
Модуль oled дисплея (0.96’ oled display module)
OLED (Organic Light-Emitting Diodes, органический светоизлучающий диод) – это светоизлучающая технология, которая применяется в большинстве современных телевизоров. В OLED дисплеях используется тот же принцип формирования изображения, что и в современных телевизорах, только количество пикселей в них значительно меньше.
Для нашего проекта мы использовали монохромный 7-ми контактный OLED дисплей SSD1306 с диагональю 0.96”. Он может использовать 3 различных коммуникационных протокола: 3-х проводный SPI, 4-х проводный SPI и I2C.
Назначение его контактов (распиновка) приведены в следующей таблице.
Номер контакта | Название контакта | Альтернативное название контакта | Назначение контакта |
1 | Gnd | Ground | земля |
2 | Vdd | Vcc, 5V | напряжение питания (в диапазоне 3-5 В) |
3 | SCK | D0, SCL, CLK | используется как контакт синхронизации (clock pin). Применяется в интерфейсах I2C и SPI |
4 | SDA | D1, MOSI | контакт данных. Применяется в интерфейсах I2C и SPI |
5 | RES | RST, RESET | контакт сброса модуля. Применяется в интерфейсе SPI |
6 | DC | A0 | контакт команд (Data Command pin). Применяется в интерфейсе SPI |
7 | CS | Chip Select (выбор чипа) | используется когда несколько устройств взаимодействуют по интерфейсу SPI |
Подключение данного дисплея к плате Arduino рассматривалось в этой статье, а все проекты с использованием данного дисплея на нашем сайте вы можете посмотреть по следующей ссылке.
Технические характеристики OLED дисплея SSD1306:
- драйвер микросхемы OLED: SSD1306;
- разрешение: 128 x 64;
- угол зрения: >160°;
- входное напряжение: 3.3V ~ 6V;
- цвет пикселов: синий;
- диапазон рабочих температур: -30°C ~ 70°C.
Необходимые компоненты
- Плата Arduino Nano (купить на AliExpress).
- Инфракрасный датчик гравитации CO2 (Gravity Infrared CO2 Sensor V1.1) (купить на AliExpress).
- 0.96’ SPI OLED Display Module – модуль OLED дисплея с диагональю 0.96’ и поддержкой интерфейса SPI (купить на AliExpress – если будете покупать по приведенной ссылке, то выбирайте модель OLED дисплея с 7 контактами).
- Макетная плата.
- Соединительные провода.
Подключение mh-z14a к разным микроконтроллерам
Во-первых, нам нужно подключить MH-Z14A к нашему микроконтроллеру. На следующих рисунках показана проводка между датчиком CO2 и различными платами микроконтроллеров Arduino, ESP8266 и ESP32.
Подключение и настройка
Датчик газа MQ-135 подключается к управляющей электронике по 5 проводам. Для подключения используются два трёхпроводных шлейфа. Для быстрого подключения модуля к Iskra JS или Arduino используйте Troyka Shield.
С Troyka Slot Shield можно обойтись без лишних проводов.
Преобразователь логических уровней
Преобразователь логических уровней PCA9306 необходим для сопряжения датчика с разными напряжениями логических уровней от 3,3 до 5 вольт. Другими словами сенсор совместим как с 3,3 вольтовыми платами, например, Raspberry Pi, так и с 5 вольтовыми — Arduino Uno.
Программный код arduino для сигнализации co2 с mh-z14a
После разводки создадим программный скрипт. Большая часть программного сценария не зависит от микроконтроллера, но, поскольку есть некоторые небольшие различия, я создал программный сценарий индивидуально для Arduino, ESP8266 и ESP32.
#include <SoftwareSerial.h> SoftwareSerial SerialCom(13, 12); // RX, TX // analog interface const int analogPin = A0; // PWM interface const int PWMPin = 9; void setup() { SerialCom.begin(9600); pinMode(PWMPin, INPUT_PULLUP); delay(180000); // preheat the CO2 sensor for 3 minutes Serial.begin(115200); Serial.println("Analog:,UART:,PWM:"); } void loop() { int ppm_analog = get_analog(); int ppm_uart = gas_concentration_uart(); int ppm_PWM = gas_concentration_PWM(); Serial.print(ppm_analog); Serial.print(","); Serial.print(ppm_uart); Serial.print(","); Serial.println(ppm_PWM); delay(60000); // sleep for 1 minute } int get_analog() { float v = analogRead(analogPin) * 5.0 / 1023.0; int gas_concentration = int((v) * (5000 / 2)); return gas_concentration; } int gas_concentration_uart() { byte addArray[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; char dataValue[9]; SerialCom.write(addArray, 9); SerialCom.readBytes(dataValue, 9); int resHigh = (int) dataValue[2]; int resLow = (int) dataValue[3]; int ppm_uart = (resHigh * 256) resLow; return ppm_uart; } int gas_concentration_PWM() { while (digitalRead(PWMPin) == LOW) {}; long t0 = millis(); while (digitalRead(PWMPin) == HIGH) {}; long t1 = millis(); while (digitalRead(PWMPin) == LOW) {}; long t2 = millis(); long tH = t1 - t0; long tL = t2 - t1; long ppm = 5000L * (tH - 2) / (tH tL - 4); while (digitalRead(PWMPin) == HIGH) {}; delay(10); return int(ppm); }
#include <SoftwareSerial.h> SoftwareSerial SerialCom(D8, D7); // RX, TX // analog interface const int analogPin = A0; // PWM interface const int PWMPin = D6; void setup() { SerialCom.begin(9600); pinMode(PWMPin, INPUT_PULLUP); delay(180000); // preheat the CO2 sensor for 3 minutes Serial.begin(115200); Serial.println("Analog:,UART:,PWM:"); } void loop() { int ppm_analog = get_analog(); int ppm_uart = gas_concentration_uart(); int ppm_PWM = gas_concentration_PWM(); Serial.print(ppm_analog); Serial.print(","); Serial.print(ppm_uart); Serial.print(","); Serial.println(ppm_PWM); delay(60000); // sleep for 1 minute } int get_analog() { float v = analogRead(analogPin) * 3.3 / 1023.0; int gas_concentration = int((v) * (5000 / 2)); return gas_concentration; } int gas_concentration_uart() { byte addArray[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; char dataValue[9]; SerialCom.write(addArray, 9); SerialCom.readBytes(dataValue, 9); int resHigh = (int) dataValue[2]; int resLow = (int) dataValue[3]; int ppm_uart = (resHigh * 256) resLow; return ppm_uart; } int gas_concentration_PWM() { while (digitalRead(PWMPin) == LOW) {}; long t0 = millis(); while (digitalRead(PWMPin) == HIGH) {}; long t1 = millis(); while (digitalRead(PWMPin) == LOW) {}; long t2 = millis(); long th = t1 - t0; long tl = t2 - t1; long ppm = 5000L * (th - 2) / (th tl - 4); while (digitalRead(PWMPin) == HIGH) {}; delay(10); return int(ppm); }
В первой части программного кода мы определяем переменные и конфигурации для интерфейса связи между микроконтроллером и датчиком CO2.
При запуске сценария программы определяются следующие переменные:
- Контакты для последовательной связи UART: SerialCom
- Аналоговый вывод: analogPin
- Цифровой вывод для интерфейса ШИМ: PWMPin
Для программного кода Arduino и ESP8266 мы определяем программный серийный номер для интерфейса UART. Мы не можем использовать стандартный интерфейс, потому что стандартный интерфейс используется для USB-связи между микроконтроллером и ПК, чтобы отправлять измерения через USB-кабель в Arduino IDE.
ESP32 имеет в общей сложности 3 интерфейса UART, которые вы можете использовать. Но из сценария программы видно, что я не определял интерфейс UART. Причина в том, что я получаю много сбросов, когда пытался включить интерфейс UART. Я не нашел причину этих сбросов и попробовал все три интерфейса UART, но ничего не помогло.
В setup мы запускаем программную последовательную связь со скоростью 9600 бод, которая указана в техническом описании MH-Z14A. Кроме того, мы устанавливаем вывод для сигнала ШИМ в качестве входа и используем внутренний подтягивающий резистор микроконтроллера.
Поскольку датчику CO2 нужно время, чтобы нагреть инфракрасную лампу, мы создаем задержку в 3 минуты.
После задержки мы устанавливаем скорость передачи данных для последовательной связи через USB с ПК на 115200 и распечатываем заголовок нашей таблицы, который содержит три наших измерительных интерфейса для Arduino и ESP8266 и два интерфейса для ESP32.
В loop мы считываем концентрацию CO2 из каждой функции, которую вы можете найти в функции цикла. В каждой функции мы реализуем метод, описанный в главе об интерфейсе. Если у вас есть какие-либо вопросы относительно функций чтения концентрации CO2, задайте свой вопрос в разделе комментариев ниже.
После того, как мы получили все наши измерения CO2, мы записываем значения концентрации CO2 на последовательный выход и ждем 1 минуту, прежде чем снова запустить функцию цикла, чтобы прочитать новые значения датчика MH-Z14A.
Распиновка mh-z14a
В технической спецификации, вы найдете следующую распиновку (смотрите на MH-Z14A сверху).
Связь между MH-Z14A и различными микроконтроллерами Arduino, ESP8266 и ESP32 показана в следующей главе этой статьи.
Регулятор напряжения 3v3
Линейный понижающий регулятор напряжения NCP582LSQ33 обеспечивает питание чипа CCS811 и других компонентов сенсора. Диапазон входного напряжения от 3,3 до 5 вольт. Выходное напряжение 3,3 В с максимальным выходным током 150 мА.
Результаты использования arduino с mh-z14a после повторной калибровки
Возможно, вы видели, что значения датчиков в предыдущей главе были слишком высокими (между 1700 и 3200 частей на миллион), чтобы быть реальной концентрацией CO2 в моем офисе.
Мы определили, что в хорошо вентилируемом помещении концентрация CO2 ниже 800 ppm (наш предупреждающий сигнал) и должна быть ниже 1000 ppm (наш сигнал тревоги).
Поэтому нам необходимо откалибровать MH-Z14A, соединив контакт 8 (HD) MH-Z14A с землей вашего микроконтроллера на 7-10 секунд. На следующем рисунке показано измерение CO2 с моей Arduino Uno после повторной калибровки.
Теперь моя концентрация CO2 составляет около 600 частей на миллион, когда дверь моего офиса открыта, а окно закрыто. Когда я закрываю дверь (у меня небольшой офис), концентрация CO2 повышается и превышает пороговые значения 800–1000 частей на миллион. В конце я открыл окно, и вы видите, что концентрация СО2 снижается за счет свежего воздуха.
Повторная калибровка не устраняет ошибочное поведение аналогового интерфейса и интерфейса UART.
Смена адреса модуля
Иногда в проекте необходимо использовать несколько сенсоров. Для смена адреса капните каплей припоя на отведённую контактную площадку на обратной стороне модуля. После чего адрес датчика сменится с 0x5A на 0x5B.
Создание сигнализации co2 с помощью mh-z14a
Теперь мы хотим создать нашу сигнализацию CO2 с помощью MH-Z14A и различных плат микроконтроллеров Arduino, ESP8266 и ESP32. Наша сигнализация CO2 должна измерять концентрацию CO2 в комнате каждую минуту и передавать данные в консоль. Кроме того, мы хотим использовать все три варианта, чтобы считывать концентрацию CO2 и сравнивать различные варианты, чтобы выяснить, какой вариант является наилучшим с точки зрения стабильности и точности.
Схема проекта
Схема подключения инфракрасного датчика CO2 к плате Arduino представлена на следующем рисунке.
Как видите, схема достаточно простая. Инфракрасный датчик CO2 и OLED дисплей запитываются от контактов 5V и GND платы Arduino. Сигнальный аналоговый контакт датчика CO2 подключен к контакту A0 платы Arduino Nano. OLED дисплей подключен к плате Arduino по интерфейсу SPI. Соединения между OLED дисплеем и платой Arduino представлены в следующей таблице:
OLED дисплей | Плата Arduino |
GND | Ground |
VCC | 5V |
D0 | 10 |
D1 | 9 |
RES | 13 |
DC | 11 |
CS | 12 |
После сборки проекта на макетной плате у нас получилась конструкция следующего вида:
Шим интерфейс mh-z14a
Концентрация CO2 также может передаваться через сигнал ШИМ (Широтно-импульсная модуляция) от MH-Z14A на микроконтроллер. Вы можете использовать любой цифровой вывод микроконтроллера для чтения сигнала ШИМ.
Чтобы прочитать сигнал ШИМ, мы должны сделать два изменения, которые описаны в таблице данных и показаны на следующем рисунке.
- tH: время высокого уровня ШИМ-сигнала в течение одного цикла.
- tL: время, когда сигнал ШИМ низкий в течение одного цикла.
Поскольку микроконтроллер Arduino, ESP8266 и ESP32 не может измерять временной диапазон, мы должны использовать millis() функцию, которая возвращает количество миллисекунд, прошедших с момента включения микроконтроллера. На основе этих временных меток, когда сигнал ШИМ показывает нарастающий или спадающий фронт, мы можем вычислить временные диапазоны следующим образом:
Теперь рассчитывается концентрация CO2 C = 5000 * (tH-2ms) / (tH tL-4ms).
Заключение по созданию сигнализации co2 с помощью mh-z14a
Следующие пункты суммируют все мои знания, полученные во время создания этой статьи.
- Поместите датчик CO2 MH-Z14A в среду, в которой вы хотите измерять концентрацию CO2, в течение как минимум 24 часов.
- Используя интерфейс ШИМ, вы получите достоверные измерения концентрации CO2.
- Выполните повторную калибровку MH-Z14A, соединив контакт 8 (HD) с землей на 10 секунд.
- Если вы создаете систему без подключения к Wi-Fi, используйте микроконтроллер Arduino, а если вы хотите создать датчик измерения CO2 для Интернет штук, который отправляет значения CO2 в центральный регистр, используйте ESP32, но не ESP8266.
Если у вас есть какие-либо вопросы относительно этой статьи, не стесняйтесь задавать свои вопросы в следующем разделе комментариев, и я отвечу на них как можно скорее.