добавлен mhz19 и sds011

This commit is contained in:
Dmitry Borisenko
2022-09-28 10:28:52 +02:00
parent adfeb9ef55
commit af2b015dea
4 changed files with 791 additions and 562 deletions

View File

@@ -11,15 +11,25 @@
extern IoTGpio IoTgpio; extern IoTGpio IoTgpio;
// SoftwareSerial* swSerialCO2 = nullptr;
int rxPinCO2; // зеленый провод сенсора к прописаному по умолчанию D7 (GPIO13) int rxPinCO2; // зеленый провод сенсора к прописаному по умолчанию D7 (GPIO13)
int txPinCO2; // синий провод сенсора к прописаному по умолчанию D6 (GPIO12) int txPinCO2; // синий провод сенсора к прописаному по умолчанию D6 (GPIO12)
#ifdef ESP8266
SoftwareSerial *swSerialCO2 = nullptr; SoftwareSerial *swSerialCO2 = nullptr;
#endif
#ifdef ESP32
#include <HardwareSerial.h>
HardwareSerial swSerialCO2(1);
#endif
int MHZ19_request(int request); int MHZ19_request(int request);
void MHZ19uart_init(); void MHZ19uart_init();
bool MHZ19uart_flag = true; bool MHZ19uartInit_flag = true;
int MHZ19C_PREHEATING_TIME = 2 * 30 * 1000; // покажет реальные данные после прогрева, через 2 мин. bool MHZ19uartUpdateInputs_flag = true;
unsigned int preheating = 2 * 60; // покажет реальные данные после прогрева, через 2 мин.
int temperature = 0; int temperature = 0;
bool temperatureUpdated = false; bool temperatureUpdated = false;
@@ -32,7 +42,8 @@ bool ABCchanged = false;
//Это файл сенсора, в нем осуществляется чтение сенсора. //Это файл сенсора, в нем осуществляется чтение сенсора.
class Mhz19uart : public IoTItem { class Mhz19uart : public IoTItem
{
private: private:
//======================================================================================================= //=======================================================================================================
// Секция переменных. // Секция переменных.
@@ -40,24 +51,43 @@ class Mhz19uart : public IoTItem {
public: public:
//======================================================================================================= //=======================================================================================================
Mhz19uart(String parameters) : IoTItem(parameters) { Mhz19uart(String parameters) : IoTItem(parameters)
{
rxPinCO2 = jsonReadInt(parameters, "rxPin"); rxPinCO2 = jsonReadInt(parameters, "rxPin");
txPinCO2 = jsonReadInt(parameters, "txPin"); txPinCO2 = jsonReadInt(parameters, "txPin");
preheating = jsonReadInt(parameters, "warmUp");
range = jsonReadInt(parameters, "range"); range = jsonReadInt(parameters, "range");
ABC = jsonReadInt(parameters, "ABC"); 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() // doByInterval()
void doByInterval() { void doByInterval()
{
MHZ19uart_init(); MHZ19uart_init();
if (millis() > MHZ19C_PREHEATING_TIME) {
Serial.println("Start checkUARTCO2"); if (millis() > preheating * 1000)
value.valD = MHZ19_request(1); {
// Serial.println("Start checkUARTCO2");
int reply = MHZ19_request(1);
if (reply)
{
value.valD = reply;
regEvent(value.valD, "Mhz19uart");
}
} }
regEvent(value.valD, "Mhz19uart"); //обязательный вызов хотяб один
} }
//======================================================================================================= //=======================================================================================================
@@ -69,63 +99,110 @@ class Mhz19uart : public IoTItem {
//создание и контроль соответствующих глобальных переменных //создание и контроль соответствующих глобальных переменных
//замер по ШИМ создает задержку. вызываем его нечасто, по умолчанию раз в 5 минут //замер по ШИМ создает задержку. вызываем его нечасто, по умолчанию раз в 5 минут
class Mhz19pwm : public IoTItem { class Mhz19pwm : public IoTItem
{
private: 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");
}
//=======================================================================================================
void doByInterval() {
MHZ19pwm_init();
if (millis() > MHZ19C_PREHEATING_TIME) //
{ {
Serial.println("Start checkPWM_CO2"); pwmPin = jsonReadInt(parameters, "pin");
value.valD = MHZ19pwm_request(); preheating = jsonReadInt(parameters, "warmUp");
} maxRetriesNotAvailable = jsonReadInt(parameters, "maxRetriesNotAvailable");
regEvent(value.valD, "Mhz19pwm"); //обязательный вызов хотяб один
} }
//======================================================================================================= //=======================================================================================================
void MHZ19pwm_init() { void doByInterval()
{
MHZ19pwm_init();
if (millis() > preheating * 1000) //
{
// 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");
}
}
}
//=======================================================================================================
void MHZ19pwm_init()
{
static bool MHZ19pwm_flag = true; static bool MHZ19pwm_flag = true;
if (MHZ19pwm_flag) { if (MHZ19pwm_flag)
{
pinMode(pwmPin, INPUT); pinMode(pwmPin, INPUT);
MHZ19pwm_flag = false; MHZ19pwm_flag = false;
} }
} }
int MHZ19pwm_request() { int MHZ19pwm_request()
{
int reply; int reply;
Serial.println("Запрос замера по PWM запущен"); // Serial.println("Запрос замера по PWM запущен");
unsigned long th, tl, ppm = 0, ppm2 = 0, ppm3 = 0; unsigned long th = 0, tl, ppm = 0, ppm2 = 0, ppm3 = 0;
do { // int pwmPinReading1 = digitalRead(pwmPin);
// SerialPrint("E", "Sensor Mhz19uart", "pwmPinReading1 = " + String(pwmPinReading1));
/*
do
{
th = pulseIn(pwmPin, HIGH, 1004000) / 1000; th = pulseIn(pwmPin, HIGH, 1004000) / 1000;
tl = 1004 - th; tl = 1004 - th;
ppm2 = 2000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 2000ppm ppm2 = 2000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 2000ppm
ppm3 = 5000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 5000ppm ppm3 = 5000 * (th - 2) / (th + tl - 4); // расчёт для диапазона от 0 до 5000ppm
} while (th == 0); } while (th == 0);
*/
for (int i = 0; i < maxRetriesNotAvailable; i++)
{
th = pulseIn(pwmPin, HIGH, 1004000) / 1000;
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);
}
if (!th)
{
SerialPrint("E", "Sensor Mhz19pwm", "No reading from PWM pin. Check wiring.");
reply = 0;
}
else
{
// Serial.print(th); // Serial.print(th);
// Serial.println(" <- Milliseconds PWM is HIGH"); // Serial.println(" <- Milliseconds PWM is HIGH");
if (range == 2000)
if (range == 2000) { {
reply = ppm2; reply = ppm2;
Serial.print(ppm2); // Serial.print(ppm2);
Serial.println(" <- ppm2 (PWM) with 2000ppm as limit"); // 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"); 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; return reply;
} }
@@ -134,35 +211,51 @@ class Mhz19pwm : public IoTItem {
//====================TEMP=================================================================================== //====================TEMP===================================================================================
class Mhz19temp : public IoTItem { class Mhz19temp : public IoTItem
{
private: private:
//======================================================================================================= //=======================================================================================================
// Секция переменных. // Секция переменных.
public: public:
//====================TEMP=================================================================================== //====================TEMP===================================================================================
Mhz19temp(String parameters) : IoTItem(parameters) { Mhz19temp(String parameters) : IoTItem(parameters)
{
rxPinCO2 = jsonReadInt(parameters, "rxPin"); rxPinCO2 = jsonReadInt(parameters, "rxPin");
txPinCO2 = jsonReadInt(parameters, "txPin"); txPinCO2 = jsonReadInt(parameters, "txPin");
range = jsonReadInt(parameters, "range");
ABC = jsonReadInt(parameters, "ABC"); #ifdef ESP8266
if (!swSerialCO2) swSerialCO2 = new SoftwareSerial(rxPinCO2, txPinCO2); 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"); // Serial.println("Start Mhz19temp doByInterval");
if (temperatureUpdated) { if (temperatureUpdated)
value.valD = temperature; {
reply = temperature;
temperatureUpdated = false; 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,156 +264,103 @@ class Mhz19temp : public IoTItem {
~Mhz19temp(){}; ~Mhz19temp(){};
}; };
//=======================Range================ void *getAPI_Mhz19(String subtype, String param)
class Mhz19range : public IoTItem { {
private: if (subtype == F("Mhz19uart"))
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")) {
return new Mhz19uart(param); return new Mhz19uart(param);
} else if (subtype == F("Mhz19pwm")) { }
else if (subtype == F("Mhz19pwm"))
{
return new Mhz19pwm(param); return new Mhz19pwm(param);
} else if (subtype == F("Mhz19temp")) { }
else if (subtype == F("Mhz19temp"))
{
return new Mhz19temp(param); return new Mhz19temp(param);
} else if (subtype == F("Mhz19range")) { }
return new Mhz19range(param); else
} else if (subtype == F("Mhz19ABC")) { {
return new Mhz19ABC(param);
} else {
return nullptr; return nullptr;
} }
} }
void MHZ19uart_init() { void MHZ19uart_init()
if (MHZ19uart_flag) { {
int reply; if (MHZ19uartInit_flag)
{
#ifdef ESP8266
swSerialCO2->begin(9600); swSerialCO2->begin(9600);
#endif
#ifdef ESP32
// if(swSerialCO2.available()) { Serial.println("ok"); }
swSerialCO2.begin(9600, SERIAL_8N1, rxPinCO2, txPinCO2);
#endif
delay(50); delay(50);
int reply;
reply = MHZ19_request(2); // show range, for test of uart only reply = MHZ19_request(2); // show range, for test of uart only
Serial.print("show range reply = "); // Serial.print("show range reply = ");
Serial.println(reply); // Serial.println(reply);
if (reply) { if (reply)
MHZ19uart_flag = false; {
prevRange = reply;
MHZ19uartInit_flag = false;
} }
} }
if (!MHZ19uart_flag) { if (!MHZ19uartInit_flag && ABC != prevABC)
static int prevABC; {
int reply; int reply;
if (ABC != prevABC) { if (ABC != prevABC)
if (ABC) { {
if (ABC)
{
reply = MHZ19_request(7); // ABC on reply = MHZ19_request(7); // ABC on
} else { }
else
{
reply = MHZ19_request(8); // ABC off reply = MHZ19_request(8); // ABC off
} }
Serial.print("ABC change reply = "); // Serial.print("ABC change reply = ");
Serial.println(reply); // Serial.println(reply);
} }
if (reply) { if (reply)
{
prevABC = ABC; prevABC = ABC;
} }
} }
static bool MHZ19_range_flag = true; if (range != prevRange && !MHZ19uartInit_flag)
if (MHZ19_range_flag && !MHZ19uart_flag && (millis() > 30 * 1000)) { {
int reply; int reply;
if (range == 2000) { if (range == 2000)
reply = MHZ19_request(9); // Установка шкалы 0-2000 {
// 255 155 0 0 7 208 0 3 139 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
} }
Serial.print("Scale change reply = "); else
Serial.println(reply); {
if (reply) { reply = MHZ19_request(10); // Установка шкалы 0-5000 - 255 155 0 0 19 136 0 3 199
reply = MHZ19_request(2); // show range }
Serial.print("show range reply = "); // Serial.print("Scale change reply = ");
Serial.println(reply); // Serial.println(reply);
if (reply)
MHZ19_range_flag = false; {
// 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; int reply;
Serial.print("prevRange = "); // Serial.print("prevRange = ");
Serial.println(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 // 255 1 134 0 0 0 0 0 121
@@ -331,11 +371,9 @@ int MHZ19_request(int request) {
// Response 255 121 1 0 0 0 0 0 134 // 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 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 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 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 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 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 byte uartReqSample5000Range[9] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88, 0xCB}; // задаёт диапазон 0 - 5000ppm
// 255 1 153 0 0 0 19 136 203 // 255 1 153 0 0 0 19 136 203
// Response 255 153 1 0 0 0 0 0 102 // Response 255 153 1 0 0 0 0 0 102
@@ -344,85 +382,120 @@ int MHZ19_request(int request) {
// reply // 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 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 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 uartReqSampleReset1[9] = {0xFF, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; // reset - did not work out
byte request_cmd[9]; byte request_cmd[9];
// byte c; // byte c;
switch (request) { switch (request)
{
// случаи 3-7 для перезапуска сенсора // случаи 3-7 для перезапуска сенсора
case 1: { case 1:
Serial.println("Запрос No.1 - отправлен. Запрос замера по UART"); {
for (int i = 0; i < 9; i++) { // Serial.println("Запрос No.1 - отправлен. Запрос замера по UART");
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSamplePpm[i]; request_cmd[i] = uartReqSamplePpm[i];
} }
} break; }
break;
case 2: { case 2:
for (int i = 0; i < 9; i++) { {
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSampleRequestRange[i]; request_cmd[i] = uartReqSampleRequestRange[i];
} }
Serial.println("Запрос No.2 - отправлен. Запрос шкалы"); // Serial.println("Запрос No.2 - отправлен. Запрос шкалы");
} break; }
break;
case 3: { case 3:
{
// код для запуска сенсора с работой по UART (запуск таймера) // код для запуска сенсора с работой по UART (запуск таймера)
Serial.println("Запрос No.3 - отправлен. Сенсор по UART запущен"); // Serial.println("Запрос No.3 - отправлен. Сенсор по UART запущен");
} break; }
case 4: { break;
case 4:
{
// код для остановке сенсора с работой по UART (остановка таймера) // код для остановке сенсора с работой по UART (остановка таймера)
Serial.println("Запрос No.4 - отправлен. Сенсор по UART остановлен"); // Serial.println("Запрос No.4 - отправлен. Сенсор по UART остановлен");
} break; }
case 5: { break;
case 5:
{
// код для запуска сенсора с работой по PWM (запуск таймера) // код для запуска сенсора с работой по PWM (запуск таймера)
Serial.println("Запрос No.5 - отправлен. Сенсор по PWM запущен"); // Serial.println("Запрос No.5 - отправлен. Сенсор по PWM запущен");
} break; }
case 6: { break;
case 6:
{
// код для остановки сенсора с работой по PWM (остановка таймера) // код для остановки сенсора с работой по PWM (остановка таймера)
Serial.println("Запрос No.6 - отправлен. Сенсор по PWM остановлен"); // Serial.println("Запрос No.6 - отправлен. Сенсор по PWM остановлен");
} break; }
case 7: { break;
for (int i = 0; i < 9; i++) { case 7:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSampleABCon[i]; request_cmd[i] = uartReqSampleABCon[i];
} }
Serial.println("Запрос No.7 - отправлен. Включаем функцию атокалибровки"); // Serial.println("Запрос No.7 - отправлен. Включаем функцию атокалибровки");
} break; }
case 8: { break;
for (int i = 0; i < 9; i++) { case 8:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSampleABCoff[i]; request_cmd[i] = uartReqSampleABCoff[i];
} }
Serial.println("Запрос No.8 - отправлен. Выключаем функцию атокалибровки"); // Serial.println("Запрос No.8 - отправлен. Выключаем функцию атокалибровки");
} break; }
case 9: { break;
for (int i = 0; i < 9; i++) { case 9:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSample2000Range[i]; request_cmd[i] = uartReqSample2000Range[i];
} }
Serial.println("Запрос No.9 - отправлен. Установливаем шкалу 0-2000"); // Serial.println("Запрос No.9 - отправлен. Установливаем шкалу 0-2000");
} break; }
case 10: { break;
for (int i = 0; i < 9; i++) { case 10:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSample5000Range[i]; request_cmd[i] = uartReqSample5000Range[i];
} }
Serial.println("Запрос No.10 - отправлен. Установливаем шкалу 0-5000"); // Serial.println("Запрос No.10 - отправлен. Установливаем шкалу 0-5000");
} break; }
case 11: { break;
for (int i = 0; i < 9; i++) { case 11:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSampleZeroPnt[i]; request_cmd[i] = uartReqSampleZeroPnt[i];
} }
Serial.println("Запрос No.11 - отправлен. Калибровка. Установливаем нулевой уровень"); // Serial.println("Запрос No.11 - отправлен. Калибровка. Установливаем нулевой уровень");
} break; }
case 12: { break;
for (int i = 0; i < 9; i++) { case 12:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSampleReset1[i]; request_cmd[i] = uartReqSampleReset1[i];
} }
Serial.println("Запрос No.11 - отправлен. Запрос на Сброс"); // Serial.println("Запрос No.11 - отправлен. Запрос на Сброс");
} break; }
case 13: { break;
for (int i = 0; i < 9; i++) { case 13:
{
for (int i = 0; i < 9; i++)
{
request_cmd[i] = uartReqSamplePpm[i]; request_cmd[i] = uartReqSamplePpm[i];
} }
Serial.println("Запрос No.13 - отправлен. Запрос по Температуре"); // Serial.println("Запрос No.13 - отправлен. Запрос по Температуре");
} break; }
break;
default: default:
// byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
// if nothing else matches, do the default // if nothing else matches, do the default
@@ -430,110 +503,159 @@ int MHZ19_request(int request) {
break; break;
} }
#ifdef ESP8266
swSerialCO2->write(request_cmd, 9); swSerialCO2->write(request_cmd, 9);
#endif
#ifdef ESP32
swSerialCO2.write(request_cmd, 9);
#endif
/*
Serial.print("Request : "); Serial.print("Request : ");
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++)
{
Serial.print(" "); Serial.print(" ");
Serial.print(request_cmd[i]); Serial.print(request_cmd[i]);
} }
Serial.println(" "); Serial.println(" ");
*/
delay(50); delay(5);
unsigned char response[9]; unsigned char response[9];
Serial.print("Response :"); #ifdef ESP8266
swSerialCO2->readBytes(response, 9); swSerialCO2->readBytes(response, 9);
#endif
for (int i = 0; i < 9; i++) { #ifdef ESP32
swSerialCO2.readBytes(response, 9);
#endif
/*
Serial.print("Response :");
for (int i = 0; i < 9; i++)
{
Serial.print(" "); Serial.print(" ");
Serial.print(response[i]); Serial.print(response[i]);
} }
Serial.println(" "); Serial.println(" ");
*/
byte crc = 0; byte crc = 0;
for (int i = 1; i < 8; i++) crc += response[i]; for (int i = 1; i < 8; i++)
crc += response[i];
crc = 255 - crc; crc = 255 - crc;
crc += 1; crc += 1;
if (!(response[0] == 0xFF && response[8] == crc)) { if (!(response[0] == 0xFF && response[8] == crc))
Serial.println("Range CRC error: " + String(crc) + " / " + String(response[8])); {
String msg = "Range CRC error: " + String(crc) + " / " + String(response[8]) + " Check wiring";
SerialPrint("E", "Sensor Mhz19uart", msg);
reply = 0; reply = 0;
} else { MHZ19uartInit_flag = true; //
}
else
{
// Serial.println("No CRC errors"); // Serial.println("No CRC errors");
switch (request) { switch (request)
case 1: { {
case 1:
{
unsigned int responseHigh = (unsigned int)response[2]; unsigned int responseHigh = (unsigned int)response[2];
unsigned int responseLow = (unsigned int)response[3]; unsigned int responseLow = (unsigned int)response[3];
unsigned int ppm = (256 * responseHigh) + responseLow; unsigned int ppm = (256 * responseHigh) + responseLow;
Serial.print("CO2 UART = "); // Serial.print("CO2 UART = ");
Serial.println(ppm); // Serial.println(ppm);
temperature = response[4] - 44; // - 40; temperature = response[4] - 44; // - 40;
Serial.print("Temperature = "); // Serial.print("Temperature = ");
Serial.println(temperature); // Serial.println(temperature);
temperatureUpdated = true; temperatureUpdated = true;
reply = ppm; reply = ppm;
} break; }
break;
case 2: { case 2:
reply = 1; {
Serial.println("Case 2 - OK. На запрос шкалы пришел ответ");
} break; unsigned int responseHigh = (unsigned int)response[4];
case 3: { 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"); // Serial.println("Case 3 - OK");
reply = 1; reply = 1;
} break; }
case 4: { break;
case 4:
{
// Serial.println("Case 4 - OK"); // Serial.println("Case 4 - OK");
reply = 1; reply = 1;
} break; }
case 5: { break;
case 5:
{
// Serial.println("Case 5 - OK"); // Serial.println("Case 5 - OK");
reply = 1; reply = 1;
} break; }
case 6: { break;
Serial.println("Case 6 - OK"); case 6:
{
// Serial.println("Запрос No.6 - сработал.");
reply = 1; reply = 1;
} break; }
case 7: { break;
Serial.println("Case 7 - OK. ABC включен"); case 7:
{
SerialPrint("i", "Sensor Mhz19uart", "Запрос No.7 - сработал. ABC включен");
reply = 1; reply = 1;
} break; }
case 8: { break;
Serial.println("Case 8 - OK. ABC выключен"); case 8:
{
SerialPrint("i", "Sensor Mhz19uart", "Запрос No.8 - сработал. ABC выключен");
reply = 1; reply = 1;
} break; }
case 9: { break;
Serial.println("Case 9 - OK. Установлена шкала 0-2000"); case 9:
{
SerialPrint("i", "Sensor Mhz19uart", "Запрос No.9 - сработал. Установлена шкала 0-2000");
reply = 1; reply = 1;
prevRange = 2000; prevRange = 2000;
} break; }
case 10: { break;
Serial.println("Case 9 - OK. Установлена шкала 0-5000"); case 10:
{
SerialPrint("i", "Sensor Mhz19uart", "Запрос No.10 - сработал. Установлена шкала 0-5000");
reply = 1; reply = 1;
prevRange = 5000; prevRange = 5000;
} break; }
case 11: { break;
case 11:
{
reply = 1; reply = 1;
Serial.println("Запрос No.11 - сработал. Калибровка. Установлен нулевой уровень"); SerialPrint("i", "Sensor Mhz19uart", "Запрос No.11 - сработал. Калибровка. Установлен нулевой уровень");
} break; }
break;
case 12: { case 12:
{
reply = 1; reply = 1;
Serial.println("Запрос No.12 - сработал. Сброс произошел"); SerialPrint("i", "Sensor Mhz19uart", "Запрос No.12 - сработал. Сброс произошел");
} break; }
break;
case 13: { case 13:
reply = 1; {
temperature = response[4] - 44; // - 40; temperature = response[4] - 44; // - 40;
reply = temperature;
Serial.println("Запрос No.12 - сработал. Температура получена"); // SerialPrint("i", "Sensor Mhz19uart", "Запрос No.13 - сработал. Температура получена - " + String(temperature));
Serial.println(temperature); // Serial.print("Запрос No.13 - сработал. Температура получена - ");
} break; // Serial.println(temperature);
}
break;
default: default:
// byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // byte c = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};

View File

@@ -2,7 +2,7 @@
"menuSection": "Сенсоры", "menuSection": "Сенсоры",
"configItem": [ "configItem": [
{ {
"name": "MHZ-19 CO2 (UART)", "name": "MHZ-19 CO2 UART",
"type": "Reading", "type": "Reading",
"subtype": "Mhz19uart", "subtype": "Mhz19uart",
"id": "co2uart", "id": "co2uart",
@@ -12,7 +12,7 @@
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 1, "round": 1,
"pin": 0, "warmUp": 120,
"rxPin": 13, "rxPin": 13,
"txPin": 12, "txPin": 12,
"int": 15, "int": 15,
@@ -20,7 +20,7 @@
"ABC": 1 "ABC": 1
}, },
{ {
"name": "MHZ-19 CO2 (PWM)", "name": "MHZ-19 CO2 PWM",
"type": "Reading", "type": "Reading",
"subtype": "Mhz19pwm", "subtype": "Mhz19pwm",
"id": "co2pwm", "id": "co2pwm",
@@ -30,11 +30,13 @@
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 1, "round": 1,
"warmUp": 120,
"pin": 15, "pin": 15,
"maxRetriesNotAvailable": 10,
"int": 300 "int": 300
}, },
{ {
"name": "Cенсор температуры от MHZ-19 UART", "name": "MHZ-19 Температура UART",
"type": "Reading", "type": "Reading",
"subtype": "Mhz19temp", "subtype": "Mhz19temp",
"id": "Mhz19temp", "id": "Mhz19temp",
@@ -46,64 +48,28 @@
"round": 1, "round": 1,
"rxPin": 13, "rxPin": 13,
"txPin": 12, "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 "int": 30
} }
], ],
"about": { "about": {
"authorName": "Alex K", "authorName": "Alex K",
"authorContact": "https://t.me/cmche", "authorContact": "https://t.me/cmche",
"authorGit": "", "authorGit": "https://github.com/CHE77/Mhz19forIotManager",
"specialThanks": "", "specialThanks": "",
"moduleName": "Mhz19", "moduleName": "Mhz19",
"moduleVersion": "1.0", "moduleVersion": "2.0 - можно переназначать пины",
"usedRam": 15, "moduleDesc": "Позволяет получить значения уровня концетрации CO2 с Mhz19 по UART и/или ШИМ. Замер по ШИМ может производить 1-2 сек. задержки",
"subTypes": [
"Mhz19uart",
"Mhz19pwm",
"Mhz19temp",
"Mhz19range",
"Mhz19ABC"
],
"title": "Датчик температуры и CO2 с Mhz19",
"moduleDesc": "Позволяет получить значения температуры и CO2 с Mhz19.",
"propInfo": { "propInfo": {
"plus": "поправочный коэффиент +c",
"multiply": "поправочный коэффиент k*",
"round": "округление",
"int": "Количество секунд между опросами датчика.", "int": "Количество секунд между опросами датчика.",
"rxPin": "", "rxPin": "Esp8266: GPIO 13 - D7, ESP32: GPIO 19 - RX1, > MHZ19: TXD зеленый провод",
"txPin": "", "txPin": "Esp8266: GPIO 12 - D6, ESP32: GPIO 18 - TX1, > MHZ19: RXD синий провод",
"range": "", "range": "Шкала по умолчанию 0-5000ppm. Также можно выбрать 2000",
"ABC": "" "ABC": "Автокалибровка. По умолчанию включена. Раз в сутки на 20 мин. надо выставлять на свежий воздух.",
"pin": "пин получения значений по ШИМ. Esp8266: GPIO 15 - D8, ESP32: GPIO 21, > MHZ19: PWM желтый провод",
"maxRetriesNotAvailable": "Максимальное количество попыток опроса сенсора по ШИМ. (может задерживать контроллер)"
} }
}, },
"defActive": false, "defActive": false,

View File

@@ -14,33 +14,50 @@ extern IoTGpio IoTgpio;
#include "SdsDustSensor.h" #include "SdsDustSensor.h"
//встроена в ядро для 8266, для 32 по этому же имени обращаемся к другой библиотеке plerup/EspSoftwareSerial //#define __DEBUG_SDS_DUST_SENSOR__
#include <SoftwareSerial.h>
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 #ifdef ESP32
#include <HardwareSerial.h> #include <HardwareSerial.h>
HardwareSerial sdsSerial(2); HardwareSerial sdsSerial(2);
SdsDustSensor sds(sdsSerial); // SdsDustSensor sds(sdsSerial);
#endif #endif
unsigned int warmUp; int retryDelayMs = 5;
unsigned int period; 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; bool SDS011_init_flag = true;
void SDS011_init(); void SDS011_init();
float Sds011request(int sensorID); void Sds011request(int sensorID);
IoTItem *item_Sds011_25 = nullptr; // pointer
IoTItem *item_Sds011_10 = nullptr;
//Это файл сенсора, в нем осуществляется чтение сенсора. //Это файл сенсора, в нем осуществляется чтение сенсора.
//для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора //для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора
//Название должно быть уникальным, коротким и отражать суть сенсора. //Название должно быть уникальным, коротким и отражать суть сенсора.
class Sds011_25 : public IoTItem { class Sds011_25 : public IoTItem
{
private: private:
//======================================================================================================= //=======================================================================================================
// Секция переменных. // Секция переменных.
@@ -55,14 +72,28 @@ class Sds011_25 : public IoTItem {
//Такие как ...begin и подставлять в них параметры полученные из web интерфейса. //Такие как ...begin и подставлять в них параметры полученные из web интерфейса.
//Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: //Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции:
// jsonReadStr, jsonReadBool, jsonReadInt // jsonReadStr, jsonReadBool, jsonReadInt
Sds011_25(String parameters) : IoTItem(parameters) { Sds011_25(String parameters) : IoTItem(parameters)
// _pin = jsonReadInt(parameters, "pin"); {
#ifdef ESP8266 item_Sds011_25 = this;
rxPinSDS = jsonReadInt(parameters, "rxPin"); rxPinSDS = jsonReadInt(parameters, "rxPin");
txPinSDS = jsonReadInt(parameters, "txPin"); txPinSDS = jsonReadInt(parameters, "txPin");
#endif
warmUp = jsonReadInt(parameters, "warmUp"); // сек. пробужнение должен быть больше purge = jsonReadInt(parameters, "purge"); // сек. пробужнение должен быть больше
period = jsonReadInt(parameters, "period"); // сек. время зарогрева/продувки, затем идут замеры 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() // doByInterval()
@@ -72,20 +103,21 @@ class Sds011_25 : public IoTItem {
//если у сенсора несколько величин то делайте несколько regEvent //если у сенсора несколько величин то делайте несколько regEvent
//не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции //не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции
//и выполнить за несколько тактов //и выполнить за несколько тактов
void doByInterval() { void doByInterval()
{
SDS011_init(); SDS011_init();
Serial.println("request from 25"); // SerialPrint("i", "Sensor Sds011", "Request for 2.5");
value.valD = Sds011request(25); Sds011request(25);
// value.valD = Sds011request(25);
regEvent(value.valD, "Sds011_25"); //обязательный вызов хотяб один // regEvent(value.valD, "Sds011_25"); //обязательный вызов хотяб один
} }
~Sds011_25(){}; ~Sds011_25(){};
}; };
//////////////////////////////////// for PM 10//= //////////////////////////////////// for PM 10//=
class Sds011_10 : public IoTItem { class Sds011_10 : public IoTItem
{
private: private:
//======================================================================================================= //=======================================================================================================
// Секция переменных. // Секция переменных.
@@ -95,18 +127,46 @@ class Sds011_10 : public IoTItem {
public: public:
//======================================================================================================= //=======================================================================================================
// setup() // setup()
//это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора.
//Такие как ...begin и подставлять в них параметры полученные из web интерфейса. Sds011_10(String parameters) : IoTItem(parameters)
//Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: {
// jsonReadStr, jsonReadBool, jsonReadInt item_Sds011_10 = this;
Sds011_10(String parameters) : IoTItem(parameters) {
// _pin = jsonReadInt(parameters, "pin");
#ifdef ESP8266
rxPinSDS = jsonReadInt(parameters, "rxPin"); rxPinSDS = jsonReadInt(parameters, "rxPin");
txPinSDS = jsonReadInt(parameters, "txPin"); txPinSDS = jsonReadInt(parameters, "txPin");
#endif
warmUp = jsonReadInt(parameters, "warmUp"); // сек. пробужнение должен быть больше purge = jsonReadInt(parameters, "purge"); // сек. пробужнение должен быть больше
period = jsonReadInt(parameters, "period"); // сек. время зарогрева/продувки, затем идут замеры 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() // doByInterval()
@@ -117,12 +177,13 @@ class Sds011_10 : public IoTItem {
//не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции //не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции
//и выполнить за несколько тактов //и выполнить за несколько тактов
void doByInterval() { void doByInterval()
{
SDS011_init(); SDS011_init();
Serial.println("request from 10"); // SerialPrint("i", "Sensor Sds011", "Request for 10ppm");
value.valD = Sds011request(10); Sds011request(10);
// value.valD = Sds011request(10);
regEvent(value.valD, "Sds011_10"); //обязательный вызов хотяб один // regEvent(value.valD, "Sds011_10"); //обязательный вызов хотяб один
} }
~Sds011_10(){}; ~Sds011_10(){};
}; };
@@ -130,71 +191,148 @@ class Sds011_10 : public IoTItem {
//после замены названия сенсора, на функцию можно не обращать внимания //после замены названия сенсора, на функцию можно не обращать внимания
//если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть //если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть
//создание и контроль соответствующих глобальных переменных //создание и контроль соответствующих глобальных переменных
void* getAPI_Sds011(String subtype, String param) { void *getAPI_Sds011(String subtype, String param)
if (subtype == F("Sds011_25")) { {
if (subtype == F("Sds011_25"))
{
return new Sds011_25(param); return new Sds011_25(param);
} else if (subtype == F("Sds011_10")) { }
else if (subtype == F("Sds011_10"))
{
return new Sds011_10(param); return new Sds011_10(param);
} else { }
else
{
return nullptr; return nullptr;
} }
} }
float Sds011request(int sensorID) { void Sds011request(int sensorID)
float reply = 0; {
static int a = 0; float pm25 = 0;
static float pm25 = 0; float pm10 = 0;
static float pm10 = 0;
static int startMillis = millis();
if (a == 0) { if (firstSensor == 0)
Serial.print("SDS011 ... warmUp = "); firstSensor = sensorID;
Serial.print(warmUp);
Serial.print(" period = "); if (firstSensor == sensorID)
Serial.println(period); {
sds.wakeup(); if (!continuous)
startMillis = millis(); {
a = a + 1; ts_sds.remove(PRINT);
ts_sds.remove(WAKEUP);
} }
if (a == 1 && millis() >= (startMillis + warmUp * 1000)) {
PmResult pm = sds.readPm(); PmResult pm = sds->readPm();
if (pm.isOk()) { // SerialPrint("i", "Sensor Sds011", "sds.readPm()");
if (pm.isOk())
{
pm25 = pm.pm25; pm25 = pm.pm25;
pm10 = pm.pm10; pm10 = pm.pm10;
Serial.print("PM2.5 = "); // SerialPrint("i", "Sensor Sds011", pm.toString());
Serial.print(pm25);
Serial.print(" PM10 = "); if (item_Sds011_25 && pm25)
Serial.println(pm10); {
a = a + 1; item_Sds011_25->value.valD = pm25;
sds.sleep(); item_Sds011_25->regEvent(item_Sds011_25->value.valD, "Sds011_25");
} else {
Serial.print("Could not read values from sensor 25, reason: ");
Serial.println(pm.statusToString());
a = a + 1;
}
}
if (a > 1 && millis() >= (startMillis + period * 1000)) {
Serial.println("end of period for pm25");
a = 0;
}
if (sensorID == 25) {
reply = pm25;
}
if (sensorID == 10) {
reply = pm10;
}
return reply;
} }
void SDS011_init() { if (item_Sds011_10 && pm10)
if (SDS011_init_flag) { {
sds.begin(); item_Sds011_10->value.valD = pm10;
Serial.println(sds.queryFirmwareVersion().toString()); // prints firmware version item_Sds011_10->regEvent(item_Sds011_10->value.valD, "Sds011_10");
// Serial.println(sds.setActiveReportingMode().toString()); // }
String ReportingMode = sds.setActiveReportingMode().toString(); }
Serial.println(ReportingMode); else
if (ReportingMode == "Mode: active") { {
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);
}
}
else
{
//пропускаем вызов от второго сенсора
}
return;
}
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; SDS011_init_flag = false;
if (continuous)
{
sds->wakeup();
SerialPrint("i", "Sensor Sds011", "wakeUp if continuous");
}
}
else
{
ReportingMode += " - check wiring!";
SerialPrint("E", "Sensor Sds011", ReportingMode);
} }
} }
} }

View File

@@ -2,7 +2,7 @@
"menuSection": "Сенсоры", "menuSection": "Сенсоры",
"configItem": [ "configItem": [
{ {
"name": "SDS011 PM25 Датчик пыли", "name": "SDS011 PM25 Пыль",
"type": "Reading", "type": "Reading",
"subtype": "Sds011_25", "subtype": "Sds011_25",
"id": "pmuart25", "id": "pmuart25",
@@ -12,14 +12,16 @@
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 10, "round": 10,
"rxPin": 13, "rxPin": 14,
"txPin": 12, "txPin": 16,
"int": 15, "int": 270,
"warmUp": 30, "purge": 30,
"period": 300 "continuousMode": 0,
"maxRetriesNotAvailable": 100,
"retryDelayMs": 5
}, },
{ {
"name": "SDS011 PM10 Датчик пыли", "name": "SDS011 PM10 Пыль",
"type": "Reading", "type": "Reading",
"subtype": "Sds011_10", "subtype": "Sds011_10",
"id": "pmuart10", "id": "pmuart10",
@@ -29,33 +31,34 @@
"plus": 0, "plus": 0,
"multiply": 1, "multiply": 1,
"round": 10, "round": 10,
"rxPin": 13, "rxPin": 14,
"txPin": 12, "txPin": 16,
"int": 15, "int": 270,
"warmUp": 30, "purge": 30,
"period": 300 "continuousMode": 0,
"maxRetriesNotAvailable": 100,
"retryDelayMs": 5
} }
], ],
"about": { "about": {
"authorName": "Alex K", "authorName": "Alex K",
"authorContact": "https://t.me/cmche", "authorContact": "https://t.me/cmche",
"authorGit": "", "authorGit": "https://github.com/CHE77/SDS011forIotManager",
"specialThanks": "", "specialThanks": "",
"moduleName": "Sds011", "moduleName": "Sds011",
"moduleVersion": "1.0", "moduleVersion": "2.0 - можно переназначать пины, за один опрос - обновляются два элемента",
"usedRam": 15,
"subTypes": [
"Sds011_25",
"Sds011_10"
],
"title": "Датчик пыли",
"moduleDesc": "Позволяет получить значения концентрации пыли в воздухе с Sds011.", "moduleDesc": "Позволяет получить значения концентрации пыли в воздухе с Sds011.",
"propInfo": { "propInfo": {
"int": "Количество секунд между опросами датчика.", "plus": "поправочный коэффиент +c",
"rxPin": "", "multiply": "поправочный коэффиент k*",
"txPin": "", "round": "округление",
"warmUp": "", "rxPin": "Esp8266: GPIO 14 - D5, ESP32: GPIO 16 - RX2, > подключаем к TXD сенсора",
"period": "" "txPin": "Esp8266: GPIO 16 - D0, ESP32: GPIO 17 - TX2, > подключаем к RXD сенсора",
"int": "Количество секунд между опросами датчика",
"purge": "Время продувки сенсора перед замером. Cек.",
"continuousMode": "1 - Непрерывный режим, 0 - Режим с остановкой (щедящий)",
"maxRetriesNotAvailable": "Количество попыток ожидания ответа сенсора при опросе (не нужно менять)",
"retryDelayMs": "Задержка между попытками, миллисекунды (не нужно менять)"
} }
}, },
"defActive": false, "defActive": false,