From af2b015deaf8c0d072cdcf34ea56137a4d5daac4 Mon Sep 17 00:00:00 2001 From: Dmitry Borisenko <49808844+DmitryBorisenko33@users.noreply.github.com> Date: Wed, 28 Sep 2022 10:28:52 +0200 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20mhz19=20=D0=B8=20sds011?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/sensors/Mhz19/Mhz19.cpp | 902 ++++++++++++++---------- src/modules/sensors/Mhz19/modinfo.json | 70 +- src/modules/sensors/Sds011/Sds011.cpp | 328 ++++++--- src/modules/sensors/Sds011/modinfo.json | 53 +- 4 files changed, 791 insertions(+), 562 deletions(-) diff --git a/src/modules/sensors/Mhz19/Mhz19.cpp b/src/modules/sensors/Mhz19/Mhz19.cpp index 5a09930b..88f7bb9e 100644 --- a/src/modules/sensors/Mhz19/Mhz19.cpp +++ b/src/modules/sensors/Mhz19/Mhz19.cpp @@ -11,20 +11,30 @@ extern IoTGpio IoTgpio; -int rxPinCO2 ; // зеленый провод сенсора к прописаному по умолчанию D7 (GPIO13) -int txPinCO2 ; // синий провод сенсора к прописаному по умолчанию D6 (GPIO12) -SoftwareSerial* swSerialCO2 = nullptr; +// SoftwareSerial* swSerialCO2 = nullptr; +int rxPinCO2; // зеленый провод сенсора к прописаному по умолчанию D7 (GPIO13) +int txPinCO2; // синий провод сенсора к прописаному по умолчанию D6 (GPIO12) +#ifdef ESP8266 + +SoftwareSerial *swSerialCO2 = nullptr; +#endif +#ifdef ESP32 +#include +HardwareSerial swSerialCO2(1); +#endif + int MHZ19_request(int request); void MHZ19uart_init(); -bool MHZ19uart_flag = true; -int MHZ19C_PREHEATING_TIME = 2 * 30 * 1000; // покажет реальные данные после прогрева, через 2 мин. +bool MHZ19uartInit_flag = true; +bool MHZ19uartUpdateInputs_flag = true; +unsigned int preheating = 2 * 60; // покажет реальные данные после прогрева, через 2 мин. int temperature = 0; bool temperatureUpdated = false; int prevRange = 5000; -int range = 5000; // по умолнчанию стоит шкала 5000 (не 2000 как в мануале) +int range = 5000; // по умолнчанию стоит шкала 5000 (не 2000 как в мануале) bool rangeChaged = false; int prevABC = 1; int ABC = 1; @@ -32,32 +42,52 @@ bool ABCchanged = false; //Это файл сенсора, в нем осуществляется чтение сенсора. -class Mhz19uart : public IoTItem { - private: +class Mhz19uart : public IoTItem +{ +private: //======================================================================================================= // Секция переменных. - public: +public: //======================================================================================================= - Mhz19uart(String parameters) : IoTItem(parameters) { + Mhz19uart(String parameters) : IoTItem(parameters) + { rxPinCO2 = jsonReadInt(parameters, "rxPin"); txPinCO2 = jsonReadInt(parameters, "txPin"); + preheating = jsonReadInt(parameters, "warmUp"); range = jsonReadInt(parameters, "range"); ABC = jsonReadInt(parameters, "ABC"); - if (!swSerialCO2) swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); + MHZ19uartInit_flag = true; + MHZ19uartUpdateInputs_flag = true; +#ifdef ESP8266 + if (!swSerialCO2) + swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); +#endif +#ifdef ESP32 +// HardwareSerial swSerialCO2(1); +// HardwareSerial swSerialCO2(2); +// swSerialCO2.begin(9600); +#endif } //======================================================================================================= // doByInterval() - void doByInterval() { + void doByInterval() + { MHZ19uart_init(); - if (millis() > MHZ19C_PREHEATING_TIME) { - Serial.println("Start checkUARTCO2"); - value.valD = MHZ19_request(1); + + if (millis() > preheating * 1000) + { + // Serial.println("Start checkUARTCO2"); + int reply = MHZ19_request(1); + if (reply) + { + value.valD = reply; + regEvent(value.valD, "Mhz19uart"); + } } - regEvent(value.valD, "Mhz19uart"); //обязательный вызов хотяб один } //======================================================================================================= @@ -68,64 +98,111 @@ class Mhz19uart : public IoTItem { //если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть //создание и контроль соответствующих глобальных переменных -//замер по ШИМ создает задержку. вызываем его нечасто, по умолчанию раз в 5 минут -class Mhz19pwm : public IoTItem { - private: +//замер по ШИМ создает задержку. вызываем его нечасто, по умолчанию раз в 5 минут +class Mhz19pwm : public IoTItem +{ +private: //======================================================================================================= // Секция переменных. - int pwmPin; // желтый провод сенсора к прописаному по умолчанию D8 (GPIO15) + int pwmPin = 15; // желтый провод сенсора к прописаному по умолчанию D8 (GPIO15) + int maxRetriesNotAvailable = 10; - public: +public: //======================================================================================================= - Mhz19pwm(String parameters) : IoTItem(parameters) { + Mhz19pwm(String parameters) : IoTItem(parameters) + { pwmPin = jsonReadInt(parameters, "pin"); + preheating = jsonReadInt(parameters, "warmUp"); + maxRetriesNotAvailable = jsonReadInt(parameters, "maxRetriesNotAvailable"); } //======================================================================================================= - void doByInterval() { + void doByInterval() + { MHZ19pwm_init(); - if (millis() > MHZ19C_PREHEATING_TIME) // + + if (millis() > preheating * 1000) // { - Serial.println("Start checkPWM_CO2"); - value.valD = MHZ19pwm_request(); + // Serial.println("Start checkPWM_CO2"); + int reply = MHZ19pwm_request(); + if (reply) + { + SerialPrint("E", "Sensor Mhz19pwm", "MHZ19pwm_init reply = " + String(reply)); + value.valD = reply; + regEvent(value.valD, "Mhz19pwm"); + } } - regEvent(value.valD, "Mhz19pwm"); //обязательный вызов хотяб один } //======================================================================================================= - void MHZ19pwm_init() { + void MHZ19pwm_init() + { static bool MHZ19pwm_flag = true; - if (MHZ19pwm_flag) { + if (MHZ19pwm_flag) + { pinMode(pwmPin, INPUT); MHZ19pwm_flag = false; } } - int MHZ19pwm_request() { + int MHZ19pwm_request() + { int reply; - Serial.println("Запрос замера по PWM запущен"); - unsigned long th, tl, ppm = 0, ppm2 = 0, ppm3 = 0; - do { + // Serial.println("Запрос замера по PWM запущен"); + unsigned long th = 0, tl, ppm = 0, ppm2 = 0, ppm3 = 0; + // int pwmPinReading1 = digitalRead(pwmPin); + // SerialPrint("E", "Sensor Mhz19uart", "pwmPinReading1 = " + String(pwmPinReading1)); + /* + do + { th = pulseIn(pwmPin, HIGH, 1004000) / 1000; tl = 1004 - th; - ppm2 = 2000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 2000ppm - ppm3 = 5000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 5000ppm + ppm2 = 2000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 2000ppm + ppm3 = 5000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 5000ppm } while (th == 0); + */ + for (int i = 0; i < maxRetriesNotAvailable; i++) + { + th = pulseIn(pwmPin, HIGH, 1004000) / 1000; - // Serial.print(th); - // Serial.println(" <- Milliseconds PWM is HIGH"); - - if (range == 2000) { - reply = ppm2; - Serial.print(ppm2); - Serial.println(" <- ppm2 (PWM) with 2000ppm as limit"); - } else { - reply = ppm3; - Serial.print(ppm3); - Serial.println(" <- ppm3 (PWM) with 5000ppm as limit"); + if (th != 0) + { + tl = 1004 - th; + ppm2 = 2000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 2000ppm + ppm3 = 5000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 5000ppm + if (i > 1) + SerialPrint("E", "Sensor Mhz19pwm", "Got reading from PWM pin after " + String(i) + " tries"); + break; + } + // Serial.println(i); } - Serial.println("Completed checkPwmCO2"); + if (!th) + { + SerialPrint("E", "Sensor Mhz19pwm", "No reading from PWM pin. Check wiring."); + reply = 0; + } + else + { + + // Serial.print(th); + // Serial.println(" <- Milliseconds PWM is HIGH"); + if (range == 2000) + { + reply = ppm2; + // Serial.print(ppm2); + // Serial.println(" <- ppm2 (PWM) with 2000ppm as limit"); + } + else + { + reply = ppm3; + // Serial.print(ppm3); + // Serial.println(" <- ppm3 (PWM) with 5000ppm as limit"); + } + // Serial.println("Completed checkPwmCO2"); + } + // int pwmPinReading2 = digitalRead(pwmPin); + // SerialPrint("E", "Sensor Mhz19uart", "pwmPinReading2 = " + String(pwmPinReading2)); return reply; } @@ -134,35 +211,51 @@ class Mhz19pwm : public IoTItem { //====================TEMP=================================================================================== -class Mhz19temp : public IoTItem { - private: +class Mhz19temp : public IoTItem +{ +private: //======================================================================================================= // Секция переменных. - public: +public: //====================TEMP=================================================================================== - Mhz19temp(String parameters) : IoTItem(parameters) { + Mhz19temp(String parameters) : IoTItem(parameters) + { rxPinCO2 = jsonReadInt(parameters, "rxPin"); txPinCO2 = jsonReadInt(parameters, "txPin"); - range = jsonReadInt(parameters, "range"); - ABC = jsonReadInt(parameters, "ABC"); - if (!swSerialCO2) swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); + +#ifdef ESP8266 + if (!swSerialCO2) + swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); +#endif +#ifdef ESP32 +// HardwareSerial swSerialCO2(1); +#endif } //======================================================================================================= - void doByInterval() { + void doByInterval() + { + int reply; + // Serial.println("Start Mhz19temp doByInterval"); - if (temperatureUpdated) { - value.valD = temperature; + if (temperatureUpdated) + { + reply = temperature; temperatureUpdated = false; - } else { - MHZ19uart_init(); - Serial.println("Start temperature request"); - if (MHZ19_request(13)) { - value.valD = temperature; - }; // change } - regEvent(value.valD, "Mhz19temp"); //обязательный вызов хотяб один + else + { + MHZ19uart_init(); + // Serial.println("Start temperature request"); + reply = MHZ19_request(13); + } + + if (reply) + { + value.valD = reply; + regEvent(value.valD, "Mhz19temp"); + } } //======================================================================================================= @@ -171,375 +264,404 @@ class Mhz19temp : public IoTItem { ~Mhz19temp(){}; }; -//=======================Range================ -class Mhz19range : public IoTItem { - private: - public: - Mhz19range(String parameters) : IoTItem(parameters) { - rxPinCO2 = jsonReadInt(parameters, "rxPin"); - txPinCO2 = jsonReadInt(parameters, "txPin"); - range = jsonReadInt(parameters, "range"); - ABC = jsonReadInt(parameters, "ABC"); - if (!swSerialCO2) swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); - } - - void doByInterval() { - if (range != prevRange) { - MHZ19uart_init(); - Serial.println("Start change range"); - - if (range == 2000) { - if (MHZ19_request(9)) { - prevRange = 2000; - value.valD = 2000; - } // change range to 2000 - } else { - if (MHZ19_request(10)) { - prevRange = 5000; - value.valD = 5000; - } // change range to 5000 - } - } else { - value.valD = prevRange; - } - regEvent(value.valD, "Mhz19range"); //обязательный вызов хотяб один - } - - ~Mhz19range(){}; -}; - -//===================ABC================= - -class Mhz19ABC : public IoTItem { - private: - public: - Mhz19ABC(String parameters) : IoTItem(parameters) { - rxPinCO2 = jsonReadInt(parameters, "rxPin"); - txPinCO2 = jsonReadInt(parameters, "txPin"); - range = jsonReadInt(parameters, "range"); - ABC = jsonReadInt(parameters, "ABC"); - if (!swSerialCO2) swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); - } - - void doByInterval() { - if (ABC != prevABC) { - if (ABC == 1) { - if (MHZ19_request(7)) { - prevABC = 1; - value.valD = 1; - } // change ABC to 1 - } else { - if (MHZ19_request(8)) { - prevABC = 0; - value.valD = 0; - } // change ABC to 0 - } - } else { - value.valD = prevABC; - } - regEvent(value.valD, "Mhz19ABC"); //обязательный вызов хотяб один - } - - ~Mhz19ABC(){}; -}; - -///============== end of classes========================== - -void *getAPI_Mhz19(String subtype, String param) { - if (subtype == F("Mhz19uart")) { +void *getAPI_Mhz19(String subtype, String param) +{ + if (subtype == F("Mhz19uart")) + { return new Mhz19uart(param); - } else if (subtype == F("Mhz19pwm")) { + } + else if (subtype == F("Mhz19pwm")) + { return new Mhz19pwm(param); - } else if (subtype == F("Mhz19temp")) { + } + else if (subtype == F("Mhz19temp")) + { return new Mhz19temp(param); - } else if (subtype == F("Mhz19range")) { - return new Mhz19range(param); - } else if (subtype == F("Mhz19ABC")) { - return new Mhz19ABC(param); - } else { + } + else + { return nullptr; } } -void MHZ19uart_init() { - if (MHZ19uart_flag) { - int reply; +void MHZ19uart_init() +{ + if (MHZ19uartInit_flag) + { + +#ifdef ESP8266 swSerialCO2->begin(9600); - +#endif +#ifdef ESP32 + // if(swSerialCO2.available()) { Serial.println("ok"); } + swSerialCO2.begin(9600, SERIAL_8N1, rxPinCO2, txPinCO2); +#endif delay(50); + int reply; + reply = MHZ19_request(2); // show range, for test of uart only + // Serial.print("show range reply = "); + // Serial.println(reply); - reply = MHZ19_request(2); // show range, for test of uart only - Serial.print("show range reply = "); - Serial.println(reply); - - if (reply) { - MHZ19uart_flag = false; + if (reply) + { + prevRange = reply; + MHZ19uartInit_flag = false; } } - if (!MHZ19uart_flag) { - static int prevABC; + if (!MHZ19uartInit_flag && ABC != prevABC) + { int reply; - if (ABC != prevABC) { - if (ABC) { - reply = MHZ19_request(7); // ABC on - } else { - reply = MHZ19_request(8); // ABC off + if (ABC != prevABC) + { + if (ABC) + { + reply = MHZ19_request(7); // ABC on } - Serial.print("ABC change reply = "); - Serial.println(reply); + else + { + reply = MHZ19_request(8); // ABC off + } + // Serial.print("ABC change reply = "); + // Serial.println(reply); } - if (reply) { + if (reply) + { prevABC = ABC; } } - static bool MHZ19_range_flag = true; - if (MHZ19_range_flag && !MHZ19uart_flag && (millis() > 30 * 1000)) { + if (range != prevRange && !MHZ19uartInit_flag) + { int reply; - if (range == 2000) { - reply = MHZ19_request(9); // Установка шкалы 0-2000 - // 255 155 0 0 7 208 0 3 139 - } else { - reply = MHZ19_request(10); // Установка шкалы 0-5000 - // 255 155 0 0 19 136 0 3 199 + if (range == 2000) + { + reply = MHZ19_request(9); // Установка шкалы 0-2000 - 255 155 0 0 7 208 0 3 139 } - Serial.print("Scale change reply = "); - Serial.println(reply); - if (reply) { - reply = MHZ19_request(2); // show range - Serial.print("show range reply = "); - Serial.println(reply); - - MHZ19_range_flag = false; + else + { + reply = MHZ19_request(10); // Установка шкалы 0-5000 - 255 155 0 0 19 136 0 3 199 + } + // Serial.print("Scale change reply = "); + // Serial.println(reply); + if (reply) + { + // reply = MHZ19_request(2); // show range + // Serial.print("show range reply = "); + // Serial.println(reply); + prevRange = range; + // MHZ19_range_flag = false; } } } -int MHZ19_request(int request) { +int MHZ19_request(int request) +{ int reply; - Serial.print("prevRange = "); - Serial.println(prevRange); + // Serial.print("prevRange = "); + // Serial.println(prevRange); - byte uartReqSamplePpm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // PPM + byte uartReqSamplePpm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // PPM // 255 1 134 0 0 0 0 0 121 // Response 255 134 1 148 67 0 0 0 162 - byte uartReqSampleABCon[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; // ABC logic on - // 255 1 121 160 0 0 0 0 230 - // Response 255 121 1 0 0 0 0 0 134 - byte uartReqSampleABCoff[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; // ABC logic off - byte uartReqSampleABCstatus[9] = {0xFF, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82}; // ABC logic status - + byte uartReqSampleABCon[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6}; // ABC logic on + // 255 1 121 160 0 0 0 0 230 + // Response 255 121 1 0 0 0 0 0 134 + byte uartReqSampleABCoff[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86}; // ABC logic off + byte uartReqSampleABCstatus[9] = {0xFF, 0x01, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82}; // ABC logic status byte uartReqSample1000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x03, 0xE8, 0x7B}; - byte uartReqSample2000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x8F}; // задаёт диапазон 0 - 2000ppm - byte uartReqSample3000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x0B, 0xB8, 0xA3}; // задаёт диапазон 0 - 2000ppm - - byte uartReqSample5000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB}; // задаёт диапазон 0 - 5000ppm - // 255 1 153 0 0 0 19 136 203 - // Response 255 153 1 0 0 0 0 0 102 - byte uartReqSampleRequestRange[9] = {0xFF, 0x01, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64}; // запрос диапазона - // request // 255 1 155 0 0 0 0 0 100 - // reply // 255 1 155 0 0 0 0 0 100 - byte uartReqSampleZeroPnt[9] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; // !!ZERO POINT CALIBRATION - byte uartReqSampleReset[9] = {0xFF, 0x01, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72}; // reset - - byte uartReqSampleReset1[9] = {0xFF, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; // reset - did not work out + byte uartReqSample2000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x8F}; // задаёт диапазон 0 - 2000ppm + byte uartReqSample3000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x0B, 0xB8, 0xA3}; // задаёт диапазон 0 - 2000ppm + byte uartReqSample5000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB}; // задаёт диапазон 0 - 5000ppm + // 255 1 153 0 0 0 19 136 203 + // Response 255 153 1 0 0 0 0 0 102 + byte uartReqSampleRequestRange[9] = {0xFF, 0x01, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64}; // запрос диапазона + // request // 255 1 155 0 0 0 0 0 100 + // reply // 255 1 155 0 0 0 0 0 100 + byte uartReqSampleZeroPnt[9] = {0xFF, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78}; // !!ZERO POINT CALIBRATION + byte uartReqSampleReset[9] = {0xFF, 0x01, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72}; // reset + byte uartReqSampleReset1[9] = {0xFF, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; // reset - did not work out byte request_cmd[9]; // byte c; - switch (request) { - // случаи 3-7 для перезапуска сенсора - case 1: { - Serial.println("Запрос No.1 - отправлен. Запрос замера по UART"); - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSamplePpm[i]; - } - } break; + switch (request) + { + // случаи 3-7 для перезапуска сенсора + case 1: + { + // Serial.println("Запрос No.1 - отправлен. Запрос замера по UART"); + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSamplePpm[i]; + } + } + break; - case 2: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSampleRequestRange[i]; - } - Serial.println("Запрос No.2 - отправлен. Запрос шкалы"); - } break; + case 2: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSampleRequestRange[i]; + } + // Serial.println("Запрос No.2 - отправлен. Запрос шкалы"); + } + break; + + case 3: + { + // код для запуска сенсора с работой по UART (запуск таймера) + // Serial.println("Запрос No.3 - отправлен. Сенсор по UART запущен"); + } + break; + case 4: + { + // код для остановке сенсора с работой по UART (остановка таймера) + // Serial.println("Запрос No.4 - отправлен. Сенсор по UART остановлен"); + } + break; + case 5: + { + // код для запуска сенсора с работой по PWM (запуск таймера) + // Serial.println("Запрос No.5 - отправлен. Сенсор по PWM запущен"); + } + break; + case 6: + { + // код для остановки сенсора с работой по PWM (остановка таймера) + // Serial.println("Запрос No.6 - отправлен. Сенсор по PWM остановлен"); + } + break; + case 7: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSampleABCon[i]; + } + // Serial.println("Запрос No.7 - отправлен. Включаем функцию атокалибровки"); + } + break; + case 8: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSampleABCoff[i]; + } + // Serial.println("Запрос No.8 - отправлен. Выключаем функцию атокалибровки"); + } + break; + case 9: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSample2000Range[i]; + } + // Serial.println("Запрос No.9 - отправлен. Установливаем шкалу 0-2000"); + } + break; + case 10: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSample5000Range[i]; + } + // Serial.println("Запрос No.10 - отправлен. Установливаем шкалу 0-5000"); + } + break; + case 11: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSampleZeroPnt[i]; + } + // Serial.println("Запрос No.11 - отправлен. Калибровка. Установливаем нулевой уровень"); + } + break; + case 12: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSampleReset1[i]; + } + // Serial.println("Запрос No.11 - отправлен. Запрос на Сброс"); + } + break; + case 13: + { + for (int i = 0; i < 9; i++) + { + request_cmd[i] = uartReqSamplePpm[i]; + } + // Serial.println("Запрос No.13 - отправлен. Запрос по Температуре"); + } + break; + default: + // byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; + // if nothing else matches, do the default + // default is optional + break; + } + +#ifdef ESP8266 + swSerialCO2->write(request_cmd, 9); +#endif +#ifdef ESP32 + swSerialCO2.write(request_cmd, 9); +#endif + /* + Serial.print("Request : "); + for (int i = 0; i < 9; i++) + { + Serial.print(" "); + Serial.print(request_cmd[i]); + } + Serial.println(" "); + */ + delay(5); + unsigned char response[9]; + +#ifdef ESP8266 + swSerialCO2->readBytes(response, 9); +#endif + +#ifdef ESP32 + swSerialCO2.readBytes(response, 9); +#endif + /* + Serial.print("Response :"); + for (int i = 0; i < 9; i++) + { + Serial.print(" "); + Serial.print(response[i]); + } + Serial.println(" "); + */ + byte crc = 0; + for (int i = 1; i < 8; i++) + crc += response[i]; + crc = 255 - crc; + crc += 1; + + if (!(response[0] == 0xFF && response[8] == crc)) + { + String msg = "Range CRC error: " + String(crc) + " / " + String(response[8]) + " Check wiring"; + SerialPrint("E", "Sensor Mhz19uart", msg); + reply = 0; + MHZ19uartInit_flag = true; // + } + else + { + // Serial.println("No CRC errors"); + switch (request) + { + case 1: + { + unsigned int responseHigh = (unsigned int)response[2]; + unsigned int responseLow = (unsigned int)response[3]; + unsigned int ppm = (256 * responseHigh) + responseLow; + + // Serial.print("CO2 UART = "); + // Serial.println(ppm); + + temperature = response[4] - 44; // - 40; + // Serial.print("Temperature = "); + // Serial.println(temperature); + temperatureUpdated = true; + + reply = ppm; + } + break; + + case 2: + { + + unsigned int responseHigh = (unsigned int)response[4]; + unsigned int responseLow = (unsigned int)response[5]; + unsigned int scale = (256 * responseHigh) + responseLow; + reply = scale; + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.2 - сработал. Шкала получена - " + String(scale)); + } + break; + case 3: + { + // Serial.println("Case 3 - OK"); + reply = 1; + } + break; + case 4: + { + // Serial.println("Case 4 - OK"); + reply = 1; + } + break; + case 5: + { + // Serial.println("Case 5 - OK"); + reply = 1; + } + break; + case 6: + { + // Serial.println("Запрос No.6 - сработал."); + reply = 1; + } + break; + case 7: + { + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.7 - сработал. ABC включен"); + reply = 1; + } + break; + case 8: + { + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.8 - сработал. ABC выключен"); + reply = 1; + } + break; + case 9: + { + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.9 - сработал. Установлена шкала 0-2000"); + reply = 1; + prevRange = 2000; + } + break; + case 10: + { + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.10 - сработал. Установлена шкала 0-5000"); + reply = 1; + prevRange = 5000; + } + break; + case 11: + { + reply = 1; + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.11 - сработал. Калибровка. Установлен нулевой уровень"); + } + break; + + case 12: + { + reply = 1; + SerialPrint("i", "Sensor Mhz19uart", "Запрос No.12 - сработал. Сброс произошел"); + } + break; + + case 13: + { + temperature = response[4] - 44; // - 40; + reply = temperature; + // SerialPrint("i", "Sensor Mhz19uart", "Запрос No.13 - сработал. Температура получена - " + String(temperature)); + // Serial.print("Запрос No.13 - сработал. Температура получена - "); + // Serial.println(temperature); + } + break; - case 3: { - // код для запуска сенсора с работой по UART (запуск таймера) - Serial.println("Запрос No.3 - отправлен. Сенсор по UART запущен"); - } break; - case 4: { - // код для остановке сенсора с работой по UART (остановка таймера) - Serial.println("Запрос No.4 - отправлен. Сенсор по UART остановлен"); - } break; - case 5: { - // код для запуска сенсора с работой по PWM (запуск таймера) - Serial.println("Запрос No.5 - отправлен. Сенсор по PWM запущен"); - } break; - case 6: { - // код для остановки сенсора с работой по PWM (остановка таймера) - Serial.println("Запрос No.6 - отправлен. Сенсор по PWM остановлен"); - } break; - case 7: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSampleABCon[i]; - } - Serial.println("Запрос No.7 - отправлен. Включаем функцию атокалибровки"); - } break; - case 8: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSampleABCoff[i]; - } - Serial.println("Запрос No.8 - отправлен. Выключаем функцию атокалибровки"); - } break; - case 9: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSample2000Range[i]; - } - Serial.println("Запрос No.9 - отправлен. Установливаем шкалу 0-2000"); - } break; - case 10: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSample5000Range[i]; - } - Serial.println("Запрос No.10 - отправлен. Установливаем шкалу 0-5000"); - } break; - case 11: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSampleZeroPnt[i]; - } - Serial.println("Запрос No.11 - отправлен. Калибровка. Установливаем нулевой уровень"); - } break; - case 12: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSampleReset1[i]; - } - Serial.println("Запрос No.11 - отправлен. Запрос на Сброс"); - } break; - case 13: { - for (int i = 0; i < 9; i++) { - request_cmd[i] = uartReqSamplePpm[i]; - } - Serial.println("Запрос No.13 - отправлен. Запрос по Температуре"); - } break; default: // byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // if nothing else matches, do the default // default is optional break; - } - - swSerialCO2->write(request_cmd, 9); - - Serial.print("Request : "); - for (int i = 0; i < 9; i++) { - Serial.print(" "); - Serial.print(request_cmd[i]); - } - Serial.println(" "); - - delay(50); - - unsigned char response[9]; - - Serial.print("Response :"); - swSerialCO2->readBytes(response, 9); - - for (int i = 0; i < 9; i++) { - Serial.print(" "); - Serial.print(response[i]); - } - Serial.println(" "); - - byte crc = 0; - for (int i = 1; i < 8; i++) crc += response[i]; - crc = 255 - crc; - crc += 1; - - if (!(response[0] == 0xFF && response[8] == crc)) { - Serial.println("Range CRC error: " + String(crc) + " / " + String(response[8])); - reply = 0; - } else { - // Serial.println("No CRC errors"); - switch (request) { - case 1: { - unsigned int responseHigh = (unsigned int)response[2]; - unsigned int responseLow = (unsigned int)response[3]; - unsigned int ppm = (256 * responseHigh) + responseLow; - - Serial.print("CO2 UART = "); - Serial.println(ppm); - - temperature = response[4] - 44; // - 40; - Serial.print("Temperature = "); - Serial.println(temperature); - temperatureUpdated = true; - - reply = ppm; - } break; - - case 2: { - reply = 1; - Serial.println("Case 2 - OK. На запрос шкалы пришел ответ"); - } break; - case 3: { - // Serial.println("Case 3 - OK"); - reply = 1; - } break; - case 4: { - // Serial.println("Case 4 - OK"); - reply = 1; - } break; - case 5: { - // Serial.println("Case 5 - OK"); - reply = 1; - } break; - case 6: { - Serial.println("Case 6 - OK"); - reply = 1; - } break; - case 7: { - Serial.println("Case 7 - OK. ABC включен"); - reply = 1; - } break; - case 8: { - Serial.println("Case 8 - OK. ABC выключен"); - reply = 1; - } break; - case 9: { - Serial.println("Case 9 - OK. Установлена шкала 0-2000"); - reply = 1; - prevRange = 2000; - } break; - case 10: { - Serial.println("Case 9 - OK. Установлена шкала 0-5000"); - reply = 1; - prevRange = 5000; - } break; - case 11: { - reply = 1; - Serial.println("Запрос No.11 - сработал. Калибровка. Установлен нулевой уровень"); - } break; - - case 12: { - reply = 1; - Serial.println("Запрос No.12 - сработал. Сброс произошел"); - } break; - - case 13: { - reply = 1; - temperature = response[4] - 44; // - 40; - - Serial.println("Запрос No.12 - сработал. Температура получена"); - Serial.println(temperature); - } break; - - default: - // byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; - // if nothing else matches, do the default - // default is optional - break; } } // Serial.print("reply = "); diff --git a/src/modules/sensors/Mhz19/modinfo.json b/src/modules/sensors/Mhz19/modinfo.json index fcf848f9..7da1c1fa 100644 --- a/src/modules/sensors/Mhz19/modinfo.json +++ b/src/modules/sensors/Mhz19/modinfo.json @@ -2,7 +2,7 @@ "menuSection": "Сенсоры", "configItem": [ { - "name": "MHZ-19 CO2 (UART)", + "name": "MHZ-19 CO2 UART", "type": "Reading", "subtype": "Mhz19uart", "id": "co2uart", @@ -12,7 +12,7 @@ "plus": 0, "multiply": 1, "round": 1, - "pin": 0, + "warmUp": 120, "rxPin": 13, "txPin": 12, "int": 15, @@ -20,7 +20,7 @@ "ABC": 1 }, { - "name": "MHZ-19 CO2 (PWM)", + "name": "MHZ-19 CO2 PWM", "type": "Reading", "subtype": "Mhz19pwm", "id": "co2pwm", @@ -30,11 +30,13 @@ "plus": 0, "multiply": 1, "round": 1, + "warmUp": 120, "pin": 15, + "maxRetriesNotAvailable": 10, "int": 300 }, { - "name": "Cенсор температуры от MHZ-19 UART", + "name": "MHZ-19 Температура UART", "type": "Reading", "subtype": "Mhz19temp", "id": "Mhz19temp", @@ -46,64 +48,28 @@ "round": 1, "rxPin": 13, "txPin": 12, - "ABC": 1, - "int": 30 - }, - { - "name": "Рабочий диапазон от MHZ-19 UART", - "type": "Reading", - "subtype": "Mhz19range", - "id": "Mhz19range", - "widget": "anydataPpm", - "page": "Сенсоры", - "descr": "Диапазон", - "plus": 0, - "multiply": 1, - "round": 1, - "rxPin": 13, - "txPin": 12, - "range": 5000, - "ABC": 1, - "int": 30 - }, - { - "name": "Автокалибровка от MHZ-19 UART", - "type": "Reading", - "subtype": "Mhz19ABC", - "id": "Mhz19ABC", - "widget": "anydataDef", - "page": "Сенсоры", - "descr": "ABC", - "rxPin": 13, - "txPin": 12, - "range": 5000, - "ABC": 1, "int": 30 } ], "about": { "authorName": "Alex K", "authorContact": "https://t.me/cmche", - "authorGit": "", + "authorGit": "https://github.com/CHE77/Mhz19forIotManager", "specialThanks": "", "moduleName": "Mhz19", - "moduleVersion": "1.0", - "usedRam": 15, - "subTypes": [ - "Mhz19uart", - "Mhz19pwm", - "Mhz19temp", - "Mhz19range", - "Mhz19ABC" - ], - "title": "Датчик температуры и CO2 с Mhz19", - "moduleDesc": "Позволяет получить значения температуры и CO2 с Mhz19.", + "moduleVersion": "2.0 - можно переназначать пины", + "moduleDesc": "Позволяет получить значения уровня концетрации CO2 с Mhz19 по UART и/или ШИМ. Замер по ШИМ может производить 1-2 сек. задержки", "propInfo": { + "plus": "поправочный коэффиент +c", + "multiply": "поправочный коэффиент k*", + "round": "округление", "int": "Количество секунд между опросами датчика.", - "rxPin": "", - "txPin": "", - "range": "", - "ABC": "" + "rxPin": "Esp8266: GPIO 13 - D7, ESP32: GPIO 19 - RX1, > MHZ19: TXD зеленый провод", + "txPin": "Esp8266: GPIO 12 - D6, ESP32: GPIO 18 - TX1, > MHZ19: RXD синий провод", + "range": "Шкала по умолчанию 0-5000ppm. Также можно выбрать 2000", + "ABC": "Автокалибровка. По умолчанию включена. Раз в сутки на 20 мин. надо выставлять на свежий воздух.", + "pin": "пин получения значений по ШИМ. Esp8266: GPIO 15 - D8, ESP32: GPIO 21, > MHZ19: PWM желтый провод", + "maxRetriesNotAvailable": "Максимальное количество попыток опроса сенсора по ШИМ. (может задерживать контроллер)" } }, "defActive": false, diff --git a/src/modules/sensors/Sds011/Sds011.cpp b/src/modules/sensors/Sds011/Sds011.cpp index ab569788..fb081e38 100644 --- a/src/modules/sensors/Sds011/Sds011.cpp +++ b/src/modules/sensors/Sds011/Sds011.cpp @@ -14,55 +14,86 @@ extern IoTGpio IoTgpio; #include "SdsDustSensor.h" -//встроена в ядро для 8266, для 32 по этому же имени обращаемся к другой библиотеке plerup/EspSoftwareSerial -#include +//#define __DEBUG_SDS_DUST_SENSOR__ + +int rxPinSDS; // Esp8266: 14/D5 – подключаем к Tx сенсора +int txPinSDS; // Esp8266: 16/D0 – подключаем к Rx сенсора + +// SdsDustSensor sds(rxPinSDS, txPinSDS); +SdsDustSensor *sds = nullptr; -// to do убрать глобальный экземпляр -#ifdef ESP8266 -int rxPinSDS = 13; // D7 – подключаем к Tx сенсора -int txPinSDS = 12; // D6 – подключаем к Rx сенсора -SdsDustSensor sds(rxPinSDS, txPinSDS); -#endif #ifdef ESP32 #include HardwareSerial sdsSerial(2); -SdsDustSensor sds(sdsSerial); +// SdsDustSensor sds(sdsSerial); #endif -unsigned int warmUp; -unsigned int period; +int retryDelayMs = 5; +int maxRetriesNotAvailable = 100; +unsigned int purge = 30; +unsigned int interval = 300; +unsigned int purgeDelay = 270; +unsigned int continuous = 0; +bool startUp = true; +TickerScheduler ts_sds(2); + +enum TimerTask_t_sds +{ + WAKEUP, + PRINT +}; + +int firstSensor = 0; bool SDS011_init_flag = true; void SDS011_init(); -float Sds011request(int sensorID); +void Sds011request(int sensorID); + +IoTItem *item_Sds011_25 = nullptr; // pointer +IoTItem *item_Sds011_10 = nullptr; //Это файл сенсора, в нем осуществляется чтение сенсора. //для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора //Название должно быть уникальным, коротким и отражать суть сенсора. -class Sds011_25 : public IoTItem { - private: +class Sds011_25 : public IoTItem +{ +private: //======================================================================================================= // Секция переменных. //Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы //впоследствии использовать их в loop и setup // unsigned int _pin; - public: +public: //======================================================================================================= // setup() //это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора. //Такие как ...begin и подставлять в них параметры полученные из web интерфейса. //Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: // jsonReadStr, jsonReadBool, jsonReadInt - Sds011_25(String parameters) : IoTItem(parameters) { - // _pin = jsonReadInt(parameters, "pin"); -#ifdef ESP8266 + Sds011_25(String parameters) : IoTItem(parameters) + { + item_Sds011_25 = this; + rxPinSDS = jsonReadInt(parameters, "rxPin"); txPinSDS = jsonReadInt(parameters, "txPin"); -#endif - warmUp = jsonReadInt(parameters, "warmUp"); // сек. пробужнение должен быть больше - period = jsonReadInt(parameters, "period"); // сек. время зарогрева/продувки, затем идут замеры + + purge = jsonReadInt(parameters, "purge"); // сек. пробужнение должен быть больше + interval = jsonReadInt(parameters, "int"); // сек. время зарогрева/продувки, затем идут замеры + continuous = jsonReadInt(parameters, "continuousMode"); // сек. время зарогрева/продувки, затем идут замеры + maxRetriesNotAvailable = jsonReadInt(parameters, "maxRetriesNotAvailable"); // сек. время зарогрева/продувки, затем идут замеры + retryDelayMs = jsonReadInt(parameters, "retryDelayMs"); // сек. время зарогрева/продувки, затем идут замеры + if (continuous) + { + SerialPrint("i", "Sensor Sds011", "Continuous mode"); + ts_sds.remove(PRINT); + ts_sds.remove(WAKEUP); + } + purgeDelay = interval - purge; + + SDS011_init(); + firstSensor = 0; } //======================================================================================================= // doByInterval() @@ -72,41 +103,70 @@ class Sds011_25 : public IoTItem { //если у сенсора несколько величин то делайте несколько regEvent //не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции //и выполнить за несколько тактов - void doByInterval() { + void doByInterval() + { SDS011_init(); - Serial.println("request from 25"); - value.valD = Sds011request(25); - - regEvent(value.valD, "Sds011_25"); //обязательный вызов хотяб один + // SerialPrint("i", "Sensor Sds011", "Request for 2.5"); + Sds011request(25); + // value.valD = Sds011request(25); + // regEvent(value.valD, "Sds011_25"); //обязательный вызов хотяб один } - ~Sds011_25(){}; }; //////////////////////////////////// for PM 10//= -class Sds011_10 : public IoTItem { - private: +class Sds011_10 : public IoTItem +{ +private: //======================================================================================================= // Секция переменных. //Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы //впоследствии использовать их в loop и setup - public: +public: //======================================================================================================= // setup() - //это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора. - //Такие как ...begin и подставлять в них параметры полученные из web интерфейса. - //Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: - // jsonReadStr, jsonReadBool, jsonReadInt - Sds011_10(String parameters) : IoTItem(parameters) { -// _pin = jsonReadInt(parameters, "pin"); -#ifdef ESP8266 + + Sds011_10(String parameters) : IoTItem(parameters) + { + item_Sds011_10 = this; + rxPinSDS = jsonReadInt(parameters, "rxPin"); txPinSDS = jsonReadInt(parameters, "txPin"); -#endif - warmUp = jsonReadInt(parameters, "warmUp"); // сек. пробужнение должен быть больше - period = jsonReadInt(parameters, "period"); // сек. время зарогрева/продувки, затем идут замеры + + purge = jsonReadInt(parameters, "purge"); // сек. пробужнение должен быть больше + interval = jsonReadInt(parameters, "int"); // сек. время зарогрева/продувки, затем идут замеры + continuous = jsonReadInt(parameters, "continuousMode"); // сек. время зарогрева/продувки, затем идут замеры + if (continuous) + { + SerialPrint("i", "Sensor Sds011", "Continuous mode"); + ts_sds.remove(PRINT); + ts_sds.remove(WAKEUP); + } + else + { + SerialPrint("i", "Sensor Sds011", "WakeUp mode"); + } + purgeDelay = interval - purge; + SDS011_init(); + firstSensor = 0; + } + + //луп выполняющий переодическое дерганье + void loop() + { + ts_sds.update(); + if (enableDoByInt) + { + currentMillis = millis(); + difference = currentMillis - prevMillis; + if (difference >= _interval) + { + prevMillis = millis(); + this->doByInterval(); + } + } } //======================================================================================================= // doByInterval() @@ -117,12 +177,13 @@ class Sds011_10 : public IoTItem { //не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции //и выполнить за несколько тактов - void doByInterval() { + void doByInterval() + { SDS011_init(); - Serial.println("request from 10"); - value.valD = Sds011request(10); - - regEvent(value.valD, "Sds011_10"); //обязательный вызов хотяб один + // SerialPrint("i", "Sensor Sds011", "Request for 10ppm"); + Sds011request(10); + // value.valD = Sds011request(10); + // regEvent(value.valD, "Sds011_10"); //обязательный вызов хотяб один } ~Sds011_10(){}; }; @@ -130,71 +191,148 @@ class Sds011_10 : public IoTItem { //после замены названия сенсора, на функцию можно не обращать внимания //если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть //создание и контроль соответствующих глобальных переменных -void* getAPI_Sds011(String subtype, String param) { - if (subtype == F("Sds011_25")) { +void *getAPI_Sds011(String subtype, String param) +{ + if (subtype == F("Sds011_25")) + { return new Sds011_25(param); - } else if (subtype == F("Sds011_10")) { + } + else if (subtype == F("Sds011_10")) + { return new Sds011_10(param); - } else { + } + else + { return nullptr; } } -float Sds011request(int sensorID) { - float reply = 0; - static int a = 0; - static float pm25 = 0; - static float pm10 = 0; - static int startMillis = millis(); +void Sds011request(int sensorID) +{ + float pm25 = 0; + float pm10 = 0; - if (a == 0) { - Serial.print("SDS011 ... warmUp = "); - Serial.print(warmUp); - Serial.print(" period = "); - Serial.println(period); - sds.wakeup(); - startMillis = millis(); - a = a + 1; - } - if (a == 1 && millis() >= (startMillis + warmUp * 1000)) { - PmResult pm = sds.readPm(); - if (pm.isOk()) { + if (firstSensor == 0) + firstSensor = sensorID; + + if (firstSensor == sensorID) + { + if (!continuous) + { + ts_sds.remove(PRINT); + ts_sds.remove(WAKEUP); + } + + PmResult pm = sds->readPm(); + // SerialPrint("i", "Sensor Sds011", "sds.readPm()"); + if (pm.isOk()) + { pm25 = pm.pm25; pm10 = pm.pm10; - Serial.print("PM2.5 = "); - Serial.print(pm25); - Serial.print(" PM10 = "); - Serial.println(pm10); - a = a + 1; - sds.sleep(); - } else { - Serial.print("Could not read values from sensor 25, reason: "); - Serial.println(pm.statusToString()); - a = a + 1; + // SerialPrint("i", "Sensor Sds011", pm.toString()); + + if (item_Sds011_25 && pm25) + { + item_Sds011_25->value.valD = pm25; + item_Sds011_25->regEvent(item_Sds011_25->value.valD, "Sds011_25"); + } + + if (item_Sds011_10 && pm10) + { + item_Sds011_10->value.valD = pm10; + item_Sds011_10->regEvent(item_Sds011_10->value.valD, "Sds011_10"); + } + } + else + { + String msg = "Could not read values from sensor. Reason: " + pm.statusToString(); + SerialPrint("E", "Sensor Sds011", msg); + SDS011_init_flag = true; + } + + if (!continuous) + { + sds->sleep(); + SerialPrint("i", "Sensor Sds011", "sleep"); + String msg = "wakeUp planned in " + String(purgeDelay) + " seconds"; + SerialPrint("i", "Sensor Sds011", msg); + ts_sds.add( + PRINT, purgeDelay * 1000, [](void *) + { SerialPrint("i", "Sensor Sds011", "delayed wakeUp"); }, + nullptr, false); + ts_sds.add( + WAKEUP, purgeDelay * 1000, [](void *) + { sds->wakeup(); }, + nullptr, false); } } - if (a > 1 && millis() >= (startMillis + period * 1000)) { - Serial.println("end of period for pm25"); - a = 0; + else + { + //пропускаем вызов от второго сенсора } - if (sensorID == 25) { - reply = pm25; - } - if (sensorID == 10) { - reply = pm10; - } - return reply; + + return; } -void SDS011_init() { - if (SDS011_init_flag) { - sds.begin(); - Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version - // Serial.println(sds.setActiveReportingMode().toString()); // - String ReportingMode = sds.setActiveReportingMode().toString(); - Serial.println(ReportingMode); - if (ReportingMode == "Mode: active") { +void SDS011_init() +{ + if (SDS011_init_flag) + { + +#ifdef ESP8266 + + if (!sds) + { + Serial.println("no sds, creating"); + sds = new SdsDustSensor(rxPinSDS, txPinSDS, retryDelayMs, maxRetriesNotAvailable); + } + else + { + Serial.println("sds already created"); + } + + sds->begin(9600); + delay(200); // +#endif + +#ifdef ESP32 + sdsSerial.begin(9600, SERIAL_8N1, rxPinSDS, txPinSDS); + delay(200); + if (!sds) + { + Serial.println("no sds, creating"); + sds = new SdsDustSensor(sdsSerial, retryDelayMs, maxRetriesNotAvailable); + } + else + { + Serial.println("sds already created"); + } +#endif + + if (startUp) + { + sds->wakeup(); + SerialPrint("i", "Sensor Sds011", "wakeup on startUp"); // уже начинаем продувку + startUp = false; + } + String msg = sds->queryFirmwareVersion().toString(); // + SerialPrint("i", "Sensor Sds011", msg); + String ReportingMode = sds->setActiveReportingMode().toString(); + + if (ReportingMode == "Mode: active") + { + SerialPrint("i", "Sensor Sds011", ReportingMode); SDS011_init_flag = false; + if (continuous) + { + sds->wakeup(); + SerialPrint("i", "Sensor Sds011", "wakeUp if continuous"); + } + } + else + { + ReportingMode += " - check wiring!"; + SerialPrint("E", "Sensor Sds011", ReportingMode); } } } diff --git a/src/modules/sensors/Sds011/modinfo.json b/src/modules/sensors/Sds011/modinfo.json index cca5ad1f..ba7d0022 100644 --- a/src/modules/sensors/Sds011/modinfo.json +++ b/src/modules/sensors/Sds011/modinfo.json @@ -2,7 +2,7 @@ "menuSection": "Сенсоры", "configItem": [ { - "name": "SDS011 PM25 Датчик пыли", + "name": "SDS011 PM25 Пыль", "type": "Reading", "subtype": "Sds011_25", "id": "pmuart25", @@ -12,14 +12,16 @@ "plus": 0, "multiply": 1, "round": 10, - "rxPin": 13, - "txPin": 12, - "int": 15, - "warmUp": 30, - "period": 300 + "rxPin": 14, + "txPin": 16, + "int": 270, + "purge": 30, + "continuousMode": 0, + "maxRetriesNotAvailable": 100, + "retryDelayMs": 5 }, { - "name": "SDS011 PM10 Датчик пыли", + "name": "SDS011 PM10 Пыль", "type": "Reading", "subtype": "Sds011_10", "id": "pmuart10", @@ -29,33 +31,34 @@ "plus": 0, "multiply": 1, "round": 10, - "rxPin": 13, - "txPin": 12, - "int": 15, - "warmUp": 30, - "period": 300 + "rxPin": 14, + "txPin": 16, + "int": 270, + "purge": 30, + "continuousMode": 0, + "maxRetriesNotAvailable": 100, + "retryDelayMs": 5 } ], "about": { "authorName": "Alex K", "authorContact": "https://t.me/cmche", - "authorGit": "", + "authorGit": "https://github.com/CHE77/SDS011forIotManager", "specialThanks": "", "moduleName": "Sds011", - "moduleVersion": "1.0", - "usedRam": 15, - "subTypes": [ - "Sds011_25", - "Sds011_10" - ], - "title": "Датчик пыли", + "moduleVersion": "2.0 - можно переназначать пины, за один опрос - обновляются два элемента", "moduleDesc": "Позволяет получить значения концентрации пыли в воздухе с Sds011.", "propInfo": { - "int": "Количество секунд между опросами датчика.", - "rxPin": "", - "txPin": "", - "warmUp": "", - "period": "" + "plus": "поправочный коэффиент +c", + "multiply": "поправочный коэффиент k*", + "round": "округление", + "rxPin": "Esp8266: GPIO 14 - D5, ESP32: GPIO 16 - RX2, > подключаем к TXD сенсора", + "txPin": "Esp8266: GPIO 16 - D0, ESP32: GPIO 17 - TX2, > подключаем к RXD сенсора", + "int": "Количество секунд между опросами датчика", + "purge": "Время продувки сенсора перед замером. Cек.", + "continuousMode": "1 - Непрерывный режим, 0 - Режим с остановкой (щедящий)", + "maxRetriesNotAvailable": "Количество попыток ожидания ответа сенсора при опросе (не нужно менять)", + "retryDelayMs": "Задержка между попытками, миллисекунды (не нужно менять)" } }, "defActive": false,