• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь ESP8266+MH-Z19, проблемы

Cadil

New member
С помощью Arduino IDE заливаю в модуль CP2102 Node MCU скетч (под спойлером) для датчика углекислого газа MH-Z19.
#include <SoftwareSerial.h>;

//SoftwareSerial mySerial(2, 3); // RX, TX
//SoftwareSerial mySerial(13, 15, false, 256); // GPIO15 (TX) and GPIO13 (RX)
SoftwareSerial mySerial(13, 15); // GPIO15 (TX) and GPIO13 (RX)
byte request[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
unsigned char response[9];

void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}

void loop()
{
mySerial.write(request, 9);
memset(response, 0, 9);
mySerial.readBytes(response, 9);
int i;
byte crc = 0;
for (i = 1; i < 8; i++) crc+=response;
crc = 255 - crc;
crc++;

if ( !(response[0] == 0xFF && response[1] == 0x86 && response[8] == crc) ) {
Serial.println("CRC error");
} else {
unsigned int HLconcentration = (unsigned int) response[2];
unsigned int LLconcentration = (unsigned int) response[3];
unsigned int co2 = (256*HLconcentration) + LLconcentration;

Serial.println(co2);
for (i = 0; i < 9; i++) {
Serial.print("0x");
Serial.print(response,HEX);
Serial.print(" ");
}
Serial.println(" ");

}
delay(5000);
}
Подключаю датчик, перезапускаю, но на мониторе Arduino IDE - тишина, если не считать нечитаемой абракадабры при включении. В окнах датчика мигают инфракрасные нагреватели с периодом около 5 сек.
Помогите прояснить ситуацию: Некондиционный датчик? Ошибки в скрипте? Что-то не то делаю? Другая версия?
 

Вложения

Последнее редактирование:

Cadil

New member
Для просмотра установите скорость 78 тыс с хвостиком. Точнее не помню. Посмотрите - сообщите что выдает
Спасибо! Выдает примерно такое:
ets Jan 8 2013,rst cause:1, boot mode:(3,6)

load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v09f0c112
~ld
 

Cadil

New member
В поисках решения описанной проблемы перешел с цифрового интерфейса датчика MH-Z19 на ШИМ (у него есть и такой выход!).
Залил в ESP8266 скрипт, который один из магазинов использует для предпродажной проверки этих сенсоров.
Схема задышала. К сожалению, на мониторе редактора Arduino IDE отображается не реальный ppm в пределах 400-800, а значение 5000 (см. картинку mh-z19_2.png). При этом ESP находится в режиме записи. Если уйти от режима записи, то иногда на мониторе можно увидеть картинку, как во вложении - mh-z19_3.png.
При разрыве цепи "выход датчика - контроллер" обновление информации на мониторе останавливается, мигание светодиода 13 прекращается.
На основании этой информации можно однозначно утверждать, что датчик MH-Z19 - некондиционный?
 

Вложения

Последнее редактирование:

Cadil

New member
Работая со скриптами для MH-Z19, одна из моих попыток оказалась удачной - я увидел на мониторе редактора далекие от реальности показатели концентрации СО2 (около 1400), но, самое главное, реакцию датчика на мое дыхание (2100-2600). Скрипт под спойлером.
//#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
//#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <Wire.h>
#include <SoftwareSerial.h>;


// MH-Z19, power - 5v
// D8 - TX sensor, D7 - RX sensor
#define CO2_TX D8
#define CO2_RX D7

SoftwareSerial co2Serial(CO2_TX, CO2_RX);

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
//char auth[] = “redacted”; // Put your Auth Token here. (see Step 3 above)

SimpleTimer timer;

void setup()
{
Serial.begin(9600); // See the connection status in Serial Monitor
// Blynk.begin(auth, “xx”, “xx”); //insert here your SSID and password

// Setup a function to be called every second
timer.setInterval(10000L, sendUptime);

co2Serial.begin(9600);
co2Serial.flush();
}

int readCO2()
{
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
char response[9];

co2Serial.write(cmd, 9); //request PPM CO2
co2Serial.readBytes(response, 9);

byte crc = 0;
for (int i = 1; i < 8; i++)
{
crc += response;
}
crc = 255 - crc;
crc++;

if (response[8] != crc)
{
Serial.println("Wrong crc from co2 sensor!");
return -1;
}
if (response[0] != 0xFF)
{
Serial.println("Wrong starting byte from co2 sensor!");
return -1;
}
if (response[1] != 0x86)
{
Serial.println("Wrong command from co2 sensor!");
return -1;
}

int responseHigh = (int) response[2];
int responseLow = (int) response[3];
int ppm = (256 * responseHigh) + responseLow;
// Serial.println(ppm);
return ppm;
}

void sendUptime()
{
int co2_ppm = readCO2();
// Blynk.virtualWrite(3, co2_ppm); // virtual pin
Serial.println(co2_ppm);
}
void loop()
{
// Blynk.run();
timer.run();
}

К сожалению, это событие произошло только один раз.

Ниже - типичные сообщения с модуля ср2102:
ets Jan августа 2013, rst cause: 1, boot mode: (5,7)
waiting for host

Wrong crc from co2 sensor!
(Линии Rx, Tx - разорванные)

В нете нашел информацию, что для чипов ESP8266 нужна своя, особая библиотека SoftwareSerial для MH-Z19. Заменил ранее установленную библиотеку SoftwareSerial на указанную в ссылке, но положительного результата - нет.
Где копать?
 
Последнее редактирование:

shuraf

Member
MH-Z19 и MH-Z19B в плане опроса идентичны, и в плане подключения совпадают. Они отличаются только новыми командами, в частности автокалибровки.
MH-Z19
MH-Z19 Infrared CO2 Sensor For CO2 Indoor Air Quality Monitor UART/PWM 0-5000PPM | eBay
MH-Z19B
MH-Z19B DIP Infrared CO2 Sensor for CO2 Monitor NDIR Gas Sensor | eBay
Обрати внимание снизу маленький разьемчик, вот это различие внешнего вида.
Сейчас стали появляться MH-Z19 с другим разьемом
MH-Z19B Infrared CO2 Sensor for CO2 Monitor NDIR Gas Sensor (MH-Z19 Updated) | eBay

Рабочий код. С ним пяток датчиков стоит и работает.
Код:
void setup() {
  Serial.begin(9600);
  Serial1.begin(115200);
}

void loop () {
  ppmCO2 = readCO2();
  Serial1.println (ppmCO2);
}


int readCO2() {
  while (Serial.available() > 0) {
    Serial.read();
  }
  byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  char response[9]; // for answer
  Serial.write(cmd, 9); //request PPM CO2
  memset(response, 0, 9);
  Serial.readBytes(response, 9);
  int CRC = getCheckSum(response);
  if (response[0] != 0xFF  || response[1] != 0x86 || CRC != response[8]) {
    return -1;
  }
  int responseHigh = (int) response[2];
  int responseLow = (int) response[3];
  return (256 * responseHigh) + responseLow;
}

int getCheckSum(char *packet) {
  byte checksum = 0;
  for ( int i = 1; i < 8; i++) {
    checksum += packet[i];
  }
  checksum = 0xff - checksum;
  checksum ++;
  return checksum;
}
Обрати внимание. Что датчик подключен к Serial (для ESP12 это TXD и RXD), а получаем цифирки с Serial1 (GPIO2).
Если захочешь все перевести на первый порт, то при прошивке снимай питания с датчика CO2. Иначе можно случайно "переконфигурировать" его, "откалибровать" или перевести в режим ModBus
 

Cadil

New member
Обрати внимание. Что датчик подключен к Serial (для ESP12 это TXD и RXD), а получаем цифирки с Serial1 (GPIO2).
Спасибо за код.
В этом коде нашел одну неточность: ppmCO2 = readCO2(); вместо int ppmCO2 = readCO2();
Хотя код компилируется, я не могу понять - где в нем обращение к портам UARTa: TXD и RXD? Или обращение не требуется, раз на этих пинах организован UART? Таймера не видно. Как цикл организован? Поясни!
Или я неправильно подключаю датчик к модую: Rx (cp2102) - Tx (mh-z19), Tx (cp2102) - Rx (mh-z19)? (распиновка во вложении)
 

Вложения

Последнее редактирование:

shuraf

Member
Serial.write () - это записывает команду в порт
Seril.readBytes ()) - чтение из порта
Выдернул этот кусок по этому забыл в лупе поставить delay(), иначе датчик загнется. Не помню какой минимальный цикл у опроса можно поставить
Rx-Tx - это gpio1 и gpio3 у тебя. Сюда датчик и цепляй. Но только перекрестно rx-датчика -> tx esp, tx -> rx.
А данные тебе 'посиотреть' будут прилетать в gpio2 (serial1).
Скорости на портах разные
 
Последнее редактирование:

Cadil

New member
Serial.write () - это записывает команду в порт
Seril.readBytes ()) - чтение из порта
Выдернул этот кусок по этому забыл в лупе поставить delay(), иначе датчик загнется. Не помню какой минимальный цикл у опроса можно поставить
Rx-Tx - это gpio1 и gpio3 у тебя. Сюда датчик и цепляй. Но только перекрестно rx-датчика -> tx esp, tx -> rx.
А данные тебе 'посиотреть' будут прилетать в gpio2 (serial1).
Скорости на портах разные
Поставил период опроса 10 сек (В нете встречал и 5). Датчик подключал правильно. Функции "посмотреть" для разных скоростей записаны так:
Serial1.println(String(ppmCO2) + "ppm");
Serial.println("CO2: " + String(ppm) + "ppm");

Посмотри, пожалуйста, код - не хотелось бы угробить датчик.
Код:
void setup() {
  Serial.begin(9600);
  Serial1.begin(115200);
}


void loop () {
  int ppmCO2 = readCO2();
// Serial1.println (ppmCO2);
Serial1.println(String(ppmCO2) + "ppm");
  delay(10000);
}
 
int readCO2() {
  while (Serial.available() > 0) {
    Serial.read();
  }
  byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  char response[9]; // for answer
  Serial.write(cmd, 9); //request PPM CO2
  memset(response, 0, 9);
  Serial.readBytes(response, 9);
  int CRC = getCheckSum(response);
  if (response[0] != 0xFF  || response[1] != 0x86 || CRC != response[8]) {
    return -1;
  }
  int responseHigh = (int) response[2];
  int responseLow = (int) response[3];
  int ppm = (256 * responseHigh) + responseLow;
// return (256 * responseHigh) + responseLow;
Serial.println("CO2: " + String(ppm) + "ppm");
  return ppm;
}
int getCheckSum(char *packet) {
  byte checksum = 0;
  for ( int i = 1; i < 8; i++) {
    checksum += packet[i];
  }
  checksum = 0xff - checksum;
  checksum ++;
  return checksum;
}
 

Cadil

New member
Строка 31. Serial - порт подключения датчика
Закомметировал строку 31. Больше ничего не режет глаз?

Мне кажется, что в твоем коде на хватает функций инициализации портов. Они должны выглядеть примерно так:
#define CO2_TX D8
#define CO2_RX D7
SoftwareSerial co2Serial(CO2_TX, CO2_RX);

если порты организуются библиотекой SoftwareSerial
Посмотри, пожалуйста, как назначены Tx, Rx у тебя?
 
Последнее редактирование:

Ed007

New member
@shuraf подскажите плз, как добавить к Вашей прошивке отправку данных на народмон или thingspeak?
 

shuraf

Member
Закомметировал строку 31. Больше ничего не режет глаз?

Мне кажется, что в твоем коде на хватает функций инициализации портов. Они должны выглядеть примерно так:
#define CO2_TX D8
#define CO2_RX D7
SoftwareSerial co2Serial(CO2_TX, CO2_RX);

если порты организуются библиотекой SoftwareSerial
Посмотри, пожалуйста, как назначены Tx, Rx у тебя?
В примере не используется софтовый сериал-порт.

@shuraf подскажите плз, как добавить к Вашей прошивке отправку данных на народмон или thingspeak?
Извини, я этим не пользуюсь.
 
Сверху Снизу