-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexplanation on data format when sending.txt
108 lines (88 loc) · 7.19 KB
/
explanation on data format when sending.txt
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
SOME EXPLANATION ON THE LORA TTN SEND SEQUENCE
Schedule TX event every this many seconds (might become longer due to duty cycle limitations).
https://www.thethingsnetwork.org/forum/t/limitations-data-rate-packet-size-30-seconds-uplink-and-10-messages-downlink-per-day-fair-access-policy/1300
Golden rule: 30 seconds air-time per device per day
For 10 bytes of payload (plus 13 bytes overhead), this is whispered to imply:
approx 20 messages per day at SF12 --> approx one per hour
500 messages per day at SF7 --> 500 / 24 = 20 per hour, or 3 minutes in-between sends (average)
for 9 bytes message, the 500 count is upped to 523 or 22 messages per hour, or 2:45 minute average between sends
For each step-up in SF Spreading factor the air-time doubles, so the allowed number of messages gets divided in half
meaning for example you can send one SF8 for the same cost as two SF7 messages
Simply one setting and one interval would be easiest.
spreading | avg time between | nbr of messages
factor | 9 byte sends | per hour or per day
-----------|------------------|-----------------
DR_SF7 | 2:45 minutes | 22 per hour, 528 per day
DR_SF8 | 5:30 minutes | 11 per hour, 264 per day
DR_SF9 | 11 minutes | 5.5 per hour, 132 per day
DR_SF10 | 22 minutes | 2.75 per hour, 66 per day
DR_SF11 | 44 minutes | 1.3 per hour, 33 per day
DR_SF12 | 1:28 hours | 16.5 per day
Sending pattern would be:
a. All messages are SF7, interval 2:45 minutes = 165 seconds (setting is at 105); in tests a setting of 130 results in 180 sec intervals so the library adds 50 sec.
However in tests we found that coverage in the Netherlands still varies, so we vant a few loud sends per hour.
Let's make a mix. You can do what you prefer... I'd prefer to see where my balloon is once every 5 or 6 minutes, and one loud send every half hour.
b. Loudest. One SF12 message - will fill up the hour and will not allow more messages. Not desirable.
c. Less loud. One SF11 uses 44 minutes, leaves budget for 6 messages as SF7. Total of 7 messages per hour, not frequent enough.
d. Even less loud. One DR_SF10 is 22 minutes of budget, one SF9 adds 11 minutes; leaves budget to send another 10 messages as SF7 to add another 27.5 min.
Total 12 messages in one hour.
interval 5 minutes, message stream: DR_SF7, DR_SF7, DR_SF7, DR_SF7, DR_SF7, DR_SF10, DR_SF7, DR_SF7, DR_SF7, DR_SF7, DR_SF7, DR_SF9
let's build and test scenario (d) with interval at 5 min = 300 sec (setting at 250)
SOME EXPLANATION ON THE GPS NUMBERS
The example SodaqBallonTestPaulB by Paul was suggested to provide the valid binary format for TTNmapper.org
in this example, the Sodaq_UBlox_GPS library is used
as we experience difficulty in formatting the correct values into our message, let's analyze what is done in detail in the example
geographic Latitude measurements range from -90° to +90°, positive is nothern hemisphere
geographic Longitude measurements range from -180° to +180°, positive indicates east from Greenwich, England
>> my current position = 52.632656, 4.738389
these Sodaq_UBlox_GPS reads from GPS, then DegMi converted to DecDeg; then stored as double
((sodaq_gps.getLat() + 90) / 180) * 16777215
((sodaq_gps.getLon() + 180) / 360) * 16777215
for lat, available trough getLat as a double, these steps are performed:
90 added to recsale from -90.0 .. +90.0 to 0.0 .. 180.0,
divided by 180 to scale from 0.0 .. 1.0,
multiplied by 16777215, being (256 * 256 * 256 - 1) to scale into a 3 byte number
LatitudeBinary and LongitudeBinary are stored as a uint32_t type; displayed as hex
>> my values would be 52.632656, 4.738389 >> 142.6, 184.7 >> 0.792, 0.513 >> 13,294,326 , 8,609,432 >> 00CA DAF6, 0083 5E98
altitudeGps is stored as uint16_t
>> my value 26.7 >> 001A
accuracy is stored as uint8_t
>> my value 147 >> 0093
In Paul's example, the payload is stored in 9 bytes in txBuffer[0] .. txBuffer[8]
txBuffer[0] = ( LatitudeBinary >> 16 ) & 0xFF; // CA --> expected in Alkmaar
txBuffer[1] = ( LatitudeBinary >> 8 ) & 0xFF; // DA --> expected in Alkmaar
txBuffer[2] = LatitudeBinary & 0xFF; // F6 --> acceptable in Alkmaar
txBuffer[3] = ( LongitudeBinary >> 16 ) & 0xFF; // 83 --> expected in Alkmaar
txBuffer[4] = ( LongitudeBinary >> 8 ) & 0xFF; // 5E --> expected in Alkmaar
txBuffer[5] = LongitudeBinary & 0xFF; // 98 --> acceptable in Alkmaar
altitudeGps = sodaq_gps.getAlt();
txBuffer[6] = ( altitudeGps >> 8 ) & 0xFF; // 00 --> expected in Alkmaar
txBuffer[7] = altitudeGps & 0xFF; // 1A --> acceptable in Alkmaar
hdopGps = sodaq_gps.getHDOP()*10;
txBuffer[8] = hdopGps & 0xFF; // ??
-=-=-=-=-=-=--==---=--=-=-=-=-=
Key to do all the transformations and assignments correctly is the precision of the types
float is a single precision (32 bit, 4 bytes) with a finesse of approx -2,147,483,648 .. 2,147,483,648
double is a double precision (64 bit, 8 bytes) floating point data type
Unsigned long stores 32 bits (4 bytes) 0 .. 4,294,967,295
Unsigned short stores 16 bits (2 bytes) 0 .. 65,535
uint8_t is unsigned 8-bit integer, 1 byte 0 .. 255
uint16_t is unsigned 16-bit integer, 2 bytes 0 .. 65,535
uint32_t is unsigned 32-bit integer, 4 bytes 0 .. 4,294,967,295
When we are using 3 bytes in our messages,
we can have unsigned int values ranging 0 .. 16,777,215
what is done here in our example...
In our version, we use the TinyGPS library, where we have a choice of:
f_get_position (easier to use, adds 2k for floating point libraries)
get_position (faster and lighter)
gps.f_get_position(&flatitude, &flongitude, &age)
Returns actual position, as float type values (not pointers).
lat -90.0 .. 90.0, lon -180 .. 180
where 1 deg is approx 111,111 meters
and with floats having a finesse of a little over 9 decimal positions, using little over 2 postions before decimal point,
this leaves us 7 decimal positions of accuracy, or: the number format can distinct between 10cm precise locations
gps.get_position(&latitude, &longitude, &age)
Returns latitude*10,000 and longitude*10,000 as long type. The age variable must be unsigned long type.
lat -900,000 .. 900,000; lon -1,800,000 .. 1,800,000
where 1/10,000 degree is about 10 meters --> we'd like a finer grain so do not use get_position
Alternative explanation is that it returns degrees * 1,000,000 http://arduiniana.org/libraries/tinygps/