ARDUINO Работа с датчиком ZH-06 I

Работа с датчиком ZH-06 I
Доброго времени суток. В этой статье я опишу как работать с датчиком мелких частиц Winsen ZH-06 I на плате Arduino Nano.
1744285480338.png
В интернете про работу с этим датчиком буквально 1 статья, и то, библиотека, которую использует автор не поддерживается Arduino Nano. Исходя из этого я посчитал полезным написать статью про работу с этим датчиком.

(если ваш контроллер поддерживает Serial1, то для вас подходит библеотка CSE_ZH06
библиотека github.com/CIRCUITSTATE/CSE_ZH06?tab=readme-ov-file#cse_zh06
подключение circuitstate.com/tutorials/how-to-interface-winsen-zh06-laser-dust-sensor-with-arduino
)

1.Подключение
В разъём датчика требуется подключить кабельный шлейф. Назначение контактов следующее:
1744286084937.png(взято из официального даташита)
Датчик имеет 2 выхода: PWM (ШИМ) и UART. Я воспользуюсь вторым, так как при его помощи можно ввести датчик в режим сна.
Для подлючения к arduino nano нам потребуется логический конвертер уровней (5v <-> 3.3v, минимум 2 канала), так как ардуино имеет логический уровень 5v, а датчик - 3.3v, и подключение напрямую может повредить сенсор.
1744286308402.png(мой конвертер)
Контакты датчика RXD и TXD требуется подключить к "низкому уровню" конвертера (в моём случае - контакты группы LV). Ответные кантакты "выского уровня" (HW) требуется подключить к GPIO пинам ардуино (любым, кроме 1 и 0)
Питание датчика VDD нужно подключить в 5v, GND - в GND
Важно отметить, что внутри датчика расположена турбина и перед включением нужно убедиться, что ничего не мешает ей работать
2.Программирование

C++:
#include <SoftwareSerial.h>

SoftwareSerial mySerial(txd, rxd);

int16_t pm1 = 0;
int16_t pm25 = 0;
int16_t pm10 = 0;

void setup() {
  const byte qa[9] = {0xFF, 0x01, 0x78, 0x41, 0x00, 0x00, 0x00, 0x00, 0x46};
  mySerial.begin(9600);
  Serial.begin(9600);
  mySerial.write(qa, 9);
}


uint16_t getppm() {
  uint16_t check;
  byte res[9];
  const byte req[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
  mySerial.write(req, 9);
  do {
    mySerial.readBytes(res, 9);
    check = 0;
    for (byte i = 1; i < 8; i++)check += res[i];
    check = ~(check) + 1;
  } while ((byte)check != (byte)res[8]);

  pm1 = res[2] * 256 + res[3];
  pm25 = res[4] * 256 + res[5];
  pm10 = res[6] * 256 + res[7];

  return (pm1 + pm25 + pm10) / 3;
}

void sleep (bool h) {
  byte res[9];
  uint16_t check;
  if (h) {
    const byte sleepOn[9] = {0xFF, 0x01, 0xA7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x57};

    do {
      mySerial.write(sleepOn, 9);
      mySerial.readBytes(res, 9);


    } while (!(res[2] and res[8] == 88));


  }
  else {
    const byte sleepOff[9] = {0xFF, 0x01, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58};

    do {

      mySerial.write(sleepOff, 9);
      mySerial.readBytes(res, 9);
    } while (!(res[2] and res[8] == 88));
  }
return;
}
void loop(){
    //...
}
Для работы с датчиком я написал 2 основные функции: getppm и sleep.
Первая записывает в переменные концентрации мелких частиц:
pm1 - концентрация частиц PM1.0
pm25 - концентрация частиц PM2.5
pm10 - концентрация частиц PM10
(то есть после вызова функции в этих переменных будут лежать актуальные значения концентрации в ppm)
В коде обязательно перед вызовом функции должны быть объявлены переменные с соответсвующими названиями и типом int.
Функция ничего не принимает, возвращает среднее значение концентрации всех частиц
Вторая функция sleep принимает логический тип bool. Если true, то функция переведёт датчик в режим сна (турбина отключится, датчик перестанет проводить замеры), если false - переведёт в режим бодрствования.

Перед использованием функций должен быть инициализирован программный последовательный порт с именем mySerial (строка кода 3) и скоростью 9600 бод (строка 11). Также перед началом работы с датчиком необходимо отправить ему команду перейти в режим вопрос-ответ (строка 13)

Официальный даташит https://www.winsen-sensor.com/d/files/ZH06.pdf
 

Комментарии