diff --git a/docs/source/Plugin/P169.rst b/docs/source/Plugin/P169.rst index 08d24bf3b..9d2490a66 100644 --- a/docs/source/Plugin/P169.rst +++ b/docs/source/Plugin/P169.rst @@ -90,7 +90,7 @@ On the other hand, if the best calibration is significantly further off from the For example: * Metal parts mounted close to the antenna. -* Noisy environment. +* Noisy environment. (See also the reported noise level, as this should be around 2 or 3) * Unstable power supplied to the sensor. See the Wiring section below for more tips. @@ -161,6 +161,8 @@ The sensor can differentiate between signals that show the pattern characteristi Noise Floor ^^^^^^^^^^^ +Range: ``0`` .. ``7`` (default: ``2``) + The noise floor acts as a threshold to differentiate real signals from noise. When an interrupt signal for "noise floor threshold exceeded" is received, ESPEasy will increase the noise floor. @@ -169,12 +171,16 @@ When an interrupt signal for "noise floor threshold exceeded" is received, ESPEa Watchdog ^^^^^^^^ +Range: ``0`` .. ``15`` (default: ``2``) + This sets the duration for a signal to last before entering "Signal Validation" mode. Spike Rejection ^^^^^^^^^^^^^^^ -can be used to increase the robustness against false alarms from such disturbers. +Range: ``0`` .. ``15`` (default: ``2``) + +Can be used to increase the robustness against false alarms from such disturbers. Larger values correspond to more robust disturber rejection, yet with the drawback of a decrease in detection efficiency. @@ -190,6 +196,15 @@ Upon interrupt signals for either noise floor exceeded or disturbance detected, After 15 seconds ESPEasy will try to lower these values again to get as close as possible to the optimal settings. +Lightning Threshold +^^^^^^^^^^^^^^^^^^^ + +Values: ``1``, ``5``, ``9``, ``16`` (default: ``1``) + +This set minimum number of lightning events counted within 15 minutes must occur before the first "Lightning detected" interrupt is sent. +Once this threshold is passed, the sensor will resume its normal interrupt handling with an interrupt per detected lightning. + +This internal count will also be cleared when the internal statistics are cleared or when the sensor is put to sleep. (when the ESPEasy task is ended, the sensor is put to sleep) Wiring diff --git a/docs/source/Plugin/_plugin_sets_overview.repl b/docs/source/Plugin/_plugin_sets_overview.repl index 502e98244..04e06fcdc 100644 --- a/docs/source/Plugin/_plugin_sets_overview.repl +++ b/docs/source/Plugin/_plugin_sets_overview.repl @@ -197,26 +197,20 @@ Build set: :yellow:`COLLECTION B` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" - ":ref:`P007_page`","P007" - ":ref:`P008_page`","P008" - ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" ":ref:`P013_page`","P013" ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" - ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" - ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" - ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -227,9 +221,6 @@ Build set: :yellow:`COLLECTION B` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" - ":ref:`P040_page`","P040" - ":ref:`P041_page`","P041" - ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P045_page`","P045" @@ -307,26 +298,20 @@ Build set: :yellow:`COLLECTION C` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" - ":ref:`P007_page`","P007" - ":ref:`P008_page`","P008" - ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" ":ref:`P013_page`","P013" ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" - ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" - ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" - ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -337,9 +322,6 @@ Build set: :yellow:`COLLECTION C` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" - ":ref:`P040_page`","P040" - ":ref:`P041_page`","P041" - ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P045_page`","P045" @@ -513,20 +495,26 @@ Build set: :yellow:`COLLECTION E` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" + ":ref:`P007_page`","P007" + ":ref:`P008_page`","P008" + ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" ":ref:`P013_page`","P013" ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" + ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" + ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" + ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -537,6 +525,9 @@ Build set: :yellow:`COLLECTION E` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" + ":ref:`P040_page`","P040" + ":ref:`P041_page`","P041" + ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P045_page`","P045" @@ -723,20 +714,26 @@ Build set: :yellow:`COLLECTION G` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" + ":ref:`P007_page`","P007" + ":ref:`P008_page`","P008" + ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" ":ref:`P013_page`","P013" ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" + ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" + ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" + ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -747,6 +744,9 @@ Build set: :yellow:`COLLECTION G` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" + ":ref:`P040_page`","P040" + ":ref:`P041_page`","P041" + ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P045_page`","P045" @@ -907,26 +907,20 @@ Build set: :yellow:`DISPLAY` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" - ":ref:`P007_page`","P007" - ":ref:`P008_page`","P008" - ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" ":ref:`P013_page`","P013" ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" - ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" - ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" - ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -937,9 +931,6 @@ Build set: :yellow:`DISPLAY` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" - ":ref:`P040_page`","P040" - ":ref:`P041_page`","P041" - ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P049_page`","P049" @@ -1077,6 +1068,9 @@ Build set: :yellow:`IR` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" + ":ref:`P007_page`","P007" + ":ref:`P008_page`","P008" + ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" @@ -1084,14 +1078,17 @@ Build set: :yellow:`IR` ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" ":ref:`P016_page`","P016" + ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" + ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" + ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -1103,6 +1100,9 @@ Build set: :yellow:`IR` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" + ":ref:`P040_page`","P040" + ":ref:`P041_page`","P041" + ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P049_page`","P049" @@ -1143,20 +1143,26 @@ Build set: :yellow:`IRext` ":ref:`P004_page`","P004" ":ref:`P005_page`","P005" ":ref:`P006_page`","P006" + ":ref:`P007_page`","P007" + ":ref:`P008_page`","P008" + ":ref:`P009_page`","P009" ":ref:`P010_page`","P010" ":ref:`P011_page`","P011" ":ref:`P012_page`","P012" ":ref:`P013_page`","P013" ":ref:`P014_page`","P014" ":ref:`P015_page`","P015" + ":ref:`P017_page`","P017" ":ref:`P018_page`","P018" ":ref:`P019_page`","P019" ":ref:`P020_page`","P020" ":ref:`P021_page`","P021" + ":ref:`P022_page`","P022" ":ref:`P023_page`","P023" ":ref:`P024_page`","P024" ":ref:`P025_page`","P025" ":ref:`P026_page`","P026" + ":ref:`P027_page`","P027" ":ref:`P028_page`","P028" ":ref:`P029_page`","P029" ":ref:`P031_page`","P031" @@ -1167,6 +1173,9 @@ Build set: :yellow:`IRext` ":ref:`P037_page`","P037" ":ref:`P038_page`","P038" ":ref:`P039_page`","P039" + ":ref:`P040_page`","P040" + ":ref:`P041_page`","P041" + ":ref:`P042_page`","P042" ":ref:`P043_page`","P043" ":ref:`P044_page`","P044" ":ref:`P049_page`","P049" diff --git a/src/_P169_AS3935_LightningDetector.ino b/src/_P169_AS3935_LightningDetector.ino index 657df30af..df1ea9c99 100644 --- a/src/_P169_AS3935_LightningDetector.ino +++ b/src/_P169_AS3935_LightningDetector.ino @@ -212,7 +212,6 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) break; } - case PLUGIN_TEN_PER_SECOND: { P169_data_struct *P169_data = static_cast(getPluginTaskData(event->TaskIndex)); @@ -223,6 +222,29 @@ boolean Plugin_169(uint8_t function, struct EventStruct *event, String& string) } break; } + + case PLUGIN_WRITE: + { + P169_data_struct *P169_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P169_data) { + success = P169_data->plugin_write(event, string); + } + + break; + } + + case PLUGIN_GET_CONFIG_VALUE: + { + P169_data_struct *P169_data = static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P169_data) { + success = P169_data->plugin_get_config_value(event, string); + } + + break; + } + } return success; diff --git a/src/src/PluginStructs/P169_data_struct.cpp b/src/src/PluginStructs/P169_data_struct.cpp index bee6816be..c7ab3559c 100644 --- a/src/src/PluginStructs/P169_data_struct.cpp +++ b/src/src/PluginStructs/P169_data_struct.cpp @@ -53,6 +53,12 @@ bool P169_data_struct::loop(struct EventStruct *event) { // Lightning detected ++_lightningCount; + + // FIXME TD-er: What to do with the "Lightning Threshold" ? + // If it was > 15 minutes ago since the last detected lightning, + // or cleared statistics, then we should set _lightningCount to this + // threshold value and also increment the total counter accordingly. + const int totalStrikes = UserVar.getFloat(event->TaskIndex, 3) + 1; const int distance = getDistance(); const uint32_t energy = getEnergy(); @@ -195,39 +201,7 @@ bool P169_data_struct::plugin_init(struct EventStruct *event) } */ - // calibrate the resonance frequency. failing the resonance frequency could indicate an issue - // of the sensor. - int32_t frequency = 0; - - _sensor.setCalibrateAllAntCap(P169_GET_SLOW_LCO_CALIBRATION); - - _sensor.setFrequencyMeasureNrSamples(P169_GET_SLOW_LCO_CALIBRATION ? AS3935MI_NR_CALIBRATION_SAMPLES : (AS3935MI_NR_CALIBRATION_SAMPLES / 2)); - - if (!_sensor.calibrateResonanceFrequency(frequency)) - { - if (loglevelActiveFor(LOG_LEVEL_ERROR)) { - addLog(LOG_LEVEL_ERROR, - strformat(F("AS3935: Resonance Frequency Calibration failed: %d Hz not in range 482500 Hz ... 517500 Hz"), frequency)); - } - } else { - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, - strformat(F("AS3935: Resonance Frequency Calibration passed: ant_cap: %d, %d Hz, deviation: %.2f%%"), - _sensor.readAntennaTuning(), - frequency, computeDeviationPct(frequency))); - } - } - - // calibrate the RCO. - if (!_sensor.calibrateRCO()) - { - addLog(LOG_LEVEL_ERROR, F("AS3935: RCO Calibration failed.")); - } else { - addLog(LOG_LEVEL_INFO, F("AS3935: RCO Calibration passed.")); - } - - // stop displaying LCO on IRQ - _sensor.displayLcoOnIrq(false); + calibrate(event); # ifdef ESP32 @@ -290,9 +264,90 @@ bool P169_data_struct::plugin_init(struct EventStruct *event) return true; } -bool P169_data_struct::plugin_write(struct EventStruct *event, String& string) -{ - return true; +const char subcommands[] PROGMEM = "clearstats|calibrate|setnf|setwd|setsrej"; + +enum class subcmd_e : int8_t { + invalid = -1, + clearstats = 0, + calibrate, + setnf, // Set noise floor + setwd, // Set Watchdog Threshold + setsrej // Set Spike Rejection +}; + +/***************************************************** +* plugin_write +*****************************************************/ +bool P169_data_struct::plugin_write(struct EventStruct *event, + String & string) { + bool success = false; + + const String command = parseString(string, 1); + + if (equals(command, F("as3935"))) { + const String subcommand = parseString(string, 2); + const int subcommand_i = GetCommandCode(subcommand.c_str(), subcommands); + + if (subcommand_i < 0) { return false; } // Fail fast + + const subcmd_e subcmd = static_cast(subcommand_i); + uint32_t value{}; + const bool hasValue = validUIntFromString(parseString(string, 3), value); + + switch (subcmd) { + case subcmd_e::invalid: + break; + case subcmd_e::clearstats: + clearStatistics(); + success = true; + break; + case subcmd_e::calibrate: + calibrate(event); + success = true; + break; + case subcmd_e::setnf: + if (hasValue) { + success = true; + _sensor.writeNoiseFloorThreshold(value); + } + break; + case subcmd_e::setwd: + if (hasValue) { + success = true; + _sensor.writeWatchdogThreshold(value); + } + break; + case subcmd_e::setsrej: + if (hasValue) { + success = true; + _sensor.writeSpikeRejection(value); + } + break; + } + } + return success; +} + +/***************************************************** +* plugin_get_config_value +*****************************************************/ +bool P169_data_struct::plugin_get_config_value(struct EventStruct *event, + String & string) { + bool success = false; + + const String var = parseString(string, 1); + + if (equals(var, F("noisefloor"))) { // [#noisefloor] + string = _sensor.readNoiseFloorThreshold(); + success = true; + } else if (equals(var, F("watchdog"))) { // [#watchdog] + string = _sensor.readWatchdogThreshold(); + success = true; + } else if (equals(var, F("srej"))) { // [#srej] = current spike rejection + string = _sensor.readSpikeRejection(); + success = true; + } + return success; } int P169_data_struct::getDistance() @@ -326,6 +381,49 @@ float P169_data_struct::computeDeviationPct(uint32_t LCO_freq) return (LCO_freq / 5000.0f) - 100.0f; } +bool P169_data_struct::calibrate(struct EventStruct *event) +{ + _sensor.setInterruptMode(AS3935MI::AS3935_INTERRUPT_DETACHED); + + + // calibrate the resonance frequency. failing the resonance frequency could indicate an issue + // of the sensor. + int32_t frequency = 0; + + _sensor.setCalibrateAllAntCap(P169_GET_SLOW_LCO_CALIBRATION); + + _sensor.setFrequencyMeasureNrSamples(P169_GET_SLOW_LCO_CALIBRATION ? AS3935MI_NR_CALIBRATION_SAMPLES : (AS3935MI_NR_CALIBRATION_SAMPLES / + 2)); + + if (!_sensor.calibrateResonanceFrequency(frequency)) + { + if (loglevelActiveFor(LOG_LEVEL_ERROR)) { + addLog(LOG_LEVEL_ERROR, + strformat(F("AS3935: Resonance Frequency Calibration failed: %d Hz not in range 482500 Hz ... 517500 Hz"), frequency)); + } + } else { + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, + strformat(F("AS3935: Resonance Frequency Calibration passed: ant_cap: %d, %d Hz, deviation: %.2f%%"), + _sensor.readAntennaTuning(), + frequency, computeDeviationPct(frequency))); + } + } + + // calibrate the RCO. + if (!_sensor.calibrateRCO()) + { + addLog(LOG_LEVEL_ERROR, F("AS3935: RCO Calibration failed.")); + } else { + addLog(LOG_LEVEL_INFO, F("AS3935: RCO Calibration passed.")); + } + + // stop displaying LCO on IRQ + _sensor.displayLcoOnIrq(false); + + return frequency != 0; +} + void P169_data_struct::adjustForNoise(struct EventStruct *event) { // if the noise floor threshold setting is not yet maxed out, increase the setting. diff --git a/src/src/PluginStructs/P169_data_struct.h b/src/src/PluginStructs/P169_data_struct.h index 3b8bd2660..7895eabd5 100644 --- a/src/src/PluginStructs/P169_data_struct.h +++ b/src/src/PluginStructs/P169_data_struct.h @@ -27,11 +27,11 @@ # define P169_LIGHTNING_THRESHOLD_LABEL PCONFIG_LABEL(1) # define P169_GET_INDOOR bitRead(PCONFIG(2), 0) -# define P169_SET_INDOOR(X) bitWrite(PCONFIG(2), 0, X) +# define P169_SET_INDOOR(X) bitWrite(PCONFIG(2), 0, X) # define P169_INDOOR_LABEL "mode" # define P169_GET_MASK_DISTURBANCE bitRead(PCONFIG(2), 1) -# define P169_SET_MASK_DISTURBANCE(X) bitWrite(PCONFIG(2), 1, X) +# define P169_SET_MASK_DISTURBANCE(X) bitWrite(PCONFIG(2), 1, X) # define P169_MASK_DISTURBANCE_LABEL "maskdist" # define P169_GET_SEND_ONLY_ON_LIGHTNING bitRead(PCONFIG(2), 2) @@ -71,6 +71,9 @@ public: bool plugin_write(struct EventStruct *event, String & string); + bool plugin_get_config_value(struct EventStruct *event, + String & string); + void html_show_sensor_info(struct EventStruct *event); // Read distance in km @@ -87,12 +90,14 @@ public: // Clear lightning distance estimation statistics - void clearStatistics(); + void clearStatistics(); private: static float computeDeviationPct(uint32_t LCO_freq); + bool calibrate(struct EventStruct *event); + void adjustForNoise(struct EventStruct *event); void adjustForDisturbances(struct EventStruct *event);