Skip to content

Commit

Permalink
Merge pull request #76 from matthias-bs/feature-lightning-postproc
Browse files Browse the repository at this point in the history
Feature lightning postproc
  • Loading branch information
matthias-bs authored Jul 23, 2023
2 parents 5c9d773 + b4c70e5 commit 55b6f94
Show file tree
Hide file tree
Showing 7 changed files with 873 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .vscode/arduino.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"configuration": "Revision=TTGO_LoRa32_v21new,FlashFreq=80,UploadSpeed=921600,DebugLevel=debug,EraseFlash=none",
"board": "esp32:esp32:ttgo-lora32",
"programmer": "esptool",
"sketch": "examples/BresserWeatherSensorBasic/BresserWeatherSensorBasic.ino"
}
26 changes: 26 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64"
},
{
"name": "Arduino",
"includePath": [
"${workspaceFolder}/**",
"/home/mp/Arduino/libraries/**"
],
"defines": [],
"intelliSenseMode": "${default}",
"configurationProvider": "vsciot-vscode.vscode-arduino"
}
],
"version": 4
}
181 changes: 181 additions & 0 deletions src/Lightning.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Lightning.cpp
//
// Post-processing of lightning sensor data
//
// Input:
// * Timestamp (time and date)
// * Sensor startup flag
// * Accumulated lightning event counter
// * Estimated distance of last strike
//
// Output:
// * Number of events during last update cycle
// * Timestamp of last event
// * Number of strikes during past 60 minutes
//
// Non-volatile data is stored in the ESP32's RTC RAM to allow retention during deep sleep mode.
//
// https://github.com/matthias-bs/BresserWeatherSensorReceiver
//
//
// created: 07/2023
//
//
// MIT License
//
// Copyright (c) 2023 Matthias Prinke
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// History:
//
// 20220721 Created
//
// ToDo:
// - Store non-volatile data in NVS Flash instead of RTC RAM
// (to support ESP8266 and to keep data during power-off)
//
///////////////////////////////////////////////////////////////////////////////////////////////////

#include <Arduino.h>
#include "Lightning.h"

#ifndef RTC_DATA_ATTR
#define RTC_DATA_ATTR static
#endif
#if !defined(ESP32)
#pragma message("Lightning with SLEEP_EN only supported on ESP32!")
#endif

/**
* \typedef nvData_t
*
* \brief Data structure for lightning sensor to be stored in non-volatile memory
*
* On ESP32, this data is stored in the RTC RAM.
*/
typedef struct {
/* Data of last lightning event */
int prevCount;
int events;
uint8_t distance;
time_t timestamp;

/* Data of past 60 minutes */
uint16_t hist[LIGHTNING_HIST_SIZE];

} nvLightning_t;

RTC_DATA_ATTR nvLightning_t nvLightning = {
.prevCount = -1,
.events = 0,
.distance = 0,
.timestamp = 0,
.hist = {0}
};

void
Lightning::reset(void)
{
nvLightning.prevCount = -1;
nvLightning.events = -1;
nvLightning.distance = 0;
nvLightning.timestamp = 0;
}

void
Lightning::init(uint16_t count)
{
for (int i=0; i<LIGHTNING_HIST_SIZE; i++) {
nvLightning.hist[i] = count;
}
}

void
Lightning::update(time_t timestamp, int count, uint8_t distance, bool startup)
{
// currently unused
(void)startup;

if (nvLightning.prevCount == -1) {
nvLightning.prevCount = count;
return;
}

if (nvLightning.prevCount < count) {
nvLightning.events = count - nvLightning.prevCount;
nvLightning.prevCount = count;
nvLightning.distance = distance;
nvLightning.timestamp = timestamp;
}


struct tm timeinfo;
localtime_r(&timestamp, &timeinfo);

int min = timeinfo.tm_min;
int idx = min / LIGHTNING_UPD_RATE;
nvLightning.hist[idx] = count;

// Search for skipped entries, i.e. entries which are smaller than their predecessor

for (int i=0; i<LIGHTNING_HIST_SIZE; i++) {
log_d("i=%d: hist[i]=%d\n", i, nvLightning.hist[i]);
if ((i == idx) || (i == inc(idx))) {
continue;
}
if (nvLightning.hist[i] < nvLightning.hist[dec(i)]) {
log_d("Marking %d as invalid\n", i);
nvLightning.hist[i] = -1;
}
}
log_d("\n");
}

bool
Lightning::lastEvent(time_t &timestamp, int &events, uint8_t &distance)
{
if (nvLightning.events == -1) {
return false;
}

events = nvLightning.events;
distance = nvLightning.distance;
timestamp = nvLightning.timestamp;

return true;
}

bool
Lightning::pastHour(time_t timestamp, int &events)
{
struct tm timeinfo;
localtime_r(&timestamp, &timeinfo);

int min = timeinfo.tm_min;
int idx = min / LIGHTNING_UPD_RATE;

if (nvLightning.hist[inc(idx)] == -1) {
log_d("Invalid\n");
return false;
}
events = nvLightning.hist[idx] - nvLightning.hist[inc(idx)];
return true;
}
171 changes: 171 additions & 0 deletions src/Lightning.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
// Lightning.h
//
// Post-processing of lightning sensor data
//
// Input:
// * Timestamp (time and date)
// * Sensor startup flag
// * Accumulated lightning event counter
// * Estimated distance of last strike
//
// Output:
// * Number of events during last update cycle
// * Timestamp of last event
// * Number of strikes during past 60 minutes (TBD)
//
// Non-volatile data is stored in the ESP32's RTC RAM to allow retention during deep sleep mode.
//
// https://github.com/matthias-bs/BresserWeatherSensorReceiver
//
//
// created: 07/2023
//
//
// MIT License
//
// Copyright (c) 2023 Matthias Prinke
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// History:
//
// 20220721 Created
//
// ToDo:
// - Store non-volatile data in NVS Flash instead of RTC RAM
// (to support ESP8266 and to keep data during power-off)
// - Handle sensor counter overflow and startup flag
// - Number of strikes during past 60 minutes
//
///////////////////////////////////////////////////////////////////////////////////////////////////

#include "time.h"
#if defined(ESP32) || defined(ESP8266)
#include <sys/time.h>
#endif

/**
* \def
*
* Set to the value which leads to a reset of the lightning sensor counter output to zero (overflow).
*/
#define LIGHTNINGCOUNT_MAX_VALUE 100

/**
* \def
*
* Lightning sensor update rate [min]
*/
#define LIGHTNING_UPD_RATE 6

/**
* \def
*
* Set to 3600 [sec] / update_rate_rate [sec]
*/
#define LIGHTNING_HIST_SIZE 10

/**
* \class Lightning
*
* \brief Calculation number of lightning events during last sensor update cycle and
* during last hour (past 60 minutes); storing timestamp and distance of last event.
*/
class Lightning {
public:
float countCurr;

Lightning() {};

/**
* Initialize/reset non-volatile data
*/
void reset(void);


/**
* Initialize memory for hourly (past 60 minutes) events
*
* \param count accumulated number of events
*/
void init(uint16_t count);


/**
* \fn update
*
* \brief Update lightning data
*
* \param timestamp timestamp (epoch)
*
* \param count accumulated number of events
*
* \param startup sensor startup flag
*
* \param lightningCountMax overflow value; when reached, the sensor's counter is reset to zero
*/
void update(time_t timestamp, int count, uint8_t distance, bool startup = false /*, uint16_t lightningCountMax = LIGHTNINGCOUNT_MAX */);


/**
* \fn pastHour
*
* \brief Get number of lightning events during past 60 minutes
*
* \param timestamp current time
* \param events return number of events during past 60 minutes
*
* \return true if valid
*/
bool pastHour(time_t timestamp, int &events);

/*
* \fn lastCycle
*
* \brief Get number of events during last update cycle with detected lightning events
*
* \return number of lightning events
*/
int lastCycle(void);

/*
* \fn lastEvent
*
* \brief Get data of last lightning event
*
* \param timestamp timestamp of last event
* \param events number of lightning strikes
* \param distance estimated distance
*
* \return true if valid
*/
bool lastEvent(time_t &timestamp, int &events, uint8_t &distance);

private:
inline int inc(int x)
{
return ((x + 1) == LIGHTNING_HIST_SIZE) ? 0 : ++x;
}

inline int dec(int x)
{
return (x == 0) ? (LIGHTNING_HIST_SIZE - 1) : --x;
}
};
1 change: 1 addition & 0 deletions test/header_overrides/Arduino.h
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#define RTC_DATA_ATTR static
#define log_d(...) { printf(__VA_ARGS__); }
Loading

0 comments on commit 55b6f94

Please sign in to comment.