Было куплено 2 одинаковых (MH-Z19B) датчика в разное время в разных магазинах с интервалом в 3 месяца.
После недели мучений и разного рода тестов пришел к неутешительным выводам — в DIY можно использовать эти датчики только при условии покупки оных в количествах 10 штук в разным магазинах и последующей отборке.
Этот обзор — скорее обзор предостережение + рабочий скетч для чтения датчиков по всем 3м каналам. Поэтому фоток тут не будет, немного текста и сухих выводов.
Для желающих именно обзора датчика — оставлю пару ссылок на достойные статьи — обзоры:
РАЗ
ДВА
Итак, вначале был куплен один датчик (хотел собрать монитор воздуха по статьям на Хабре и на Муське) и пока ехали все остальные детали немного с ним поигрался. Потом не было время, позже появились еще идеи для использования второго датчика в другом устройстве и в итоге был заказан второй датчик. После получения второго датчика я его проверил (чтоб в случае фэйла открыть диспут). Датчик так же «правильно» работал, как и первый.
Спустя пару недель выдалось свободное время и я решил поиграться с датчиками и своим вторым проектом в котором хотел его использовать. Меня насторожило то, что играясь то с одним, то со вторым датчиком я получал разные показания ppm в комнате. Причем не в пределах погрешности, а весьма разные, доходило до двойной разницы. При этом на улице оба датчика нормально показывали 400ppm. Калибровка по «уличному» воздуху ситуацию не изменила.
Опустим мои почти недельные метания с этими датчиками — я перепробовал всё! но дело с мертвой точки не сдвинулось — они тупо по-разному считают концентрацию и выводят разные значения. Дело не в калибровке, а в их внутреннем «коэффициенте пересчета» Причем по всем 3м выходам (UART, PWM, Analog) данные коррелируют между собой. При этом напряжение с аналогового вывода тоже не решает ситуации — оно точно так же жестко соответствует показаниям UART. И если 2 датчика находятся в одинаковой среде, 1 показывает 940ppm имея на аналоговом выходе 700мВ, а второй 1300ppm с выходом 820мВ, то если при повышении концентрации первый насчитает свои 1300ppm -то его аналоговый выход точно так же будет отдавать 820мВ (при этом второй датчик будет показывать уже порядка 1900ppm/990мВ)
Что я пробовал (по отдельности и совмещая несколько или все из ниже перечисленного):
1) калибровку (многократную) по «уличному воздуху» методом замыкания пина Hd на время >7сек
2) калибровку по воздуху «чуть более 400ppm» — т.е. одновременно заношу датчики с улицы в дверной проём и как только один из них начинает регистрировать повышение СО2 — оба одновременно калибрую на 400
*** (п1. конечно соответственно датащиту только после >20 минут работы на улице, п2. сначала 20+ мин работы на улице, потом в дверной проём, ну и как только регистрирую рост — обнуление). Дабы не вносить «свой СО2» от кожного или легочного дыхания — калибровал датчики через закрытую балконную дверь, для чего от датчиков протянул 2 кнопки на шлейфах под дверью, дверь конечно закрывал.
3) команду запрета ABC (самокалибровки) при инициализации датчиков
4) команду принудительной работы в диапазоне 5000ppm
5) питание напрямую от павербанка
6) конвертеры уровня 5V<=>3.3V и обычные резистивные делители.
7) монтаж делал плоскими шлейфами минимально комфортной длинны.
8) множество разных скетчей, 3 разных ардуины (последнее скорее просто так вышло, а не специально)
В итоге что мы имеем:
1) Стартуют датчики после калибровки в 400 ppm все равно не равномерно, запаздывание одного из них порядка 50 ppm (т.е. когда первый уже начал показывать 450+, второй только начал регистрировать изменения). Это первый минус этих датчиков — они не показывают значения меньше 400 ppm, ни по UARТ, ни по PWM, ни по Analog. Точнее они отдают минимально возможные значения (длительность ШИМ вывода пропорционально снижается до 400ppm, после чего остаётся на этом уровне, точно так же и с напряжением — оно снижается до 400мВ, после чего остаётся на этом значении).
2) Дальнейшая регистрация ppm идет с нелинейным разбросом, если на старте отличие показаний около 10%, то к 1300ppm разбег составляет 30%, и дальше растет еще сильнее, аж до 100% при значениях около 3000ppm.
3) Я не нашел способа это исправить…
ИТОГО — если купить 1 датчик — он выглядит порядочно и создает впечатление нормальной работы. Если тестировать датчики в диапазоне 400-800ppm то тоже можно сказать что в принципе показания соответствуют регламентированным допускам (50ppm+5%), но как показала практика — реально эти датчики могут показывать что угодно. Для использования в сколько нибудь ответственных проектах нужно покупать много датчиков (а еще лучше много датчиков разных производителей) и выбирать из них те, что выдают правдоподобные, одинаковые значения на всем диапазоне их работы.
Бонусом под спойлер прячу скетч для ардуины для одновременного тестирования 2х датчиков с выводом показаний по всем трем каналам на 1602 дисплей. НЕ делал вывод на монитор, поскольку для калибровки на балконе «тестовый стенд» должен быть мобильным. Скетч можно масштабировать при наличии 2004 или бóльшего дисплея. Сам код скетча проверен и 100% работоспособен. Другие «рабочие скетчи или модули» обрабатывали данные так же.
Надеюсь кому то эта информация будет полезна.
PS. Извиняюсь за слегка сумбурное повествование, не было в планах писать обзор, это скорее сухая выжимка фактов для тех, кто захочет использовать эти и подобные датчики в своих самоделках. Очень мало свободного времени, поэтому «не причесывал» текст. Спасибо за понимание.
Дополнительная информация
// Подключение LCD (1602 с контроллером HD44780)
// LCD RS pin to digital pin 7
// LCD Enable pin to digital pin 6
// LCD D4 pin to digital pin 5
// LCD D5 pin to digital pin 4
// LCD D6 pin to digital pin 3
// LCD D7 pin to digital pin 2
// LCD R/W pin to ground
// LCD VSS pin to ground
// LCD VCC pin to 5V
// 10K resistor: ends to +5V and ground, wiper to LCD VO pin
/*
— Подключение датчиков-------------
первый подключается к: второй подключается к:
Arduino | 1 CO2 sensor MH-Z19B Arduino | 2 CO2 sensor MH-Z19B
pin A0 | RX pin A2 | RX
pin A1 | TX pin A3 | TX
pin A4 | Vo pin A5 | Vo
pin 10 | PWM pin 11 | PWM
GND и Vcc (земля и питание) датчиков подключаем соответственно к массе и к +5В ардуины
ВНИМАНИЕ! UART шину данных к Ардуино подключаем только через конвертер уровней 5V <=> 3.3V
*/
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
#define zm1_pwm_pin 10
#define zm1_a_pin A4
#define zm2_pwm_pin 11
#define zm2_a_pin A5
SoftwareSerial zm1(A0, A1); // RX, TX
SoftwareSerial zm2(A2, A3); // RX, TX
int zm1_t = 0;
int zm1_ss = 0;
int zm1_co2 = 0;
int zm2_t = 0;
int zm2_ss = 0;
int zm2_co2 = 0;
byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
byte abc[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
unsigned char response2[9];
unsigned char response1[9];
int ppm1 = 0;
int ppm2 = 0;
int anlg1 = 0;
int anlg2 = 0;
void setup() {
// Serial.begin(9600); // нужно только для дебага, в этом скетче нету вывода в консоль, не спользуется.
lcd.begin(16, 2);
pinMode(zm1_pwm_pin, INPUT);
pinMode(zm1_a_pin, INPUT);
pinMode(zm2_pwm_pin, INPUT);
pinMode(zm2_a_pin, INPUT);
while(zm1_pwm_pin == LOW || zm2_pwm_pin == LOW ){
lcd.setCursor(0, 0);
lcd.print("*Now Warming Up*");
lcd.setCursor(0, 1);
lcd.print("**Please wait!**");
}
//----------- конфигурируем 1 датчик
zm1.begin(9600);
delay(100);
zm1.write(abc, 9); // запрещаем автокалибровку
//-------- Задаем принудительно работу в диапазоне 5000ppm
byte setrangeA_cmd[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB};
unsigned char setrangeA_response[9];
zm1.write(setrangeA_cmd,9);
zm1.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;
lcd.setCursor(0, 0);
if ( !(setrangeA_response[0] == 0xFF && setrangeA_response[1] == 0x99 && setrangeA_response[8] == setrangeA_crc) ) {
lcd.print(«RangeERR» + String(setrangeA_crc) + "/"+ String(setrangeA_response[8]));
} else {
lcd.print("*Range was set!*");
}
zm1.end();
delay(100);
//----------- конфигурируем 2 датчик
zm2.begin(9600);
delay(100);
zm2.write(abc, 9); // запрещаем автокалибровку
//-------- Задаем принудительно работу в диапазоне 5000ppm
byte setrangeB_cmd[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB};
unsigned char setrangeB_response[9];
zm2.write(setrangeB_cmd,9);
zm2.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;
lcd.setCursor(0, 1);
if ( !(setrangeB_response[0] == 0xFF && setrangeB_response[1] == 0x99 && setrangeB_response[8] == setrangeB_crc) ) {
lcd.print(«RangeERR» + String(setrangeB_crc) + "/"+ String(setrangeB_response[8]));
} else {
lcd.print("*Range was set!*");
}
zm2.end();
delay(2000);
}
void loop() {
// ***** узнаём концентрацию CO2 через UART: *****
zm1.begin(9600);
zm1.write(cmd, 9);
memset(response1, 0, 9);
zm1.readBytes(response1, 9);
int i;
byte crc = 0;
for (i = 1; i < 8; i++) crc+=response1[i];
crc = 255 — crc;
crc++;
if ( !(response1[0] == 0xFF && response1[1] == 0x86 && response1[8] == crc) ) {
lcd.setCursor(0, 0);
lcd.print(«zm1 ERR: » + String(crc) + "/"+ String(response1[8]));
} else {
unsigned int responseHigh = (unsigned int) response1[2];
unsigned int responseLow = (unsigned int) response1[3];
unsigned int responseTT = (unsigned int) response1[4];
unsigned int responseSS = (unsigned int) response1[5];
zm1_t = responseTT-40;
zm1_ss = responseSS;
zm1_co2 = (256*responseHigh) + responseLow;
};
// ***** узнаём концентрацию CO2 через PWM: *****
unsigned long th, tl;
do {
th = pulseIn(zm1_pwm_pin, HIGH, 1004000) / 1000;
tl = 1004 — th;
ppm1 = 5000 * (th-2)/(th+tl-4); // расчёт для диапазона от 0 до 5000ppm
} while (th == 0);
// ***** читаем по аналогу: *****
anlg1 = analogRead(zm1_a_pin); // показания на экране отображаются в АЦП «попугаях», а точнее в 5/1024 В, для вывода в вольтах не хватило разрешения дисплея.
zm1.end();
delay(1000);
// ***** узнаём концентрацию CO2 через UART: *****
zm2.begin(9600);
zm2.write(cmd, 9);
memset(response2, 0, 9);
zm2.readBytes(response2, 9);
crc = 0;
for (i = 1; i < 8; i++) crc+=response2[i];
crc = 255 — crc;
crc++;
if ( !(response2[0] == 0xFF && response2[1] == 0x86 && response2[8] == crc) ) {
lcd.setCursor(0, 1);
lcd.print(«zm2 ERR: » + String(crc) + "/"+ String(response2[8]));
} else {
unsigned int responseHigh = (unsigned int) response2[2];
unsigned int responseLow = (unsigned int) response2[3];
unsigned int responseTT = (unsigned int) response2[4];
unsigned int responseSS = (unsigned int) response2[5];
zm2_t = responseTT-40;
zm2_ss = responseSS;
zm2_co2 = (256*responseHigh) + responseLow;
};
// ***** узнаём концентрацию CO2 через PWM: *****
unsigned long th2, tl2;
do {
th2 = pulseIn(zm2_pwm_pin, HIGH, 1004000) / 1000;
tl2 = 1004 — th2;
ppm2 = 5000 * (th2-2)/(th2+tl2-4); // расчёт для диапазона от 0 до 5000ppm
} while (th2 == 0);
// ***** читаем по аналогу: *****
anlg2 = analogRead(zm2_a_pin); // показания на экране отображаются в АЦП «попугаях», а точнее в 5/1024 В, для вывода в вольтах не хватило разрешения дисплея.
zm2.end();
//---------------------- Выводим на дисплей — // первое значение на экране «u» юзначает данные полученные по UART, второе — «w» по PWM, третье — «a» по Analog портам.
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(«u»); lcd.print(zm1_co2);
lcd.setCursor(5, 0);
lcd.print(" w"); lcd.print(ppm1);
lcd.setCursor(11, 0);
lcd.print(" a"); lcd.print(anlg1);
lcd.setCursor(0, 1);
lcd.print(«u»); lcd.print(zm2_co2);
lcd.setCursor(5, 1);
lcd.print(" w"); lcd.print(ppm2);
lcd.setCursor(11, 1);
lcd.print(" a"); lcd.print(anlg2);
delay(5000);
}
Хорошая новость в том, что Infenion обещает в 2020 году новый тип датчиков основанный на акустической спектрометрии. Посмотрим что это будет…
Придет — сделаю обзор на этот датчик CO2 и летучих загрязнений воздуха.
В доках на CCS811 не скрывается, что есть зависимость от температуры и влажности. Сказано, что если есть данные от внешнего датчика температуры и влажности — запишите в специальный регистр чипа для компенсации. Если данных нет — по умолчанию 50% влажности и 25 градусов цельсия.
Для летучих — действительно «показометр». А по СО2 — в принципе для дома очень высокой точности не нужно.
Я читал отчеты, то ли на Муське, то ли на Хабре, как такого плана датчик СО2 реагировал на парфюм девушки, причем на столько яростно реагировал, что на обычный нормальный запах сигнализировал двойной передоз СО2 :D А когда этот товарищ воспользовался освежителем в туалете — датчик зашкалило :D
Очевидно, что в обоих случаях СО2 не повышалось (ну ОК, в первом девушка что-то там надышала, но явно не на столько).
Я CSS811 использовал в тандеме с MH-Z19 и если верить графикам — эти датчики замеряют совершенно разные вещи. Мне даже показалось что CSS811 куда больше подходит для оценки качества воздуха в помещении.
(Про прибор было здесь mySKU.me/blog/china-stores/74329.html, датчик CM1106, производитель Wuhan Cubic Optoelectronics Co., Ltd.)
На улицу вынести будет 400.
Я в принципе даже думал над экспериментом. Взять канистру-бочку свежего воздуха, убедиться, что в ней показывает как свежий, ничего из стен (металлической?) канистры не набежало. Добавить туда заранее взвешенное кол-во сухого льда.
Но это раньше сухой лед был у любой мороженщицы, ща искать надо…
Зы написал и стал считать
8 гр хватит как раз добавить 400ppm к 10000 литрам воздуха. Комната 3*5*2 это 30тыс литров. То есть берем баллончик и вентилятор и можно бы калибровать — кабы знать сколько там примесей :)
Впрочем с сухим льдом та же история… + к тому же пока взвесишь, пока в гермокамеру донесешь, пока дверь закроешь — часть уже испарится. Что опять же исказит результаты опыта
12 г./0,1 г. = 120 выстрелов. Ага! Щаз!
Да, 120 выстрелов с одного баллона, шесть обойм. Последняя обойма идет уже слабее.
Хочется точности и отсутствия необходимости калибровки — купите двухканальный датчик. А вообще Т6703 и S8 — вполне достойные варианты.
P.S. Имею в коллекции десяток разных СО2 датчиков, в том числе три варианта двухканальных. После тестов выбрал Т6703 для серийных изделий (комбинированныз датчиков).
Надеюсь эта информация будет кому-то полезна.
Имею 2 19B и 4 S8. Все показывают одно и тоже (до 2000 примерно) в рамках заявленной погрешности. Как это соотносится с вашей статистикой?
Я ни в коем случае не утверждаю что 19B хороший\плохой. Я лишь о том что делать выводы по 2 датчиком — это не очень корректно.
Но есть прецендент. Где гарантия того, что 2-3 купленных из одной партии датчиков не будут одинаково врать?.. потому и выборка больше.
Ну и конечно не стоит воспринимать так добуквенно, про «10 штук» это скорее оборот речи, означает что нужна выборка и сравнение купленного с последующей отбраковкой, и чем больше будет пул для выборки тем больше шансов «выиграть в лотерею по отбору честных датчиков» без поверочных мероприятий на эталонных средах (которых у нас нету)
Работает замечательно, пока была отладка и апгрейд, с питанием и фоторезистором ну и обновы софта, все хозяйство лежало на столе в виде мотка проводов в кабинете, 8 квадратов, при микро проветривании показывало 400-450. После начала работы через 30-40 минут 800-900. В период часа полтора когда все устаканилось при заходе второго человека, через 5-10 минут уже кричал проветри. Считаю достаточно точным для бытовых нужд. Сейчас проект живет дома, жена очень довольна, зачастую глядя на показания проветривает. Хотя окно вроде всегда приоткрыто. И прогноз погоды тоже вполне устраивает. Всем добра.
1. Внутри датчиков стоит микроконтроллер и у него есть прошивка. И эта прошивка бывает разной. У меня есть два датчика с разными версиями прошивки, так вот более новая версия более адекватна, но реализация измерений и там и там вызывает вопросы.
2. Два датчика из одной партии (по крайней мере, с одной и той же прошивкой и датой изготовления) тестировались одновременно, но на одном был включен ABC, на другом — отключен. Сначала между ними была приличная разница показаний, но постепенно их показания стали выравниваться и спустя неделю они более-менее сравнялись. Это как будто бы говорит о том, что датчики исходно калибруют.
3. На «официальные» выводы датчик не выдаёт значения меньше 400ppm: в коде стоит проверка, что если насчиталось меньше 400, то выдаём 400. Но есть возможность получить значение CO2 до этого обрезания (команда 0x85).
4. Здесь я описал список всех поддерживаемых команд: revspace.nl/MH-Z19B
5. Насколько я понимаю, такому датчику для точных измерений в идеале нужна информация о давлении. В MH-Z19B нет ничего, что могло бы это давление измерить.
6. Внутри стоят регуляторы на 3.3В. То есть, если подать на питание 3.3 вместо 5 вольт, то напряжение на регуляторах уже будет меньше.
А можно подробности про команду 0x85? как выглядит полная строка с контрольной суммой и что она отдаёт? в идеале полный кусок Вашего кода бы посмотреть…
Я опрашивал RAW значения с помощью библиотеки с Хабра, но результат был совсем не в ппм-ах, полученный мной ответ это около 46.000 и 40.000 для 1 и 2 датчика соответственно.
Здесь значение, полученное из команды 0x85 совпадает со значением из команды 0x86, но иногда бывает вот так:
Видно, что финальное значение получилось 400, но значение чуть раньше по цепочке преобразований равно 398.
Это не сырое значение, а значение в ppm, но более сырое значение тоже можно получить, командой 0x84. Первое число в ответе (в моём случае 38521) — половина значения интеграла, вычисленного по измерениям датчика. Это значение (без половины) используется дальше для вычисления концентрации CO2 в ppm. И это значение интеграла вычисляется по-разному в разных прошивках, со всеми вытекающими… Это значение между двумя «одинаковыми датчиками» отличалось где-то на сотню (21149 vs 21028), между разными датчиками отличается в 1.8 раза (21000 vs 38000). Это нормально, тут имеет смысл сравнивать только значения из одинаковых прошивок.
Оба датчика корректно отрабатывают 400ррм порог, т.е. при интенсивном проветривании оба покажут близкое к 400 значение, проблема в ошибке подсчета концентрации после 400 ппм. Т.е. на одинаковую концентрацию они реагируют по разному, и расхождение в показаниях тем больше, чем больше концентрация, расхождение в геометрической прогрессии. Ни автокалибровка, ни принудительная, ни переключение диапазонов — ни-че-го в данном случае не поможет.
.
PS. Вчера муськовчанин в личку подсказал способ снятия RAW значений с датчиков, т.е. сырых «попугаев», без калибровок, без обработки, то, что «видит» сам сенсор. Так вот, при ± одинаковых условиях 1 датчик отдаёт в порт RAW около 46000, второе около 40000. Выводы я думаю очевидны.
.
PS2. Так же для спокойствия и гарантии от «китайской ошибки» я разобрал оба датчика, протер сенсоры от разводов (были какие-то странные разводы как от плохой отмывки после пайки), зеркала и призмы так же протер от пыли (правда эту пыль скорее я внёс при вскрытии датчиков). Но картины это не изменило ни на йоту.
Что было сделано — калибровал не на улице а в комнате, которую долго проветривал.
первый датчик дошел до 400 примерно через полчаса проветривания, второй в это время показывал еще около 600. Через примерно еще полчаса второй стабилизировался на около 500, первый естественно был на 400 по дисплею, и гораздо ниже по факту. В этот момент я их оба сбросил в новую «точку 400». Сейчас, спустя полтора часа с закрытыми окнами в квартире оба показывают около 800.
RAW значения по прежнему отличаются на примерно 6000
Почему точно так же не происходило при «уличной калибровки» — понятия не имею, хотя и подозреваю, что китайцы перепутали с «нулевой точкой отсчета», применяя формулу подсчета концентрации в одном случае к 400ппм, а в другом, например, к 450… Сейчас диапазон 400...800 они оба идут очень ровно. Посмотрим что будет дальше, но, повторюсь, это уже не прибор, это «показометр»…
.
UPD. на диапазоне 1400 уже снова появился разбег (один из них показывает 1400, второй 1250)
Ладно, не важно, много времени уже угроблено на эти датчики, есть идеи как их пристроить в оба моих проекта, но на этом с ними (и вообще с NDIR) я пока попрощаюсь, выйдет PAS210 — пощупаю его. А пока время на игрушки с ними закончилось.
На фото внизу партия 5шт купленная на али. Формально продавцу не предъявишь, работают. Но врут неадекватно и нелинейно.
Вверху 1 остался, уже кончились почти, те же датчики но прямо с завода WinSen — никаких проблем. Показания в рамках погрешности совпадают с поверенными CO2-метрами сделанными на других датчиках.
Вобщем, если Вам не просто «поиграться» не надо брать на Али совсем. Непонятно где продавцы Али их берут, возможно выбраковка с завода…
запускал Z19 и S8 на одинаковых модулях (с одинаковой прошивкой espeasy). гонял месяц, из него 2 недели — открытый балкон, 2 недели квартира — z19 стабильно завышал показания на 400-450 ед.
потом случайно спалил. оба сразу (
подал 12в на обе esp8266 и подключенные к ним сенсоры. есп выжили а датчики нет(
больше всего жаль S8. на него кстати в инете почему то не нашел даташита
верхний ряд 4 деталь справа