Browse Source

try to save more energy and reduce hangs

Thomas Buck 2 months ago
parent
commit
adf2562dbc
6 changed files with 87 additions and 29 deletions
  1. 1
    1
      compile_commands.json
  2. 3
    0
      include/lora.h
  3. 1
    0
      platformio.ini
  4. 62
    27
      src/lora.cpp
  5. 17
    0
      src/main.cpp
  6. 3
    1
      src/smart_meter.cpp

+ 1
- 1
compile_commands.json View File

@@ -1 +1 @@
1
-.pio/build/lorarx/compile_commands.json
1
+.pio/build/loratx/compile_commands.json

+ 3
- 0
include/lora.h View File

@@ -39,11 +39,14 @@ enum lora_sml_type {
39 39
 struct lora_sml_msg {
40 40
     uint8_t type; // enum lora_sml_type
41 41
     double value;
42
+#ifdef LORA_CLIENT_CHECKSUM
42 43
     uint32_t checksum;
44
+#endif
43 45
 } __attribute__ ((packed));
44 46
 
45 47
 #ifdef FEATURE_SML
46 48
 void lora_sml_send(enum lora_sml_type msg, double value, unsigned long counter);
49
+void lora_sml_done(void);
47 50
 #endif // FEATURE_SML
48 51
 
49 52
 double lora_get_mangled_bat(void);

+ 1
- 0
platformio.ini View File

@@ -54,6 +54,7 @@ build_flags =
54 54
   -DFEATURE_LORA
55 55
   -DFEATURE_SML
56 56
   -DFEATURE_DISABLE_WIFI
57
+  -DDISABLE_SENSORS
57 58
 lib_deps =
58 59
     https://github.com/knolleary/pubsubclient.git#2d228f2f862a95846c65a8518c79f48dfc8f188c
59 60
     https://github.com/rlogiacco/CircularBuffer.git#f29cf01b6e8603422f3668d51036ac124f803404

+ 62
- 27
src/lora.cpp View File

@@ -15,11 +15,11 @@
15 15
 
16 16
 #include <Arduino.h>
17 17
 
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
18
+#ifdef FEATURE_SML
19
+#define HELTEC_NO_DISPLAY
20
+#else // FEATURE_SML
21 21
 #define HELTEC_POWER_BUTTON
22
-#endif // ! FEATURE_SML
22
+#endif // FEATURE_SML
23 23
 
24 24
 #include <heltec_unofficial.h>
25 25
 
@@ -33,11 +33,9 @@
33 33
 
34 34
 #ifdef FEATURE_SML
35 35
 #define LORA_LED_BRIGHTNESS 0 // in percent, 50% brightness is plenty for this LED
36
-#define OLED_BAT_INTERVAL (2UL * 60UL * 1000UL) // in ms
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
36
+#define DEEP_SLEEP_DURATION_S 60
37
+#define DEEP_SLEEP_TIMEOUT_MS (30UL * 1000UL)
38
+#define DEEP_SLEEP_ABORT_NO_DATA_MS DEEP_SLEEP_TIMEOUT_MS
41 39
 #else // FEATURE_SML
42 40
 #define LORA_LED_BRIGHTNESS 25 // in percent, 50% brightness is plenty for this LED
43 41
 #endif // FEATURE_SML
@@ -86,6 +84,10 @@ static unsigned long last_tx = 0, last_rx = 0;
86 84
 static unsigned long tx_time = 0, minimum_pause = 0;
87 85
 static volatile bool rx_flag = false;
88 86
 
87
+#ifndef LORA_KEEP_SENDING_CACHE
88
+RTC_DATA_ATTR static uint8_t last_tx_msg = LORA_SML_HELLO;
89
+#endif // ! LORA_KEEP_SENDING_CACHE
90
+
89 91
 #ifdef FEATURE_SML
90 92
 
91 93
 struct sml_cache {
@@ -103,7 +105,9 @@ void lora_oled_init(void) {
103 105
 }
104 106
 
105 107
 void lora_oled_print(String s) {
108
+#ifndef FEATURE_SML
106 109
     display.print(s);
110
+#endif // ! FEATURE_SML
107 111
 }
108 112
 
109 113
 static void print_bat(void) {
@@ -120,6 +124,7 @@ double lora_get_mangled_bat(void) {
120 124
     return *((double *)data);
121 125
 }
122 126
 
127
+#ifdef LORA_CLIENT_CHECKSUM
123 128
 // adapted from "Hacker's Delight"
124 129
 static uint32_t calc_checksum(const uint8_t *data, size_t len) {
125 130
     uint32_t c = 0xFFFFFFFF;
@@ -133,6 +138,7 @@ static uint32_t calc_checksum(const uint8_t *data, size_t len) {
133 138
 
134 139
     return ~c;
135 140
 }
141
+#endif // LORA_CLIENT_CHECKSUM
136 142
 
137 143
 static void lora_rx(void) {
138 144
     rx_flag = true;
@@ -147,7 +153,10 @@ static bool lora_tx(enum lora_sml_type type, double value) {
147 153
     struct lora_sml_msg msg;
148 154
     msg.type = type;
149 155
     msg.value = value;
156
+
157
+#ifdef LORA_CLIENT_CHECKSUM
150 158
     msg.checksum = calc_checksum((uint8_t *)&msg, offsetof(struct lora_sml_msg, checksum));
159
+#endif // LORA_CLIENT_CHECKSUM
151 160
 
152 161
     uint8_t *data = (uint8_t *)&msg;
153 162
     const size_t len = sizeof(struct lora_sml_msg);
@@ -158,7 +167,7 @@ static bool lora_tx(enum lora_sml_type type, double value) {
158 167
     for (size_t i = 0; i < len; i++) {
159 168
         data[i] ^= LORA_XOR_KEY[i];
160 169
     }
161
-#endif
170
+#endif // LORA_XOR_KEY
162 171
 
163 172
     radio.clearDio1Action();
164 173
 
@@ -197,10 +206,8 @@ static bool lora_tx(enum lora_sml_type type, double value) {
197 206
 }
198 207
 
199 208
 #ifdef FEATURE_SML
200
-static bool lora_sml_cache_send(enum lora_sml_type msg) {
201
-    return lora_tx(msg, cache[msg].value);
202
-}
203 209
 
210
+#ifdef LORA_KEEP_SENDING_CACHE
204 211
 static void lora_sml_handle_cache(void) {
205 212
     // find smallest message counter that is ready
206 213
     unsigned long min_counter = ULONG_MAX;
@@ -213,7 +220,8 @@ static void lora_sml_handle_cache(void) {
213 220
     // try to transmit next value with lowest counter
214 221
     for (int i = 0; i < LORA_SML_NUM_MESSAGES; i++) {
215 222
         if (cache[i].ready && (cache[i].counter == min_counter)) {
216
-            if (lora_sml_cache_send((enum lora_sml_type)i)) {
223
+            enum lora_sml_type msg = (enum lora_sml_type)i;
224
+            if (lora_tx(msg, cache[msg].value)) {
217 225
                 if (cache[i].has_next) {
218 226
                     cache[i].has_next = false;
219 227
                     cache[i].value = cache[i].next_value;
@@ -225,6 +233,7 @@ static void lora_sml_handle_cache(void) {
225 233
         }
226 234
     }
227 235
 }
236
+#endif // LORA_KEEP_SENDING_CACHE
228 237
 
229 238
 void lora_sml_send(enum lora_sml_type msg, double value, unsigned long counter) {
230 239
     if (cache[msg].ready) {
@@ -239,6 +248,32 @@ void lora_sml_send(enum lora_sml_type msg, double value, unsigned long counter)
239 248
         cache[msg].counter = counter;
240 249
     }
241 250
 }
251
+
252
+void lora_sml_done(void) {
253
+#ifndef LORA_KEEP_SENDING_CACHE
254
+    // turn off Ve external 3.3V to Smart Meter reader
255
+    heltec_ve(false);
256
+
257
+    // select next message from cache
258
+    uint8_t n = 0;
259
+    do {
260
+        last_tx_msg++;
261
+        n++;
262
+        if (last_tx_msg >= LORA_SML_NUM_MESSAGES) {
263
+            last_tx_msg = 0;
264
+        }
265
+    } while ((!cache[last_tx_msg].ready) && (n < LORA_SML_NUM_MESSAGES + 1));
266
+
267
+    // transmit it
268
+    if (cache[last_tx_msg].ready) {
269
+        enum lora_sml_type msg = (enum lora_sml_type)last_tx_msg;
270
+        lora_tx(msg, cache[msg].value);
271
+    }
272
+
273
+    heltec_deep_sleep(DEEP_SLEEP_DURATION_S < (minimum_pause / 1000) ? (minimum_pause / 1000) : DEEP_SLEEP_DURATION_S);
274
+#endif // ! LORA_KEEP_SENDING_CACHE
275
+}
276
+
242 277
 #endif // FEATURE_SML
243 278
 
244 279
 void lora_init(void) {
@@ -251,9 +286,9 @@ void lora_init(void) {
251 286
         cache[i].counter = 0;
252 287
         cache[i].next_counter = 0;
253 288
     }
254
-#endif // FEATURE_SML
255 289
 
256
-    print_bat();
290
+    //print_bat();
291
+#endif // FEATURE_SML
257 292
 
258 293
     bool success = true;
259 294
 
@@ -305,9 +340,6 @@ void lora_init(void) {
305 340
 #ifdef FEATURE_SML
306 341
     // turn on Ve external 3.3V to power Smart Meter reader
307 342
     heltec_ve(true);
308
-
309
-    // send hello msg after boot
310
-    lora_sml_send(LORA_SML_HELLO, heltec_temperature(), 0);
311 343
 #endif // FEATURE_SML
312 344
 }
313 345
 
@@ -331,7 +363,7 @@ void lora_run(void) {
331 363
     bool got_sml = sml_data_received();
332 364
     if ((got_sml && (time >= DEEP_SLEEP_TIMEOUT_MS))
333 365
             || ((!got_sml) && (time >= DEEP_SLEEP_ABORT_NO_DATA_MS))) {
334
-        heltec_deep_sleep(DEEP_SLEEP_DURATION_S);
366
+        heltec_deep_sleep(DEEP_SLEEP_DURATION_S < (minimum_pause / 1000) ? (minimum_pause / 1000) : DEEP_SLEEP_DURATION_S);
335 367
     }
336 368
 #endif // DEEP_SLEEP_TIMEOUT_MS && DEEP_SLEEP_DURATION_S
337 369
 
@@ -376,11 +408,14 @@ void lora_run(void) {
376 408
 #endif
377 409
 
378 410
             struct lora_sml_msg *msg = (struct lora_sml_msg *)data;
411
+
412
+#ifdef LORA_CLIENT_CHECKSUM
379 413
             uint32_t checksum = calc_checksum(data, offsetof(struct lora_sml_msg, checksum));
380 414
             if (checksum != msg->checksum) {
381 415
                 debug.printf("  CRC: 0x%08X != 0x%08X\n", msg->checksum, checksum);
382 416
             } else {
383 417
                 debug.printf("  CRC: OK 0x%08X\n", checksum);
418
+#endif // LORA_CLIENT_CHECKSUM
384 419
 
385 420
 #ifdef ENABLE_INFLUXDB_LOGGING
386 421
                 if (data[0] == LORA_SML_BAT_V) {
@@ -438,7 +473,10 @@ void lora_run(void) {
438 473
                     writeSensorDatum("environment", "sml", SENSOR_LOCATION, key, msg->value);
439 474
                 }
440 475
 #endif // ENABLE_INFLUXDB_LOGGING
476
+
477
+#ifdef LORA_CLIENT_CHECKSUM
441 478
             }
479
+#endif // LORA_CLIENT_CHECKSUM
442 480
         }
443 481
 
444 482
 #ifndef FEATURE_SML
@@ -451,10 +489,11 @@ void lora_run(void) {
451 489
 #endif // ! FEATURE_SML
452 490
     }
453 491
 
454
-#ifdef FEATURE_SML
492
+#ifdef LORA_KEEP_SENDING_CACHE
455 493
     lora_sml_handle_cache();
456
-#endif // FEATURE_SML
494
+#endif // LORA_KEEP_SENDING_CACHE
457 495
 
496
+#ifndef FEATURE_SML
458 497
     if (button.isSingleClick()) {
459 498
         // In case of button click, tell user to wait
460 499
         bool tx_legal = millis() > last_tx + minimum_pause;
@@ -463,13 +502,9 @@ void lora_run(void) {
463 502
             return;
464 503
         }
465 504
 
466
-        // send test hello message on lorarx target, or battery state on loratx target
467
-#ifdef FEATURE_SML
468
-        lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), 0);
469
-#else // FEATURE_SML
470 505
         lora_tx(LORA_SML_HELLO, heltec_temperature());
471
-#endif // FEATURE_SML
472 506
     }
507
+#endif // ! FEATURE_SML
473 508
 }
474 509
 
475 510
 #endif // FEATURE_LORA

+ 17
- 0
src/main.cpp View File

@@ -17,6 +17,7 @@
17 17
 #include <ESP8266WiFi.h>
18 18
 #elif defined(ARDUINO_ARCH_ESP32)
19 19
 #include <WiFi.h>
20
+#include <esp_task_wdt.h>
20 21
 #elif defined(ARDUINO_ARCH_AVR)
21 22
 #include <UnoWiFiDevEdSerial1.h>
22 23
 #include <WiFiLink.h>
@@ -65,6 +66,7 @@ void setup() {
65 66
 
66 67
     debug.println(F("Initializing..."));
67 68
 
69
+#ifndef FEATURE_LORA
68 70
     // Blink LED for init
69 71
     for (int i = 0; i < 2; i++) {
70 72
         digitalWrite(BUILTIN_LED_PIN, LOW); // LED on
@@ -72,6 +74,7 @@ void setup() {
72 74
         digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
73 75
         delay(LED_INIT_BLINK_INTERVAL);
74 76
     }
77
+#endif // ! FEATURE_SML
75 78
 
76 79
 #ifdef FEATURE_UI
77 80
     debug.println(F("UI"));
@@ -94,8 +97,10 @@ void setup() {
94 97
     moisture_init();
95 98
 #endif // FEATURE_MOISTURE
96 99
 
100
+#ifndef DISABLE_SENSORS
97 101
     debug.println(F("Sensors"));
98 102
     initSensors();
103
+#endif // ! DISABLE_SENSORS
99 104
 
100 105
 #ifdef FEATURE_LORA
101 106
     debug.println(F("LoRa"));
@@ -148,6 +153,10 @@ void setup() {
148 153
 
149 154
 #elif defined(ARDUINO_ARCH_ESP32)
150 155
 
156
+    // add generous 30s watchdog
157
+    esp_task_wdt_init(30, true);
158
+    esp_task_wdt_add(NULL);
159
+
151 160
     // Set hostname workaround
152 161
     WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
153 162
     WiFi.setHostname(hostname.c_str());
@@ -252,7 +261,13 @@ void setup() {
252 261
 }
253 262
 
254 263
 void loop() {
264
+#ifdef ARDUINO_ARCH_ESP32
265
+    esp_task_wdt_reset();
266
+#endif // ARDUINO_ARCH_ESP32
267
+
268
+#ifndef DISABLE_SENSORS
255 269
     runSensors();
270
+#endif // ! DISABLE_SENSORS
256 271
 
257 272
 #ifdef FEATURE_SML
258 273
     sml_run();
@@ -272,10 +287,12 @@ void loop() {
272 287
     lora_run();
273 288
 #endif // FEATURE_LORA
274 289
 
290
+#ifndef FEATURE_LORA
275 291
     // blink heartbeat LED
276 292
     unsigned long time = millis();
277 293
     if ((time - last_led_blink_time) >= LED_BLINK_INTERVAL) {
278 294
         last_led_blink_time = time;
279 295
         digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN));
280 296
     }
297
+#endif // ! FEATURE_LORA
281 298
 }

+ 3
- 1
src/smart_meter.cpp View File

@@ -28,7 +28,7 @@
28 28
 #define SML_PARAM SWSERIAL_8N1
29 29
 
30 30
 static EspSoftwareSerial::UART port1, port2;
31
-static unsigned long counter = 0;
31
+RTC_DATA_ATTR static unsigned long counter = 0;
32 32
 
33 33
 static double SumWh = NAN, T1Wh = NAN, T2Wh = NAN;
34 34
 static double SumW = NAN, L1W = NAN, L2W = NAN, L3W = NAN;
@@ -193,6 +193,8 @@ void sml_run(void) {
193 193
 
194 194
         // update own battery state with each sml readout
195 195
         lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), counter);
196
+
197
+        lora_sml_done();
196 198
 #endif // FEATURE_LORA
197 199
     }
198 200
 }

Loading…
Cancel
Save