-
Notifications
You must be signed in to change notification settings - Fork 5
/
TBTracker-RX.ino
417 lines (367 loc) · 15.6 KB
/
TBTracker-RX.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/************************************************************************************
* TBTracker-RX - roel@kroes.com
*
* A mobile software platform for receiving LoRa transmissions and uploading those
* to amateur.sondehub.org. The software is designed to run on the esp32 platform.
* A TTGO T-Beam would be ideal. It has WiFi connectivity, a simple web interface and support for a OLED display
*
* First adjust the settings in the settings file <<<<<<<<<<<<<<<<<<<<
*
* Be sure you run the latest version of the Arduino IDE.
*
* V0.0.12
* 14-MAY-2024: Solved a bug in uploading your position to sondehub every 30 minutes
* 15-MAY-2024: Added a button in the webinterface to manually upload your position to sondehub
*
* V0.0.11
* WARNING: THIS VERSION REQUIRES A CHANGE IN YOUR SETTINGS.H file
* Add this to your settings.h of use the file in the code base:
* #define I2C_SDA 21
* #define I2C_SCL 22
* #define PMU_IRQ_BTN 38
*
* 28-JUN-2023: Added GPS debugging option in settings file
* 28-JUN-2023: Solved: Packet is uploaded with the wrong LoRa mode text.
* 29-JUN-2023: Compatibility with Radiolib 6.0.1 checked
* 28-JUL-2023: Added support for the APX power management chip which is found in the v1.1 and v1.2 T-BEAMs
*
* V0.0.10
* 22-May-2023: Architecture changes to minimise the time taken to get the radio listening for the next packet.
* 22-MAY-2023: Updated for RadioLib 6.0.0 - https://github.com/jgromes/RadioLib/releases/tag/6.0.0
* 24-MAY-2023: Re-enabled OLED Flash and Flash Pin on Packet Receive
*
* v0.0.9
* 03-MAR-2023: Serial port baudrate to 115200
* 15-MAR-2023: Added support for SSDV
* 20-MAR-2023: changed uploading part of the code. uploading will now take place from a queue and in a seperate thread
* 07-APR-2023: disabled temporary timed OLED update and OLED Flash and PIN flash
*
* v0.0.8
* 23-FEB-2023: Added support for different visual modes for the OLED (default, all, chase)
* 24-FEB-2023: Added support for a "FLASH PIN" which will set HIGH for 300ms when a packet is received (new entry in settings file!)
*
* Thanks to Star Holden, Luc Bodson and Eelco de Graaff for testing and suggesting improvements
*
* v0.0.7
* 03-FEB-2023: The link to Sondehub in the web interface now opens in a new window
* 03-FEB-2023: Software now works also without WiFi (data on Serial output or OLED display)
*
* v0.0.6
* 29-JAN-2023: Added a parser for the APRS packets to display on the Serial interface, webinterface and SSD1306 display
*
* v0.0.5
* 21-JAN-2023: Print length of received packet in the Serial monitor
* 21-JAN-2023: Check if the received packet is indeed a HAB telemetry packet
* 21-JAN-2023: Removed the RAW telemetry string from the Serial monitor to avoid double info and unreadable characters
* 21-JAN-2023: Added support for LoRa-APRS packets
* 21-JAN-2023: Added a packet Log trail in the web interface
*
* v0.0.4
* 14-JAN-2023: Added support for LoRa Mode 5 (Explicit mode, Error coding 4:8, Bandwidth 41.7kHz, SF 11, Low data rate optimize off)
* 14-JAN-2023: Added support for LoRa Mode 3 (Explicit mode, Error coding 4:6, Bandwidth 250kHz, SF 7, Low data rate optimize off)
* 20-JAN-2023: Added support for LoRa Mode 0 (Explicit mode, Error coding 4:8, Bandwidth 20.8kHz, SF 11, Low data rate optimize on)
* 20-JAN-2023: Added support for LoRa Mode 1 (Implicit mode, Error coding 4:5, Bandwidth 20.8kHz, SF 6, Low data rate optimize off)
* 20-JAN-2023: Added support for showing and changing the LoRa Mode in the webinterface
* 20-JAN-2023: Solved several bugs
* 20-JAN-2023: Added autotune to the radio (based on the frquency error calculated by the radio)
*
* v0.0.3
* 06-JAN-2023: Added SNR, RSSI to the web interface
* 06-JAN-2023: Added time since latest packet to the web interface
* 06-JAN-2023: Made the Google Maps open in a new window
* 06-JAN-2023: Solved several reported bugs / unexpected behaviour
* 07-JAN-2023: Changed some UI language. (I apologize, English is not my native language)
*
* v0.0.2
* 23-DEC-2022: Added upload result to the web interface
* 23-DEC-2022: "comment" string is now disabled by default
* 23-DEC-2022: Try to determine if the packet received is an actual HAB packet or an invalid or unknown packet
* 23-DEC-2022: Changed the wording of "Test mode" in the webinterface
*
* v0.0.1:
* 19-DEC-2022: Changed to x.y.z version numbering
* 19-DEC-2022: Moved version number to TBTracker-rx.ino from settings.h
* 19-DEV-2022: The OLED display will now show frequency updates
* 19-DEC-2022: Added a way to change the DEVFLAG in the webinterface
*
* v0.1ß:
* 18-DEC-2022: Initial version, released in the Facebook HAB-NL group
************************************************************************************/
#include <RadioLib.h>
#include <soc/soc.h>
#include <soc/rtc_cntl_reg.h>
#include "settings.h"
// TBTracker-RX version number
#define TBTRACKER_VERSION "V0.0.12"
// MAX possible length for a packet
#define PACKETLEN 255
// Struct to hold LoRA settings
struct TLoRaSettings
{
uint8_t LoRaMode = LORA_MODE;
float Frequency = LORA_FREQUENCY;
float Bandwidth;
uint8_t SpreadFactor;
uint8_t CodeRate;
uint8_t SyncWord;
uint8_t Power;
uint16_t PreambleLength;
uint8_t Gain;
size_t implicitHeader = 255;
uint8_t packetType;
String ModeString = "LoRa";
} LoRaSettings;
struct TTBScanner
{
float scanFreq[5] = {LORA_FREQUENCY,0,0,0,0};
int currentNr = 0;
int maxNr = 4;
} TBScanner;
// Struct to hold Time information
struct tm timeinfo;
// Keeps track of uploading your position to Sondehub
bool uploader_position_sent = false;
// Is the local GPS position (of this reciever) valid
bool gps_valid = false;
// Just a variable to calculate simple time difference
unsigned long timeCounter = 0;
// global counter for the number of valid packets we receive
unsigned long packetCounter = 0;
// Holder for the dev flag. If dev flag is true than data sent to Sondehub is not added to the database. Can be set in settings.h
bool devflag;
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// Variable to hold the time that the OLED display was turned inverted / Flash LED was turned on
unsigned long flashMillis = 0;
unsigned long pinMillis = 0;
// Variable to hold the time that the OLED was updated
unsigned long oledLastUpdated=0;
bool oledUpdateNeeded = false;
TaskHandle_t task_UploadSSDV; // Uploading the queue with SSDV packets to the SSDV server on core 0.
TaskHandle_t task_UploadTelemetry; // Uploading the queue with Telemetry packets to the Sondehub server on core 0.
TaskHandle_t task_updateDisplay; // Task for updating the oled display in the background in Core 0
QueueHandle_t ssdv_Queue; // queue which will hold the SSDV records to send to the server
QueueHandle_t telemetry_Queue; // queue which will hold the JSON docs to upload to the Sondehub server
volatile unsigned long start; // various timing measurements
/************************************************************************************
* Struct and variable which contains the latest telemetry
************************************************************************************/
struct TTelemetry
{
String raw; // Raw received telemetry
float uploader_position[3]; // position of yourself in GPS coordinates and altitude in meters [ -34.0, 138.0, 0 ]
float snr; // Receiver metadata - SNR
float rssi; // Receiver metadata - RSSI
float frequency; // Receiver Metadata - RX Frequency
float frequency_error; // Measured by Radio. Based on this value the radio will be retuned.
size_t rxPacketLen=0; // Length of received packet
String modulation; // Modulation type
unsigned long atmillis=0; // Reported millis when packet was received by the radio
char time_received[30]; // Date/Time the packet was received on the network (example: "2022-04-18T04:36:59.899304Z")
char datetime[30]; // Date/time reported by the payload itself. Use todays UTC date if no date available. (example: "2022-04-18T04:36:58.000000Z")
String payload_callsign; // Callsign of the payload
long frame; // Optional - Frame number as reported by the payload
float lat; // Position latitude as reported by the payload
float lon; // Position longitude as reported by the payload
float alt; // Altitude in meters as reported by the payload
unsigned int sats; // Number of satellites as reported by the payload
float temp; // Measured temperature by the payload
float batt; // Battery voltage measured by the payload
float heading; // compass heading as reported by payload
float pressure; // Pressure (hPa)
float humidity; // humidity (%)
float distance; // Distance in km to payload
float bearing; // Bearing to payload
String comment; // Optional comment for upload to Sondehub
String compass; // Compass direction in terms of "N", "SW", ...
String lastField; // Contains info about what data is in the fields after the location and altitude
bool extraFields; // is true when there are custom fields at the end of the payload data
bool uploadSondehub; // is true when the telemetry should be uploaded to Sondehub
String uploadResult; // holds the latest upload result to Sondehub
} Telemetry;
/************************************************************************************
* Parallel task that runs on core 0 and handles uploading of the SSDV packets
************************************************************************************/
void uploadSSDV(void * parameter)
{
for (;;) // Run forever
{
// Processing the queue
postSSDVToServer();
}
}
/************************************************************************************
* Parallel task that runs on core 0 and handles uploading of the Telemetry packets
************************************************************************************/
void uploadTelemetry(void * parameter)
{
for (;;) // Run forever
{
// Processing the queue
postTelemetryToServer();
}
}
/************************************************************************************
* Setting up all parts of the program
************************************************************************************/
void setup()
{
// disable brownout
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
// Switching off bluetooth
btStop();
devflag = DEVFLAG;
if (devflag)
{
Serial.println(F("SOFTWARE IS IN DEVELOPMENT MODE, Data will not be shown on Sondehub. Change DEVFLAG in settings.h"));
}
// Initialize the Power Management chip if present
XPowerInit();
// Create the Telemetry queue with 3 slots of 10124 bytes
telemetry_Queue = xQueueCreate(3, 1024);
if (telemetry_Queue == NULL)
{
Serial.println("Error creating the telemetry queue");
}
else
{
// Start the SSDV queue uploader task on core 0
xTaskCreatePinnedToCore
(
uploadTelemetry, /* Function to implement the task */
"task_UploadTelemetry", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&task_UploadTelemetry, /* Task handle. */
0 /* Core where the task should run */
);
}
// Create the SSDV queue with 10 slots of 256 bytes
ssdv_Queue = xQueueCreate(10, 256);
if (ssdv_Queue == NULL)
{
Serial.println("Error creating the SSDV queue");
}
else
{
// Start the SSDV queue uploader task on core 0
xTaskCreatePinnedToCore
(
uploadSSDV, /* Function to implement the task */
"task_UploadSSDV", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&task_UploadSSDV, /* Task handle. */
0 /* Core where the task should run */
);
}
#if defined(USE_SSD1306)
// Setup the SSD1306 display if there is any
setupSSD1306();
#endif
setupLoRa();
setupWifi();
updateTime();
setupWebserver();
#if defined(FLASH_PIN)
// Setup the pin that flashes when a packet is received
setupFlashPin();
#endif
// Sync the time keeper
timeCounter = millis();
#if defined(USE_SSD1306)
// Init the OLED display
updateOLEDforFrequency();
#endif
// When there is no valid GPS postion, we will take the GPS coordinates from the settings file
Telemetry.uploader_position[0] = UPL_LAT;
Telemetry.uploader_position[1] = UPL_LON;
Telemetry.uploader_position[2] = UPL_ALT;
// Upload telemetry?
if (UPLOAD_PAYLOAD_PACKET)
Telemetry.uploadSondehub = true;
else
Telemetry.uploadSondehub = false;
#if defined(USE_GPS)
// Setup the GPS if there is any
Serial2.begin(GPS_BAUD, SERIAL_8N1, GPS_RX, GPS_TX);
delay(500);
smartDelay(5000);
#endif
}
/************************************************************************************
* As most events are interrupt driven, there is only a small loop
************************************************************************************/
void loop()
{
// Process received LoRa packets
if (receivedFlag) {
receiveLoRa();
}
#if defined(USE_GPS)
// Poll the GPS, drops back here early if packet recieved
smartDelay(20);
// Process received LoRa packets
if (receivedFlag) {
receiveLoRa();
}
#endif
#if defined(FLASH_PIN)
// disable the LED after Xms
// Takes less than 1ms, so dont bother checking if it is on first
if (millis() > (pinMillis + 300) )
{
disablePin();
}
// Process received LoRa packets
if (receivedFlag) {
receiveLoRa();
}
#endif
#if defined(USE_SSD1306)
// disable the inverted display after Xms
// Takes less than 1ms, so dont bother checking if it is on first
if (millis() > (flashMillis + 100) )
{
disableFlash();
}
// Process received LoRa packets
if (receivedFlag) {
receiveLoRa();
}
// Update the OLED
// Includes if (oledUpdateNeeded) check to ensure only completed just after we have received a packet
displayUpdate(); // 24/05/23 Measured as 27ms on a T-Beam when a display update is needed in OLED_DEFAULT mode
// Blocks for around 25ms, so only safe to call just after we have received a packet, at which point it would always
// show 1s since last packet received - so gives no value, unless we can move to a seperate thread?
// if (millis() > (oledLastUpdated + 1000) )
// {
// timedOledUpdate(); // Takes around 25ms, so only safe to call just after we have received a packet,
// oledLastUpdated = millis();
// }
// Process received LoRa packets
if (receivedFlag) {
receiveLoRa();
}
#endif
// Keep track of the time for re-uploading your position
// Update every 30 minutes.
if (millis()-timeCounter > 1800000ul)
{
uploader_position_sent = false;
timeCounter = millis();
}
// Send your position to sondehub if enabled
// TODO Move to a parallel task otherwise we will loose packets here
if (UPLOAD_YOUR_POSITION && !uploader_position_sent)
{
start = millis();
postStationToServer(); // 24/05/23 Measured as 2 to 5 seconds!
uploader_position_sent = true;
//Serial.print(F("\nTIME spent in postStationToServer():\t\t"));
//Serial.println(millis()- start);
}
}