fixed the LDRO usage. It only enables when the symble time exceeds

16ms, which is described in the SX1276 datasheet.
master
Shoichi Sakane 2017-10-08 22:21:49 +09:00
parent 4616bf6472
commit e49ac9855c
11 changed files with 307 additions and 228 deletions

View File

@ -2,15 +2,42 @@ LoRa Time on Air calculator
===========================
A calculator of the time on air of LoRa PHY frame in Python.
This script refers to the section 4.1.1.6. LoRa Packet Structure,
[SX1276/77/78/79 Datasheet][http://www.semtech.com/images/datasheet/sx1276_77_78_79.pdf].
The default value is aligned to LoRaWAN AS923.
The default parameters of the equation is based on LoRaWAN AS923
in the LoRaWAN regional parameters v1.1.
## Note
The default value of Explicit Header is enable.
It is guessed from the PHY frame format
though there is no explit text in the LoRaWAN specification.
The value of LowDataRateOptimization is set automatically
when the symbol duration exceeds 16ms.
Because the datasheet requires that it must be used
when the symbol duration exceeds 16ms.
This is the case below:
- SF=12 and 11 in 125 kHz.
- SF=12 in 250 kHz.
You can disable this feature by the --disable-auto-ldro option.
The LDRO is disabled by default if you disable the auto LDRO.
If you want to enable the LDRO, you can specify the --enable-ldro option.
In the downlink stream, the CRC at the tail of the PHY frame is not used.
To calculate the ToA for the downlink stream,
the --downlink option should be specified.
## Usage
lorawan_toa.py [-h] [--band-width N_BW] [--disable-dro] [--disable-eh]
[--cr N_CR] [--preamble N_PREAMBLE] [-v] [-d]
lorawan_toa.py [-h] [--band-width N_BW] [--disable-auto-ldro]
[--enable-ldro] [--disable-eh] [--downlink]
[--disable-crc] [--cr N_CR] [--preamble N_PREAMBLE] [-v]
[-d]
SF SIZE
positional arguments:
@ -21,10 +48,13 @@ The default value is aligned to LoRaWAN AS923.
optional arguments:
-h, --help show this help message and exit
--band-width N_BW bandwidth in kHz. default is 125 kHz.
--disable-dro disable the low data rate optimization. default is
enable as LoRaWAN does.
--disable-eh disable the explicit header. default is enable as
LoRaWAN does.
--disable-auto-ldro disable the auto LDRO and disable LDRO.
--enable-ldro This option is available when the auto LDRO is
disabled.
--disable-eh disable the explicit header.
--downlink disable the CRC field, which is for the LoRaWAN
downlink stream.
--disable-crc same effect as the --downlink option.
--cr N_CR specify the CR value. default is 1 as LoRaWAN does.
--preamble N_PREAMBLE
specify the preamble. default is 8 for AS923.
@ -34,6 +64,8 @@ The default value is aligned to LoRaWAN AS923.
## Examples
with the -v option, it shows the ToA as well as the related information.
below example, it show detail information in SF 12, 64 bytes of PHY payload,
125 kHz bandwidth, preamble 8.
% python lorawan_toa.py 12 64 -v
PHY payload size : 64 Bytes
@ -43,19 +75,23 @@ with the -v option, it shows the ToA as well as the related information.
Low data rate opt. : enable
Explicit header : enable
CR (coding rate) : 1 (4/5)
Symbol Rate : 30.518 symbol/s
Symbol Time : 32.768 msec/symbol
Preamble size : 8 symbols
Packet symbol size : 73 symbols
Preamble ToA : 401.408 msec
Payload ToA : 2392.064 msec
Time on Air : 2793.472 msec
MAC frame data rate : 63.998 bps
without the -v option, it simply shows the ToA.
% python lorawan_toa.py --band-width=500 7 128
71.744
% python lorawan_toa.py 12 64
2793.472
## graph_as923.py
It makes a set of figures about Time on Air and PHYPayload size,
especially LoRaWAN AS923 using matlib like below.
![LoRa ToA](lora_toa.png)
![LoRa ToA](image/as923-toa.png)

View File

@ -10,273 +10,274 @@ from lorawan_toa import *
def get_line(list_size, n_sf, bw=125):
return [ get_toa(i, n_sf, n_bw=bw)["t_packet"] for i in list_size ]
'''
test code
'''
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("SF and ToA (BW=125 kHz)")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("SF and ToA (BW=125 kHz)")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", label="SF12", linewidth=3, alpha=1)
plt.plot(x, get_line(x, 11), "g-", label="SF11", linewidth=3, alpha=1)
plt.plot(x, get_line(x, 10), "k-", label="SF10", linewidth=3, alpha=1)
plt.plot(x, get_line(x, 9), "c-", label="SF9", linewidth=3, alpha=1)
plt.plot(x, get_line(x, 8), "m-", label="SF8", linewidth=3, alpha=1)
plt.plot(x, get_line(x, 7), "y-", label="SF7", linewidth=3, alpha=1)
ax.plot(x, get_line(x, 12), "b-", label="SF12", linewidth=3, alpha=1)
ax.plot(x, get_line(x, 11), "g-", label="SF11", linewidth=3, alpha=1)
ax.plot(x, get_line(x, 10), "k-", label="SF10", linewidth=3, alpha=1)
ax.plot(x, get_line(x, 9), "c-", label="SF9", linewidth=3, alpha=1)
ax.plot(x, get_line(x, 8), "m-", label="SF8", linewidth=3, alpha=1)
ax.plot(x, get_line(x, 7), "y-", label="SF7", linewidth=3, alpha=1)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="upper left", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="upper left", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/lora-toa-125.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("AS923 No DwellTime")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("AS923 No DwellTime")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
# no dwellTime consideration
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-", label="SF12",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-", label="SF12",
linewidth=3, alpha=1)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-", label="SF11",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-", label="SF11",
linewidth=3, alpha=1)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-", label="SF10",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-", label="SF10",
linewidth=3, alpha=1)
plt.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-", label="SF9",
ax.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-", label="SF9",
linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-", label="SF8",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-", label="SF8",
linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", label="SF7",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", label="SF7",
linewidth=3, alpha=1)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="upper left", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="upper left", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/as923-without-dwelltime.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("AS923 DwellTime 400ms")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("AS923 DwellTime 400ms")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
# required dwellTime consideration
plt.plot([0], [0], "b-", label="SF12", linewidth=3, alpha=1)
plt.plot([0], [0], "c-", label="SF11", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 19), get_line(mpsrange(8, 19), 10), "k-", label="SF10", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 9), "c-", label="SF9", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 133), get_line(mpsrange(8, 133), 8), "m-", label="SF8", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", label="SF7", linewidth=3, alpha=1)
ax.plot([0], [0], "b-", label="SF12", linewidth=3, alpha=1)
ax.plot([0], [0], "c-", label="SF11", linewidth=3, alpha=1)
ax.plot(mpsrange(8, 19), get_line(mpsrange(8, 19), 10), "k-", label="SF10", linewidth=3, alpha=1)
ax.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 9), "c-", label="SF9", linewidth=3, alpha=1)
ax.plot(mpsrange(8, 133), get_line(mpsrange(8, 133), 8), "m-", label="SF8", linewidth=3, alpha=1)
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", label="SF7", linewidth=3, alpha=1)
plt.plot(x, [400 for i in range(0, 255)], "r,", linewidth=1, alpha=0.7)
ax.plot(x, [400 for i in range(0, 255)], "r,", linewidth=1, alpha=0.7)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="upper left", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="upper left", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/as923-with-dwelltime.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("AS923")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("AS923")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
# no dwellTime consideration
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", linewidth=1.2, alpha=0.7)
# required dwellTime consideration
plt.plot([0], [0], "b-", label="SF12/125kHz", linewidth=3, alpha=1)
plt.plot([0], [0], "g-", label="SF11/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 19), get_line(mpsrange(8, 19), 10), "k-",
ax.plot([0], [0], "b-", label="SF12/125kHz", linewidth=3, alpha=1)
ax.plot([0], [0], "g-", label="SF11/125kHz", linewidth=3, alpha=1)
ax.plot(mpsrange(8, 19), get_line(mpsrange(8, 19), 10), "k-",
label="SF10/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 9), "c-",
ax.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 9), "c-",
label="SF9/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 133), get_line(mpsrange(8, 133), 8), "m-",
ax.plot(mpsrange(8, 133), get_line(mpsrange(8, 133), 8), "m-",
label="SF8/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-",
label="SF7/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b--",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b--",
label="SF7/250kHz", linewidth=3, alpha=0.5)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="upper left", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="upper left", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/as923-toa.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("AS923 and ARIB STD-T108")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("AS923 and ARIB STD-T108")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
# no dwellTime consideration
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-", linewidth=1.2, alpha=0.7)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-", linewidth=1.2, alpha=0.7)
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-", linewidth=1.2, alpha=0.7)
# required dwellTime consideration
plt.plot([0], [0], "b-", label="SF12/125kHz", linewidth=3, alpha=1)
plt.plot([0], [0], "g-", label="SF11/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 19), get_line(mpsrange(8, 19), 10), "k-",
ax.plot([0], [0], "b-", label="SF12/125kHz", linewidth=3, alpha=1)
ax.plot([0], [0], "g-", label="SF11/125kHz", linewidth=3, alpha=1)
ax.plot(mpsrange(8, 19), get_line(mpsrange(8, 19), 10), "k-",
label="SF10/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 9), "c-",
ax.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 9), "c-",
label="SF9/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 133), get_line(mpsrange(8, 133), 8), "m-",
ax.plot(mpsrange(8, 133), get_line(mpsrange(8, 133), 8), "m-",
label="SF8/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-",
label="SF7/125kHz", linewidth=3, alpha=1)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b--",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b--",
label="SF7/250kHz", linewidth=3, alpha=0.5)
plt.plot(x, [400 for i in range(0, 255)], "r--", linewidth=2, alpha=0.7)
plt.plot(x, [200 for i in range(0, 255)], "r--", linewidth=2, alpha=0.7)
plt.plot(x, [4000 for i in range(0, 255)], "r--", linewidth=2, alpha=0.7)
ax.plot(x, [400 for i in range(0, 255)], "r--", linewidth=2, alpha=0.7)
ax.plot(x, [200 for i in range(0, 255)], "r--", linewidth=2, alpha=0.7)
ax.plot(x, [4000 for i in range(0, 255)], "r--", linewidth=2, alpha=0.7)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="upper left", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="upper left", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/as923-with-arib180.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("AS923 vs Others (SF12)")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("AS923 vs Others (SF12)")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 12, bw=500), "r-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12, bw=500), "r-", linewidth=3, alpha=0.05)
# no dwellTime consideration
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-",
label="SF12/125kHz", linewidth=3.0, alpha=1)
# LoRa: SF12 / 500 kHz
plt.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 12, bw=500), "r-",
ax.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 12, bw=500), "r-",
label="SF12/500kHz", linewidth=3, alpha=1)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="best", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="best", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/as923-vs-others-sf12.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("AS923 vs Others (SF10)")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("AS923 vs Others (SF10)")
x = range(0, 255)
plt.plot(x, get_line(x, 10), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 10, bw=500), "r-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10, bw=500), "r-", linewidth=3, alpha=0.05)
# no dwellTime consideration
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "b-",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "b-",
label="SF10/125kHz", linewidth=3.0, alpha=1)
# LoRa: SF10 / 500 kHz
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 10, bw=500), "r-",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 10, bw=500), "r-",
label="SF10/500kHz", linewidth=3, alpha=1)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="best", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="best", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/as923-vs-others-sf10.png")
#########
#
#
#
plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
plt.title("LoRaWAN")
plt.ylim(0, 5000)
fig = plt.figure(num=None, figsize=(16, 8), facecolor='w', edgecolor='k')
ax = fig.add_subplot(1,1,1)
ax.set_title("LoRaWAN")
x = range(0, 255)
plt.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
plt.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 12), "b-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 11), "g-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 10), "k-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 9), "c-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 8), "m-", linewidth=3, alpha=0.05)
ax.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
# SF BW bit rate Max. MACPayload
# 12 125 250 59
@ -285,22 +286,22 @@ plt.plot(x, get_line(x, 7), "y-", linewidth=3, alpha=0.05)
# 9 125 1760 123
# 8 125 3125 250
# 7 125 5470 250
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 12), "b-",
label="SF12/125kHz", linewidth=2.0)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 11), "g-",
label="SF11/125kHz", linewidth=2.0)
plt.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-",
ax.plot(mpsrange(8, 59), get_line(mpsrange(8, 59), 10), "k-",
label="SF10/125kHz", linewidth=2.0)
plt.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-",
ax.plot(mpsrange(8, 123), get_line(mpsrange(8, 123), 9), "c-",
label="SF9/125kHz", linewidth=2.0)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8), "m-",
label="SF8/125kHz", linewidth=2.0)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7), "y-",
label="SF7/125kHz", linewidth=2.0)
# SF BW bit rate Max. MACPayload
# 7 250 11000 250
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b-.",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b-.",
label="SF7/250kHz", linewidth=2.0)
# SF BW bit rate Max. MACPayload
@ -310,24 +311,27 @@ plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=250), "b-.",
# 9 500 7000 250
# 8 500 12500 250
# 7 500 21900 250
plt.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 12, bw=500), "b--",
ax.plot(mpsrange(8, 61), get_line(mpsrange(8, 61), 12, bw=500), "b--",
label="SF12/500kHz", linewidth=2.0)
plt.plot(mpsrange(8, 137), get_line(mpsrange(8, 137), 11, bw=500), "g--",
ax.plot(mpsrange(8, 137), get_line(mpsrange(8, 137), 11, bw=500), "g--",
label="SF11/500kHz", linewidth=2.0)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 10, bw=500), "k--",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 10, bw=500), "k--",
label="SF10/500kHz", linewidth=2.0)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 9, bw=500), "c--",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 9, bw=500), "c--",
label="SF9/500kHz", linewidth=2.0)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8, bw=500), "m--",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 8, bw=500), "m--",
label="SF8/500kHz", linewidth=2.0)
plt.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=500), "y--",
ax.plot(mpsrange(8, 250), get_line(mpsrange(8, 250), 7, bw=500), "y--",
label="SF7/500kHz", linewidth=2.0)
plt.xlabel("PHY Payload Size (Byte)")
plt.ylabel("Time on Air (ms)")
plt.legend(loc="upper right", fancybox=True, shadow=True)
plt.grid(True)
ax.set_xlim(0, 260)
ax.set_ylim(0, 5000)
ax.set_xlabel("PHY Payload Size (Byte)")
ax.set_ylabel("Time on Air (ms)")
ax.grid(True)
ax.legend(loc="upper right", fancybox=True, shadow=True)
fig.tight_layout()
plt.show()
fig.savefig("image/lorawan-toa.png")

BIN
image/as923-toa.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@ -15,24 +15,32 @@ def mpsrange(a, b):
b += 6 # MHDR + MIC + 1
return range(a, b)
def get_toa(n_size, n_sf, n_bw=125, enable_dro=1, disable_h=0, n_cr=1,
n_preamble=8):
def get_toa(n_size, n_sf, n_bw=125, enable_auto_ldro=True, enable_ldro=False,
enable_eh=True, enable_crc=True, n_cr=1, n_preamble=8):
'''
Parameters:
n_size:
PL in the fomula. PHY Payload size in byte (= MAC Payload + 5)
n_sf: SF (12 to 7)
n_bw: Bandwidth in kHz. default is 125 kHz for AS923.
enable_dro:
DE in the fomula.
1 when the low data rate optimization is enabled.
0 for disabled.
LoRaWAN always use the low data optimization.
disable_eh:
IH in the fomula.
0 when the explicit header is enabled.
1 when no header is present.
LoRaWAN always use the header.
enable_auto_ldro
flag whether the auto Low Data Rate Optimization is enabled or not.
default is True.
enable_ldro:
if enable_auto_ldro is disabled, LDRO is disable by default,
which means that DE in the fomula is going to be 0.
When enable_ldro is set to True, DE is going to be 1.
LoRaWAN specification does not specify the usage.
SX1276 datasheet reuiqres to enable LDRO
when the symbol duration exceeds 16ms.
enable_eh:
when enable_eh is set to False, IH in the fomula is going to be 1.
default is True, which means IH is 0.
LoRaWAN always enables the explicit header.
enable_crc:
when enable_crc is set to False, CRC in the fomula is going to be 0.
The downlink stream doesn't use the CRC in the LoRaWAN spec.
default is True to calculate ToA for the uplink stream.
n_cr:
CR in the fomula, should be from 1 to 4.
Coding Rate = (n_cr/(n_cr+1)).
@ -53,8 +61,24 @@ def get_toa(n_size, n_sf, n_bw=125, enable_dro=1, disable_h=0, n_cr=1,
r_sym = (n_bw*1000.) / math.pow(2,n_sf)
t_sym = 1000. / r_sym
t_preamble = (n_preamble + 4.25) * t_sym
a = 8.*n_size - 4.*n_sf + 28 + 16 - 20.*disable_h
b = 4.*(n_sf-2.*enable_dro)
# LDRO
v_DE = 0
if enable_auto_ldro:
if t_sym >= 16:
v_DE = 1
elif enable_ldro:
v_DE = 1
# IH
v_IH = 0
if not enable_eh:
v_IH = 1
# CRC
v_CRC = 1
if enable_crc == False:
v_CRC = 0
#
a = 8.*n_size - 4.*n_sf + 28 + 16*v_CRC - 20.*v_IH
b = 4.*(n_sf-2.*v_DE)
v_ceil = a/b
n_payload = 8 + max(math.ceil(a/b)*(n_cr+4), 0)
t_payload = n_payload * t_sym
@ -65,6 +89,7 @@ def get_toa(n_size, n_sf, n_bw=125, enable_dro=1, disable_h=0, n_cr=1,
ret["t_sym"] = t_sym
ret["n_preamble"] = n_preamble
ret["t_preamble"] = t_preamble
ret["v_DE"] = v_DE
ret["v_ceil"] = v_ceil
ret["n_payload"] = n_payload
ret["t_payload"] = t_payload
@ -87,12 +112,17 @@ if __name__ == "__main__" :
p.add_argument("--band-width", action="store", dest="n_bw", type=int,
default=125,
help="bandwidth in kHz. default is 125 kHz.")
p.add_argument("--disable-dro", action="store_const", dest="v_de",
const=0, default=1,
help="disable the low data rate optimization. default is enable as LoRaWAN does.")
p.add_argument("--disable-eh", action="store_const", dest="v_h",
const=1, default=0,
help="disable the explicit header. default is enable as LoRaWAN does.")
p.add_argument("--disable-auto-ldro", action="store_false",
dest="enable_auto_ldro",
help="disable the auto LDRO and disable LDRO.")
p.add_argument("--enable-ldro", action="store_true", dest="enable_ldro",
help="This option is available when the auto LDRO is disabled.")
p.add_argument("--disable-eh", action="store_false", dest="enable_eh",
help="disable the explicit header.")
p.add_argument("--downlink", action="store_false", dest="enable_crc",
help="disable the CRC field, which is for the LoRaWAN downlink stream.")
p.add_argument("--disable-crc", action="store_false", dest="enable_crc",
help="same effect as the --downlink option.")
p.add_argument("--cr", action="store", dest="n_cr", type=int, default=1,
help="specify the CR value. default is 1 as LoRaWAN does.")
p.add_argument("--preamble", action="store", dest="n_preamble",
@ -105,6 +135,8 @@ if __name__ == "__main__" :
const=1, help="increase debug mode.")
args = p.parse_args()
args.v_de = False
args.debug_level = len(args._f_debug)
return args
@ -112,15 +144,20 @@ if __name__ == "__main__" :
# main
#
opt = parse_args()
ret = get_toa(opt.n_size, opt.n_sf, n_bw=opt.n_bw, enable_dro=opt.v_de,
disable_h=opt.v_h, n_cr=opt.n_cr, n_preamble=opt.n_preamble)
ret = get_toa(opt.n_size, opt.n_sf, n_bw=opt.n_bw,
enable_auto_ldro=opt.enable_auto_ldro,
enable_ldro=opt.enable_ldro,
enable_eh=opt.enable_eh, enable_crc=opt.enable_crc,
n_cr=opt.n_cr, n_preamble=opt.n_preamble)
if opt.f_verbose:
print "PHY payload size : %d Bytes" % opt.n_size
print "MAC payload size : %d Bytes" % (opt.n_size-5)
print "Spreading Factor : %d" % opt.n_sf
print "Band width : %d kHz" % opt.n_bw
print "Low data rate opt. : %s" % ("enable" if opt.v_de else "disable")
print "Explicit header : %s" % ("disable" if opt.v_h else "enable")
print "Low data rate opt. : %s" % ("enable" if ret["v_DE"]
else "disable")
print "Explicit header : %s" % ("enable" if opt.enable_eh
else "disable")
print "CR (coding rate) : %d (4/%d)" % (opt.n_cr, 4+opt.n_cr)
print "Symbol Rate : %.3f symbol/s" % ret["r_sym"]
print "Symbol Time : %.3f msec/symbol" % ret["t_sym"]
@ -131,7 +168,9 @@ if __name__ == "__main__" :
print "Time on Air : %.3f msec" % ret["t_packet"]
if opt.debug_level:
ret0 = get_toa(0, opt.n_sf, n_bw=opt.n_bw,
enable_dro=opt.v_de, disable_h=opt.v_h,
enable_auto_ldro=opt.enable_auto_ldro,
enable_ldro=opt.enable_ldro,
enable_eh=opt.enable_eh, enable_crc=opt.enable_crc,
n_cr=opt.n_cr, n_preamble=opt.n_preamble)
print "PHY PL=0 ToA : %.3f msec" % (ret0["t_packet"])
# preamble=8 cr=1? payload-len=7? crc=16 (payload) payload-crc=16