Тёмная сторона MH-Z19

Что, опять? Сколько ж можно?

Да, сегодня мы снова поговорим о всеми нами любимом датчике углекислого газа Winsen MH-Z19. Нет, повторов не будет*.



* почти

Как вы могли заметить, на страницах настоящего ресурса регулярно появляются страшилки статьи об опасностях высокой концентрации СО2 в помещении. И хотя утверждения, что концентрации выше 1000 ppm несут ад и погибель, слегка преувеличены (википедия говорит, что хоть какие-то эффекты начинаются с 1%, то бишь 10 000 ppm, тогда как у датчика весь диапазон — 5000 ppm) — СО2 может служить индикатором присутствия других нехороших вещей в силу недостаточности вентиляции. Потому я тоже решил приобщиться к увлекательному миру СО2-метрии и разжился упомянутым датчиком.

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

Но пока я копипастил, в душу закрался червь сомнения — а отчего это датчик выдаёт девять байт, а на СО2 из них приходится всего два байта? Может быть, он хочет сказать мне что-то ещё?

Поиск в интернете навёл меня на такую интересную страничку. Автор экспериментирует с MH-Z19 и выявляет его реакцию на недокументированные (да и документированные) команды. Команды он перепробовал ещё не все, так что и на нашу долю останется, где порезвиться. Этим мы и займёмся.

Первым делом разберёмся с «классической» командой 0x86 (или по-простому 134), с помощью которой мы и получаем концентрацию СО2. Revspace сообщает:

A response to command 0x86 typically looks like this:
0xFF CM HH LL TT SS Uh Ul CS
where
CM is the command repeated back
HH/LL is the CO2 ppm value, high/low part
TT is the temperature in degrees Celcius, plus 40. For example, when temperature is 25 deg C, then TT = 0x41
SS is some kind of status byte, this byte always has only one bit set!
Uh/Ul is some unknown value, perhaps related to pressure? After booting the sensor, it starts out at 15000 exactly, then typically settles to about 10500.
Cs is the checksum

То есть в ответе датчика на эту команду содержится также температура T (сдвинутая на 40 градусов) и две величины неизвестного предназначения — однобайтная S и двухбайтная U. S принимает значения степеней двойки, а U при запуске датчика падает с 15 000 до чуть более чем 10 000.

Как понять, что значат числа S и U? Конечно, надо нарисовать график! В любой непонятной ситуации рисуй график.

Унылые технические подробности
А чтобы нарисовать график, хорошо бы загнать показания датчика в компьютер. Что я и сделал посредством Serial.println(). Каждые пять секунд ардуина опрашивает датчик и пишет его показания в USB-UART, остаётся их только прочитать на компьютере и сохранить в файл. Делаю я это (в линуксе) так:

rlwrap cat | cu -l /dev/ttyACM0 > sensor_$(date '+%Y%m%d_%H%M%S').log


Ногами не пинать
Да, я знаю, что можно сделать просто cat /dev/ttyACM0 > .., но отчего-то у меня это работает далеко не всегда, порою сия команда сразу молча завершается. Приведённая команда (rlwrap cat | cu -l /dev/ttyACM0) также нравится мне тем, что позволяет удобно общаться с микроконтроллером в интерактивном режиме (хоть в данном случае это и не нужно). Наверняка есть более лучшие средства для этой цели, но я, к сожалению, их не знаю.

В другом окне терминала можно смотреть этот файл в реальном времени:

tail -f sensor_датавремя.log

Получается вот такая простыня из чисел:

...
1188 62 64 42 38 10790 
1188 62 64 42 38 10790 
1190 62 64 42 38 10790 
1191 62 64 42 38 10790 
1192 62 64 42 38 10790 
1193 62 64 42 38 10790 
1195 62 64 42 38 10790 
...

В каждой строчке — CO2, T, S, U (U повторено дважды — как два байта и двухбайтное число, не спрашивайте зачем).

Теперь можно и графики построить. Делать я это буду при помощи ipython --pylab.

y = map(lambda a: map(int, a.split()), open("sensor1.log", "r").readlines()) # читаем файл как список строк, разбиваем строки по разделяющим пробелам, преобразуем в числа
yt = transpose(y)
x = arange(len(yt[0])) / 720. # массив для оси абсцисс, чтобы по ней было время в часах
figure()
plot(x, yt[0]) # CO2
figure(); plot(x, yt[1], "g"); # T
figure(); plot(x, yt[2], "r"); # S
figure(); plot(x, yt[-1], "m"); # U


Итак, график СО2:

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

Температура:

Хорошо заметен момент, когда я открыл окно. Подвирает на 1 — 2 градуса, что для недокументированной возможности неплохо. Впрочем, если вспомнить принцип NDIR-датчика, можно понять, что, большой точности от встроенного в него градусника ждать не следует. Эти приборы измеряют поглощение света в дальнем инфракрасном диапазоне, а для генерации этого света используется старая добрая лампочка Ильича, и можно даже через окошки разглядеть, как она каждые пять секунд загорается (на КДПВ пойман именно такой момент). И эта лампочка расходует немало энергии и, как следствие, нагревает весь датчик, а насколько она его нагреет — зависит от сиюминутной конъюнктуры воздушных потоков.

Подходим к самому интересному. Величина S:

Ничего не говорит? Мне тоже. С горя нарисуем СО2 и S на одном графике и немного увеличим:

Ага! Вот теперь всё ясно! Когда всё хорошо, S равна 64, а когда показания датчика СО2 начинает колбасить, она опускается до 4. Таким образом, можно использовать S для того, чтобы узнавать, насколько хорошо чувствует себя датчик и насколько точны его показания.

Осталась, как говорят парашютисты, крайняя величина — U:

К сожалению, фокус с наложением здесь мало что даёт. Видно только, что, как и обещал revspace, в начале она равна 15 000, а затем падает до чуть более 10 000 (но может немного падать и по прошествии длительного времени). И раз в сутки цикл повторяется.

Зато когда я подключил питание датчика не к 5, а к 3,3 вольтам ардуины, ситуация изменилась:

3,3 вольта на ардуине берутся от микросхемы LP2985, каковая представляет собой линейный стабилизатор на 160 миллиампер. А лампочка, судя по статьям в интернете, приблизительно столько и кушает. При взгляде на датчик заметно, что лампочка при таком питании разгорается за большее время, чем при пяти вольтах. И величина U в полтора раза выше.

Вырисовывается следующая гипотеза — датчик автоматически определяет, сколько времени надо жечь лампочку, чтобы получить достаточно ИК-излучения, и если тока не хватает, жжёт лампочку дольше. И величина U как раз отражает время горения лампочки (или ещё какую-то связанную с этим величину, например, затраченную энергию).

Чтобы проверить это предположение, запитаем датчик от литий-ионного аккумулятора, который заведомо может выдать намного больший ток:

И действительно, U порою опускается ниже 10 000! Впрочем, это очевидно не абсолютное доказательство, да и после 24 часов всё становится едва ли не наоборот. Так что гипотеза остаётся только гипотезой, но ничего лучшего я не придумал.

УПД: Уважаемый unsvp таки разгадал загадку величины U. Предоставляю ему слово:

величина U, очевидно, является минимальным значением измеренного поглощения IR CO2 за сутки, в каких-то внутренних единицах измерения.

Добавить нечего, разве что график:

Почему я до этого сам не додумался? Всё просто. Я нарисовал график четырёх величин сразу и на этом успокоился. А надо было нарисовать две величины (как на картинке выше), тогда посторонний мусор в лице величины S не мешал бы восприятию. Не повторяйте моих ошибок.

Пожалуй, добавлю вот что: видите ступеньку величиной более 1000 ppm на 48 часах? Это датчик так автоматически откалибровался. При этом значение U упало по сравнению с тем, что было до калибровки. Тогда как очевидно, что действительная концентрация СО2 в этот период только росла. Вывод из этого очень простой — величина U — не совсем «сырое» значение поглощения, а рассчитывается уже с поправкой на текущую калибровку, представляя собой, видимо, некоторую разность минимальных показаний в текущем и предыдущем цикле калибровки.

В общем, на мой взгляд, автокалибровка (по крайней мере в том виде, в котором она реализована в MH-Z19) — зло. Revspace говорит, что её можно отключить командой 0x79: ABC logic on/off.

/УПД

Ну что же, с одной командой разобрались. Пора бы идти дальше, а то статья близится к концу, а ещё 255 команд не тестировано!

В статье на revspace перечень протестированных команд оканчивается так:

command 0x89-0x8F
No response is returned, however command 0x8d seems to reset the sensor.

command 0x99 (range)
...

Кроме того, команды с меньшими номерами проверены не все. Таким образом, неизведанных команд остаётся ещё чуть более половины из общего числа.

Не мудрствуя лукаво, я решил подавать команды случайно (точнее, псевдослучайно). И вот что я получил:

...
Command: 255 1 47 0 0 0 0 0 208  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 17 0 0 0 0 0 238  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 45 0 0 0 0 0 210  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 5 0 0 0 0 0 250  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 88 0 0 0 0 0 167  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 245 0 0 0 0 0 10  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 107 0 0 0 0 0 148  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 214 0 0 0 0 0 41  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 136 0 0 0 0 0 119  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 7 0 0 0 0 0 248  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 153 0 0 0 0 0 102  Response: 255 153 1 0 0 0 0 0 102  CRC: 102102 CO2/t/s/u: 256 0 0 0
Command: 255 1 146 0 0 0 0 0 109  Response: 0 0 0 0 0 0 0 0 0  CRC: 00 CO2/t/s/u: 0 0 0 0
Command: 255 1 72 0 0 0 0 0 183  Response: 96 249 2 211 215 212 17 215 204  CRC: 159204 CO2/t/s/u: 723 215 212 4567
Command: 255 1 51 0 0 0 0 0 204  Response: 93 151 80 143 212 255 255 255 217  CRC: 185217 CO2/t/s/u: 20623 212 255 -1
Command: 255 1 98 0 0 0 0 0 157  Response: 16 136 252 75 66 50 48 48 13  CRC: 9313 CO2/t/s/u: -949 66 50 12336
Command: 255 1 65 0 0 0 0 0 190  Response: 10 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 243 0 0 0 0 0 12  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 13 0 0 0 0 0 242  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 35 0 0 0 0 0 220  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 229 0 0 0 0 0 26  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 95 0 0 0 0 0 160  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 48 0 0 0 0 0 207  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 209 0 0 0 0 0 46  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 200 0 0 0 0 0 55  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
...

Здесь Command — то, что было послано датчику (сам номер команды — третье число с начала), Response — что датчик ответил, на остальное можно не смотреть (CRC — контрольная сумма вычисленная/фактическая, CO2/t/s/u — результат разбивки ответа датчика на четыре числа, как если бы он отвечал на «дефолтную» команду).

Как видим, не густо. Более того, с некоторого момента датчик вовсе отказался выдавать что-либо, кроме нулей. Последнее, что я получил от датчика, было:

Command: 255 1 134 0 0 0 0 0 121  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 130 0 0 0 0 0 125  Response: 242 98 200 201 207 216 178 130 33  CRC: 50 33 CO2/t/s/u: -14135 207 216 -19838
Command: 255 1 134 0 0 0 0 0 121  Response: 204 91 151 80 143 212 255 255 236  CRC: 93 236 CO2/t/s/u: -26800 143 212 -1
Command: 255 1 200 0 0 0 0 0 55  Response: 181 156 252 77 79 68 66 85 83  CRC: 241 83 CO2/t/s/u: -947 79 68 16981
Command: 255 1 134 0 0 0 0 0 121  Response: 13 10 0 0 0 0 0 0 0  CRC: 246 0 CO2/t/s/u: 0 0 0 0
Command: 255 1 216 0 0 0 0 0 39  Response: 0 0 0 0 0 0 0 0 0  CRC: 0 0 CO2/t/s/u: 0 0 0 0

И далее нули. Я попробовал вводить команды последовательно, начиная с 0x8e — снова нули. Я пробовал подавать «стандартную» команду 0x86 — нули. Неужели я убил датчик? По правде говоря, все условия для этого присутствуют — я мало что ввожу недокументированные команды, так ещё и подключаю интерфейс датчика прямиком к пятивольтовой ардуине, хотя в даташите прямо сказано, что он рассчитан на 3,3 вольта.

Первым делом я попробовал старый добрый рецепт любого эникейщика — выключить и снова включить. То бишь вынул и воткнул у датчика плюс питания при работающем всём остальном. Датчик выдал приблизительно то же, что и в последнем процитированном отрывке (но с немного различающимися цифрами). Ага, значит, датчик не совсем помер и при каждой загрузке что-то говорит, догадался штирлиц.

Тогда я ещё немного пораскинул мозгами и догадался ещё до одной истины — те нули, которые мы видели выше — вовсе не ответ датчика. На самом деле датчик молчит, а моя программа рисует то, что выдала ардуиновская функция приёма n байт (сиречь нули). А если каждый раз перед приёмом убеждаться, что есть что принимать — выяснится, что принимать нечего. Разве что кроме случаев, когда датчик только что перезагрузился.

Получается, что датчик вовсе прекратил воспринимать какие-либо команды. Видимо, 5 вольт на последовательный интерфейс не прошли даром. Да, не задалась как-то статья. Всем спасибо за внимание. Расходимся, здесь не на что смотреть.

Ах, постойте…

Видите эти цифры в конце?

13 10

Ничего не напоминает?

Конечно, это старый добрый перевод строки! Другими словами, 0x0D 0x0A — так принято переводить строку, например, в Windows (а в Unix поступают проще — 0x0A, потому-то некоторые файлы при открытии в виндовом блокноте лишаются переводов строк).

Так может быть, датчик хочет что-то нам сказать человеческим языком? Впрочем, если этот язык — китайский, мне это мало поможет. Так что будем надеяться, что это более понятный язык, и расшифруем сообщение по таблице ASCII:

print reduce(lambda a, b: a + b, map(lambda a: chr(int(a)), "255 255 255 250 24 220 207 254 77 79 68 66 85 83 13 10".split()))
�������MODBUS

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

print reduce(lambda a, b: a + b, map(lambda a: chr(int(a)), "96 249 2 211 215 212 17 215 204  93 151 80 143 212 255 255 255 217  16 136 252 75 66 50 48 48 13  10 ".split()))
`������]�P��������KB200

Разница налицо — строка KB200 сменилась на строку MODBUS. Остальное — похоже, что вовсе не текст, даже не китайские иероглифы — хотя бы потому, что большая их часть раз от раза меняется.

Так что же такое говорит нам датчик? По запросу KB200 поиск в интернете выдаёт клавиатуру, керноотборник, утюг, пеленальный столик, контроллер управления поворотными PTZ камерами, смеситель, разве что чёрта лысого не выдаёт. Хорошо, но не вполне ясно, как эти знания применить к нашему случаю. Ну что же, поищем MODBUS. На этот раз к нашим услугам сама википедия:

Modbus — открытый коммуникационный протокол, основанный на архитектуре ведущий-ведомый (master-slave). Широко применяется в промышленности для организации связи между электронными устройствами. Может использоваться для передачи данных через последовательные линии связи RS-485, RS-422, RS-232, а также сети TCP/IP (Modbus TCP).

Сама собой напрашивается гипотеза — после одной из недокументированных команд датчик переключился на протокол Modbus и теперь доступными ему способами оповещает нас об этом. Поскольку других вариантов не предвидится — займёмся прямой проверкой этой гипотезы, то бишь попробуем обратиться к датчику по Modbus.

На просторах интернета была найдена реализация Modbus для ардуины. Только вот незадача — Arduino Leonardo не поддерживается, а у меня по чудовищной случайности как раз Leonardo.

Но, как я вскорости понял, это даже к лучшему. Протокол Modbus прост, как три копейки. И к тому же до боли похож на «родной» протокол MH-Z19. Так зачем тащить всякую гадость из интернета и мучительно разбираться в ней, когда можно за две минуты (ну хорошо, за два часа) реализовать всё необходимое самостоятельно?

Итак, раньше мы, желая узнать показания, просили датчик их выдать следующим образом:

0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79

Или в десятичном выражении:

255, 1, 134, 0, 0, 0, 0, 0, 121

Где 255 — магическое число, 1 — адрес датчика, 134 — команда, 121 — байт контрольной суммы.

А как это будет выглядеть в Modbus? Точного соответствия не будет, но можно сделать, например, так:

1, 4, 0, 0, 0, 4, 213, 197

1 — адрес датчика.

4 — номер команды. Команды в Modbus можно пересчитать по пальцам, и нас пока будут интересовать лишь две из них — 3 и 4. По причинам, сокрытым в тьме веков, они называются Read Multiple Holding Registers и Read Input Registers, а по сути — дают команду на чтение заданного количества двухбайтовых чисел по заданному адресу. По команде 3 читаются числа, доступные на чтение/запись, а по команде 4 — только на чтение.

0, 0 — адрес, по которому мы собираемся читать (в данном случае 0). Если один и тот же адрес задать с командой 3 или 4 — мы получим в общем случае разные результаты.

0, 4 — количество чисел, которые мы хотим прочитать (в данном случае 4). Здесь есть забавный момент. Хотя можно задать это число вплоть до 65535, фактически протокол позволяет читать не более 125 чисел за раз. А всё потому, что в ответе указывается количество байт посланной информации, и оно занимает всего один байт (а числа-то двухбайтовые). К тому же, насколько я понял, длина самого ответа ограничена 255 байтами.

213, 197 — два байта контрольной суммы (CRC16). В общем-то это самый сложный момент во всей нашей реализации. По правде говоря, я даже не вникал, как оно считается, а просто скопипастил код отсюда. Поскольку различных CRC16 существует море, надо ответственно подходить к выбору функции. Проверить, подходит ли конкретная функция для Modbus, можно, например, здесь.

Вот, собственно, и всё, что нам нужно знать о Modbus. По крайней мере, для начала.

Хотя вы уже давно догадались, что моё воззвание к MH-Z19 по Modbus завершилось успехом, но давайте сделаем вид, что интрига сохраняется. Пока что мы ещё даже не знаем, какой у нашего датчика адрес (хотя «в оригинале» он равен 1, далеко не факт, что по Modbus он такой же). Значит, надо повторить команду с разными адресами (а их всего 255) и посмотреть, на какой наш датчик откликнется:

...
Command: 254 4 0 3 0 1 213 197  CRC: 213 197 Response: 
Command: 255 4 0 3 0 1 212 20  CRC: 212 20 Response: 
Command: 0 4 0 3 0 1 192 27  CRC: 192 27 Response: 
Command: 1 4 0 3 0 1 193 202  CRC: 193 202 Response: 
Command: 2 4 0 3 0 1 193 249  CRC: 193 249 Response: 1 132 2 194 193 
Command: 3 4 0 3 0 1 192 40  CRC: 192 40 Response: 
Command: 4 4 0 3 0 1 193 159  CRC: 193 159 Response: 
...

Похоже, что адрес — 2. Повторяю несколько команд с адресом 2 — нет ответа. Меняю адрес на 1 — есть ответ! Таким образом, адрес датчика такой же, какой и был — 1.

А почему в приведённом отрывке получился адрес 2? Здесь снова вылезает индусскость моего кода. После отдачи команды я проверяю, есть ли байты на приём. Но поскольку я делаю это сразу же, датчик не успевает ничего послать, так что ответ датчика принимается программой лишь в следующем цикле. Что и можно наблюдать в приведённом логе — первое число в ответе — 1, а оно как раз обозначает адрес датчика. Эту неприятность я обошёл, попросту добавив задержку в 50 миллисекунд перед приёмом ответа.

Рассмотрим ответ датчика на нашу команду:

1 132 2 194 193

1 — как мы уже выяснили — адрес датчика.

132 — код команды и код ошибки. Если бы ошибки не было, это число было бы таким же, как и посланная команда — то бишь 4. Но ошибка произошла, о чём говорит выставленный в 1 старший бит, так что число стало равно 4 + 128 = 132. Поэтому, кстати, команда в Modbus не может иметь номер более 127 — для такой команды код успешного завершения был бы таким же, как код ошибки.

2 — код ошибки. Говорит, какая именно ошибка произошла. Как говорит википедия, 02 — Адрес данных, указанный в запросе, недоступен. Значит, по этому адресу рыбы нет и ловить нечего. Будем пробовать другие адреса.

194 193 — CRC16.

Теперь, наконец, пора бы прошерстить адресное пространство датчика, чтобы понять, где там рыба. Это я сделал просто — посылал команду на прочтение одного числа с новым адресом каждые 0,1 секунды. Поскольку адресов 65536, этот процесс завершается приблизительно за два часа. Результаты вкратце таковы:

Команда 1 (Read Coils) — с любым адресом ошибка 2.
Команда 2 (Read Discrete Inputs) — с любым адресом ошибка 2.
Команда 4 (Read Input Registers) — с любым адресом ошибка 2.
Команда 3 (Read Multiple Holding Registers) — выдаёт успех при адресах от 0 до 289.
Команды на запись значений (например, 6) — вроде работают, но, похоже, что записанное значение вскорости заменяется тем, что было. Но вплотную этот вопрос не исследовал.

Итак, круг поиска сужается — нам нужны числа по команде 3 и адресам от 0 до 289. Представление о богатом внутреннем мире датчика можно получить по этим строкам:

Command: 1 3 0 0 0 64 68 58  CRC: 68 58 Response: 1 3 128 0 0 0 255 0 1 0 1 0 255 0 255 0 255 0 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 158 124 
Command: 1 3 0 64 0 64 69 238  CRC: 69 238 Response: 1 3 128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 27 165 
Command: 1 3 0 128 0 64 69 210  CRC: 69 210 Response: 1 3 128 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 82 0 153 0 8 0 17 0 177 0 19 0 19 0 196 0 18 0 20 0 214 0 18 0 21 0 232 0 18 0 22 0 250 0 5 0 24 0 255 0 5 0 18 1 4 0 3 0 23 1 7 0 25 0 0 0 0 0 0 0 0 0 0 0 255 0 255 0 1 0 0 0 5 0 0 0 0 0 0 0 0 0 0 137 122 
Command: 1 3 0 192 0 64 68 6  CRC: 68 6 Response: 1 3 128 165 165 0 165 0 0 255 255 255 255 255 255 255 255 0 15 3 232 0 100 0 90 0 0 0 63 128 0 0 255 0 15 0 5 0 10 0 5 0 5 0 30 0 15 0 0 0 20 0 40 0 60 0 80 0 100 0 0 0 5 0 5 3 232 255 255 255 255 165 165 0 165 0 0 16 3 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 163 198

Правда, в архиве сохранились числа только до адреса 255. Здесь, опять же, 1 3 — адрес и команда, 128 — число переданных байт, два байта в конце — CRC, а всё остальное — содержимое памяти.

Из всего этого великолепия нас с очевидностью интересуют те адреса, содержимое которых меняется со временем. И здесь у датчика оказалось для меня две новости — хорошая и плохая. Хорошая — такие адреса есть. А плохая — их всего два — 261 и 264. Сравните с «прошлой жизнью», когда по одной команде выдавалось сразу четыре числа! Я уж было раскатал губу — думал, ко всем внутренним переменным доступ получу. Ну что же, два так два.

Время снова строить графики!

Величина по адресу 261:

Похоже на концентрацию СО2. Видно, когда я пробовал дышать на датчик. Правда, минимальное значение лежит заметно ниже, чем «эталонные» 400 ppm, так что калибровка оставляет желать лучшего. Так или иначе, датчик объявляется воскресшим.

Величина по адресу 264:

Приблизительно то же, только в другом масштабе и перевёрнутое.

И обе величины на одном графике:

Возникает естественный вопрос — быть может, одна из этих величин — это и есть то самое «сырое» значение, которое приходит с АЦП и которое датчик одному ему ведомым способом преобразует в оценку СО2? Если так, то это открывает большие возможности по перекалибровке и повышению точности датчика, а быть может, и по использованию его не по назначению. Ответ на этот вопрос (и на некоторые другие) мы попытаемся получить в следующей серии.

В каментах принимаются пожелания и предложения — как ещё поиздеваться над MH-Z19 в следующей статье. Правда, обещать ничего не буду.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Что делать?

Поделиться публикацией

Комментарии 63

  • НЛО прилетело и опубликовало эту надпись здесь
      0
      А к датчику не нагугливалось никаких даташитов или мануалов?
        +1
        Наличие Modbus это здорово. С для работы с ним полно готового софта, куча разных утилит и почти все SCADA системы умеют работать с Modbus.
        На хабре была статья «Программное обеспечение для тестирования и наладки устройств и сетей на базе MODBUS»:
        https://habrahabr.ru/post/281430/
          +15

          Статья, достойная Старого Хабра!

            +2
            Ударьте его и посмотрите, какого он станет цвета.
              0
              Думаешь там внутри, в виде датчика насекомое?
                0
                А вдруг канарейка?
                +1
                Не сработает. Это же датчик, а не Индикатор.
                +1
                Это мегалайк! Теперь не знаю, что вкуснее, подключение к modbus без ардуино-переходника, или возможность пользоваться термометром.
                  0
                  Мой экземпляр иногда (крайне редко) не отвечает положенными 10 байтами. Вернее конструкции
                  while (Serial2.available()) {
                   mhzBuffer[mhzBufferIndex] = Serial2.read();
                   mhzBufferIndex++;
                  }
                  
                  не всегда удается прочитать все 10 байт, и оставшиеся байты приходят только спустя 1-2 секунды при повторном чтении. Так и не смог решить эту проблему, но в остальном уже около года MH-Z19 в домашней метеостанции круглосуточно мониторит СО2 в квартире. Этот датчик приучил меня проветривать комнату!
                    0
                    А почему бы не делать так:

                    Serial2.write(cmd, 9);
                    memset(mhzBuffer, 0, 9);
                    Serial2.readBytes(mhzBuffer, 9);
                      0
                      Кажется именно так я и делал изначально, но readBytes ожидает все 10 байт в течении setTimeout миллисекунд (1000 по умолчанию). Ждать ответа от переферии по 1-2 секунды я не захотел, так как нужно еще обновить дисплей и обрабатывать нажатия кнопок управления (прерываниями пользоваться не умею, да), поэтому способ был отброшен.
                    0
                    В моём случае датчик умирал после пайки и после подключения к 5В. Оживал всегда сам после небольшого «отдыха»
                      +1
                      У меня проблема с калибровкой работы датчика, после непрерывной работы более 2 дней показания стали в начале расти до 3500 ppm потом после перезагрузке ходит около 400-500 ppm
                      Хочу сделать «Calibrate zero point» но не могу понять это калибровка под 0 ppm или 400 ppm? на одном сайте пишут что это типа 0 ppm и без азота не обойтись а на другом пишут что это 400 ppm и достаточно хорошо проветрить помещение в течении 20 мин подержать датчик в нем и можно делать калибровку.
                      Есть еще «SPAN POINT CALIBRATION» код 0x88 где можно задать свое значение, побывал его но никакой особой ракции
                        0
                        понять это калибровка под 0 ppm или 400 ppm
                        Под 0, :-(.
                        Я так два датчика убил (первый откалибровал ради интереса, второй – просто по ошибке, эта калибровка запускается при замыкании одного из входов на землю – а я не знал, что его корпус из проводящего метализированного пластика, и заземлённй), не повторяйте моих ошибок.
                        Исправить без баллона нельзя потом, я его даже в эксикаторе с щёлочью держал – не помогает.
                          0
                          В крупных городах продается жидкий азот, стоит копейки. Единственное — учтите, что у co2 температура сжижения сильно выше, чем у азота. Поэтому наливать в пакет с датчиком азот неправильно.
                          Кислород тоже сжижается при температуре жидкого азота, но не знаю влияет ли он на датчик.

                          Я положил в пакет датчик, провода наружу. И несколько раз давал наполниться пакету азотом из термоса и потом выдавливал весь газ наружу. Потом запустил калибровку.
                            0
                            Хех, я с азота и начал – благо, его даже покупать не надо, достаточно в лаборатории у знакомого отлить. Увы, «Не помог и испаряющийся жидкий азот (оказалось, что он набирает углекислый газ из воздуха, и датчик зашкаливает, даже если у него сбита калибровка и он не реагирует ни на что другое).»

                            Вы, собственно, сами чуть ниже говорите, что никакого эффекта не добились.
                          0
                          Я пытался калибровать азотом и замыканием контакта калибровки на землю (или на vcc, не помню). Никакого эффекта не добился.
                            0
                            Как мне кажется, самое простое и правильное решение – вручную составить таблицу перекалибровки датчика по работающему – ставить рядом два датчика, записывать показания, а потом составить таблицу пересчёта (с шагом в 50-100 ppm, большую точность они всё равно не дают), и на её основе написать калибровочную функцию.
                            Беда в том, что работающего измерителя концентрации CO2 я для пока найти пока не могу, :- (.
                              0
                              У меня была похожая проблема, когда датчик начинает работать, то он постоянно повышал значение, а если его выключить и снова включить, то сразу падало.
                              Я так думаю, что бы это было связано с напряжением, я когда с 3.7В на 5В поменял, то стало нормально.
                              0
                              Очень интересная статья!
                              Только пара замечаний:
                              1). В интернете есть PDF-файлы под названием «datasheet» к датчикам этой серии – MH-Z19, MH-Z14 и другим. Они, в отличии от настоящих даташитов, очень куцые, но часть встреченных в статье «недокументированных функций» там описаны.

                              Правда, минимальное значение лежит заметно ниже, чем «эталонные» 400 ppm, так что калибровка оставляет желать лучшего.
                              Скорее всего, вы, среди прочих, подали команду сброса калибровки датчика – перекалибровали его так, что он теперь думает, что находится в воздухе с минимальной понятной ему концентрацией СО2, она как раз порядка 150 ppm.
                                +1
                                В сети есть 2 datasheet один для MH-Z19 второй для новой ревизии MH-Z19B отличается от старого датчика то что может работать и с 5v логикой а так же эти датчики уже продают с распаянными колодками, так вот там в PDF MH-Z19B написано:

                                — 0x87-ZERO POINT CALIBRATION NOTE:ZERO POINT is 400PPM, PLS MAKE SURE THE SENSOR HAD BEEN WORKED UNDER 400PPM FOR OVER 20MINUTES

                                получается новая ревизия имеет калибровку нуля не 0 ppm а 400 ppm
                                  0
                                  О, значит китайцы молодцы. Легко доступная функция калибровки, убивающая датчик – это ужас.
                                +1
                                Поиздеваться можно попробовать так: заменить микропроцессор датчика на arduino и сделать опенсорсную прошивку по прямой работе с железом.
                                  +3
                                  Там и так на борту стоит вполне человеческий STM32F1 и пины для перепрошивки выведены наружу.
                                    0
                                    Нет, лучше заменить STM32 на атмел и все писать в недо-IDE arduino!
                                  +4
                                  Отличная статья, спасибо!

                                  Если вы не сильно далеко от Москвы и вам вдруг нужны сенсоры MH-Z19 или MH-Z19B для дальнейших экспериментов, то с радостью отдадим на растерзание — мы их используем в своих железках и поэтому у нас их всегда много.
                                    +1
                                    Не тот график привёл для величины 261. Вечером исправлю. Правильный график — как на последней картинке синим цветом.

                                    Rast1234
                                    > А к датчику не нагугливалось никаких даташитов или мануалов?

                                    Ну вот есть официальный даташит (хотел привести в статье ссылку, но забыл):

                                    http://www.winsen-sensor.com/d/files/PDF/Infrared%20Gas%20Sensor/NDIR%20CO2%20SENSOR/MH-Z19%20CO2%20Ver1.0.pdf

                                    Ни о каком модбусе там не говорится, да и вообще информации с гулькин нос. Я честно пытался найти статьи, где бы люди его более детально изучали — нашёл только вышеприведённую статью https://revspace.nl/MHZ19 и пост на форуме http://www.letscontrolit.com/forum/viewtopic.php?t=1785, насколько я понял, того же автора.

                                    arcman
                                    > Наличие Modbus это здорово.

                                    Это да. Только меня смущает адрес датчика — 1. Небось если его подключать совместно с другими устройствами, то наверняка найдётся другое не менее «умное устройство» с таким же адресом (а если мы хотим мерять СО2 в двух и более местах — то эта вероятность становится равной единице). Хотя, быть может, удастся изменить этот адрес — вон в содержимом памяти три единицы виднеются.

                                    legrus
                                    > Теперь не знаю, что вкуснее, подключение к modbus без ардуино-переходника, или возможность пользоваться термометром.

                                    Ну, по оригинальному протоколу тоже можно с компа без ардуины общаться. https://geektimes.ru/post/272090/ Или у вас готовая modbus-железка? А термометр там не очень точный, как я упомянул в статье.

                                    @ Weles
                                    > В моём случае датчик умирал после пайки и после подключения к 5В. Оживал всегда сам после небольшого «отдыха»

                                    Насколько я понял, он вообще при включении «разогревается» три минуты, и в это время показывает различную чепуху. Пишут, что тепловой режим должен установиться, а после пайки он как раз нарушен.

                                    APLe
                                    > Я так два датчика убил

                                    Ну почему же сразу убил? Повышение-то СО2 показывает. Ну и можно что-нибудь придумать с калибровкой. Первое, что вспоминается — получить водород электролизом воды (кислород брать я бы не стал — мало ли что окислит).

                                    Ещё бы придумать, где брать СО2 для калибровки и как его точно измерять. Я уже попробовал соду с лимонной кислотой — в принципе получается наполнить пакет львиной долей СО2, только непонятно, насколько она львиная. Скорее всего, куплю точные весы и буду добавлять раствор соды к раствору кислоты.

                                    > Скорее всего, вы, среди прочих, подали команду сброса калибровки датчика – перекалибровали его так, что он теперь думает, что находится в воздухе с минимальной понятной ему концентрацией СО2, она как раз порядка 150 ppm.

                                    У меня было веселее. Он раз в сутки сам автоматически калибруется — вроде как минимальное значение принимает за 400 ппм. Так вот, он у меня так замечательно откалибровался, что стал показывать в 2 — 3 раза меньше, чем до этого, и показания обрезались на 400 ппм (то бишь сам он явно намерял меньше, но стеснялся в этом признаться). А вот по modbus он ничего не обрезает, зато минимум стал показывать даже меньше 150. Графики в следующий раз приведу.

                                    Кстати говоря. Самая главная команда, которая упомянута на revspace — 0x79: ABC logic on/off. Взята из даташита на MH-Z19B. Я сначала не мог понять — алфавит отключает, что ли? И только после того, как я почитал даташитов на более понтовые датчики, я понял — это automatic baseline correction, то бишь таким способом можно отключать самовольную калибровку. Я считаю, это первое, что надо делать с датчиком после покупки. Хотя быть может, конечно, что со временем показания плывут, но по крайней мере так можно быть уверенным, что если сегодня показания одни, а завтра другие — это действительно что-то изменилось в среде, а не датчик решил пошутить.

                                    SegreyBorovkov
                                    > В крупных городах продается жидкий азот, стоит копейки.

                                    А тара для него тоже копейки стоит? Вообще, как его покупают, чтобы дёшево и сердито?

                                    > Я пытался калибровать азотом и замыканием контакта калибровки на землю (или на vcc, не помню). Никакого эффекта не добился.

                                    А почему? Получается, что датчик настолько тролльский, что в условиях атмосферы сбить калибровку может, а в условиях азота калиброваться отказывается?

                                    evgeny_boger
                                    > Там и так на борту стоит вполне человеческий STM32F1 и пины для перепрошивки выведены наружу.

                                    О, значит, кто-то всё-таки его уже мучал! Было бы интересно почитать вашу статью на эту тему, она наверняка будет познавательнее моей. В частности, как его вскрывать, чтобы ничего не сломать.

                                    > с радостью отдадим на растерзание

                                    Спасибо! Если свой убью, то с радостью приму.
                                      0
                                      Ну почему же сразу убил? Повышение-то СО2 показывает.
                                      Потому что повышение он тоже показывает очень криво, :-(.
                                      Я так понимаю, у него теперь «0» откалиброван по атмосферной концентрации (уже чуть ниже, после калибровке в эксикаторе над щёлочью), и «400» – тоже по атмосферной концентрации. Поэтому показания жутко нелинейные и непонятно где и как завышенные. В общем, надо вручную калибровать – по рабочему, которого у меня нет.

                                      Он раз в сутки сам автоматически калибруется
                                      Ого, а он калибруется разве? Вот этого в даташите я не видел (или не понял, что такое «ABC logic», тоже возможно).
                                      Если да, то это может объяснять многие странности в его поведении.

                                      А тара для него тоже копейки стоит?
                                      Любой термос подходит. Лучше, на всякий случай, из нержавейки.
                                        0
                                        О, значит, кто-то всё-таки его уже мучал! Было бы интересно почитать вашу статью на эту тему, она наверняка будет познавательнее моей. В частности, как его вскрывать, чтобы ничего не сломать.


                                        Да нет, мы как раз один сенсор разломали и посмотрели, что внутри :)
                                        Я кстати немного ошибся, там стоит STM32F051

                                        Статью думаю напишем, но я больше хотел написать про показания и автокалибровку. Мы делаем долговременные тесты, сравниваем между собой MH-Z19B и другие китайские, Fibaro CDM7160, SensAir S8 и т.д.
                                          0
                                          Я жидкий азот купил, приехав с металлическим литровым термосом. Мне сказали, что можно наливать только в дьюары. И тут же налили в термос :-).

                                          >> Я пытался калибровать азотом и замыканием контакта калибровки на землю (или на vcc, не помню). Никакого эффекта не добился.

                                          >А почему? Получается, что датчик настолько тролльский, что в условиях атмосферы сбить калибровку может, а в условиях азота калиброваться отказывается?

                                          Я допускаю, что датчик немного изменил калибровку, но существенного изменения после калибровки по свежему воздуху не последовало. Как и раньше, раз в сутки на графике видна ступенька рекалибровки датчика.

                                          Могу сказать, что в моих условиях (аптайм — месяцы, случайное проветривание, бывает минимум за сутки и 600ppm, это не влияет!), ступенька постепенно уменьшается. Если в первую неделю после калибровки и последующего полноценного подключения, калибровка легко сдвигала показания на 200ppm, то сейчас в большинстве случаев калибровка меняет значение меньше, чем на 50 ppm.

                                          Я вполне допускаю, что если неверно откалиброванный датчик подключить к питанию, то он через месяц начнет показывать что-то адекватное.

                                          Записывается ли такая ежесуточная калибровка в ППЗУ датчика — не знаю.
                                            0
                                            >Могу сказать, что в моих условиях (аптайм — месяцы, случайное проветривание, бывает минимум за сутки и 600ppm, это не влияет!), ступенька постепенно уменьшается. Если в первую неделю после калибровки и последующего полноценного подключения, калибровка легко сдвигала показания на 200ppm, то сейчас в большинстве случаев калибровка меняет значение меньше, чем на 50 ppm.

                                            Получается что автоматическая калибровка или не имеет ограничения на размер единовременного изменения, или оно очень большое, если за сутки может сдвинуть значение на 200… В таком случае, вероятно, имеет смысл отключать ABC и делать ее снаружи, мне (умозрительно) кажется, что было бы логично ограничить возможность разовой калибровки 50ppm и проводить ее не раз в сутки, а раз в неделю, так будет значительно ниже вероятность перекалибровки (мало ли, пару дней комнату не проветривали и при этом там тусила толпа).
                                              0
                                              Измерители co2, типа
                                              фотка
                                              image
                                              именно так и поступают — раз в неделю калибруются на <=50ppm.
                                            0
                                            Датчик вы скорее всего уже убили, и теперь его можно смело разбирать. Посылать случайные команды в сенсор с доступными конфигурационными параметрами в EEPROM (или его эмуляцией во флэш) — верный способ сбить настройки. Если Zero вы еще сможете восстановить в домашних условиях, то Span и температурные коррекции малореально. Если всё же займётесь — для калибровки нужны газы не более верхнего порога измерения, т.е. сода с лимонной кислотой не годится.
                                            Так как в сенсоре есть ABC с периодом 24 часа, то величина U, очевидно, является минимальным значением измеренного поглощения IR CO2 за сутки, в каких-то внутренних единицах измерения.
                                            ABC фича полезная, отключать её стоит лишь в средах, где 400ppm не бывает. Калибровка раз в сутки, конечно, слишком часто, даже в жилых помещениях не всегда бывает свежий воздух.
                                              0
                                              > Датчик вы скорее всего уже убили

                                              Как вы, однако, смело записали его в покойники. А он работает и не знает, что уже труп.

                                              > Посылать случайные команды в сенсор с доступными конфигурационными параметрами в EEPROM (или его эмуляцией во флэш) — верный способ сбить настройки.

                                              Не думаю, что он в «родном» режиме что-то воспринимал как настройки. По крайней мере ежели бы они все слетели, он бы, скорее всего, показывал бы бред. А так показывает что-то похожее на правду, хоть и несколько смещённую.

                                              > для калибровки нужны газы не более верхнего порога измерения

                                              Процедуру разбавления уже запретили? Ну и по секрету скажу, что порог измерения у него теперь где-то в районе ста процентов. Про это будет в следующей статье.

                                              > величина U, очевидно, является минимальным значением измеренного поглощения IR CO2 за сутки, в каких-то внутренних единицах измерения.

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

                                              > ABC фича полезная, отключать её стоит лишь в средах, где 400ppm не бывает.

                                              Интересно вы рассуждаете. Немного слетела калибровка (хотя можно программно сделать поправку в случае чего) — это уже труп. А когда сам датчик самоуправством занимается (и программно это учесть либо невозможно, либо очень сложно) — это так и должно быть.
                                                0
                                                Мне кажется, вы смотрите с разных точек зрения =)
                                                Для unsvp датчик — это откалиброванное устройство, работающее по известному алгоритму с известными, повторяемыми параметрами, и изменение этих параметров = потере старого датчика (и, возможно, приобретение нового с неизвестными параметрами).
                                                Вы же рассматриваете его как устройство для изучения/реверса, ранее заложенный алгоритм Вам неизвестен, к тому же нет калиброванного известного датчика рядом, и вы работаете только с относительными значениями, которые похожи на абсолютные, но погрешность никто высчитать не может.

                                                Спасибо Вам за работу =)
                                                0x79 у меня работает на одну сессию (одно включение, надо подавать при инициализации) и позволяет смотреть изменение без ежесуточных сбоев. В долговременном плане меня смущает, конечно, засирание внутренней поверхности в условиях города с пылью/табачным дымом рядом, пока я просто вывожу недельный минимум рядом с текущим показанием. Минимум считаю скользящим окном, а не по фиксированным срокам.
                                                0
                                                > величина U, очевидно, является минимальным значением измеренного поглощения IR CO2 за сутки, в каких-то внутренних единицах измерения.

                                                Да, вы знаете, сейчас посмотрел — всё происходит (происходило..) ровно так, как вы сказали. Посыпаю голову пеплом. Сейчас в пост добавлю.
                                                0
                                                Хотя, быть может, удастся изменить этот адрес — вон в содержимом памяти три единицы виднеются.

                                                Обычно, можно менять адрес у любых устройств. Т.е. если даже нельзя у датчика, то у другого устройства с этим адресом будет можно.
                                                0
                                                Del. Не туда ответил.
                                                  +2
                                                  Читается как роман. Надеюсь автору не подвернется на часок «ядерный чемоданчик»
                                                    0
                                                    попробовать считать прошивку если не залоченная и реверснуть
                                                      0
                                                      Не подскажете от чего возникают такие скачки? Правда у меня MH-Z14
                                                      График
                                                      image
                                                        0

                                                        верхний график: какая то ошибка в бите. прыжки +- 256.
                                                        нижний график: неверное преобразование знаковый/беззнаковый

                                                          0
                                                          так вот они (прыжки) стабильные, они сохраняются на протяжении нескольких часов, при запросах к датчику кажде 15 секунд. Только когда людей нет в помещении график ровный.
                                                          Про то, что нижний без знаковый знаю, но руки никак не дойдут поправить прошивку.
                                                            0
                                                            > Про то, что нижний без знаковый знаю, но руки никак не дойдут поправить прошивку.

                                                            Коли знаете, то зачем спрашиваете?
                                                              0
                                                              Картинка не удачная, у меня вопрос про верхний график только был. По нижнему четко виден переход знака.
                                                                0

                                                                у вас на обоих графиках "сбои" происходят одновременно. причем с нижним всё в порядке на самом деле. А вот для построения верхнего вы похоже используете байт из нижнего. В общем ищите где данные меняются местами. Или вы при вычитывании один байт не обновляете, а используете старое значение вычитанное для другой величины.

                                                                  0
                                                                  Не всегда, при построении использую точно верные данные. График рисует совершенно независимая машина. Данные концентрации и температуры приходят из ардуины. Там единственный косяк на текущий момент, что все int знаковые.
                                                                  Бессмысленно и беспощадно
                                                                      mySerial.write(cmd,9);
                                                                      mySerial.readBytes(response, 9);
                                                                      int responseHigh = (int) response[2];
                                                                      int responseLow = (int) response[3];
                                                                      tem = (unsigned int) response[4]; // Удет в комп
                                                                      ppm = (256*responseHigh)+responseLow; // Уйдет в комп
                                                                  
                                                            0
                                                            Да с верхним графиком то же самое небось. Скорее всего, предыдущий оратор читает в два байта со знаком, а затем складывает их наподобие байт1 * 256 + байт2. Вот и прыжки на 256. А надо использовать беззнаковые. Хотя без вашего камента я бы не догадался.
                                                              0
                                                              А вот до этого я не додумался. Попробую, посмотрим, что получится.
                                                          0
                                                          У меня с датчиком MH-Z19 что то не заладилось совсем, первый стал глючить, второй китац прислал не рабочий(корозия на ножках) да и в инете постоянные жалобы на него

                                                          вопрос: у кого есть модель MH-Z14, у вас такаие же проблемы?
                                                            0
                                                            Подскажите, пожалуйста, где можно купить такую коробочку, которая бы показывала содержание углекислого газа в воздухе с небольшой погрешностью за вменяемые деньги?
                                                            Очень хочу такую, но собирать самому очень не хочется.
                                                              0
                                                              От даджет-а, за 5500р.
                                                              0
                                                              Нашел в интернете пост одного японца который утверждает что «Calibrate zero poin» это калибровка на 400 ppm (https://lowreal.net/2016/12/25/3) на датчике MH-Z19.

                                                              И так я решился сделать калибровку «Calibrate zero poin», решил не трогать ножку HD и все делать через команды UART.

                                                              Дома в одной из комнат решил сделать проветривание(окна у меня выходят на лесок, воздух должен был достаточно чистый) при температуре за бортом -15 я положил датчик возле окна а сам пошел на 30 мин в другую комнату чтобы выдыхаемый мной CO2 не портил картину.

                                                              Это была моя первая ошибка, после того как я через 30 мин отправил команду на калибровку я первый раз увидел как датчик стал выдавать 130-150 ppm, думал что уже тоже окончательно сломал датчик.

                                                              Но тут обратил внимание на то какую температура была в самом датчике (за это отвечает 4 байт в ответе TT is the temperature in degrees Celcius, plus 40. For example, when temperature is 25 deg C, then TT = 0x41) оно было +3..+5 и понял что калибровку лучше делать при постоянно не меняющейся температуре.

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

                                                              Через 15 мин показания температуры в датчике стабилизировались на отметке +19 и 5 байт ответа(SS is some kind of status byte, this byte always has only one bit set!) стал показывать стабильно долго одно значение «64», через 5 мин я запустил калибровку по новой, после этого обесточив датчик и включив его заново уже в другой комнате где я ожидал проветривание, датчик стал показывать с ростом ppm и остановился на отметки 850 через 10 мин что с ощущениями похоже на правду.

                                                              p.s. Вот уже несколько часов показания датчика похоже на те что были до поломки
                                                              p.s.s. ABC калибровку я отключил от греха подальше
                                                              p.s.s.s. Для контроля нужно купить еще один датчик, осталось выбрать или новую модель MH-Z19B(там не только припаяна колодка ног но и убрали микросхему) или взять MH-Z14A(меньше негатива об этом датчике)

                                                              Новый датчкик mh-z19b:
                                                              image


                                                                0
                                                                Привет всем!
                                                                После нескольких дней непрерывной работы на момент сегодняшнего утра датчик стабильно выдавал 500-530 ппм в сухой пятилитровой бутылке (в бутылке я сделал небольшой надрез, чтобы просунуть туда датчик и после плотно заклеил скотчем). После работы в бутылке я поместил датчик на створку окна, открыл окно на проветривание. Датчик откалибровался и стал выдавать значение на 70-100 ппм больше, чем в бутылке. После чего я вернул его в бутылку и он ожидаемо стал выдавать 640 ппм (вместо 530 ранее в той же бутылке, в бутылку я не дышал=)).
                                                                Теперь самое интересное. Я открутил крышку, сделал выдох в бутылку, закрутил крышку. Датчик за несколько измерений подошел к 5000 ппм и стал стабильно показывать эту цифру. Мне показалось, что от одного выдоха концентрация до 5000 ппм скакнуть не должна была, я отключил датчик, и после включения он показывал не 5000, а всего 950!!! После очередного выдоха в бутылку датчик уже не зашкалил, но подошел вплотную к 5000. Он стабилизировался на уровне 4950-4990. Затем я вытащил датчик к окну и он стал давать показания 150-550. В бутылке с уличным воздухом показания медленно ползли вниз от 500 до 400. После отключения питания и подключения снова выдает 500 и показания продолжают медленно расти вверх.
                                                                Прошу прощения за длинный пост. В итоге совсем не могу понять почему показания плавно меняются то вверх то вниз, не стабилизируются даже в изолированной бутылке.
                                                                  0
                                                                  Буквально сейчас аналогичный тест произвожу. Только более долговременный. Надышал в бутылку и закрыл. Показания болтаются в районе 12600+-100. И тоже не понимаю, отчего это они гуляют. С изменениями температуры вроде не соотносится. Но долговременная (несколько суток) стабильность есть.

                                                                  Кстати говоря, в выдыхаемом воздухе «по уставу» 4% СО2, сиречь 40 000 ppm. Правда, никто не говорит, при каких это условиях. У меня в зависимости от того, насколько я задерживаю дыхание, показания в полтора раза меняются.

                                                                  > в бутылке я сделал небольшой надрез, чтобы просунуть туда датчик и после плотно заклеил скотчем

                                                                  Ну кто так делает? Я вот просверлил в крышке отверстие, просунул провода и залил термоклеем. Теперь можно считать, что она абсолютно герметична (по крайней мере в пределах нескольких дней при атмосферном давлении).

                                                                  > я отключил датчик, и после включения он показывал не 5000, а всего 950!!!

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

                                                                  > я поместил датчик на створку окна, открыл окно на проветривание

                                                                  Интересно, а у меня он при малейшем ветерке какую-то шерсть показывает. Каким напряжением питаете? Я для своего сделал вывод, что лучше всего он работает на нижней границе диапазона, то бишь 3,6 В. Правда, чуть ниже — уже начинает глючить. И, конечно, никак не говорит, что напряжения не хватает.
                                                                    0
                                                                    Задержка дыхания, естественно влияет =) на продолжительность и эффективность диффузии газов из/в крови в лёгких. Думаю, 4% — это либо средний максимум, либо максимальное значение, обусловленное падением эффективности переноса газов при большей концентрации
                                                                  0
                                                                  Очень интересная статья. Для исследования протокола Модбас всё таки лучше бы использовать специализированную программу типа Modbus Poll. Было бы интересно найти регистр переключения протоколов. Да и адрес, скорее всего меняется в каком то регистре.
                                                                    0
                                                                    > специализированную программу типа Modbus Poll

                                                                    Быть может, но я с Modbus первый раз встречаюсь, потому никаких программ не знаю.

                                                                    > Было бы интересно найти регистр переключения протоколов. Да и адрес, скорее всего меняется в каком то регистре.

                                                                    Да, это тоже попроверяю. В принципе содержимое памяти есть, можно в случае чего обратно «первоначальные» значения записать.
                                                                    0
                                                                    А нормально, что на (условно) чистом городском воздухе датчик (В версия) может показывать 395ppm?
                                                                      0
                                                                      Ну вроде как он наименьшее значение за сутки принимает за 400 ппм. Это, конечно, не очень хорошо, но вот так.
                                                                        0
                                                                        А вот теперь наоборот… Купил ещё один такой же датчик, так он за городом на улице показывает 700 с копейками. Неужели калибровать придётся?
                                                                          0
                                                                          Откалибровал по уличному воздуху. Вроде нормально стал показывать.

                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.