Browse Source

try to save more energy and reduce hangs

Thomas Buck 4 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
-.pio/build/lorarx/compile_commands.json
1
+.pio/build/loratx/compile_commands.json

+ 3
- 0
include/lora.h View File

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

+ 1
- 0
platformio.ini View File

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

+ 62
- 27
src/lora.cpp View File

15
 
15
 
16
 #include <Arduino.h>
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
 #define HELTEC_POWER_BUTTON
21
 #define HELTEC_POWER_BUTTON
22
-#endif // ! FEATURE_SML
22
+#endif // FEATURE_SML
23
 
23
 
24
 #include <heltec_unofficial.h>
24
 #include <heltec_unofficial.h>
25
 
25
 
33
 
33
 
34
 #ifdef FEATURE_SML
34
 #ifdef FEATURE_SML
35
 #define LORA_LED_BRIGHTNESS 0 // in percent, 50% brightness is plenty for this LED
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
 #else // FEATURE_SML
39
 #else // FEATURE_SML
42
 #define LORA_LED_BRIGHTNESS 25 // in percent, 50% brightness is plenty for this LED
40
 #define LORA_LED_BRIGHTNESS 25 // in percent, 50% brightness is plenty for this LED
43
 #endif // FEATURE_SML
41
 #endif // FEATURE_SML
86
 static unsigned long tx_time = 0, minimum_pause = 0;
84
 static unsigned long tx_time = 0, minimum_pause = 0;
87
 static volatile bool rx_flag = false;
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
 #ifdef FEATURE_SML
91
 #ifdef FEATURE_SML
90
 
92
 
91
 struct sml_cache {
93
 struct sml_cache {
103
 }
105
 }
104
 
106
 
105
 void lora_oled_print(String s) {
107
 void lora_oled_print(String s) {
108
+#ifndef FEATURE_SML
106
     display.print(s);
109
     display.print(s);
110
+#endif // ! FEATURE_SML
107
 }
111
 }
108
 
112
 
109
 static void print_bat(void) {
113
 static void print_bat(void) {
120
     return *((double *)data);
124
     return *((double *)data);
121
 }
125
 }
122
 
126
 
127
+#ifdef LORA_CLIENT_CHECKSUM
123
 // adapted from "Hacker's Delight"
128
 // adapted from "Hacker's Delight"
124
 static uint32_t calc_checksum(const uint8_t *data, size_t len) {
129
 static uint32_t calc_checksum(const uint8_t *data, size_t len) {
125
     uint32_t c = 0xFFFFFFFF;
130
     uint32_t c = 0xFFFFFFFF;
133
 
138
 
134
     return ~c;
139
     return ~c;
135
 }
140
 }
141
+#endif // LORA_CLIENT_CHECKSUM
136
 
142
 
137
 static void lora_rx(void) {
143
 static void lora_rx(void) {
138
     rx_flag = true;
144
     rx_flag = true;
147
     struct lora_sml_msg msg;
153
     struct lora_sml_msg msg;
148
     msg.type = type;
154
     msg.type = type;
149
     msg.value = value;
155
     msg.value = value;
156
+
157
+#ifdef LORA_CLIENT_CHECKSUM
150
     msg.checksum = calc_checksum((uint8_t *)&msg, offsetof(struct lora_sml_msg, checksum));
158
     msg.checksum = calc_checksum((uint8_t *)&msg, offsetof(struct lora_sml_msg, checksum));
159
+#endif // LORA_CLIENT_CHECKSUM
151
 
160
 
152
     uint8_t *data = (uint8_t *)&msg;
161
     uint8_t *data = (uint8_t *)&msg;
153
     const size_t len = sizeof(struct lora_sml_msg);
162
     const size_t len = sizeof(struct lora_sml_msg);
158
     for (size_t i = 0; i < len; i++) {
167
     for (size_t i = 0; i < len; i++) {
159
         data[i] ^= LORA_XOR_KEY[i];
168
         data[i] ^= LORA_XOR_KEY[i];
160
     }
169
     }
161
-#endif
170
+#endif // LORA_XOR_KEY
162
 
171
 
163
     radio.clearDio1Action();
172
     radio.clearDio1Action();
164
 
173
 
197
 }
206
 }
198
 
207
 
199
 #ifdef FEATURE_SML
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
 static void lora_sml_handle_cache(void) {
211
 static void lora_sml_handle_cache(void) {
205
     // find smallest message counter that is ready
212
     // find smallest message counter that is ready
206
     unsigned long min_counter = ULONG_MAX;
213
     unsigned long min_counter = ULONG_MAX;
213
     // try to transmit next value with lowest counter
220
     // try to transmit next value with lowest counter
214
     for (int i = 0; i < LORA_SML_NUM_MESSAGES; i++) {
221
     for (int i = 0; i < LORA_SML_NUM_MESSAGES; i++) {
215
         if (cache[i].ready && (cache[i].counter == min_counter)) {
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
                 if (cache[i].has_next) {
225
                 if (cache[i].has_next) {
218
                     cache[i].has_next = false;
226
                     cache[i].has_next = false;
219
                     cache[i].value = cache[i].next_value;
227
                     cache[i].value = cache[i].next_value;
225
         }
233
         }
226
     }
234
     }
227
 }
235
 }
236
+#endif // LORA_KEEP_SENDING_CACHE
228
 
237
 
229
 void lora_sml_send(enum lora_sml_type msg, double value, unsigned long counter) {
238
 void lora_sml_send(enum lora_sml_type msg, double value, unsigned long counter) {
230
     if (cache[msg].ready) {
239
     if (cache[msg].ready) {
239
         cache[msg].counter = counter;
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
 #endif // FEATURE_SML
277
 #endif // FEATURE_SML
243
 
278
 
244
 void lora_init(void) {
279
 void lora_init(void) {
251
         cache[i].counter = 0;
286
         cache[i].counter = 0;
252
         cache[i].next_counter = 0;
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
     bool success = true;
293
     bool success = true;
259
 
294
 
305
 #ifdef FEATURE_SML
340
 #ifdef FEATURE_SML
306
     // turn on Ve external 3.3V to power Smart Meter reader
341
     // turn on Ve external 3.3V to power Smart Meter reader
307
     heltec_ve(true);
342
     heltec_ve(true);
308
-
309
-    // send hello msg after boot
310
-    lora_sml_send(LORA_SML_HELLO, heltec_temperature(), 0);
311
 #endif // FEATURE_SML
343
 #endif // FEATURE_SML
312
 }
344
 }
313
 
345
 
331
     bool got_sml = sml_data_received();
363
     bool got_sml = sml_data_received();
332
     if ((got_sml && (time >= DEEP_SLEEP_TIMEOUT_MS))
364
     if ((got_sml && (time >= DEEP_SLEEP_TIMEOUT_MS))
333
             || ((!got_sml) && (time >= DEEP_SLEEP_ABORT_NO_DATA_MS))) {
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
 #endif // DEEP_SLEEP_TIMEOUT_MS && DEEP_SLEEP_DURATION_S
368
 #endif // DEEP_SLEEP_TIMEOUT_MS && DEEP_SLEEP_DURATION_S
337
 
369
 
376
 #endif
408
 #endif
377
 
409
 
378
             struct lora_sml_msg *msg = (struct lora_sml_msg *)data;
410
             struct lora_sml_msg *msg = (struct lora_sml_msg *)data;
411
+
412
+#ifdef LORA_CLIENT_CHECKSUM
379
             uint32_t checksum = calc_checksum(data, offsetof(struct lora_sml_msg, checksum));
413
             uint32_t checksum = calc_checksum(data, offsetof(struct lora_sml_msg, checksum));
380
             if (checksum != msg->checksum) {
414
             if (checksum != msg->checksum) {
381
                 debug.printf("  CRC: 0x%08X != 0x%08X\n", msg->checksum, checksum);
415
                 debug.printf("  CRC: 0x%08X != 0x%08X\n", msg->checksum, checksum);
382
             } else {
416
             } else {
383
                 debug.printf("  CRC: OK 0x%08X\n", checksum);
417
                 debug.printf("  CRC: OK 0x%08X\n", checksum);
418
+#endif // LORA_CLIENT_CHECKSUM
384
 
419
 
385
 #ifdef ENABLE_INFLUXDB_LOGGING
420
 #ifdef ENABLE_INFLUXDB_LOGGING
386
                 if (data[0] == LORA_SML_BAT_V) {
421
                 if (data[0] == LORA_SML_BAT_V) {
438
                     writeSensorDatum("environment", "sml", SENSOR_LOCATION, key, msg->value);
473
                     writeSensorDatum("environment", "sml", SENSOR_LOCATION, key, msg->value);
439
                 }
474
                 }
440
 #endif // ENABLE_INFLUXDB_LOGGING
475
 #endif // ENABLE_INFLUXDB_LOGGING
476
+
477
+#ifdef LORA_CLIENT_CHECKSUM
441
             }
478
             }
479
+#endif // LORA_CLIENT_CHECKSUM
442
         }
480
         }
443
 
481
 
444
 #ifndef FEATURE_SML
482
 #ifndef FEATURE_SML
451
 #endif // ! FEATURE_SML
489
 #endif // ! FEATURE_SML
452
     }
490
     }
453
 
491
 
454
-#ifdef FEATURE_SML
492
+#ifdef LORA_KEEP_SENDING_CACHE
455
     lora_sml_handle_cache();
493
     lora_sml_handle_cache();
456
-#endif // FEATURE_SML
494
+#endif // LORA_KEEP_SENDING_CACHE
457
 
495
 
496
+#ifndef FEATURE_SML
458
     if (button.isSingleClick()) {
497
     if (button.isSingleClick()) {
459
         // In case of button click, tell user to wait
498
         // In case of button click, tell user to wait
460
         bool tx_legal = millis() > last_tx + minimum_pause;
499
         bool tx_legal = millis() > last_tx + minimum_pause;
463
             return;
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
         lora_tx(LORA_SML_HELLO, heltec_temperature());
505
         lora_tx(LORA_SML_HELLO, heltec_temperature());
471
-#endif // FEATURE_SML
472
     }
506
     }
507
+#endif // ! FEATURE_SML
473
 }
508
 }
474
 
509
 
475
 #endif // FEATURE_LORA
510
 #endif // FEATURE_LORA

+ 17
- 0
src/main.cpp View File

17
 #include <ESP8266WiFi.h>
17
 #include <ESP8266WiFi.h>
18
 #elif defined(ARDUINO_ARCH_ESP32)
18
 #elif defined(ARDUINO_ARCH_ESP32)
19
 #include <WiFi.h>
19
 #include <WiFi.h>
20
+#include <esp_task_wdt.h>
20
 #elif defined(ARDUINO_ARCH_AVR)
21
 #elif defined(ARDUINO_ARCH_AVR)
21
 #include <UnoWiFiDevEdSerial1.h>
22
 #include <UnoWiFiDevEdSerial1.h>
22
 #include <WiFiLink.h>
23
 #include <WiFiLink.h>
65
 
66
 
66
     debug.println(F("Initializing..."));
67
     debug.println(F("Initializing..."));
67
 
68
 
69
+#ifndef FEATURE_LORA
68
     // Blink LED for init
70
     // Blink LED for init
69
     for (int i = 0; i < 2; i++) {
71
     for (int i = 0; i < 2; i++) {
70
         digitalWrite(BUILTIN_LED_PIN, LOW); // LED on
72
         digitalWrite(BUILTIN_LED_PIN, LOW); // LED on
72
         digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
74
         digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
73
         delay(LED_INIT_BLINK_INTERVAL);
75
         delay(LED_INIT_BLINK_INTERVAL);
74
     }
76
     }
77
+#endif // ! FEATURE_SML
75
 
78
 
76
 #ifdef FEATURE_UI
79
 #ifdef FEATURE_UI
77
     debug.println(F("UI"));
80
     debug.println(F("UI"));
94
     moisture_init();
97
     moisture_init();
95
 #endif // FEATURE_MOISTURE
98
 #endif // FEATURE_MOISTURE
96
 
99
 
100
+#ifndef DISABLE_SENSORS
97
     debug.println(F("Sensors"));
101
     debug.println(F("Sensors"));
98
     initSensors();
102
     initSensors();
103
+#endif // ! DISABLE_SENSORS
99
 
104
 
100
 #ifdef FEATURE_LORA
105
 #ifdef FEATURE_LORA
101
     debug.println(F("LoRa"));
106
     debug.println(F("LoRa"));
148
 
153
 
149
 #elif defined(ARDUINO_ARCH_ESP32)
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
     // Set hostname workaround
160
     // Set hostname workaround
152
     WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
161
     WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
153
     WiFi.setHostname(hostname.c_str());
162
     WiFi.setHostname(hostname.c_str());
252
 }
261
 }
253
 
262
 
254
 void loop() {
263
 void loop() {
264
+#ifdef ARDUINO_ARCH_ESP32
265
+    esp_task_wdt_reset();
266
+#endif // ARDUINO_ARCH_ESP32
267
+
268
+#ifndef DISABLE_SENSORS
255
     runSensors();
269
     runSensors();
270
+#endif // ! DISABLE_SENSORS
256
 
271
 
257
 #ifdef FEATURE_SML
272
 #ifdef FEATURE_SML
258
     sml_run();
273
     sml_run();
272
     lora_run();
287
     lora_run();
273
 #endif // FEATURE_LORA
288
 #endif // FEATURE_LORA
274
 
289
 
290
+#ifndef FEATURE_LORA
275
     // blink heartbeat LED
291
     // blink heartbeat LED
276
     unsigned long time = millis();
292
     unsigned long time = millis();
277
     if ((time - last_led_blink_time) >= LED_BLINK_INTERVAL) {
293
     if ((time - last_led_blink_time) >= LED_BLINK_INTERVAL) {
278
         last_led_blink_time = time;
294
         last_led_blink_time = time;
279
         digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN));
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
 #define SML_PARAM SWSERIAL_8N1
28
 #define SML_PARAM SWSERIAL_8N1
29
 
29
 
30
 static EspSoftwareSerial::UART port1, port2;
30
 static EspSoftwareSerial::UART port1, port2;
31
-static unsigned long counter = 0;
31
+RTC_DATA_ATTR static unsigned long counter = 0;
32
 
32
 
33
 static double SumWh = NAN, T1Wh = NAN, T2Wh = NAN;
33
 static double SumWh = NAN, T1Wh = NAN, T2Wh = NAN;
34
 static double SumW = NAN, L1W = NAN, L2W = NAN, L3W = NAN;
34
 static double SumW = NAN, L1W = NAN, L2W = NAN, L3W = NAN;
193
 
193
 
194
         // update own battery state with each sml readout
194
         // update own battery state with each sml readout
195
         lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), counter);
195
         lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), counter);
196
+
197
+        lora_sml_done();
196
 #endif // FEATURE_LORA
198
 #endif // FEATURE_LORA
197
     }
199
     }
198
 }
200
 }

Loading…
Cancel
Save