4 Ревизии

Автор SHA1 Съобщение Дата
  Thomas Buck 3777cef70d date time printing on lorarx and auto reset преди 3 месеца
  Thomas Buck 9e7fd20188 lora tx goes to deep sleep преди 3 месеца
  Thomas Buck 24c671bf83 lora transmitter never needs to receive. also dont light bright white led to save more power. преди 3 месеца
  Thomas Buck 7211a8d1ca consolidate redundant sml energy fields преди 3 месеца
променени са 9 файла, в които са добавени 156 реда и са изтрити 59 реда
  1. 6
    0
      include/config.h
  2. 2
    0
      include/smart_meter.h
  3. 10
    0
      include/ui.h
  4. 2
    0
      platformio.ini
  5. 9
    0
      src/influx.cpp
  6. 37
    7
      src/lora.cpp
  7. 5
    0
      src/main.cpp
  8. 38
    11
      src/smart_meter.cpp
  9. 47
    41
      src/ui.cpp

+ 6
- 0
include/config.h Целия файл

@@ -57,6 +57,12 @@
57 57
 #define LED_ERROR_BLINK_INTERVAL 100
58 58
 #define MQTT_RECONNECT_INTERVAL (5 * 1000)
59 59
 
60
+#define NTP_SERVER "pool.ntp.org"
61
+// TODO auto-detect?!
62
+//#warning hard-coded timezone and daylight savings offset
63
+#define gmtOffset_sec (60 * 60)
64
+#define daylightOffset_sec (60 * 60)
65
+
60 66
 #if defined(SENSOR_LOCATION_LIVINGROOM)
61 67
 #define SENSOR_LOCATION "livingroom"
62 68
 #define SENSOR_ID SENSOR_LOCATION

+ 2
- 0
include/smart_meter.h Целия файл

@@ -19,6 +19,8 @@
19 19
 void sml_init(void);
20 20
 void sml_run(void);
21 21
 
22
+bool sml_data_received(void);
23
+
22 24
 #endif // FEATURE_SML
23 25
 
24 26
 #endif // __ESP_ENV_SMART_METER__

+ 10
- 0
include/ui.h Целия файл

@@ -14,6 +14,14 @@
14 14
 #ifndef __UI_H__
15 15
 #define __UI_H__
16 16
 
17
+#ifdef FEATURE_NTP
18
+#include <time.h>
19
+String time_to_date_str(struct tm timeinfo);
20
+String time_to_time_str(struct tm timeinfo);
21
+#endif // FEATURE_NTP
22
+
23
+#ifdef FEATURE_UI
24
+
17 25
 enum bathroom_light_states {
18 26
     BATH_LIGHT_OFF,
19 27
     BATH_LIGHT_NONE,
@@ -52,4 +60,6 @@ void ui_run(void);
52 60
 
53 61
 void ui_progress(enum ui_state state);
54 62
 
63
+#endif // FEATURE_UI
64
+
55 65
 #endif // __UI_H__

+ 2
- 0
platformio.ini Целия файл

@@ -28,6 +28,7 @@ build_flags =
28 28
   -DUSER_SETUP_LOADED=1
29 29
   -include include/User_Setup.h
30 30
   -DDISABLE_ALL_LIBRARY_WARNINGS
31
+  -DFEATURE_NTP
31 32
 lib_ldf_mode = deep
32 33
 lib_deps =
33 34
     https://github.com/knolleary/pubsubclient.git#2d228f2f862a95846c65a8518c79f48dfc8f188c
@@ -82,6 +83,7 @@ build_flags =
82 83
   -DFEATURE_LORA
83 84
   -DENABLE_INFLUXDB_LOGGING
84 85
   -DUSE_INFLUXDB_LIB
86
+  -DFEATURE_NTP
85 87
 lib_deps =
86 88
     ESP8266 Influxdb
87 89
     https://github.com/knolleary/pubsubclient.git#2d228f2f862a95846c65a8518c79f48dfc8f188c

+ 9
- 0
src/influx.cpp Целия файл

@@ -18,6 +18,7 @@
18 18
 #include "sensors.h"
19 19
 #include "relais.h"
20 20
 #include "moisture.h"
21
+#include "ui.h"
21 22
 #include "influx.h"
22 23
 
23 24
 #ifdef ENABLE_INFLUXDB_LOGGING
@@ -129,6 +130,14 @@ void writeSensorDatum(String measurement, String sensor, String placement, Strin
129 130
     debug.print(" ");
130 131
     debug.printf("%.2lf\n", value);
131 132
     writeMeasurement(ms);
133
+
134
+#ifdef FEATURE_NTP
135
+    struct tm timeinfo;
136
+    if (getLocalTime(&timeinfo)) {
137
+        debug.print(time_to_time_str(timeinfo) + " ");
138
+    }
139
+#endif // FEATURE_NTP
140
+
132 141
     debug.println(F("Done!"));
133 142
 }
134 143
 

+ 37
- 7
src/lora.cpp Целия файл

@@ -16,21 +16,28 @@
16 16
 #include <Arduino.h>
17 17
 
18 18
 // Turns the 'PRG' button into the power button, long press is off
19
+// this also increases deep sleep power usage!
20
+#ifndef FEATURE_SML
19 21
 #define HELTEC_POWER_BUTTON
22
+#endif // ! FEATURE_SML
20 23
 
21 24
 #include <heltec_unofficial.h>
22 25
 
23 26
 #include "config.h"
24 27
 #include "DebugLog.h"
25 28
 #include "influx.h"
29
+#include "smart_meter.h"
26 30
 #include "lora.h"
27 31
 
28 32
 //#define DEBUG_LORA_RX_HEXDUMP
29 33
 
30 34
 #ifdef FEATURE_SML
31
-#define LORA_LED_BRIGHTNESS 1 // in percent, 50% brightness is plenty for this LED
35
+#define LORA_LED_BRIGHTNESS 0 // in percent, 50% brightness is plenty for this LED
32 36
 #define OLED_BAT_INTERVAL (2UL * 60UL * 1000UL) // in ms
33 37
 #define FORCE_BAT_SEND_AT_OLED_INTERVAL
38
+#define DEEP_SLEEP_TIMEOUT_MS (1UL * 60UL * 1000UL) // gather data for 1min
39
+#define DEEP_SLEEP_ABORT_NO_DATA_MS (20UL * 1000UL) // if no data appears, abort after 20s
40
+#define DEEP_SLEEP_DURATION_S (5UL * 60UL) // then sleep for 5min
34 41
 #else // FEATURE_SML
35 42
 #define LORA_LED_BRIGHTNESS 25 // in percent, 50% brightness is plenty for this LED
36 43
 #endif // FEATURE_SML
@@ -75,7 +82,8 @@
75 82
 
76 83
 static unsigned long last_bat_time = 0;
77 84
 static bool use_lora = true;
78
-static unsigned long last_tx = 0, tx_time = 0, minimum_pause = 0;
85
+static unsigned long last_tx = 0, last_rx = 0;
86
+static unsigned long tx_time = 0, minimum_pause = 0;
79 87
 static volatile bool rx_flag = false;
80 88
 
81 89
 #ifdef FEATURE_SML
@@ -133,7 +141,6 @@ static void lora_rx(void) {
133 141
 static bool lora_tx(enum lora_sml_type type, double value) {
134 142
     bool tx_legal = millis() > (last_tx + minimum_pause);
135 143
     if (!tx_legal) {
136
-        //debug.printf("Legal limit, wait %i sec.\n", (int)((minimum_pause - (millis() - last_tx)) / 1000) + 1);
137 144
         return false;
138 145
     }
139 146
 
@@ -145,13 +152,14 @@ static bool lora_tx(enum lora_sml_type type, double value) {
145 152
     uint8_t *data = (uint8_t *)&msg;
146 153
     const size_t len = sizeof(struct lora_sml_msg);
147 154
 
155
+    debug.printf("TX [%d] (%lu) ", data[0], len);
156
+
148 157
 #ifdef LORA_XOR_KEY
149 158
     for (size_t i = 0; i < len; i++) {
150 159
         data[i] ^= LORA_XOR_KEY[i];
151 160
     }
152 161
 #endif
153 162
 
154
-    debug.printf("TX [%d] (%lu) ", data[0], len);
155 163
     radio.clearDio1Action();
156 164
 
157 165
     heltec_led(LORA_LED_BRIGHTNESS);
@@ -177,11 +185,13 @@ static bool lora_tx(enum lora_sml_type type, double value) {
177 185
 
178 186
     radio.setDio1Action(lora_rx);
179 187
 
188
+#ifndef FEATURE_SML
180 189
     success = true;
181 190
     RADIOLIB_CHECK(radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF));
182 191
     if (!success) {
183 192
         use_lora = false;
184 193
     }
194
+#endif // ! FEATURE_SML
185 195
 
186 196
     return r;
187 197
 }
@@ -283,12 +293,14 @@ void lora_init(void) {
283 293
         return;
284 294
     }
285 295
 
296
+#ifndef FEATURE_SML
286 297
     // Start receiving
287 298
     RADIOLIB_CHECK(radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF));
288 299
     if (!success) {
289 300
         use_lora = false;
290 301
         return;
291 302
     }
303
+#endif // ! FEATURE_SML
292 304
 
293 305
 #ifdef FEATURE_SML
294 306
     // turn on Ve external 3.3V to power Smart Meter reader
@@ -302,8 +314,9 @@ void lora_init(void) {
302 314
 void lora_run(void) {
303 315
     heltec_loop();
304 316
 
305
-#ifdef OLED_BAT_INTERVAL
306 317
     unsigned long time = millis();
318
+
319
+#ifdef OLED_BAT_INTERVAL
307 320
     if (((time - last_bat_time) >= OLED_BAT_INTERVAL) || (last_bat_time == 0)) {
308 321
         last_bat_time = time;
309 322
         print_bat();
@@ -312,15 +325,30 @@ void lora_run(void) {
312 325
         lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), 0);
313 326
 #endif // FORCE_BAT_SEND_AT_OLED_INTERVAL
314 327
     }
315
-#endif
328
+#endif // OLED_BAT_INTERVAL
329
+
330
+#if defined(DEEP_SLEEP_TIMEOUT_MS) && defined(DEEP_SLEEP_DURATION_S)
331
+    bool got_sml = sml_data_received();
332
+    if ((got_sml && (time >= DEEP_SLEEP_TIMEOUT_MS))
333
+            || ((!got_sml) && (time >= DEEP_SLEEP_ABORT_NO_DATA_MS))) {
334
+        heltec_deep_sleep(DEEP_SLEEP_DURATION_S);
335
+    }
336
+#endif // DEEP_SLEEP_TIMEOUT_MS && DEEP_SLEEP_DURATION_S
337
+
338
+#ifndef FEATURE_SML
339
+    if (time >= (6UL * 60UL * 60UL * 1000UL) // running for at least 6h
340
+        && ((time - last_rx) >= (30UL * 1000UL))) { // and last lora rx at least 30s ago
341
+        heltec_deep_sleep(10); // attempt reset to avoid lorarx hanging
342
+    }
343
+#endif // ! FEATURE_SML
316 344
 
317 345
     if (!use_lora) {
318 346
         return;
319 347
     }
320 348
 
321
-    // If a packet was received, display it and the RSSI and SNR
322 349
     if (rx_flag) {
323 350
         rx_flag = false;
351
+        last_rx = time;
324 352
 
325 353
         bool success = true;
326 354
         uint8_t data[sizeof(struct lora_sml_msg)];
@@ -413,12 +441,14 @@ void lora_run(void) {
413 441
             }
414 442
         }
415 443
 
444
+#ifndef FEATURE_SML
416 445
         success = true;
417 446
         RADIOLIB_CHECK(radio.startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF));
418 447
         if (!success) {
419 448
             use_lora = false;
420 449
             return;
421 450
         }
451
+#endif // ! FEATURE_SML
422 452
     }
423 453
 
424 454
 #ifdef FEATURE_SML

+ 5
- 0
src/main.cpp Целия файл

@@ -224,6 +224,11 @@ void setup() {
224 224
 
225 225
 #endif // ARCH
226 226
 
227
+#ifdef FEATURE_NTP
228
+    // get time via NTP
229
+    configTime(gmtOffset_sec, daylightOffset_sec, NTP_SERVER);
230
+#endif
231
+
227 232
     debug.println(F("Seeding"));
228 233
     randomSeed(micros());
229 234
 

+ 38
- 11
src/smart_meter.cpp Целия файл

@@ -33,6 +33,10 @@ static unsigned long counter = 0;
33 33
 static double SumWh = NAN, T1Wh = NAN, T2Wh = NAN;
34 34
 static double SumW = NAN, L1W = NAN, L2W = NAN, L3W = NAN;
35 35
 
36
+bool sml_data_received(void) {
37
+    return counter > 0;
38
+}
39
+
36 40
 static void EnergySum(void) {
37 41
     smlOBISWh(SumWh);
38 42
 }
@@ -115,27 +119,19 @@ void sml_run(void) {
115 119
 
116 120
         if (!isnan(SumWh)) {
117 121
             debug.printf("Sum: %14.3lf Wh\n", SumWh);
118
-#ifdef FEATURE_LORA
119
-            lora_sml_send(LORA_SML_SUM_WH, SumWh, counter);
120
-#endif // FEATURE_LORA
121 122
         }
122 123
 
123 124
         if (!isnan(T1Wh)) {
124 125
             debug.printf(" T1: %14.3lf Wh\n", T1Wh);
125
-#ifdef FEATURE_LORA
126
-            lora_sml_send(LORA_SML_T1_WH, T1Wh, counter);
127
-#endif // FEATURE_LORA
128 126
         }
129 127
 
130 128
         if (!isnan(T2Wh)) {
131 129
             debug.printf(" T2: %14.3lf Wh\n", T2Wh);
132
-#ifdef FEATURE_LORA
133
-            lora_sml_send(LORA_SML_T2_WH, T2Wh, counter);
134
-#endif // FEATURE_LORA
135 130
         }
136 131
 
137 132
         if (!isnan(SumW)) {
138 133
             debug.printf("Sum: %14.3lf W\n", SumW);
134
+
139 135
 #ifdef FEATURE_LORA
140 136
             lora_sml_send(LORA_SML_SUM_W, SumW, counter);
141 137
 #endif // FEATURE_LORA
@@ -150,6 +146,7 @@ void sml_run(void) {
150 146
 
151 147
         if (!isnan(L2W)) {
152 148
             debug.printf(" L2: %14.3lf W\n", L2W);
149
+
153 150
 #ifdef FEATURE_LORA
154 151
             lora_sml_send(LORA_SML_L2_W, L2W, counter);
155 152
 #endif // FEATURE_LORA
@@ -157,16 +154,46 @@ void sml_run(void) {
157 154
 
158 155
         if (!isnan(L3W)) {
159 156
             debug.printf(" L3: %14.3lf W\n", L3W);
157
+
160 158
 #ifdef FEATURE_LORA
161 159
             lora_sml_send(LORA_SML_L3_W, L3W, counter);
162 160
 #endif // FEATURE_LORA
163 161
         }
164 162
 
163
+        debug.println();
164
+
165 165
 #ifdef FEATURE_LORA
166
+        // the power readings (Watt) are just sent as is, if available.
167
+        // the energy readings are consolidated if possible, to avoid
168
+        // unneccessary data transmission
169
+        if ((!isnan(SumWh)) && (!isnan(T1Wh))
170
+                && (fabs(SumWh - T1Wh) < 0.1)
171
+                && ((isnan(T2Wh)) || (fabs(T2Wh) < 0.1))) {
172
+            // (SumWh == T1Wh) && ((T2Wh == 0) || (T2Wh == NAN))
173
+            // just send T1Wh
174
+            lora_sml_send(LORA_SML_T1_WH, T1Wh, counter);
175
+        } else if ((!isnan(SumWh)) && (!isnan(T2Wh))
176
+                && (fabs(SumWh - T2Wh) < 0.1)
177
+                && ((isnan(T1Wh)) || (fabs(T1Wh) < 0.1))) {
178
+            // (SumWh == T2Wh) && ((T1Wh == 0) || (T1Wh == NAN))
179
+            // just send T2Wh
180
+            lora_sml_send(LORA_SML_T2_WH, T2Wh, counter);
181
+        } else {
182
+            // just do normal sending if available
183
+            if (!isnan(SumWh)) {
184
+                lora_sml_send(LORA_SML_SUM_WH, SumWh, counter);
185
+            }
186
+            if (!isnan(T1Wh)) {
187
+                lora_sml_send(LORA_SML_T1_WH, T1Wh, counter);
188
+            }
189
+            if (!isnan(T2Wh)) {
190
+                lora_sml_send(LORA_SML_T2_WH, T2Wh, counter);
191
+            }
192
+        }
193
+
194
+        // update own battery state with each sml readout
166 195
         lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), counter);
167 196
 #endif // FEATURE_LORA
168
-
169
-        debug.println();
170 197
     }
171 198
 }
172 199
 

+ 47
- 41
src/ui.cpp Целия файл

@@ -20,7 +20,6 @@
20 20
 
21 21
 #include <Arduino.h>
22 22
 #include <WiFi.h>
23
-#include <time.h>
24 23
 
25 24
 #include "config.h"
26 25
 #include "DebugLog.h"
@@ -72,7 +71,6 @@
72 71
 #define FULL_BRIGHT_MS (1000 * 30)
73 72
 #define NO_BRIGHT_MS (1000 * 2)
74 73
 
75
-#define NTP_SERVER "pool.ntp.org"
76 74
 #define STANDBY_REDRAW_MS 500
77 75
 
78 76
 #define CALIB_1_X 42
@@ -80,11 +78,6 @@
80 78
 #define CALIB_2_X LCD_WIDTH - 1 - CALIB_1_X
81 79
 #define CALIB_2_Y LCD_HEIGHT - 1 - CALIB_1_Y
82 80
 
83
-// TODO auto-detect?!
84
-#warning hard-coded timezone and daylight savings offset
85
-#define gmtOffset_sec (60 * 60)
86
-#define daylightOffset_sec (60 * 60)
87
-
88 81
 #if (LCD_MIN_BRIGHTNESS <= STANDBY_BRIGHTNESS)
89 82
 #error STANDBY_BRIGHTNESS needs to be bigger than LCD_MIN_BRIGHTNESS
90 83
 #endif
@@ -259,38 +252,12 @@ static void draw_standby(void) {
259 252
     tft.drawString(ESP_PLATFORM_NAME " " NAME_OF_FEATURE " V" ESP_ENV_VERSION, LCD_WIDTH / 2, 0, 2);
260 253
     tft.drawString("by xythobuz.de", LCD_WIDTH / 2, 16, 2);
261 254
 
255
+    String date = "?";
256
+    String time = "?";
262 257
     struct tm timeinfo;
263
-    String date, time;
264
-    String weekday[7] = { "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa." };
265
-    if(getLocalTime(&timeinfo)) {
266
-        date += weekday[timeinfo.tm_wday % 7];
267
-        date += " ";
268
-        if (timeinfo.tm_mday < 10) {
269
-            date += "0";
270
-        }
271
-        date += String(timeinfo.tm_mday);
272
-        date += ".";
273
-        if ((timeinfo.tm_mon + 1) < 10) {
274
-            date += "0";
275
-        }
276
-        date += String(timeinfo.tm_mon + 1);
277
-        date += ".";
278
-        date += String(timeinfo.tm_year + 1900);
279
-
280
-        if (timeinfo.tm_hour < 10) {
281
-            time += "0";
282
-        }
283
-        time += String(timeinfo.tm_hour);
284
-        time += ":";
285
-        if (timeinfo.tm_min < 10) {
286
-            time += "0";
287
-        }
288
-        time += String(timeinfo.tm_min);
289
-        time += ":";
290
-        if (timeinfo.tm_sec < 10) {
291
-            time += "0";
292
-        }
293
-        time += String(timeinfo.tm_sec);
258
+    if (getLocalTime(&timeinfo)) {
259
+        date = time_to_date_str(timeinfo);
260
+        time = time_to_time_str(timeinfo);
294 261
     }
295 262
 
296 263
     tft.setTextDatum(MC_DATUM); // middle center
@@ -474,9 +441,6 @@ void ui_progress(enum ui_state state) {
474 441
         } break;
475 442
 
476 443
         case UI_READY: {
477
-            // get time via NTP
478
-            configTime(gmtOffset_sec, daylightOffset_sec, NTP_SERVER);
479
-
480 444
             ui_page = UI_START;
481 445
             ui_draw_menu();
482 446
         } break;
@@ -648,3 +612,45 @@ void ui_run(void) {
648 612
 }
649 613
 
650 614
 #endif // FEATURE_UI
615
+
616
+#ifdef FEATURE_NTP
617
+
618
+String time_to_date_str(struct tm timeinfo) {
619
+    static String weekday[7] = { "So.", "Mo.", "Di.", "Mi.", "Do.", "Fr.", "Sa." };
620
+    String date;
621
+    date += weekday[timeinfo.tm_wday % 7];
622
+    date += " ";
623
+    if (timeinfo.tm_mday < 10) {
624
+        date += "0";
625
+    }
626
+    date += String(timeinfo.tm_mday);
627
+    date += ".";
628
+    if ((timeinfo.tm_mon + 1) < 10) {
629
+        date += "0";
630
+    }
631
+    date += String(timeinfo.tm_mon + 1);
632
+    date += ".";
633
+    date += String(timeinfo.tm_year + 1900);
634
+    return date;
635
+}
636
+
637
+String time_to_time_str(struct tm timeinfo) {
638
+    String time;
639
+    if (timeinfo.tm_hour < 10) {
640
+        time += "0";
641
+    }
642
+    time += String(timeinfo.tm_hour);
643
+    time += ":";
644
+    if (timeinfo.tm_min < 10) {
645
+        time += "0";
646
+    }
647
+    time += String(timeinfo.tm_min);
648
+    time += ":";
649
+    if (timeinfo.tm_sec < 10) {
650
+        time += "0";
651
+    }
652
+    time += String(timeinfo.tm_sec);
653
+    return time;
654
+}
655
+
656
+#endif // FEATURE_NTP

Loading…
Отказ
Запис