Skip to content
This repository was archived by the owner on Sep 4, 2025. It is now read-only.

Commit c06ff46

Browse files
authored
Merge pull request #1 from fprwi6labs/dev_lora
First release to use the I-NUCLEO-LRWAN1 expansion board as a LoRaWAN node in ABP or OTAA mode.
2 parents 5e2315d + f1c2f95 commit c06ff46

23 files changed

+7466
-1
lines changed

README.md

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,65 @@
11
# I-NUCLEO-LRWAN1
2-
Arduino library to support I-NUCLEO-LRWAN1 LoRa® expansion board based on USI® LoRaWAN™ technology module.
2+
3+
Arduino library to support I-NUCLEO-LRWAN1 LoRa® expansion board based on USI®
4+
LoRaWAN™ technology module.
5+
6+
## API
7+
8+
This library provides an Arduino API to manage the I-NUCLEO-LRWAN1 expansion
9+
board as a LoRaWAN™ node.
10+
11+
* You will be able to choose the ABP or OTAA mode and set the corresponding keys.
12+
* Send and receive some data.
13+
* Select the EU or US band.
14+
* Enable or disable the duty cycle (must be enabled in EU band).
15+
* Enable the adaptative data rate and configure the data rate.
16+
* Put the device in sleep mode.
17+
18+
This library provides also an API to manage the I-NUCLEO-LRWAN1 expansion board
19+
as a simple LoRa® radio module.
20+
21+
* Configure the radio parameters (frequency, tx power, spreading factor, band width, ...)
22+
* Send/receive data
23+
* LoRaWAN stack disabled
24+
25+
## Known limitations
26+
27+
* The module supports only class A.
28+
* Sleep mode is not supported in OTAA mode with the version 2.6 of the firmware.
29+
* The same USART is shared between I-NUCLEO-LRWAN1 LoRa® expansion board and
30+
Nucleo boards. See UM1724, 6.8 section to solve the issue.
31+
32+
## Examples
33+
34+
* **getDevEUI**: display the unique device EUI.
35+
* **LoRaWANABP**: send/receive data in ABP mode.
36+
* **LoRaWANOTAA**: send/receive data in OTAA mode.
37+
* **LoRaPingPong**: P2P exchange in LoRa®
38+
39+
## Advice
40+
41+
LoRaWAN default configuration:
42+
43+
* Join accept delay is set to 5000 ms (LoRaWAN default value).
44+
* The network type is public by default. Use `setPublicNwkMode()` to set the network
45+
type in private.
46+
* RX1 window delay is 1000 ms by default. Use `setRx1Delay()` to set a new value.
47+
48+
In case of high latency between the gateway and the network server, it is recommended
49+
to increase the delay time of the RX1 window.
50+
51+
## Version
52+
53+
This library is based on the STM32CubeExpansion_LRWAN_V1.1.2 driver.
54+
This library has been validated with the version 2.6 of the firmware.
55+
56+
## Documentation
57+
58+
You can find the source files at
59+
https://github.com/stm32duino/I-NUCLEO-LRWAN1
60+
61+
The I-NUCLEO-LRWAN1 module datasheet is available at
62+
https://github.com/USILoRaModule/USI_I-NUCLEO-LRWAN1
63+
64+
LoRaWAN standard
65+
https://www.lora-alliance.org
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
LoRaPingPong.ino
3+
4+
Provides an example to use the shield as a simple LoRa radio.
5+
Data are exchange between two boards. The first receiving the PING message
6+
becomes slave and will just send a PONG answer.
7+
8+
*/
9+
10+
#include "LoRaRadio.h"
11+
12+
#define SEND_PERIOD_MS 1000 //send period every second.
13+
14+
// Serial port use to communicate with the USI shield. Specific to the board Discovery L475 IoT.
15+
HardwareSerial SerialLora(PA_1, PA_0);
16+
17+
// Messages to exchange
18+
uint8_t PingMsg[] = "PING";
19+
uint8_t PongMsg[] = "PONG";
20+
21+
bool isMaster = true;
22+
bool next = true;
23+
int timer = 0;
24+
25+
void setup()
26+
{
27+
Serial.begin(9600);
28+
Serial.println("-- LoRa Ping Pong sketch --");
29+
30+
while(!loraRadio.begin(&SerialLora)) {
31+
Serial.println("LoRa module not ready");
32+
delay(1000);
33+
}
34+
35+
Serial.println("LoRa module ready\n");
36+
}
37+
38+
void loop()
39+
{
40+
uint8_t rcvData[64];
41+
42+
if((isMaster == true) && (next == true)) {
43+
next = false;
44+
loraRadio.write(PingMsg, 4);
45+
timer = millis();
46+
}
47+
48+
if(loraRadio.read(rcvData) > 0) {
49+
if(memcmp(rcvData, PongMsg, 4) == 0) {
50+
Serial.println((char *)PongMsg);
51+
} else if(memcmp(rcvData, PingMsg, 4) == 0) {
52+
isMaster = false;
53+
loraRadio.write(PongMsg, 4);
54+
Serial.println((char *)PingMsg);
55+
}
56+
memset(rcvData, 0, 5);
57+
}
58+
59+
if(((millis() - timer) >= SEND_PERIOD_MS) && (isMaster == true)){
60+
next = true;
61+
}
62+
}

examples/LoRaWANABP/LoRaWANABP.ino

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
LoRaABP.ino
3+
4+
Establish a connection on a LoRaWAN network in ABP mode.
5+
Exchange data to/from the network.
6+
7+
Extract of the LoRaWAN standard:
8+
9+
Activation by personalization directly ties an end-device to a specific network by-passing the join request
10+
- join accept procedure.
11+
12+
Activating an end-device by personalization means that the DevAddr and the two session
13+
keys NwkSKey and AppSKey are directly stored into the end-device instead of the DevEUI,
14+
AppEUI and the AppKey. The end-device is equipped with the required information for
15+
participating in a specific LoRa network when started.
16+
17+
*/
18+
19+
#include "LoRaWANNode.h"
20+
21+
#define FRAME_DELAY 300000 // in ms. Every 5 minutes by default.
22+
23+
HardwareSerial SerialLora(PA_1, PA_0);
24+
25+
// Device address, network & application keys
26+
const char devAddr[] = "ef00cb01";
27+
const char nwkSKey[] = "abcdef0123456789abcdef0123456789";
28+
const char appSKey[] = "0123456789abcdef0123456789abcdef";
29+
30+
// Data send
31+
char frameTx[] = "Hello world!";
32+
33+
void setup()
34+
{
35+
Serial.begin(9600);
36+
Serial.println("-- LoRaWAN ABP sketch --");
37+
38+
// Enable the USI module and set the radio band.
39+
while(!loraNode.begin(&SerialLora, LORA_BAND_EU_868)) {
40+
Serial.println("Lora module not ready");
41+
delay(1000);
42+
}
43+
44+
// Set the network keys of the module
45+
while(!loraNode.joinABP(devAddr, nwkSKey, appSKey)) {
46+
Serial.println("joinABP failed!!");
47+
delay(1000);
48+
}
49+
50+
Serial.println("Lora module ready\n");
51+
52+
String str = "Device address: ";
53+
loraNode.getDevAddr(&str);
54+
Serial.println(str);
55+
str = "NwkSKey: ";
56+
loraNode.getNwkSKey(&str);
57+
Serial.println(str);
58+
str = "AppSKey: ";
59+
loraNode.getAppSKey(&str);
60+
Serial.println(str);
61+
}
62+
63+
void loop()
64+
{
65+
receive();
66+
transmit();
67+
delay(FRAME_DELAY);
68+
}
69+
70+
void receive(void) {
71+
uint8_t frameRx[64];
72+
uint8_t len;
73+
uint8_t port;
74+
75+
// Check if data received from a gateway
76+
if(loraNode.receiveFrame(frameRx, &len, &port)) {
77+
uint8_t n = 0;
78+
Serial.print("frame received: 0x");
79+
while(len > 0) {
80+
Serial.print(frameRx[n], HEX);
81+
Serial.print(',');
82+
len--;
83+
n++;
84+
}
85+
Serial.print(" on port "); Serial.println(port);
86+
} else {
87+
Serial.println("No data");
88+
}
89+
}
90+
91+
void transmit(void) {
92+
// Send unconfirmed data to a gateway (port 1 by default)
93+
int status = loraNode.sendFrame(frameTx, sizeof(frameTx), UNCONFIRMED);
94+
if(status == LORA_SEND_ERROR) {
95+
Serial.println("Send frame failed!!!");
96+
} else if(status == LORA_SEND_DELAYED) {
97+
Serial.println("Module busy or duty cycle");
98+
} else {
99+
Serial.println("Frame sent");
100+
}
101+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
LoRaOTAA.ino
3+
4+
Establish a connection on a LoRaWAN network in OTAA mode.
5+
Send a join request and wait the join accept.
6+
Exchange data to/from the network.
7+
8+
Extract of the LoRaWAN standard:
9+
10+
For Over The Air Activation, end-devices must follow a join procedure prior to participating in
11+
data exchanges with the network server. An end-device has to go through a new join
12+
procedure every time it has lost the session context information.
13+
14+
The join procedure requires the end-device to be personalized with the following information
15+
before its starts the join procedure: a globally unique end-device identifier (DevEUI), the
16+
application identifier (AppEUI), and an AES-128 key (AppKey).
17+
18+
USI will burn the unique IEEE EUI64 at factory.
19+
20+
*/
21+
22+
#include "LoRaWANNode.h"
23+
24+
#define FRAME_DELAY 300000 // in ms. Every 5 minutes by default.
25+
26+
// Serial port use to communicate with the USI shield. Specific to the board Discovery L475 IoT.
27+
HardwareSerial SerialLora(PA_1, PA_0);
28+
29+
// AppKey and AppEUI.
30+
const char appKey[] = "0123456789abcdef0123456789abcdef";
31+
const char appEUI[] = "abcdef0123456789abcdef0123456789";
32+
33+
// Data send
34+
char frameTx[] = "Hello world!";
35+
36+
void setup()
37+
{
38+
Serial.begin(9600);
39+
Serial.println("-- LoRaWAN OTAA sketch --");
40+
41+
// Enable the USI module and set the radio band.
42+
while(!loraNode.begin(&SerialLora, LORA_BAND_EU_868)) {
43+
Serial.println("Lora module not ready");
44+
delay(1000);
45+
}
46+
47+
// Send a join request and wait the join accept
48+
while(!loraNode.joinOTAA(appKey, appEUI)) {
49+
Serial.println("joinOTAA failed!!");
50+
delay(1000);
51+
}
52+
53+
Serial.println("Lora module ready, join accepted.\n");
54+
55+
String str = "Device EUI: ";
56+
loraNode.getDevEUI(&str);
57+
Serial.println(str);
58+
str = "Application key: ";
59+
loraNode.getAppKey(&str);
60+
Serial.println(str);
61+
str = "Application EUI: ";
62+
loraNode.getAppEUI(&str);
63+
Serial.println(str);
64+
}
65+
66+
void loop()
67+
{
68+
receive();
69+
transmit();
70+
delay(FRAME_DELAY);
71+
}
72+
73+
void receive(void) {
74+
uint8_t frameRx[64];
75+
uint8_t len;
76+
uint8_t port;
77+
78+
// Check if data received from a gateway
79+
if(loraNode.receiveFrame(frameRx, &len, &port)) {
80+
uint8_t n = 0;
81+
Serial.print("frame received: 0x");
82+
while(len > 0) {
83+
Serial.print(frameRx[n], HEX);
84+
Serial.print(',');
85+
len--;
86+
n++;
87+
}
88+
Serial.print(" on port "); Serial.println(port);
89+
} else {
90+
Serial.println("No data");
91+
}
92+
}
93+
94+
void transmit(void) {
95+
// Send unconfirmed data to a gateway (port 1 by default)
96+
int status = loraNode.sendFrame(frameTx, sizeof(frameTx), UNCONFIRMED);
97+
if(status == LORA_SEND_ERROR) {
98+
Serial.println("Send frame failed!!!");
99+
} else if(status == LORA_SEND_DELAYED) {
100+
Serial.println("Module busy or duty cycle");
101+
} else {
102+
Serial.println("Frame sent");
103+
}
104+
}

examples/getDevEUI/getDevEUI.ino

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
getDevEUI.ino
3+
4+
Display the unique device EUI of the module. The devEUI of the USI module
5+
can't be modified. It is useful to read it to configure the module in a
6+
LoRaWAN network when asked by the network server.
7+
8+
*/
9+
10+
11+
#include "LoRaWANNode.h"
12+
13+
// Serial port use to communicate with the USI shield. Specific to the board Discovery L475 IoT.
14+
HardwareSerial SerialLora(PA_1, PA_0);
15+
16+
void setup()
17+
{
18+
Serial.begin(9600);
19+
Serial.println("-- Get DevEUI sketch --");
20+
21+
// Enable the USI module and set the radio band.
22+
while(!loraNode.begin(&SerialLora, LORA_BAND_EU_868)) {
23+
Serial.println("Lora module not ready");
24+
delay(1000);
25+
}
26+
27+
// Get the DevEUI
28+
String str ="The unique DevEUI is: 0x";
29+
loraNode.getDevEUI(&str);
30+
Serial.println(str);
31+
}
32+
33+
void loop()
34+
{
35+
//empty loop
36+
}

library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=STM32duino I-NUCLEO-LRWAN1
2+
version=1.0.0
3+
author=STMicroelectronics, Wi6labs
4+
maintainer=stm32duino
5+
sentence=This library provides the LoRa® driver for the expansion board I-NUCLEO-LRWAN1.
6+
paragraph=The I-NUCLEO-LRWAN1 features the USI® LoRaWAN™ technology module, addressing low-cost and low-power wide area network (LPWAN) which comes with embedded AT-commands stack pre-loaded. The I-NUCLEO-LRWAN1 is LoRaWAN™ class A certified.
7+
category=Communication
8+
url=https://github.com/stm32duino/I-NUCLEO-LRWAN1
9+
architectures=stm32

0 commit comments

Comments
 (0)