2022-03-07 11:54:25 +03:00
/******************************************************************
Supports Sds011 , implements whole Laser Dust Sensor Control Protocol V1 .3 ,
should also work with other Sds sensors .
https : //github.com/lewapek/sds-dust-sensors-arduino-library
2022-03-15 12:56:05 +01:00
2022-03-07 11:54:25 +03:00
adapted for version 4 @ cmche
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "Global.h"
# include "classes/IoTItem.h"
extern IoTGpio IoTgpio ;
# include "SdsDustSensor.h"
2022-03-15 12:56:05 +01:00
//встроена в ядро для 8266, для 32 по этому же имени обращаемся к другой библиотеке plerup/EspSoftwareSerial
# include <SoftwareSerial.h>
2022-03-15 15:59:26 +01:00
// to do убрать глобальный экземпляр
2022-03-15 12:56:05 +01:00
# ifdef ESP8266
int rxPinSDS = 13 ; // D7 – подключаем к Tx сенсора
int txPinSDS = 12 ; // D6 – подключаем к Rx сенсора
2022-03-07 11:54:25 +03:00
SdsDustSensor sds ( rxPinSDS , txPinSDS ) ;
2022-03-15 12:56:05 +01:00
# endif
# ifdef ESP32
# include <HardwareSerial.h>
HardwareSerial sdsSerial ( 2 ) ;
SdsDustSensor sds ( sdsSerial ) ;
# endif
2022-03-07 11:54:25 +03:00
unsigned int warmUp ;
unsigned int period ;
bool SDS011_init_flag = true ;
void SDS011_init ( ) ;
float Sds011request ( int sensorID ) ;
//Это файл сенсора, в нем осуществляется чтение сенсора.
//для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора
//Название должно быть уникальным, коротким и отражать суть сенсора.
2022-03-15 12:56:05 +01:00
class Sds011_25 : public IoTItem {
private :
2022-03-07 11:54:25 +03:00
//=======================================================================================================
// Секция переменных.
//Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы
//впоследствии использовать их в loop и setup
// unsigned int _pin;
2022-03-15 12:56:05 +01:00
public :
2022-03-07 11:54:25 +03:00
//=======================================================================================================
// setup()
//это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора.
//Такие как ...begin и подставлять в них параметры полученные из web интерфейса.
//В с е параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции:
// jsonReadStr, jsonReadBool, jsonReadInt
2022-03-15 12:56:05 +01:00
Sds011_25 ( String parameters ) : IoTItem ( parameters ) {
2022-03-07 11:54:25 +03:00
// _pin = jsonReadInt(parameters, "pin");
2022-03-15 12:56:05 +01:00
# ifdef ESP8266
2022-03-07 11:54:25 +03:00
rxPinSDS = jsonReadInt ( parameters , " rxPin " ) ;
txPinSDS = jsonReadInt ( parameters , " txPin " ) ;
2022-03-15 12:56:05 +01:00
# endif
warmUp = jsonReadInt ( parameters , " warmUp " ) ; // сек. пробужнение должен быть больше
period = jsonReadInt ( parameters , " period " ) ; // сек. время зарогрева/продувки, затем идут замеры
2022-03-07 11:54:25 +03:00
}
//=======================================================================================================
// doByInterval()
//это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора
//а затем выполнить regEvent - это регистрация произошедшего события чтения
//здесь так же доступны все переменные из секции переменных, и полученные в setup
//если у сенсора несколько величин то делайте несколько regEvent
//не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить е е на порции
//и выполнить за несколько тактов
2022-03-15 12:56:05 +01:00
void doByInterval ( ) {
2022-03-07 11:54:25 +03:00
SDS011_init ( ) ;
Serial . println ( " request from 25 " ) ;
value . valD = Sds011request ( 25 ) ;
2022-03-15 12:56:05 +01:00
regEvent ( value . valD , " Sds011_25 " ) ; //обязательный вызов хотяб один
2022-03-07 11:54:25 +03:00
}
2022-03-15 12:56:05 +01:00
~ Sds011_25 ( ) { } ;
2022-03-07 11:54:25 +03:00
} ;
//////////////////////////////////// for PM 10//=
2022-03-15 12:56:05 +01:00
class Sds011_10 : public IoTItem {
private :
2022-03-07 11:54:25 +03:00
//=======================================================================================================
// Секция переменных.
//Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы
//впоследствии использовать их в loop и setup
2022-03-15 12:56:05 +01:00
public :
2022-03-07 11:54:25 +03:00
//=======================================================================================================
// setup()
//это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора.
//Такие как ...begin и подставлять в них параметры полученные из web интерфейса.
//В с е параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции:
// jsonReadStr, jsonReadBool, jsonReadInt
2022-03-15 12:56:05 +01:00
Sds011_10 ( String parameters ) : IoTItem ( parameters ) {
// _pin = jsonReadInt(parameters, "pin");
# ifdef ESP8266
2022-03-07 11:54:25 +03:00
rxPinSDS = jsonReadInt ( parameters , " rxPin " ) ;
txPinSDS = jsonReadInt ( parameters , " txPin " ) ;
2022-03-15 12:56:05 +01:00
# endif
warmUp = jsonReadInt ( parameters , " warmUp " ) ; // сек. пробужнение должен быть больше
period = jsonReadInt ( parameters , " period " ) ; // сек. время зарогрева/продувки, затем идут замеры
2022-03-07 11:54:25 +03:00
}
//=======================================================================================================
// doByInterval()
//это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора
//а затем выполнить regEvent - это регистрация произошедшего события чтения
//здесь так же доступны все переменные из секции переменных, и полученные в setup
//если у сенсора несколько величин то делайте несколько regEvent
//не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить е е на порции
//и выполнить за несколько тактов
2022-03-15 12:56:05 +01:00
void doByInterval ( ) {
2022-03-07 11:54:25 +03:00
SDS011_init ( ) ;
Serial . println ( " request from 10 " ) ;
value . valD = Sds011request ( 10 ) ;
2022-03-15 12:56:05 +01:00
regEvent ( value . valD , " Sds011_10 " ) ; //обязательный вызов хотяб один
2022-03-07 11:54:25 +03:00
}
2022-03-15 12:56:05 +01:00
~ Sds011_10 ( ) { } ;
2022-03-07 11:54:25 +03:00
} ;
//после замены названия сенсора, на функцию можно не обращать внимания
//если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть
//создание и контроль соответствующих глобальных переменных
2022-03-15 12:56:05 +01:00
void * getAPI_Sds011 ( String subtype , String param ) {
if ( subtype = = F ( " Sds011_25 " ) ) {
2022-03-07 11:54:25 +03:00
return new Sds011_25 ( param ) ;
2022-03-15 12:56:05 +01:00
} else if ( subtype = = F ( " Sds011_10 " ) ) {
2022-03-07 11:54:25 +03:00
return new Sds011_10 ( param ) ;
2022-03-15 12:56:05 +01:00
} else {
2022-03-07 11:54:25 +03:00
return nullptr ;
}
}
2022-03-15 12:56:05 +01:00
float Sds011request ( int sensorID ) {
2022-03-07 11:54:25 +03:00
float reply = 0 ;
static int a = 0 ;
static float pm25 = 0 ;
static float pm10 = 0 ;
static int startMillis = millis ( ) ;
2022-03-15 12:56:05 +01:00
if ( a = = 0 ) {
2022-03-07 11:54:25 +03:00
Serial . print ( " SDS011 ... warmUp = " ) ;
Serial . print ( warmUp ) ;
Serial . print ( " period = " ) ;
Serial . println ( period ) ;
sds . wakeup ( ) ;
startMillis = millis ( ) ;
a = a + 1 ;
}
2022-03-15 12:56:05 +01:00
if ( a = = 1 & & millis ( ) > = ( startMillis + warmUp * 1000 ) ) {
2022-03-07 11:54:25 +03:00
PmResult pm = sds . readPm ( ) ;
2022-03-15 12:56:05 +01:00
if ( pm . isOk ( ) ) {
2022-03-07 11:54:25 +03:00
pm25 = pm . pm25 ;
pm10 = pm . pm10 ;
Serial . print ( " PM2.5 = " ) ;
Serial . print ( pm25 ) ;
Serial . print ( " PM10 = " ) ;
Serial . println ( pm10 ) ;
a = a + 1 ;
sds . sleep ( ) ;
2022-03-15 12:56:05 +01:00
} else {
2022-03-07 11:54:25 +03:00
Serial . print ( " Could not read values from sensor 25, reason: " ) ;
Serial . println ( pm . statusToString ( ) ) ;
a = a + 1 ;
}
}
2022-03-15 12:56:05 +01:00
if ( a > 1 & & millis ( ) > = ( startMillis + period * 1000 ) ) {
2022-03-07 11:54:25 +03:00
Serial . println ( " end of period for pm25 " ) ;
a = 0 ;
}
2022-03-15 12:56:05 +01:00
if ( sensorID = = 25 ) {
2022-03-07 11:54:25 +03:00
reply = pm25 ;
}
2022-03-15 12:56:05 +01:00
if ( sensorID = = 10 ) {
2022-03-07 11:54:25 +03:00
reply = pm10 ;
}
return reply ;
}
2022-03-15 12:56:05 +01:00
void SDS011_init ( ) {
if ( SDS011_init_flag ) {
2022-03-07 11:54:25 +03:00
sds . begin ( ) ;
2022-03-15 12:56:05 +01:00
Serial . println ( sds . queryFirmwareVersion ( ) . toString ( ) ) ; // prints firmware version
// Serial.println(sds.setActiveReportingMode().toString()); //
2022-03-07 11:54:25 +03:00
String ReportingMode = sds . setActiveReportingMode ( ) . toString ( ) ;
Serial . println ( ReportingMode ) ;
2022-03-15 12:56:05 +01:00
if ( ReportingMode = = " Mode: active " ) {
2022-03-07 11:54:25 +03:00
SDS011_init_flag = false ;
}
}
}