IOT

OTAA-based LoRaWAN Node with Arduino & LoRa SX1276

In this post, we will discover how to develop an OTAA-based LoRaWAN node using Arduino and the SX1276 LoRa module. This guide explains how to build a DIY LoRaWAN End Node that can be operated in OTAA mode using the SX1276 LoRa module and Arduino Pro Mini. The node may publish “Hello, world!” to The Things Network Dashboard. We will learn how to decrypt the encrypted data transmitted over the LoRaWAN in order to read the message in a readable format.

Hardware Required

S.N.COMPONENTS NAMEDESCRIPTION
1Arduino BoardArduino Pro Mini 3.3V
3USB-to-TTL ConverterFTDI Module
2LoRa ModuleSX1276 868 MHz
4Connecting WiresJumper Wires
5Breadboard

LoRa Module SX1276

You can use any LoRa chip based on the SX1276 and operating at 868MHz. If you are employing a 915MHz Gateway, you can utilize SX1276 with a 915MHz frequency variant. In this tutorial, an 868MHz-frequency LPS8 LoRaWAN gateway is utilized.

Semtech has designed the SX1276 LoRa chip. The SX1276 incorporates the LoRa spread spectrum modem, which is capable of attaining a substantially greater range than previous FSK or OOK-based systems. At maximum data rates, the sensitivity of LoRa is 8dB greater than that of FSK. In contrast, utilizing a low-cost bill of materials with a 2Oppm XTAL LoRa can increase receiver sensitivity by more than 20dB compared to FSK.

SX1276 Pinout

In this tutorial, we are using the SX1276 chip manufactured by Gplus-IoT. The Gplus-IoT LoRa Module SX1276 has a total of 18 pins whose functionalities are as follows:

SX1276 Pinout

Designing SX1276 Breakout Board

The Gplus-IoT SX1276 chip is extremely small, making it challenging to interface with any controller. I used EasyEDA software to create a simple breakout board, which I then translated into a PCB. The PCB layout is like this roughly.

SX1276 PCB

The Gerber File for the PCB is given below. You can simply download the Gerber File and order the PCB from NextPCB.

Download Gerber File: SX1276 Breakout PCB

Now you can visit the NextPCB official website by clicking here: https://nextpcb.com. So you will be directed to the NextPCB website. From here you can directly order the PCB.

SX1276 PCB

The SX1276 chip was then put onto the PCB. The SX1276 chip features an extremely narrow space between adjacent pins. Therefore, excellent soldering abilities are required to solder the components.

SX1276 Breakout Board

Hardware Setup & Connection

Let’s examine how to connect the SX1276 LoRa Module to the Arduino Pro Mini. The question is why Arduino Pro Mini is being utilized instead of Arduino UNO or Nano. LoRa Chip is an SPI-based chip with a 3.3V logic level, which is the reason why. In order to obtain the 3.3V logic level, we must use an Arduino board with 3.3V logic. Arduino Pro Mini Board is responsible for this logic.

Here is a diagram of the connection between the SX1276 LoRa Module and the Arduino Board.

OTAA LoRaWAN Node Arduino SX1276

Connect each SPI Pin of the SX1276 to an SPI pin on the Arduino. At least two digital input-output pins of the SX1276 must be connected to an Arduino digital pin. In this circuit, the DIO0, DIO1, and DIO2 pins of the SX1276 are accordingly linked to the Arduino D3, D4, and D5 pins. If these pins are left disconnected, the LoRaWAN hardware will not function in ABP & OTAA Mode.

ABP vs OTAA Activation Method

The LoRaWAN Nodes can be activated using either the ABP Activation or OTAA Activation procedures. Let’s examine the distinctions between the ABP and OTAA activation modes for LoRaWAN endpoints.

ABP

During ABP activation, a fixed DevAddr and session keys for a pre-selected network are hardcoded into the end device and remain unchanged for the duration of the device’s life. With this mode, an end device bypasses the join procedure, which appears to be simpler, but ABP has quite a few restrictions.

OTAA

Root keys are provisioned on OTAA endpoints. An end device performs a join operation with a LoRaWAN network during OTAA activation, during which a dynamic DevAddr is assigned and root keys are used to derive session keys. Therefore, DevAddr and session keys vary with each new session.

Registration of LoRaWAN Node on The Things Network Server

For delivering LoRaWAN Node data to TTN (The Things Network), prior knowledge of TTN is required, such as how to configure an application and activate a LoRaWAN device via the OTAA technique. After configuring your TTN application, there are three parameters to consider: Device EUI, Application Key, and Application EUI.

Log in to your account on the TTN website, https://console.thethingsnetwork.org/ Then, navigate to the console and choose a cluster to begin adding devices. In my situation, I opted for the EU cluster.

Choose Application from the drop-down menu and create a new application. Then, enter the application ID and other details, and create the application.

Add an End device, then select the desired frequency plan and LoRaWAN version.

LoRaWAN The Things Network

Select manually to select the active mode for OTAA and LoRaWAN versions, then enter the values using the prompts. Create then Device EUI, App EUI, and AppKey. Next, click register end devices

Now the terminal node is created successfully. Therefore, you can see that three arguments have to be added to the code.

On the device page, the payload formatters must be configured to decode the payload the LoRaWAN node transmitted. Select the Uplink and the Javascript option. Enter and save the following code.

function Decoder(bytes, port) {
var result = “”;
for (var i = 0; i < bytes.length; i++) {
result += (String.fromCharCode(bytes[i]));
}

return {text: result};
}

The TTN application configuration is now complete.

Source Code & Programming

Now let’s program the Arduino Pro Mini to utilize the OTAA method to activate the SX1276-based LoRaWAN node.

Arduino-LMIC library will be utilized for this purpose. Download the library from the Github source and install it using the Arduino IDE’s add zip library functionality.

Arduino-LMIC library ABP OTAA LoRaWAN SX1276

Open the ttn-otaa example by selecting the IBM LMIC framework under the examples section of the file menu.

SX1276 Arduino OTAA Activation

Before submitting the code, several modifications must be made to the example code. Add Device EUI, APP Key, and APP EUI to the lines shown below.

static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM DEVEUI[8]={ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM APPKEY[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };

Also make changes to the Arduino Pins here.

const lmic_pinmap lmic_pins = {
.nss = 6,
.rxtx = LMIC_UNUSED_PIN,
.rst = 5,
.dio = {2, 3, 4},
};

You also need to modify some library files to get this code working in case the code fails.

Here is the complete code for the project.


#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>

// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}

// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}

// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
// The key shown here is the semtech default key.
static const u1_t PROGMEM APPKEY[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}

static uint8_t mydata[] = “Hello, world!”;
static osjob_t sendjob;

// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 60;

// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 6,
.rxtx = LMIC_UNUSED_PIN,
.rst = 5,
.dio = {2, 3, 4},
};

void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(“: “);
switch(ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F(“EV_SCAN_TIMEOUT”));
break;
case EV_BEACON_FOUND:
Serial.println(F(“EV_BEACON_FOUND”));
break;
case EV_BEACON_MISSED:
Serial.println(F(“EV_BEACON_MISSED”));
break;
case EV_BEACON_TRACKED:
Serial.println(F(“EV_BEACON_TRACKED”));
break;
case EV_JOINING:
Serial.println(F(“EV_JOINING”));
break;
case EV_JOINED:
Serial.println(F(“EV_JOINED”));

// Disable link check validation (automatically enabled
// during join, but not supported by TTN at this time).
LMIC_setLinkCheckMode(0);
break;
case EV_RFU1:
Serial.println(F(“EV_RFU1”));
break;
case EV_JOIN_FAILED:
Serial.println(F(“EV_JOIN_FAILED”));
break;
case EV_REJOIN_FAILED:
Serial.println(F(“EV_REJOIN_FAILED”));
break;
break;
case EV_TXCOMPLETE:
Serial.println(F(“EV_TXCOMPLETE (includes waiting for RX windows)”));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F(“Received ack”));
if (LMIC.dataLen) {
Serial.println(F(“Received “));
Serial.println(LMIC.dataLen);
Serial.println(F(” bytes of payload”));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F(“EV_LOST_TSYNC”));
break;
case EV_RESET:
Serial.println(F(“EV_RESET”));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F(“EV_RXCOMPLETE”));
break;
case EV_LINK_DEAD:
Serial.println(F(“EV_LINK_DEAD”));
break;
case EV_LINK_ALIVE:
Serial.println(F(“EV_LINK_ALIVE”));
break;
default:
Serial.println(F(“Unknown event”));
break;
}
}

void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F(“OP_TXRXPEND, not sending”));
} else {
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
Serial.println(F(“Packet queued”));
}
// Next TX is scheduled after TX_COMPLETE event.
}

void setup() {
Serial.begin(115200);
Serial.println(F(“Starting”));

#ifdef VCC_ENABLE
// For Pinoccio Scout boards
pinMode(VCC_ENABLE, OUTPUT);
digitalWrite(VCC_ENABLE, HIGH);
delay(1000);
#endif

// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();

// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
}

void loop() {
os_runloop_once();
}

Testing OTAA based LoRaWAN Node

Now we must test the SX1276 LoRa Module and Arduino Pro Mini OTAA-based LoRaWAN Node. So, after uploading the preceding code, launch the Arduino IDE’s Serial Monitor.

If the EV-TXCOMPLETE text appears on the serial display, it indicates that your Lora device is transmitting Lora data packets.

Now go to applications live data. where you may view the payload received from the device. You can view the received data packet’s data, spreading factor, signal-to-noise ratio, and RSSI.

As we have already prepared the payload while configuring The Things Network Dashboard, the data we have received is already decrypted.

Conclusion

I hope all of you have understood the basics of OTAA-based LoRaWAN Node with Arduino & LoRa SX1276. We MATHA ELECTRONICS will be back soon with more informative blogs soon.

Leave a Reply

Your email address will not be published.