Winsen ZPHS01B
- Войдите на сайт для отправки комментариев
Приехал ко мне Winsen ZPHS01B - многофункциональный модуль для контроля качества воздуха.
В состав устройства входят следующие датчики:
• Лазерный датчик пыли;
• Датчик углекислого газа (CO2);
• Электрохимический датчик формальдегида (CH2O);
• Электрохимический датчик озона (O3);
• Датчик угарного газа (CO);
• Датчик летучих органических веществ;
• Датчик диоксида азота;
• Датчик температуры;
• Датчик влажности.
Основные особенности и технические характеристики:
• Определяемые вещества: CO, CO2, CH2O, O3, NO2, летучие органические вещества, мелкодисперсные частицы;
• Измерение температуры и влажности;
• Напряжение питания: 5В;
• Средний потребляемый ток: <300мА;
• Выходной интерфейс: UART;
• Диапазон рабочих температур: от -10°C до +50°C;
• Габаритные размеры: 135x50x26,2мм.
Сперва - ссылки на превосходные обзоры от коллеги по форуму на датчики Winsen по отдельности:
https://arduino.ru/forum/obshchii/winsen-ze15-co
https://arduino.ru/forum/obshchii/winsen-zs05
https://arduino.ru/forum/obshchii/winsen-ze08-ch2o
Сайт производителя сенсора https://www.winsen-sensors.com, сенсор продаётся на али продавцом по имени Winsen (удивительно), стоит $90, ехал ~2.5 недели (на 20-сентября-2022). Содержит пачку распаянных датчиков из тех, что указаны выше по ссылкам.
Коробочка была довольно помятая, но содержимое оказалось в целости и сохранности. Немножко прифигел, когда достал из коробочки ещё и два листа сертификатов "поверок", аж с подписью!
Стоит сделать отступление: ВАЖНО! Получившееся устройство не является поверенным/сертифицированным измерителем, не стоит использовать и полагаться на него в критических для жизни и здоровья ситуациях - можно больно и мучительно умереть.
Устройство собирал на клоне Lolin Wemos D1 R1 mini, хотел передавать данные по вайфаю, на самом-то деле, убил вчера почти целый день, прежде чем осознал, что SoftwareSerial у esp8266 конфликтует с вайфаем, и ведь помнил же, но естественно, забыл )) Как только отказался от вайфая - всё сразу заработало.
Схема очень простая, если берём 3.3V плату:
Winsen G --> Wemos GND
Winsen V --> Wemos +5V !!!
Winsen R(rx) --> Wemos D3 (3.3V !!!)
Winsen T(tx) --> Wemos D4 (3.3V !!!)
Разъём на сенсоре - XH2.54-4P. Поскольку у меня дома (разумеется) такого нет, воспользовался обычными ардуиновскими дюпонами папа-мама, папами в ардуину, мамы отлично налезли на штырьки xh2.54 (ещё бы не налезли).
Измучившись с вимосом, решил хотя бы проверить, а живой ли вообще сенсор. В usb-uart с али на ch340g впихивать побоялся, поскольку там на уарте вроде бы 5V на выходе, поэтому залил в тот же вимос serial-мост, пусть работает переходником.
#include <SoftwareSerial.h> SoftwareSerial WinsenSerial(D4, D3); void setup() { Serial.begin(9600); WinsenSerial.begin(9600); } void loop() { String str = ""; if (Serial.available()) { while (Serial.available() > 0) { char c = Serial.read(); str += c; } WinsenSerial.print(str); } str = ""; if (WinsenSerial.available() > 0) { while (WinsenSerial.available() > 0) { char c = WinsenSerial.read(); str += c; } Serial.print(str); } }Заливаем, запускаем, и обращаемся к нему из любой софтины, работающей с ком-портом.
import serial import time serialPort = serial.Serial(port="COM3", baudrate=9600, bytesize=serial.EIGHTBITS, timeout=1, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE) if serialPort.isOpen(): print("Opened " + serialPort.portstr) while True: serialPort.flush() serialPort.flushInput() serialPort.flushOutput() serialPort.write(b'\xff\x01\x86\x00\x00\x00\x00\x00\x79') s = serialPort.read(26) if len(s) == 26 and s[0] == 0xff and s[1] == 0x86: result = { 'pm1.0': s[2] * 256 + s[3], 'pm2.5': s[4] * 256 + s[5], 'pm10': s[6] * 256 + s[7], 'co2': s[8] * 256 + s[9], 'voc': s[10], 'temperature': ((s[11] * 256 + s[12]) - 435) * 0.1, 'rh': s[13] * 256 + s[14], 'ch2o': (s[15] * 256 + s[16]) * 0.001, 'co': (s[17] * 256 + s[18]) * 0.1, 'o3': (s[19] * 256 + s[20]) * 0.01, 'no2': (s[21] * 256 + s[22]) * 0.01 } print(time.ctime()) print(*result.items(), sep='\r\n') print("") else: print(time.ctime() + " no data") print("") time.sleep(10)Работает, показания выдаёт ))
Маленький нюанс - видите, при подсчёте температуры нужно вычитать коэффицент. Правильный коэффицент -435, а в даташите ( https://www.winsen-sensor.com/d/files/zphs01b-english-version1_1-20200713.pdf ) написано вычитать -500!!! Поубивал бы ногами за такое.
При питании по проводу от USB 2.0 сенсор углекислого газа выдаёт всегда 5000ppm, максимальную границу. При питании от павербанка всё в порядке; видимо не хватает, хотя судя по показаниям, трескало максимально 5V 0.41А - на сенсор+вимос+ssd1306.
Ну, а удостоверившись в работоспособности сенсора, и решив отказаться от вайфая, уже вполне можно дотюнить работу с SoftwareSerial, и добавить дисплей для автономности.
SSD1306 SCK --> Wemos D2
SSD1306 SDA --> Wemos D1
SSD1306 VDD --> Wemos +5V !!!
Куда подключать SSD1306 GND, предлагаю догадаться самостоятельно (гусары, молчать!). :)
Работающую для esp8266 библиотеку SoftwareSerial взял вот тут, просто положил два файла в папку и сделал инклюд через кавычки, как и написано на странице библиотеки: https://github.com/CrazyRobMiles/Esp8266EdgeSoftwareSerial
Библиотека для OLED SSD1306 для ESP8266 у меня тоже сторонняя: https://github.com/ThingPulse/esp8266-oled-ssd1306
#include <Adafruit_GFX.h> #include "SoftwareSerial.h" #include <Wire.h> #include <SSD1306Wire.h> SSD1306Wire display(0x3C, D1, D2); #define TX D3 #define RX D4 SoftwareSerial WinsenSerial(RX, TX); int pm1; int pm25; int pm10; int co2; int voc; float temp; float rh; float ch2o; float co; float o3; float no2; int chk; void read_winsen() { const uint8_t cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; for (int i = 0; i < 9; i++) { WinsenSerial.write(cmd[i]); } byte s[26]; if (WinsenSerial.available()) { for (int i = 0; i < 26; i++) { s[i] = WinsenSerial.read(); } pm1 = s[2] * 256 + s[3]; pm25 = s[4] * 256 + s[5]; pm10 = s[6] * 256 + s[7]; co2 = s[8] * 256 + s[9]; voc = s[10]; temp = ((s[11] * 256 + s[12]) - 435) * 0.1; rh = s[13] * 256 + s[14]; ch2o = (s[15] * 256 + s[16]) * 0.001; co = (s[17] * 256 + s[18]) * 0.1; o3 = (s[19] * 256 + s[20]) * 0.01; no2 = (s[21] * 256 + s[22]) * 0.01; chk = s[25]; } } void draw_1306() { display.clear(); display.drawString(1, 1, "CO2: " + String(co2)); display.drawString(80, 1, "VOC: " + String(voc)); display.drawString(1, 14, "Temp: " + String(temp)); display.drawString(1, 22, "RH: " + String(rh)); display.drawString(1, 30, "CH2O: " + String(ch2o)); display.drawString(1, 38, "CO: " + String(co)); display.drawString(1, 46, "O3: " + String(o3)); display.drawString(1, 54, "NO2: " + String(no2)); display.drawString(90, 22, String(pm1)); display.drawString(90, 30, String(pm25)); display.drawString(90, 38, String(pm10)); display.display(); } void setup() { display.init(); display.flipScreenVertically(); display.setContrast(7); display.display(); WinsenSerial.begin(9600); while (!WinsenSerial) { delay(100); } } void loop() { read_winsen(); draw_1306(); delay(5000); }При питании от повербанка все значения выглядят более-менее похожими на правду, вечерком ещё поковыряюсь.
Единственное, что мне не очень нравится - показания влажности 65%. Рядом стоит несколько других датчиков, все показывают ~35-40%, между собой они согласны, датчики разные, а этот вот 65-67 и всё. Ну да ладно, мне от этого сенсора гигрометр особо-то и не нужен, а может просто надо ещё какой коэффицент из лживого датащита поправить.
Хлопнул пива, подышал на датчик - формальдегид сантиметров с 30 чувствует. Лазеру очень не нравятся сигареты - моментально добавляется загрязнение х3-x4, из-за тяжёлых частиц дыма, наверное. Причём я не дышу на прямо сам датчик, от него до меня сантиметров 50-60, и дым я выдуваю в другую сторону, а всё равно всё ему видно.
PS Не имею отношения к китайцам и компании винсен, но точно так же, как и коллега, вынужден постоянно повторять именно их название - ибо это весьма доступные датчики по относительно доступной цене, лучше хлама, хуже профессиональных. Остальные, более профессиональные, весьма дороже; да и эти-то уже не каждый подряд DIYщик будет покупать.
PPS За почти неделю так и не удалось особо поиграться с датчиком, другие дела, но датчик не выключал, поглядывал днём, показания показывает стабильные, ПДК вроде в норме, ничего не сломалось, всё работает.
Датчик углекислоты, конечно, колбасит, видимо всё же нужно сенсору отдельное питание, не тянет плата вимоса.
Китайцы в своём репертуаре...
Вижу распаянный ZP07-MP503 Air-Quality Detection Module (с маленьким бочонком на борту и контактами A-B). В даташите на него указано: "Output Data 0-10 grade pollution signal". Но сама общая плата возвращает только TVOC Range 0~3 grades. Какие там три из десяти взяты - ни слова. Да и что за эти "0-10 grade", какие у них размерности - тайна, покрытая мраком. Написано, конечно, что это Pollution Class, но, что-то, интернеты про такие классы безмолвствуют. Т.е. смысла в этой цифире на данный момент никакого. Разве что значение 0 будет успокаивать.
Посмотрел на картинки Winsen Dust sensor (видимо ZH06-II) и понял, что контактная группа и корпус имеют знакомый вид. Похоже, что это брат-близнец датчика PMS7003 от Plantower https://www.plantower.com/en/products_33/76.html . Протокольная часть, наверное, прояснила бы ситуацию, но винсен не хочет её публиковать. По первому "релизу" протокол описан и https://www.winsen-sensor.com/d/files/ZH06.pdf и он заголовком 0x42 0x4D выдает родство с Plantower (https://download.kamami.pl/p564008-PMS7003%20series%20data%20manua_Engli...). По метрикам же Winsen == усеченный Plantower.
Еще заметил на плате MH-Z19 новой модификации. Полез на сайт перепроверить и да, действительно, Winsen наклепал новых CO2 NDIR сенсоров. В частности - MH-Z19C / MH-Z19E (https://www.winsen-sensor.com/sensors/co2-sensor/mh-z19e.html) с увеличенным вдвое сроком службы (>10 лет против >5 лет у классической MH-Z19B).
Так же, как оказалось, выпущен CO2 NDIR MH-Z1311A c быстрым разогревом и пониженным потреблением. Его средний ток "< 800uA " против "< 60mA" у MH-Z19B. У нового сенсора, правда, с точностью измерения есть нюансы, но для "батареечных" девайсов, похоже, он получше.
sadman41
С питанием, вроде, разобрался, питания хватает (сенсор+esp8266+ssd1306) и напрямую от usb, и от павербанка.
Из того, что я успел заметить, VOC он считает, скорее всего, по частицам 1, 2.5, 10, после сигареты за столом частицы (дым) увеличиваются раз в 10, быстро нарушая все пдк, VOC становится 3, потом в течение получаса падает на место. Но - не всегда ведёт себя так. Возможно, учитывает ещё CO2 и формальдегид, иногда бывает и без курения, после закрытия окна становится 1-2.
Датчик PM1/2.5/10 - очень чувствительный, показывает сигареты большими пиками на графике, когда курю на кухне - метров 10 до неё по коридорам - ан нет, всё видит, дым разъезжается по всей квартире мгновенно.
CO всегда стоит на 0.5, что бы я ни делал, хоть обдышаться прямо на него. В банку со свечкой не запихивал пока, нет свечки. Двуокись азота тоже всегда на месте, ну, как бы я азотную кислоту дома и не синтезирую; пытались, скорее всего, всё же для производства датчик сделать (странно, тогда и серу было бы логично добавить), а не для дома. Озон - почти всегда 0.02, очень редкие замеры раз в несколько часов скачут до 0.04-0.05, закономерности особо не заметил, может что натираю где. Искусственно вызвать озон тоже не получилось, озонатора нет, грозы ещё не скоро, на пьезо ему пофиг, а чем-то более мощным пробивать воздух искрами на рабочем столе я постеснялся.
Показания этого датчика CO2, кстати, надо фильтровать, выбросы с интервалом 3-4 минуты, только непонятно как - по среднему, по выбросам, или по медиане. Этот датчик на дыхание реагирует, быстро растёт и так же быстро падает (при этом выбросы остаются на месте).
Наврядли он в интегральную оценку по VOC включает частицы. VOC - это больше химия, а Particles - физика. Просто по VOC он ловит крайне широкий спектр химозы и сигарета легко организует его выброс. То, что 3 - максимальное, 0 - минимальное, а 2 - посередине - логично. Вопрос только в том, для какого существа эта середина и сколько ею можно наслаждаться. Этого без абсолютных показателей не понять.
Как мне писал один химик, которому я датчик озона приматывал к ардуине, - O3 быстро распадается и в быту его засечь практически невозможно.
CO2 действительно странный. Если все это не в барокамере происходит, то так скакать не должно. Процесс инерционный и выравнивание в сторону нормализации за секунды не происходит. Тем более пила в одних и тех же границах... Непонятное явление. Может они читают датчик по PWM и есть проблема с таймингами.... Надо по схеме смотреть. Там же какой-то общий МК стоит?
Да, там стоит stm32f051k86, с обратной стороны платы. Почему-то думал, что VOC просто будет оценка качества по существующим датчикам, из-за цейтнота получается только урывками поиграться. CO2 очень инерционный, и пила долгая - 2-3 минуты растёт, пиковое значение, 2-3 минуты падает, потом 2-3 минуты покоя, потом всё повторяется.
Такой явной пилы я никогда не видел. На моих вот так: https://arduino.ru/forum/obshchii/telaire-t6703#comment-480605
Для VOC отдельный электрохимический датчик, смысла что-то вычислять, исходя из показаний других, как-то не наблюдается.
Надо попробовать ABC включить, может тогда он будет сам усреднять, может он не хочет калиброваться, обязательно попробую.
PS Да, подтверждаю, PM очень мелкие показания, а VOC показывает 2-3.
Специально поставил период опроса 15sec, на графике диапазон в пять минут. Пилы нет. На диапазоне в 15 мин и выше - тоже. Датчик смонтирован в пластиковом корпусе электрического 6-постового бокса, стоит на шкафу в комнате. Никто на него специально не дышит.
Нескладуха на этой плате какая-то. Может осциллограффом подсесть на PWM NDIR-у и посмотреть, что он там выдает... ABС не должен повлиять на пилу, так как он вычисляет только смещение по оси Y в зависимости от намерянного за сутки/неделю (в зависимости от датчика). Т.е. с ABC пила будет или выше или ниже, но останется пилой.
По VOC у меня было наблюдение: рядом со свежим пластиком сенсор фонил, как безумный.
Всё-таки дело было в питании, от повербанка пила совсем малюсенькая.
а вот кстати, компактный сигнализатор СО2 и метана весьма актуален, кто исследует пещеры