Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Radio SX127x (LoRA) #11

Open
jdavid opened this issue Nov 10, 2020 · 9 comments
Open

Radio SX127x (LoRA) #11

jdavid opened this issue Nov 10, 2020 · 9 comments

Comments

@jdavid
Copy link
Member

jdavid commented Nov 10, 2020

With the Feather M0 Adalogger we use the FeatherWing - RFM95W 900 MHz shield, this has the SX1276 chip. With the Waspmote we have a shield with the SX1272 chip.

RIOT has the sx127x driver which supports both the SX1272 and SX1276. By default it uses SX1276 but can be changed with the option DRIVER=sx1272

First I've tested the Feather M0 using Arduino. To do so I've followed this guide, https://learn.adafruit.com/radio-featherwing/overview

As described in the guide I've wired 3 pins, but not like in the image from the guide. Like this:

IMG_20201110_193825

In the example programs from the guide I made 2 changes:

  • Uncomment the section Feather m0 w/wing (this defines the 3 pins wired as in the image above)
  • Change RF95_FREQ to 868 for Europe

And it worked!

@jdavid
Copy link
Member Author

jdavid commented Nov 10, 2020

Next I tried with RIOT.

First I created the boards/feather-m0/include/sx127x_params.h file with the pins configuration:

[...]
static const sx127x_params_t sx127x_params[] = 
{
    {
        .spi       = SPI_DEV(0),
        .nss_pin   = GPIO_PIN(PA, 18),
        .reset_pin = GPIO_PIN(PA, 16),
        .dio0_pin  = GPIO_PIN(PA, 20),
        .dio1_pin  = GPIO_UNDEF,
        .dio2_pin  = GPIO_UNDEF,
        .dio3_pin  = GPIO_UNDEF,
    }
};
[...]

But I've not committed it anywhere. The options here is to submit a PR to RIOT, or to add it somewhere in our tree, or maybe we can achieve the same using some defines. See the sx127x_params.h files in RIOT tree.

Next I tried tests/driver_sx127x, see tests/driver_sx127x/README.md

This is an excerpt from the board attached to /dev/ttyACM1:

$ PORT=/dev/ttyACM1 BOARD=feather-m0 make -C tests/driver_sx127x all flash term
[...]
> setup 500 12 5
2020-11-10 19:22:48,666 #  setup 500 12 5
2020-11-10 19:22:48,669 # setup: setting 500KHz bandwidth
2020-11-10 19:22:48,672 # [Info] setup: configuration set with success
> channel set 868000000
2020-11-10 19:26:05,100 #  channel set 868000000
2020-11-10 19:26:05,102 # New channel set
> listen
2020-11-10 19:29:22,076 #  listen
2020-11-10 19:29:22,077 # Listen mode set
> 2020-11-10 19:29:59,271 #  {Payload: "This is RIOT!" (14 bytes), RSSI: 137, SNR: -5, TOA: 289}
2020-11-10 19:29:59,273 # Data reception started

And this is an excerpt from the board attached to /dev/ttyACM0:

$ PORT=/dev/ttyACM0 BOARD=feather-m0 make -C tests/driver_sx127x all flash term
[...]
> setup 500 12 5
2020-11-10 19:22:48,666 #  setup 500 12 5
2020-11-10 19:22:48,669 # setup: setting 500KHz bandwidth
2020-11-10 19:22:48,672 # [Info] setup: configuration set with success
> channel set 868000000
2020-11-10 19:26:05,100 #  channel set 868000000
2020-11-10 19:26:05,102 # New channel set
> send This\ is\ RIOT!
2020-11-10 19:29:32,534 #  send This\ is\ RIOT!
2020-11-10 19:29:32,537 # sending "This is RIOT!" payload (14 bytes)
> 2020-11-10 19:29:32,829 #  Transmission completed

So it worked 🎉

With this we have verified that RIOT already supports the SX127x modules, and that it works with the feather-m0 board, it just needs the proper pin configuration. Regarding the configuration note that RIOT also has the feather-m0-lora board, but the pin configuration is not the same.

Next step is to learn about the RIOT network stack.

@jdavid
Copy link
Member Author

jdavid commented Nov 11, 2020

RIOT's netdev provides an abstraction layer over network drivers, so network stacks can be built on top of them.

$ USEMODULE=sx1276 BOARD=feather-m0 make -C tests/driver_netdev_common flash term
[...]
> ifconfig
2020-11-11 12:09:27,643 #  ifconfig
2020-11-11 12:09:27,646 # Iface  4  Frequency: 868299987Hz  BW: 125kHz  SF: 7  CR: 4/5
2020-11-11 12:09:27,649 #            TX-Power: 14dBm  State: SLEEP
2020-11-11 12:09:27,650 #           L2-PDU:15615
2020-11-11 12:09:27,651 #
> txtsnd
2020-11-11 12:14:58,799 #  txtsnd
2020-11-11 12:14:58,802 # usage: txtsnd <if> [<L2 addr>|bcast] <data>
> txtsnd 4 bcast hola
2020-11-11 12:15:09,696 #  txtsnd 4 bcast hola

Meanwhile in the other node:

$ PORT=/dev/ttyACM1 BOARD=feather-m0 make -C tests/driver_sx127x flash term
[...]
> 2020-11-11 12:18:09,408 #  listen
2020-11-11 12:18:09,409 # Listen mode set
> 2020-11-11 12:18:13,220 #  {Payload: "hola" (4 bytes), RSSI: 151, SNR: 6, TOA: 37}
2020-11-11 12:18:13,221 # Data reception started

As seen above the txtsnd command may take a L2 address instead of broadcast, but thus far it's unclear which is the address.

@jdavid
Copy link
Member Author

jdavid commented Nov 11, 2020

A few more things I've learnt:

  • To do anything useful, like sending, netdev is used. The driver alone is very low level.
  • The send implementation always sends to the broadcast address 0x00. In our old stack we used the destination address (0-255) but here it's hardcoded.
  • Support NETOPT_ADDRESS is not implemented, so we cannot assign a L2 address.

RIOT supports LoraWAN, either with Semtech package, or integrated into RIOT network stack (GNRC). But this means joining the LoraWAN network, and it's probably not what we want.

TODO:

  • Try adding support for NETOPT_ADDRESS and then sending to a specific address, then maybe ifconfig will display a L2 address and we will be able to send to just one device. Maybe then we can use the higher levels of the network stack, without LoraWAN.

@jdavid
Copy link
Member Author

jdavid commented Nov 13, 2020

The sx127x chips support 2 modes, LoRa and FSK. RIOT only supports the Lora mode, there's an open issue to add support for FSK, see RIOT-OS/RIOT#11333

The Waspmote API only works in Lora mode as well, this is what the documentation says:

Libelium has decided to only use the LoRa™ modulation due to the range improvement it provides.

Then we want to use LoRa as well, for the same reason. So RIOT not supporting FSK is not an issue.

In FSK mode there's a register (0x33) to store the node address, but the same register is used for another purpose in LoRa mode. In the Waspmote API they store the node address only in memory, and the receiver code checks the destination address. So the link layer addressing is done at software level.

Now I've to check the send/receive code in RIOT as we have to do L2 addressing in software (like Libelium does).

@jdavid
Copy link
Member Author

jdavid commented Nov 13, 2020

Have investigated a bit more...

Actually LoRaWAN belongs to the MAC (Media Access Control) layer of the network. So we could use it... but the big problem is it implements a single-hop star topology; and we have deployments where we need multi-hop, as some nodes don't have direct access to the gateway.

Options...

(1) Use LoRaWAN.
Advantages: Best range, probably lowest power usage
Disadvantages: Single-hop, and probably it would be best to buy a LoRaWAN gateway than to do one ourselves.

(2) Use 802.15.4
Advantages: Easiest solution (everything should just work), multi-hop.
Disadvantages: RIOT doesn't yet support FSK modulation for the sx127x driver, so we will need another shield.

(3) Build 802.15.4 on top of LoRa?
Advantages: Best of both worlds
Disadvantages: too hard.

Just for reference, this is something I found while searching:

Conclusion. From this analysis (2) is the way to go because multi-hop is a hard requirement, and solution (3) is probably unfeasible.
But I still want to give another look...

Things I would like to do:

  • Try with the remote-revb board, because it has a 802.15.4 network module, to better see what the RIOT stack looks like.
  • Give another closer look to LoRaWAN, maybe try to join a network such as thethingsnetwork.com and see how LoRaWAN integrates with GNRC (the RIOT's network stack).

@jdavid
Copy link
Member Author

jdavid commented Nov 13, 2020

I will post an image here, because a picture is worth a thousand words:

Screenshot_2020-11-13 A-Sockets-API-for-LoRa-Andreas-Färber-SUSE-1 pdf

@jdavid jdavid changed the title Lora SX127x Radio SX127x (LoRA) Nov 19, 2020
@jdavid
Copy link
Member Author

jdavid commented Dec 16, 2021

One year later I think we just have to implement NETOPT_ADDRESS in sx127x driver as explained in a comment above. Then we should be able to send packets to a specific module using netdev.

@jdavid
Copy link
Member Author

jdavid commented Jan 26, 2022

Update: I got LoRa working with 2 nodes using RIOT's tests/driver_sx127x program, and a Raspberry Pi with Pi Supply's LoRa hat (which uses the RAK811 module). Communication both ways.

Instead of the change in a previous commit I've done this:

diff --git boards/feather-m0/include/board.h boards/feather-m0/include/board.h
index 0f89ef0b52..c1c29ece2d 100644
--- boards/feather-m0/include/board.h
+++ boards/feather-m0/include/board.h
@@ -59,9 +59,13 @@ extern "C" {
  * @{
  **/
 #define SX127X_PARAM_SPI                SPI_DEV(0)
-#define SX127X_PARAM_SPI_NSS            GPIO_PIN(PA, 6)
-#define SX127X_PARAM_RESET              GPIO_PIN(PA, 8)
-#define SX127X_PARAM_DIO0               GPIO_PIN(PA, 9)
+//#define SX127X_PARAM_SPI_NSS            GPIO_PIN(PA, 6)
+//#define SX127X_PARAM_RESET              GPIO_PIN(PA, 8)
+//#define SX127X_PARAM_DIO0               GPIO_PIN(PA, 9)
+#define SX127X_PARAM_SPI_NSS            GPIO_PIN(PA, 18) // CS  -> B -> D10
+#define SX127X_PARAM_RESET              GPIO_PIN(PA, 16) // RST -> A -> D11
+#define SX127X_PARAM_DIO0               GPIO_PIN(PA, 20) // IRQ -> D -> D6
+
 #define SX127X_PARAM_DIO1               GPIO_UNDEF
 #define SX127X_PARAM_DIO2               GPIO_UNDEF
 #define SX127X_PARAM_DIO3               GPIO_UNDEF

Not sure but I think the difference is using #define SX127X_PARAM_PASELECT (SX127X_PA_BOOST) (as defined in boards/feather-m0/include/board.h) instead of #define SX127X_PARAM_PASELECT (SX127X_PA_RFO) (the default in the sx172x driver).

For the record I tested with setup 500 12 5 (bw = 500, sf = 12, cr = 5), and frequency 868300000 (the default). This in the RAK811 test program is defined with:

freq = 868.300
sf = 12
bw = 2
cr = 1

@jdavid
Copy link
Member Author

jdavid commented Jan 26, 2022

Tested as well sending with the upper layer, with tests/driver_netdev_common
To change the parameters I used:

USEMODULE=sx1276 BOARD=feather-m0 make -C tests/driver_netdev_common menuconfig

Then go to System -> Networking -> Configure LoRa PHY:

  • Channel bandwidth (500kHz) - Default is 125
  • Spreading factor (SF12) - Default is 7
  • Coding rate (CR 4/5)

The frequency is not configurable from menuconfig, but I used the default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant