Single Channel Packet Forwarder part 1 [Deprecated]

I agree that a Gateway should be as compliant as possible. I just made a pull request for your excellent single channel gateway. With a few small changes the gateway will not send hard coded “codr”:“4/5”, but instead will detect the used coding rate and set it accordingly. I hope you will accept my pull request :smile:

BIG I2C (2.42") oled display (will be mounted in the transparant gateway cover to show packet info)


MicroPython on ESP8266 documentation

Hi guys,

Just to let you know I’ve released a new version of NodeMCU Lora board (V1.3), nothing fancy, just small improvements but could be usefull

  • SMA/UFL Antenna connector has been size reduced
  • Antenna trace and RF Module surrounded with via for better RF performance
  • Increased “Isolate” ground planes to avoid shorts between connectors and ground (may happen sometimes after soldering)
  • I2C OLED connector is now “lock” version, you can just plug to test it will fit without connector
  • No more LED solder pad to choose VIN/3V3, added 1N4148 diode from 5V for the 1st LED to decrease VCC to 4.4V, always works
  • added Microchip 64 bits Unique ID footprint 24AA02E64
  • done a diode logic OR for DIO0/DIO1/DIO2 for current LIMC implementation

Schematics, pictures, board files on github repo and you can order boards PCB from

And for those fan of tiny boards, the new WeMos version with same features except connecting stuff)

Have fun


I’ve managed to use your code and get a RPi1B up and (almost) running.

I can see status updates every 30 second (so it found my RFM95W. But I don’t see any data. All counters remain 0.

I can find my gateway going to:
I can even find my gateway on the ttn map (I entered the correct lattitude and longitude in main.cpp).
The Gateway is listening to 868.1
// Set center frequency
uint32_t freq = 868100000; // in Mhz! (868.1)

My node (a Nexus running the LoRaWan v3.1 sketch from Ideetron) gets its payload to staging, but I’m not sure it’s using my gateway.
01 23:58:34 32 -121 868.10000

So it is using 868.1

What can I do to make this work?

I have a prototype of the Lua Single channel gateway that can receive all SF’s on a frequency!

I have a OTTA node configured to use SF9 after joining and my gateway receives the OTTA request in SF7 as well as the messages in SF9!

The strategy I used to make this work is to first detect a signal on the channel frequency using RSSI detection in the FSK mode of the SX1276.

When a signal is detected, CAD is used to detect a SF7 preamble. If a preamble is detected the message is received using the RX_SINGLE mode of the SX1276.

If a preamble is not detected on SF7, 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. When SF7 CAD does not detect a preamble, two SF7 symbols are gone which acounts for ONE SF8 symbol. So there are 7 preamble symbols available to detect a SF8 signal.

For a SF9 signal there will be 8-(1+0.5) = 6.5 symbols available
For a SF10 signal there will be 8-(1+0.5+0.25) = 6.25 symbols available
For a SF11 signal there will be 8-(1+0.5+0.25+0.125) = 6.125 symbols available
For a SF12 signal there will be 8-(1+0.5+0.25+0.125+0.0625) = 6.0625 symbols available.

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 in FSK mode can be 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.

I will publish my code after I tidied it up…

Logging of the gateway:

rxpk 012f560018fe34ffffde9937 message {“rxpk”:[{“rssi”:-30,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:18308070,“datr”:“SF7BW125”,“lsnr”:-55,“time”:“2016-08-08T00:32:11.068090Z”,“codr”:“4/5”,“data”:“AB4FANB+1bNwAQAAAAAAAACRlKq0Wxw=”,“freq”:868.099975,“chan”:0,“size”:23}]} length 241
txpk {“txpk”:{“codr”:“4/5”,“data”:“IN5EWks8Z7xtvGOJ0VSIwBEe2eyYuRgqliFvfqs7AG+b”,“freq”:868.1,“ipol”:true,“modu”:“LORA”,“powe”:14,“rfch”:0,“size”:33,“tmst”:23308070,“datr”:“SF7BW125”}}
txpk_ack {“txpk_ack”:{“error”:“NONE”}}
rxpk 0192bb0018fe34ffffde9937 message {“rxpk”:[{“rssi”:-31,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:23565219,“datr”:“SF9BW125”,“lsnr”:-54,“time”:“2016-08-08T00:32:16.325123Z”,“codr”:“4/5”,“data”:“QKIozxyAAAAB0GqbYA==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 229
rxpk 011c2d0018fe34ffffde9937 message {“rxpk”:[{“rssi”:-30,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:49674595,“datr”:“SF9BW125”,“lsnr”:-53,“time”:“2016-08-08T00:32:42.434631Z”,“codr”:“4/5”,“data”:“QKIozxyAAQAB6hF2qg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 229
rxpk 013e410018fe34ffffde9937 message {“rxpk”:[{“rssi”:-30,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:76115004,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:33:08.875066Z”,“codr”:“4/5”,“data”:“QKIozxyAAgABXhBICg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 229
rxpk 01503f0018fe34ffffde9937 message {“rxpk”:[{“rssi”:-29,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:102934195,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:33:35.694263Z”,“codr”:“4/5”,“data”:“QKIozxyAAwABdeY8IA==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 01d5cf0018fe34ffffde9937 message {“rxpk”:[{“rssi”:-30,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:128162079,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:34:00.922157Z”,“codr”:“4/5”,“data”:“QKIozxyABAABCaL+Tg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 0157210018fe34ffffde9937 message {“rxpk”:[{“rssi”:-28,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:154106470,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:34:26.866515Z”,“codr”:“4/5”,“data”:“QKIozxyABQABWFvHlg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 0128e90018fe34ffffde9937 message {“rxpk”:[{“rssi”:-28,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:180873907,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:34:53.633930Z”,“codr”:“4/5”,“data”:“QKIozxyABgABw0KZwg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 0126df0018fe34ffffde9937 message {“rxpk”:[{“rssi”:-28,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:206762780,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:35:19.522842Z”,“codr”:“4/5”,“data”:“QKIozxyABwABjJwTTQ==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 01b0910018fe34ffffde9937 message {“rxpk”:[{“rssi”:-29,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:233323162,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:35:46.083213Z”,“codr”:“4/5”,“data”:“QKIozxyACAABKEsjvQ==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 01538e0018fe34ffffde9937 message {“rxpk”:[{“rssi”:-28,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:258992621,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:36:11.752688Z”,“codr”:“4/5”,“data”:“QKIozxyACQABR8Lzwg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
rxpk 0169730018fe34ffffde9937 message {“rxpk”:[{“rssi”:-28,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:284625055,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:36:37.385133Z”,“codr”:“4/5”,“data”:“QKIozxyACgABoWiDwQ==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230
ntp synced using
rxpk 01b5b70018fe34ffffde9937 message {“rxpk”:[{“rssi”:-28,“stat”:1,“modu”:“LORA”,“rfch”:0,“tmst”:310634200,“datr”:“SF9BW125”,“lsnr”:-51,“time”:“2016-08-08T00:37:03.394192Z”,“codr”:“4/5”,“data”:“QKIozxyACwABnACQGg==”,“freq”:868.099975,“chan”:0,“size”:13}]} length 230

The logging shows the JOIN request (SF7), the JOIN response (txpk) and the messages received after joining (SF9)


wow ! great work … (and many hours I think)

It looks like the detection of all SF’s on a channel works quite well!

So now the LUA single channel gateway supports:

  • Receive messages using all spreading factors on one channel
  • Send messages to nodes
  • OTTA nodes

The new LUA single channel gateway software can be cloned from . Please report your findings if you do so…

Next thing to do is to support more than one channel. The strategy will be to check for a transmission on a channel using RSSI. If no activity is detected, hop to the next channel and try again. If activity is detected start the SF detection mechanism and receive the message.

If the channel hopping turns out to be fast enough, more than one channel can be used to receive messages! (But only one at a time…)


Thart sounds good! My compliments

I’m making the original IDE version capable of 2-way traffic also. The prototype is working OK.
Somebody knows an easy way to tell an OTAA node (TeensyLC based) not to use any other channels or SF settings than the DR-SF7 (or DR-SF9) we are using for the single channel gateway?

At this moment it starts OK, but if the JOIN is not successful next attempts will be on SF8-SF12 and on other frequencies as well.

The ABP nodes stick to the requested channel fortunately.



1 Like

Version 2 of the Sigle Channel gateway for the ESP8266 is now on github: 1ch Gateway 2.0

It works with TeensyLC and Arduino Pro-Mini nodes and has new features:

  • OTAA support and Downstream for SF7 and SF8
  • Possibility to have several WiFi access points configured.
  • Communication with two (UDP) backend servers
  • Enhancements to the webserver (on port 8080)
  • Bug fixes

There are several Pro-Mini versions on the market, some are 8MHz versions while others even are 16MHz. Not all versions work with OTAA and downstream functions which is probably due to timing issues of the Arduino itself. You will have to check for yourself if your Pro-Mini works. I had best results with the standard 8MHz/3.3V type with the big Chrystal close to the reset button.



Good idea to cycle the CAD detection of all SF in the same order of CAD/symbol duration.

Why change to FSK? in LORA modulation you can also read RSSI values, even during CAD.

The current version does use the LoRa Rssi values…

which file should be change? could you help to point specific source? thanks


First of all, great work!

I succesfully used a previous version of your lua gateway. Now I tried to update to the current version, but it didn’t work anymore.

After the reset this error always occurs:

lua: ?:0: attempt to call field ‘epoch2cal’ (a nil value)
stack traceback:

?: in function <?:30>
?: in main chunk

[�]: in function ‘require’
[C]: ?

I tried it on two different esp8266…

Do you have any idea where the problem could be?

Thank you in advance!


The rtctime.epoch2cal function was added to the NodeMCU firmware on the 19th of july. Is your firmware older than that?

You can build a current version of the firmware on and reflash your ESP8266; this will solve your problem…

Thank you for your help.
I’m sure you are right, the build date of the firmware I used was 16.07.16…

But now I have an other problem: I flashed the firmware as I always did. But now i can’t connect to them anymore and they are getting hot! I flashed back the old firmware but it didn’t help :frowning:

Do you maybe also have an idea what the problem now is?


If somebody else is experiencing the same problem then I did, this is what I needed to do:

I am try to set channel for US 915. Could you advice? This is orginal for EU.

local CHN={}
CHN[9]=chan(868800000,“FSK” ,MC1.BW150)

I change to 915 US subband 0

local CHN={}
CHN[9]=chan(904100000,“FSK” ,MC1.BW150)

managed to received tx from node running LMIC but i am not sure on the downlink freq… pls advice

The downlink freq does not have to be configured: the network will send a txpk message containing all information (including the frequency and the precise timing) of the message that the gateway has to transmit.

btw: the gateway will only listen on a single channel at the moment, default only CHN[0] will be used…