From 1f268bbf39edfc65135767ba6c4256f88b5b5cba Mon Sep 17 00:00:00 2001 From: Bastian Urschel Date: Thu, 17 Oct 2019 13:10:43 +0200 Subject: [PATCH] Changed the type for getting sensor values to polling. Before we used the "working period" method (the sensor starts/stops periodically on it's own and reports the data if Tasmota asks for values). Because of that I've detected a drift after some time which means that you don't get current values if "tele_period" is reached. Another point was that the "working period" method only allows a frequency above 1 minute. The new code starts the sensor directly (with commands sleep and work) if we reached a time we set in define "STARTING_OFFSET". 5 seconds before tele_period, we are doing 4 measurements, calculate the average and current values are present if tele_period is reached. The new method allows us also to get a polling frequency below 1 minute (usable for early fire detection). For precise measurements values of STARTING_OFFSET above 30 seconds are recommended. If using STARTING_OFFSET of 30 seconds and tele_period of 30 seconds the sensor now runs permanent. Fixed also wrong values at defines NOVA_SDS_SLEEP and NOVA_SDS_WORK. --- sonoff/my_user_config.h | 4 +-- sonoff/xsns_20_novasds.ino | 69 +++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 0e25ea3ed..d205335d5 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -429,8 +429,8 @@ #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) -#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) - #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes +#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+1k5 code) + #define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index ec6369a28..a434e56a3 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -31,14 +31,11 @@ #include -#ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 // NodaSDS sleep working period in minutes +#ifndef STARTING_OFFSET +#define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached #endif -#ifndef NOVA_SDS_REINIT_CHECK -#define NOVA_SDS_REINIT_CHECK 80 // NodaSDS reinitalized check in seconds -#endif -#ifndef NOVA_SDS_QUERY_INTERVAL -#define NOVA_SDS_QUERY_INTERVAL 3 // NodaSDS query interval in seconds +#if STARTING_OFFSET < 10 +#error "Please set STARTING_OFFSET >= 10" #endif #ifndef NOVA_SDS_RECDATA_TIMEOUT #define NOVA_SDS_RECDATA_TIMEOUT 150 // NodaSDS query data timeout in ms @@ -51,11 +48,14 @@ TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; +uint8_t cont_mode = 1; struct sds011data { uint16_t pm100; uint16_t pm25; } novasds_data; +uint16_t pm100_sum; +uint16_t pm25_sum; // NovaSDS commands #define NOVA_SDS_REPORTING_MODE 2 // Cmnd "data reporting mode" @@ -68,8 +68,8 @@ struct sds011data { #define NOVA_SDS_SET_MODE 1 // Subcmnd "set mode" #define NOVA_SDS_REPORT_ACTIVE 0 // Subcmnd "report active mode" - Sensor received query data command to report a measurement data #define NOVA_SDS_REPORT_QUERY 1 // Subcmnd "report query mode" - Sensor automatically reports a measurement data in a work period - #define NOVA_SDS_WORK 0 // Subcmnd "work mode" - #define NOVA_SDS_SLEEP 1 // Subcmnd "sleep mode" + #define NOVA_SDS_SLEEP 0 // Subcmnd "sleep mode" + #define NOVA_SDS_WORK 1 // Subcmnd "work mode" bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) @@ -124,10 +124,10 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor void NovaSdsSetWorkPeriod(void) { - // set sensor working period - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, Settings.novasds_period, NOVA_SDS_DEVICE_ID, nullptr); - // set sensor report only on query - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); + // set sensor working period to default + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, 0, NOVA_SDS_DEVICE_ID, nullptr); + // set sensor report on query + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); } bool NovaSdsReadData(void) @@ -146,19 +146,40 @@ bool NovaSdsReadData(void) void NovaSdsSecond(void) // Every second { - if (0 == (uptime % NOVA_SDS_REINIT_CHECK)) { - if (!novasds_valid) { - NovaSdsSetWorkPeriod(); - } - } else if (0 == (uptime % NOVA_SDS_QUERY_INTERVAL)) { - if (NovaSdsReadData()) { - novasds_valid = 10; - } else { - if (novasds_valid) { - novasds_valid--; - } + if (!novasds_valid) + { //communication problem, reinit + NovaSdsSetWorkPeriod(); + novasds_valid=1; + } + if((Settings.tele_period - STARTING_OFFSET <= 0)) + { + if(!cont_mode) + { //switched to continuous mode + cont_mode = 1; + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); } } + else + cont_mode = 0; + + if(tele_period == Settings.tele_period - STARTING_OFFSET && !cont_mode) + { //lets start fan and laser + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); + } + if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) + { //we are doing 4 measurements here + if(!(NovaSdsReadData())) novasds_valid=0; + pm100_sum += novasds_data.pm100; + pm25_sum += novasds_data.pm25; + } + if(tele_period == Settings.tele_period-1) + { //calculate the average of 4 measuremens + novasds_data.pm100 = pm100_sum >> 2; + novasds_data.pm25 = pm25_sum >> 2; + if(!cont_mode) + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_SLEEP, NOVA_SDS_DEVICE_ID, nullptr); //stop fan and laser + pm100_sum = pm25_sum = 0; + } } /*********************************************************************************************\