spectraphilic / wsn_riot

RIOT OS for WSN application at UiO
0 stars 0 forks source link

Radio SX127x (LoRA) #11

Open jdavid opened 3 years ago

jdavid commented 3 years ago

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:

And it worked!

jdavid commented 3 years ago

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 :tada:

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 commented 3 years ago

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 commented 3 years ago

A few more things I've learnt:

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:

jdavid commented 3 years ago

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 https://github.com/RIOT-OS/RIOT/issues/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 commented 3 years ago

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:

jdavid commented 3 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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:

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