Подписаться YouTube

Учебное пособие по измерителю CO2 MH-Z14A с Arduino, ESP8266 или ESP32

Целью этого учебного пособия по измерителю CO2 MH-Z14A является изучение основных функций MH-Z14A и того, как этот датчик CO2 может быть полезен во времена короны.

Вы узнаете, как создать сигнализацию CO2, которую можно использовать в офисе, и как использовать три интерфейса связи MH-Z14A в сочетании с различными микроконтроллерами Arduino, ESP8266 и ESP32.

Почему измерение CO2 важно во времена короны?

Основная причина, по которой люди заражаются SARS-CoV-2 (вирусом, вызывающимся COVID-19), - это контакт с респираторными каплями, переносящими инфекционный вирус.

Во время выдоха образуются дыхательные капли (дыхание, речь, пение, кашель, чихание и т.д.). Размер этих капель различается и в основном делится на две категории:

  • Более крупные капли
  • Более мелкие капли и частицы

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

Мы можем избежать передачи через вентиляцию, например, через открытые окна в офисах или классах. Цель состоит в том, чтобы избежать высокой концентрации респираторных капель и частиц в воздухе.

Но когда достигается концентрация, то я должен открыть окна в своем офисе? Концентрацию респираторных капель в воздухе измерить крайне сложно. Но мы можем измерить концентрацию углекислого газа (CO2) в выдыхаемом воздухе во время дыхания. Эта концентрация CO2 пропорциональна концентрации респираторных капель в воздухе.

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

Как измерить концентрацию CO2 в воздухе?

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

Длина волны CO2

На длине волны около 4250 нм поглощение CO2 является самым высоким. Таким образом, ИК-детектор CO2 может измерять концентрацию CO2 в воздухе, если измерения других длин волн отсутствуют. На следующем рисунке показана схема ИК-детектора.

Схема ИК-детектора

На картинке видно, что есть вход и выход для газа. Инфракрасная лампа создает инфракрасное излучение через измеряемый газ. Это ИК-излучение фильтруется интерференционным фильтром до нужного газа, который необходимо измерять, в нашем случае CO2. Фильтр предотвращает попадание на ИК-детектор волны другой длины, кроме CO2. Инфракрасный детектор измеряет интенсивность света и преобразует ее в значение концентрации газа, которое измеряется в частях на миллион (ppm).

Как и у всех газов, концентрация зависит от температуры и давления. Стандартная температура окружающей среды составляет 25 ° C, а давление - 1013 кПа. Уравнение для расчета концентрации газа при различных температурах и давлениях: p = p (25 ° C, 1013 кПа) * p / 1013 * 298 / (273 + t)

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

Датчик 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 частей на миллион (наш сигнал тревоги).

Коррекция базовой линии MH-Z14A

MH-Z14A имеет встроенную температурную компенсацию, называемую автоматической коррекцией базовой линии (ABC), для измерения точных значений CO2 также после смены комнаты с разными температурами. Базовым показателем для датчика CO2 является то, что уровень CO2 должен составлять 400 частей на миллион, что соответствует уровню CO2 в уличном воздухе. Включив эту функцию, датчик собирает результаты измерений в течение 24 часов и устанавливает минимальное значение внутреннего датчика, равное 400 ppm. Есть два способа активировать автоматическую коррекцию базовой линии:

  1. Подключите контакт 8 к GND минимум на 7 секунд.
  2. Отправьте определенную комбинацию байтов через интерфейс UART, см. Программный код для сигнализации аэрозолей.

Коммуникационные интерфейсы MH-Z14A

Всего существует три варианта считывания значений датчика с MH-Z14A, которые подробно описаны в следующих разделах.

Аналоговый интерфейс MH-Z14A

Всего имеется два разных аналоговых выхода MH-Z14A, которые отличаются выходным напряжением аналогового выхода.

  • Vout1 имеет расширение. выходное напряжение от 0 В до 2,5 В для диапазона выходного сигнала от 0 до 5000 частей на миллион.
  • Vout2 имеет расширение. выходное напряжение от 0,4 В до 2 В для диапазона выходного сигнала от 0 до 5000 частей на миллион.

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

Чтобы рассчитать концентрацию CO2, мы должны сделать следующие шаги:

  1. Считайте аналоговое значение с помощью analogRead функции.
  2. Пересчитайте аналоговое напряжение на основе рабочего напряжения микроконтроллера и максимального значения аналого-цифрового преобразователя (АЦП) микроконтроллера.
  3. Рассчитайте концентрацию газа, используя следующий градиентный треугольник.

МикроконтроллерРабочее напряжениеДиапазон значений АЦП
Ардуино0… 1023
ESP82663,3 В0… 1023
ESP323,3 В0… 4095

Теперь мы можем погрузиться в уравнения для расчета концентрации CO2 от MH-Z14A, когда вы используете вывод Vout1 или Vout2 на MH-Z14A.

Формулы, когда Vout1 используется для расчета концентрации газа.

МикроконтроллерAnalog VoltageКонцентрация газа
Ардуиноfloat v = analogRead (analogPin) * 5.0 / 1023;int gas_concentration = int ((v-0) * (5000/2));
ESP8266float v = analogRead (analogPin) * 3,3 / 1023;
ESP32float v = analogRead (analogPin) * 3,3 / 4095;

Формулы, когда Vout2 используется для расчета концентрации газа.

МикроконтроллерAnalog VoltageКонцентрация газа
Ардуиноfloat v = analogRead (analogPin) * 5.0 / 1023;int gas_concentration = int ((v-0,4) * (5000 / (2-0,4));
ESP8266float v = analogRead (analogPin) * 3,3 / 1023;
ESP32float v = analogRead (analogPin) * 3,3 / 4095;

Интерфейс 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 или ниже, в нашем примере программирования.

ШИМ интерфейс MH-Z14A

Концентрация CO2 также может передаваться через сигнал ШИМ (Широтно-импульсная модуляция) от MH-Z14A на микроконтроллер. Вы можете использовать любой цифровой вывод микроконтроллера для чтения сигнала ШИМ.

Чтобы прочитать сигнал ШИМ, мы должны сделать два изменения, которые описаны в таблице данных и показаны на следующем рисунке.

  1. tH: время высокого уровня ШИМ-сигнала в течение одного цикла.
  2. tL: время, когда сигнал ШИМ низкий в течение одного цикла.

Поскольку микроконтроллер Arduino, ESP8266 и ESP32 не может измерять временной диапазон, мы должны использовать millis() функцию, которая возвращает количество миллисекунд, прошедших с момента включения микроконтроллера. На основе этих временных меток, когда сигнал ШИМ показывает нарастающий или спадающий фронт, мы можем вычислить временные диапазоны следующим образом:

  • tH = t1-t0
  • tL = t2-t1

Теперь рассчитывается концентрация CO2 C = 5000 * (tH-2ms) / (tH + tL-4ms).

Распиновка MH-Z14A

В технической спецификации, вы найдете следующую распиновку (смотрите на MH-Z14A сверху).

Связь между MH-Z14A и различными микроконтроллерами Arduino, ESP8266 и ESP32 показана в следующей главе этой статьи.

Создание сигнализации CO2 с помощью MH-Z14A

Теперь мы хотим создать нашу сигнализацию CO2 с помощью MH-Z14A и различных плат микроконтроллеров Arduino, ESP8266 и ESP32. Наша сигнализация CO2 должна измерять концентрацию CO2 в комнате каждую минуту и передавать данные в консоль. Кроме того, мы хотим использовать все три варианта, чтобы считывать концентрацию CO2 и сравнивать различные варианты, чтобы выяснить, какой вариант является наилучшим с точки зрения стабильности и точности.

Подключение MH-Z14A к разным микроконтроллерам

Во-первых, нам нужно подключить MH-Z14A к нашему микроконтроллеру. На следующих рисунках показана проводка между датчиком CO2 и различными платами микроконтроллеров Arduino, ESP8266 и ESP32.

MH-Z14 Arduino Nano

MH-Z14 Arduino Pro Mini

MH-Z14 Arduino Uno

MH-Z14 Arduino Mega

MH-Z14 ESP32 ESP-WROOM-32

MH-Z14 ESP32 ESP-WROOM-32 ESP8266 NodeMCU

MH-Z14 ESP8266 WeMos D1 Mini

Программный код 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);
}
// analog interface
const int analogPin = 4;

// PWM interface
const int PWMPin = 0;

void setup() {
  pinMode(PWMPin, INPUT_PULLUP);

  delay(180000); // preheat the CO2 sensor for 3 minutes

  Serial.begin(115200);
  Serial.println("Analog:,PWM:");
}

void loop() {
  int ppm_analog = get_analog();
  int ppm_PWM = gas_concentration_PWM();

  Serial.print(ppm_analog);
  Serial.print(",");
  Serial.println(ppm_PWM);

  delay(60000); // sleep for 1 minute
}


int get_analog() {
  float v = analogRead(analogPin) * 3.3 / 4095.0;
  int gas_concentration = int((v) * (5000 / 2));

  return gas_concentration;
}

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, но ничего не помогло. Когда я удалил интерфейс UART, все работает нормально. Если у вас работает интерфейс UART для ESP32, дайте мне знать, как вы этого добились, в разделе комментариев.

В setup мы запускаем программную последовательную связь со скоростью 9600 бод, которая указана в техническом описании MH-Z14A. Кроме того, мы устанавливаем вывод для сигнала ШИМ в качестве входа и используем внутренний подтягивающий резистор микроконтроллера.

Поскольку датчику CO2 нужно время, чтобы нагреть инфракрасную лампу, мы создаем задержку в 3 минуты.

После задержки мы устанавливаем скорость передачи данных для последовательной связи через USB с ПК на 115200 и распечатываем заголовок нашей таблицы, который содержит три наших измерительных интерфейса для Arduino и ESP8266 и два интерфейса для ESP32.

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

После того, как мы получили все наши измерения CO2, мы записываем значения концентрации CO2 на последовательный выход и ждем 1 минуту, прежде чем снова запустить функцию цикла, чтобы прочитать новые значения датчика MH-Z14A.

Основные выводы при создании сигнализации CO2 с помощью MH-Z14A

В последней главе этой статьи я хочу обсудить свои основные выводы, полученные при использовании разных микроконтроллеров и CO2 датчика MH-Z14A.

Основные результаты использования Arduino с MH-Z14A

На следующем рисунке показаны мои измерения с Arduino Uno, визуализированные с помощью последовательного плоттера Arduino IDE. Калибровка MH-Z14A во время этого измерения не производилась. Разница после повторной калибровки показана в следующем подразделе.

MH-Z14A Последовательный плоттер Arduino

Использование аналогового интерфейса MH-Z14A с микроконтроллером Arduino (синяя линия)

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

Использование интерфейса UART MH-Z14A с микроконтроллером Arduino (красная линия)

Использование связи UART для получения значений CO2 от MH-Z14A вызывает те же проблемы, что и аналоговый интерфейс. Мы можем видеть, что значения датчика UART частично совпадают с ШИМ интерфейсом, но часто падают. Такое поведение кажется необычным и не позволяет использовать интерфейс UART для сигнализации CO2.

Использование интерфейса ШИМ MH-Z14A с микроконтроллером Arduino (зеленая линия)

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

Результаты использования Arduino с MH-Z14A после повторной калибровки

Возможно, вы видели, что значения датчиков в предыдущей главе были слишком высокими (между 1700 и 3200 частей на миллион), чтобы быть реальной концентрацией CO2 в моем офисе.

Мы определили, что в хорошо вентилируемом помещении концентрация CO2 ниже 800 ppm (наш предупреждающий сигнал) и должна быть ниже 1000 ppm (наш сигнал тревоги).

Поэтому нам необходимо откалибровать MH-Z14A, соединив контакт 8 (HD) MH-Z14A с землей вашего микроконтроллера на 7-10 секунд. На следующем рисунке показано измерение CO2 с моей Arduino Uno после повторной калибровки.

Последовательный плоттер MH-Z14A Arduino после повторной калибровки

Теперь моя концентрация CO2 составляет около 600 частей на миллион, когда дверь моего офиса открыта, а окно закрыто. Когда я закрываю дверь (у меня небольшой офис), концентрация CO2 повышается и превышает пороговые значения 800–1000 частей на миллион. В конце я открыл окно, и вы видите, что концентрация СО2 снижается за счет свежего воздуха.

Повторная калибровка не устраняет ошибочное поведение аналогового интерфейса и интерфейса UART.

Основные результаты использования ESP8266 с MH-Z14A

Ключевой вывод при использовании ESP8266 с MH-Z14A заключается в том, что эта комбинация у меня не заработала. Я попробовал взять другой микроконтроллер ESP8266 и пробовал каждый интерфейс измерения отдельно. Но у меня всегда был один и тот же код ошибки, который вы видите на следующем рисунке.

MH-Z14A ESP8266 Проблемы последовательного монитора

Основные результаты использования ESP32 с MH-Z14A

Когда я использовал ESP32 с MH-Z14A, у меня возникли проблемы с интерфейсом UART, что привело к постоянному перезапуску ESP32. По этой причине я использовал только аналоговый интерфейс и интерфейс ШИМ для получения концентрации CO2. Обратите внимание, что все значения датчика записываются перед повторной калибровкой.

MH-Z14A ESP32 Последовательный плоттер

Использование аналогового интерфейса MH-Z14A с микроконтроллером ESP32 (синяя линия)

Аналоговый интерфейс ESP32 демонстрирует то же поведение, что и Arduino. Мы регулярно получаем более высокие концентрации CO2.

Использование интерфейса ШИМ MH-Z14A с микроконтроллером ESP32 (красная линия)

Интерфейс ШИМ показывает действительные значения датчика без каких-либо выбросов. Поэтому я бы рекомендовал использовать интерфейс ШИМ MH-Z14A при использовании микроконтроллера ESP32.

Заключение по созданию сигнализации CO2 с помощью MH-Z14A

Следующие пункты суммируют все мои знания, полученные во время создания этой статьи.

  • Поместите датчик CO2 MH-Z14A в среду, в которой вы хотите измерять концентрацию CO2, в течение как минимум 24 часов.
  • Используя интерфейс ШИМ, вы получите достоверные измерения концентрации CO2.
  • Выполните повторную калибровку MH-Z14A, соединив контакт 8 (HD) с землей на 10 секунд.
  • Если вы создаете систему без подключения к Wi-Fi, используйте микроконтроллер Arduino, а если вы хотите создать датчик измерения CO2 для Интернет штук, который отправляет значения CO2 в центральный регистр, используйте ESP32, но не ESP8266.

Если у вас есть какие-либо вопросы относительно этой статьи, не стесняйтесь задавать свои вопросы в следующем разделе комментариев, и я отвечу на них как можно скорее.

Комментарии пользователей