Датчик PM2.5 Wuhan Cubic PM2012

sadman41
Offline
Зарегистрирован: 19.10.2016

В поисках идеального датчика PM2.5: Wuhan Cubic PM2012.

sadman41
Offline
Зарегистрирован: 19.10.2016
Большая просьба не комментировать этот пост, так как возможны дополнение и актуализация сведений, приведенных в нем (мыслительные процессы проистекают у меня медленно :)).
 
Не прошло и трёх лет с того момента, когда я описывал датчик пыли от Plantower - PMS-A003. Теоретические данные за это вермя не устарели, поэтому смело их пропускаю, отсылая к посту "PMS-A003 и все-все-все"
 
Как показала продолжительная эксплуатация, датчик от Plantower вобщем-то неплох, но лично меня мою лень не устраивает следующее: 
1) Интерфейс UART;
2) TTL level 3.3V;
3) Ограниченная управляемость.
 
По первому пункту: требуется выделять под датчик один или два дополнительных входа/выхода и при разделении в "метеостанции" холодной (там, где датчики) и горячей (где МК, всякие нагретые сетевые чипы и DC-DC) приходится тащить из одной в другую лишние провода.
 
По второму пункту: при возникновении необходимости управления датчиком (погружение в сон, к примеру) требуется ставить согласователь уровней между 5V TTL микроконтроллера и 3.3V датчика. Действие несложное, но оно должно быть произведено.
 
По третьему пункту: желание продлить жизнь датчику диктует особые правила игры - включение лазера/кулера только при замере. В противном случае, при деградации  лазерного светодиода, датчик начнёт выдавать недостоверные сведения. Так написано в  интернетах. Однако, для правильного замера, вентилятор, прогоняющий  запылённый воздух через камеру датчика, должен работать не менее 30 секунд. Стало быть - алгоритм опроса усложняется, получение результата перестаёт быть мгновенным. Некоторые производители идут навстречу пользователю и датчик сам включается и выключается по заданному циклу. Примером может служить SDS-011 от NovaFitness.  Конечно же такая "экономия ресурса" становится заметна на слух, если измеритель находится рядом, в жилой комнате. Нельзя сказать, что вентилятор SDS-011 работает, как самолётная турбина, но людей с чутким слухом и измученной нервной системой он способен раздражать. Особенно сильно, полагаю, эффект проявится через год-другой эксплуатации датчика.
 
В неспешных попытках найти свой "идеальный" датчик, периодически посматривая предложения на Aliexpress, у одного из продавцов (и только одного!) я наткнулся на интересное, как показалось, семейство приборов от неизвестной мне ранее компании Wuhan Cubic. Как это водится у китайского производителя, на сайте компании никакой документации не нашлось, однако услужливый Google посоветовал обратится на http://www.gassensor.com.cn/ , который, как я понимаю, является витриной подразделения Sifang Wuhan Optoelectronic, производящего всякие environment sensors. 
 
После некоторых метаний по характеристикам разнообразных модификаций одних и тех же датчиков, мой глаз зацепился за модель PM2012. Datasheet обещал 110,000 hrs (continuous turn on) (у PMS-A003, по заявлениям техподдержки, гарантированно только 3*365*24 = 26,280 hrs - "Our sensor lifetime in our datasheet is 3years, but actually it can use more than 4.5year with works continuously."). Так же в комплекте должен прилагаться I2C (привет общая шина для всех датчиков) и TTL 3.3V/5V (прощайте конверторы уровней). Кроме того - всяческие алгоритмы динамических измерений и отдельная команда " 0x08 Close/open laser diode". Т.е. пропеллер мотает всегда (с единым звуковым фоном), а лазер можно включать на время измерения, например на пару секунд. В добавок к этому обещали выдать регистр статуса, через который можно узнать не заклинило ли вентилятор и не перегревается ли сам прибор.
 
Что тут скажешь... Мечты сбываются?
 
Пройдя небольшой дополнительный квест по поиску коннектора (в datasheet, видимо, описка - шаг коннектора 1.27, а не 1.25), я заказал датчик, разъёмы и ждал, мечтательно закатывая глаза.
 
Но, как говорится, человек предполагает, а Си Цзиньпин посылает. Получив датчик и немедля подключив его к Arduino, я обнаружил, что всё расписанное в разделе "I2C протокол" Datasheet-а, мягко говоря, не соответствует действительности. Адрес не совпадает (0x12 вместо 0x50), заголовок пакета вовсе похож на тот, что применяет Plantower...
 
При дальнейших расспросах Google указал на корейский сайт, который таких датчиков в ассортименте не имел, но по прямой ссылке отдавал другой datasheet, в котором от MTTF = 110,000 hrs осталось только 37,297 hrs (continuous turn on), исчезло описание команд включения/выключения лазера, да и вообще всё начало выглядеть незамысловато...
 
Таким образом, можно предполагать, что купленный на Aliexpress PM2012 является какой-то странной модификацией официально предлагаемого Wuhan Cubic на собственном сайте. Более старая это модель или более новая - разобраться не удаётся, техподдержка производителя не отвечает. Тем не менее - в нём действительно есть I2C и, при подключении контроллера с TTL 5V, сенсор дым не испустил. По I2C он отвечает гораздо быстрее, чем по UART, но уложить его в сон записью волшебного числа в какой-либо регистр - не получится. Имеется байт статуса, что немного сглаживает досаду от такого приобретения.
 
Итог: PM2012 немного лучше по функционалу, чем PMS-A003, но не кардинально. Байт статуса действительно помогает - например, если остановить рукой вентилятор, то значение концентрации частиц в измерительной камере начинает расти. По статусу же можно определить - связано ли это с неисправностью карлсона или имеется иная причина .
 
Закончив с лирикой, перехожу к сухой технической части.
 
Фотосравнение
Как можно видеть на фотографиях - оба датчика внешне (и, возможно, внутренне) очень похожи и это характерно для продукции Wuhan Cubic. Например, PM2008 похож на PMS-7003, а PM2009 на PMS-6003.
Основное различие я вижу в месте расположения выдува. У PM2012 он располагается с противоположной от отверстия воздухозаборника стороны. Уровень шума от миникулеров обоих датчиков сопоставимый и очень низкий. 
 
 
 
Подключение
Вследствие некоей конструктивной близости продуктов Plantower и Wuhan Cubic переходные адаптеры для сенсора PMS-A003 подходят и для PM2012. К моему PMS-A003 продавец положил переходник G7->G135 и он прекрасно подошёл и к PM2012.
 
Так же должен быть неплох такой: 
 
Лично я заказал 1.27mm SMT female connector и припаял к SOP-14 board (уже были в наличии). Всё работает, если заизолировать места пайки. Корпус датчика всё-таки из жестянки...
+
 
Получение показаний
 
Тестовый скетч накатал сам, потому что в интернетах для PM2012 даже правдивый даташит найти сложно, не то что программный код.
 
#include <Wire.h>

#define PM2012_I2C_ADDRESS  0x12

typedef struct {
  uint16_t frameHeader;
  uint16_t frameLength;
  uint16_t PM10, PM25, PM100;
  uint16_t ePM10, ePM25, ePM100;
  uint16_t particles03um, particles05um, particles10um, particles25um, particles50um, particles100um;
  //  wuhanParticleSensorStatus_s status;
  struct {
    uint8_t fanSpeedHigh: 1;
    uint8_t fanSpeedLow:  1;
    uint8_t temperaturedHigh: 1;
    uint8_t temperaturedLow:  1;
    uint8_t unused:   4;
  } status;

  uint8_t version;
  uint16_t crc;
} wuhanParticleSensor_t;

uint8_t pm2012ReadMetric(wuhanParticleSensor_t& _particleSensor) {
  uint8_t  rc = false;
  uint16_t crc = 0x00;
  // _particleSensor structure can be used directly w/o temporary structure and copying on the end of routine
  wuhanParticleSensor_t particleSensor;
  uint8_t*  ptrRawBuffer = (uint8_t*) &particleSensor;
  uint16_t* ptrConvertedBuffer = (uint16_t*) &particleSensor;

  uint8_t readedBytes = Wire.requestFrom(PM2012_I2C_ADDRESS, sizeof(particleSensor));

  if (sizeof(particleSensor) != readedBytes) {
    goto finish;
  }

  for (uint8_t i = 0x00; sizeof(particleSensor) > i; i++) {
    ptrRawBuffer[i] = Wire.read();
    Serial.print(" 0x"); Serial.print(ptrRawBuffer[i], HEX);
    if (sizeof(particleSensor) - sizeof(crc) > i) {
      crc += ptrRawBuffer[i];
    }
  }
  Serial.println();
  for (uint8_t i = 0; i < (sizeof(particleSensor) / 0x02); i++) {
    *ptrConvertedBuffer = (ptrRawBuffer[0x00] << 0x08) | ptrRawBuffer[0x01];
    ptrRawBuffer += 0x02;
    ptrConvertedBuffer += 0x01;
  }

  //Serial.print("\nCRC: 0x"); Serial.println(crc, HEX); Serial.print("particleSensor.crc: 0x"); Serial.println(particleSensor.crc, HEX);
  rc = (crc == particleSensor.crc);

  if (rc) {
    memcpy((uint8_t*)&_particleSensor, (uint8_t*)&particleSensor, sizeof(particleSensor));
  }

finish:
  return rc;
}

void setup() {
  Wire.begin();
  Serial.begin(115200);
}

void loop() {
  static wuhanParticleSensor_t particleSensor;
  uint8_t rc = pm2012ReadMetric(particleSensor);
  if (!rc) {
    Serial.println("[!] Read error");
  }
  Serial.print("Version: "); Serial.println(particleSensor.version);
  //  Serial.print("Status:  "); Serial.println(particleSensor.error, BIN);
  Serial.print("Status: ");
  if (0x00 == *((uint8_t*)&particleSensor.status)) {
    Serial.println("OK");
  } else {
    Serial.print("\n\tFan revolving speed HIGH: "); Serial.println(particleSensor.status.fanSpeedHigh);
    Serial.print("\tFan revolving speed LOW : "); Serial.println(particleSensor.status.fanSpeedLow);
    Serial.print("\tWorking temperature HIGH: "); Serial.println(particleSensor.status.temperaturedHigh);
    Serial.print("\tWorking temperature LOW : "); Serial.println(particleSensor.status.temperaturedLow);
  }
  Serial.print("PM1.0 (ug/m^3): "); Serial.println(particleSensor.PM10);
  Serial.print("PM2.5 (ug/m^3): "); Serial.println(particleSensor.PM25);
  Serial.print("PM10  (ug/m^3): "); Serial.println(particleSensor.PM100);
  Serial.print("ePM1.0 (ug/m^3): "); Serial.println(particleSensor.ePM10);
  Serial.print("ePM2.5 (ug/m^3): "); Serial.println(particleSensor.ePM25);
  Serial.print("ePM10  (ug/m^3): "); Serial.println(particleSensor.ePM100);
  Serial.print("Particle num >0.3um:  "); Serial.println(particleSensor.particles03um);
  Serial.print("Particle num >0.5um:  "); Serial.println(particleSensor.particles05um);
  Serial.print("Particle num >1.0um:  "); Serial.println(particleSensor.particles10um);
  Serial.print("Particle num >2.5um:  "); Serial.println(particleSensor.particles25um);
  Serial.print("Particle num >5.0um:  "); Serial.println(particleSensor.particles50um);
  Serial.print("Particle num >10.0um: "); Serial.println(particleSensor.particles100um);
  Serial.print("\n\n");
  delay(1500);
}

Эксплуатация

В целом PMS-A003 схож с PM2012 (кто у кого переманил разработчика - дракон его знает), что и видно по графикам. Первый - имеет более резкую реакцию на изменение среды, а в последнем, видимо применён какой-то программный сглаживающий фильтр. Так же - у него показания концентраций более "плотно" следуют рядом (см. график "PM concentration"). 
 
Непонятен остался один момент: при нулевом количестве частиц PM2.5 концентрацию датчик выдаёт в 4.0 ug/m^3. 
 
Примечание: Plantower находится в постоянно включенном состоянии около одного года.
 
Концентрации пыли.
 
 
Измерение кол-ва частиц по шести каналам сенсором Plantower PMS-A003
Измерение кол-ва частиц по шести каналам сенсором Plantower PM2012
 
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

осталось придумать куда бы его применить, в серверной?