A LoRaWan Gateway in LUA
A LoRaWan Gateway in Lua, listening to all spreading factors on one specific channel.
Lua is an event driven language, which is a good match for a gateway: a gateway has to respond to incoming messages from nodes and routers. The LoraWanGateway runs on an ESP8266 chip, with the NodeMCU firmware it runs a full WiFi stack and a Lua runtime. The NodeMCU contains a lot of libraries that are usefull for a gateway: WiFi, NTP support, SPI, 6 timers, JSON support etc.
Unlike complex LoRaWAN concentrator modules (such as SX1301/SX1308), a simple SX1276/SX1278 module needs to be told exactly for which channel and spreading factor (SF) it should perform channel activity detection (CAD). This works fine when using the module in an end device (node), as then LoRaWAN explicitly defines which combination is to be used. But for a single channel gateway the goal is to listen on all SFs of that single channel.
The strategy to make this work for a simple SX1276/SX1278 module is to first start a SF7 CAD on the channel frequency. While performing the CAD, RSSI is used to detect the presence of a signal on the channel.
If a preamble is detected the message is received using the RX_SINGLE mode of the module. If a preamble is not detected on SF7 and RSSI shows that a signal is present, CAD is used to detect a SF8 preamble. This is repeated for all spreading factors.
This works because the preamble always uses 8 symbols, and the length of a symbol is dependent on the spreading factor. The next SF's symbol length is twice the length of the previous length.
Detecting a signal using CAD takes less than two symbols. So when a SF7 CAD returns, two symbols of the preamble are 'used', leaving 6 more to synchronize the reading of the message. The two SF7 symbols that are gone, acount for one SF8 symbol. So there are 7 preamble symbols available to detect a SF8 signal. Likewise:
So there are always enough preamble symbols left to try to detect a higher SF signal, if the lower SF detection fails.
In order to make this work it is important to detect the presence of a signal on the channel as soon as possible; the RSSI detection during CAD is used to do that. A drawback of this approach is that the range of this gateway will be less of that of a 'real' gateway; it can only receive messages that can be detected by RSSI.
In order to run a LoRaWanGateway you need:
Connections
ESP PIN | SX1276 PIN |
---|---|
D1 (GPIO5) | DIO0 |
D2 (GPIO4) | DIO1 |
D5 (GPIO14) | SCK |
D6 (GPIO12) | MISO |
D7 (GPIO13) | MOSI |
D0 (GPIO16) | NSS |
GND | GND |
3.3V | VCC |
The LoRaWanGateway needs quite some RAM and processing power, so it is necessary to flash firmware that uses as little resources as possible. The firmware that we will use contains only the modules needed. There are two ways to obtain the minimum build:
Build and download the latest NodeMCU firmware on https://nodemcu-build.com/
OR
Use the build that I supply in the firmware directory, along with the NodeMCU flasher application.
In the directory "firmware" look for the .bin file that starts with "nodemcu-master"
A Python-based, open source, platform independent, utility.
https://nodemcu.readthedocs.io/en/master/en/flash/#esptoolpy
Self-contained NodeMCU flasher with GUI based on esptool.py and wxPython.
https://nodemcu.readthedocs.io/en/master/en/flash/#nodemcu-pyflasher
Suggested tool: nodemcu-uploader.py
https://github.com/kmpm/nodemcu-uploader
Use a serial connection at 115200 baud to connect and configure your gateway:
The LoRaWanGateway is configured to listen for all spreadingsfactors on EU channel 0 (868.1 Mhz).
The LoRaWanGateway can be run in two modes
When listening to a single SF, the range of your gateway will increase a lot because messages below the noise floor will be received too.
Changing the configuration can be done from the LUA shell using the new CONFIG object.
Values can be changed using CONFIG.PARAMETER=VALUE i.e. CONFIG.GW_FREQ=902300000 for listening to channel
0 on the US915 band.
CONFIG.print() shows the current configuration.
CONFIG.save() saves the current configuration.
Parameter | Description | Default |
---|---|---|
GW_HOSTNAME | Hostname for telnet server | "lorawangw" |
GW_NTP_SERVER | Dns name of the ntp server to connect | "nl.pool.ntp.org" |
GW_ROUTER | Dns name of the router to connect | "router.eu.thethings.network" |
GW_PORT | Port number of the router to connect | 1700 |
GW_FREQ | Frequency (in Hz) to listen to | 868100000 |
GW_BW | BW to listen to | "BW125" |
GW_SF | SF to listen to ("SF7".."SF12"|"ALL") | "ALL" (listen to all SF's) |
GW_ALT | Altitude of your gateway location | 0 |
GW_LAT | Latitude of your gateway location | "0.0" |
GW_LON | Longitude of your gateway location | "0.0" |
GW_NSS | NSS pin number | 0 |
GW_DIO0 | DIO0 pin number | 1 |
GW_DIO1 | DIO1 pin number | 2 |
The gateway will listen to only one specific channel. It will send on whatever channel or datarate the router seems fit...
You can connect to your gateway using a telnet client. If you connect to GW_HOSTNAME:23 you will get access
to the LUA shell of your gateway.
From this shell you can monitor your gateway, and execute lua commands like node.restart() and =node.heap().
You can view statistics by entering statistics() in the LUA shell or in your telnet terminal.