How to work with LoRaWAN and a PLC controller

Using a PLC Arduino to work with LoRaWAN communication
February 12, 2024 by
How to work with LoRaWAN and a PLC controller
Boot & Work Corp. S.L., Queralt del Águila Munté



LoRaWAN is a long-term, low-power wireless network specification, (LPWAN), based on LoRa modulation that can achieve communications up to 20 Km in favorable conditions. It is a MAC (Media Access Control) used to connect different LoRa devices and provide authentication through the connections following standard protocols. If you wish to know more about LoRa and LoRaWAN check out the Related Link blogs.

When working with LoRaWAN, authentication and encryption of the data are required. Furthermore, before you can communicate with devices, you will have to add an application and a gateway to a network and register the devices to it. A Network Session Key and an Application Session Key are required in order to encrypt the data. There are two possible methods the device can use to get these keys, by activating the connection with OTAA or ABP. Below you will see how to work with both configurations and their advantages and disadvantages. Industrial Shields provides some examples to work with industrial controllers for Arduino automation.


Related links


What is OTAA?

Over-The-Air Activation (OTAA) is an authentication method where the Network Session Key and the Application Session key are generated on every new connection. When connecting using a join-request, a device is given an Appeui, a Deveui and the AppKey that will be used to generate the Network Session Key and the Application Session Key. 

On the OTAA method the keys are generated on every new connection, making it safer as the keys are also deleted when the connection is over. Moreover, the device can easily be change to a new network and the keys cannot be as easily intercepted. Even though, the device be able to store the keys and decide when a join request is necessary.

What is ABP?

Activation By Personalisation (ABP) is an authentication method where the Network Session Key and the Application Session Key are programmed by default on the device. As the keys are preprogramed, it is not necessary to establish a join connection every time that a new connection is required.

Having the keys preprogramed reduce time connections as any join request is needed when connecting to the server. However, the method cannot repeat keys and must be sure that they are unique. Although, the keys can be easily discovered even before the connection is establish. 

How to program it

In order to test the LoRaWAN we will be working with The Things Network, so we will be using one of their gateways in order to make the connection. Make sure to have an account and have set the previous configuration of the application and the gateway. By applications, we mean whatever it is your devices communicate with on the internet.

On this basic example, we will send to the server by our gateway some data every 60 seconds. It will help us introduce the LoRaWAN communication and see how the connections work.

First of all, Arduino IDE must have been downloaded and being installed with our Industrial Shields boards. Then choose the board M-Duino Family and the model that you are working with. We will be using an M-Duino LoRa 21+. If not, please configure it before moving on to the next step following our tutorial.

After setting all the previous setup, open the MCCI LoRaWAN LMIC library examples and choose the ttn-otaa or ttn-abp depending on the activation that you wish to work with.

Both configurations have a similar code but with important differences. Make sure to know which one you are going to work on as different keys are needed and it would be impossible to work otherwise. The differences will appear on the first lines of the code where the defines are declared. See the sections on the end to know which parameters must be changed in order to work with OTAA or ABP.

How to work with LoRaWAN and a PLC controller

On the following lines can be seen how to set the data that will be sent and the time interval in seconds that the device will be sending the packets. By default, it will send the string “Hello, world!” every minute. 

It is important to correctly set the Arduino pins. On our industrial Arduino Programmable Logic Controller, we will be using pin 12 for the Chip Select and pin 13 for the Reset*. The Industrial Shields adopted LoRa library does not use the RXTX and DIO pins as the reception and transmission checks are done internally reading the pin registers and sending the data via ModBus.  

(*In the case of the Ardbox LoRa Family, we will be using the pin 23 for the Chip Select and the pin 3 for the Reset. Be careful with the interruptions configuration using LoRa). 

Configure these parameters as the following lines:

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 = 12,
.rst = 13,
In both examples, the void function onEvent(ev_t ev) can be called for debugging if it is wished. However, in this example, we will not be using this function. For more detail check the library readme.
The do_send(osjob_t* j) will be the one used to transmit the data to the used gateway. Also, it will print “Packet queued” as an indicator.

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.
On the setup function, we will initialize the serial for being able to print messages on the Serial Monitor and all the configurations for the LoRa communication. By default, only three base channels from the LoRaWAN specification are used, that had been set up by The Things Network. If only working with one LoRa device, the default configuration may not be changed, however adding more channels is recommended as the network will work better. For adding them add the following lines (this are configurated for the Europe standards, see the library specification for other regions):

#if defined(CFG_eu868)
LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band
LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band
LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band
# error Region not supported

Finally, the os_runloop_once()must be called on the loop() function for constantly checking and updating the LoRaWAN communication. Other debug options as blinking LEDs up can be implemented for a more visual debug option.

void loop() {
    unsigned long now;
    now = millis();
    if ((now & 512) != 0) digitalWrite(13, HIGH);
    else digitalWrite(13, LOW);

The Things Network

OTTA example

If working with OTAA example, the keys for AppEui, DevEui and AppKey must be passed. Those parameters are private and must be obtained through The Things Network personal account.
Remember that AppEui and the DevEui must be passed in little-endian format (least-significant-byte first) while the AppKey must be passed in big-endian format. Put them on the following lines replacing the FILLME text:

static const u1_t PROGMEM APPEUI[8]={ FILLMEIN };
static const u1_t PROGMEM DEVEUI[8]={ FILLMEIN };
static const u1_t PROGMEM APPKEY[16] = { FILLMEIN };
Cómo trabajar con LoRaWAN y un controlador PLC

ABP example

If working with ABP example, the keys for DevAddr, NetwKey and AppKey must be passed. Those parameters are private and must be obtained through The Things Network personal account. Remember that NetKey and the AppKey must be passed in big-endian format. Put them on the following lines replacing the FILLME text:

static const PROGMEM u1_t NWKSKEY[16] = { FILLMEIN };
static const u1_t PROGMEM APPSKEY[16] = { FILLMEIN };
static const u4_t DEVADDR = FILLMEIN ;

Device configuration

To configure this application, you need to register for free on The Things Network. This registration will enable communication with your device using LoRaWAN. First and foremost, it's important to understand the application. Follow these steps:

  1. Create an application and choose a name for it. This step is simple; you can invent any name you like.
  2. Register a device by clicking on "+Register end device."
  3. Choose the manual option: "Enter end device specifics manually."
  4. Select the following options:
    • Frequency plan: "Europe 863-870MHz (SF9 for RX2 - recommended)"
    • LoRaWAN version: Choose either "LoRaWAN 1.0.1" or "LoRaWAN 1.0.2"
    • Regional Parameters version: For 1.0.1, there are no parameters; for 1.0.2, choose "RP001 Regional Parameters 1.0.2."
  5. Enter a JoinEUI, which is the same as AppEUI. Contact the manufacturer to obtain the JoinEUI. If unavailable, using all-zeros is acceptable.
  6. Confirm the configuration and generate the DevEUI and AppKey parameters.

After completing these steps, your device is completely created. Additionally, you can specify the device's location and format the payload.

A recommended way to format the payload, especially when using the LMIC library or OTAA example, is to select the custom JavaScript formatter and insert the following code:

function decodeUplink(input) {
  if (input.bytes && input.bytes.length > 0) {
    const decodedChars = [];

    for (let i = 0; i < input.bytes.length; i++) {
      const charValue = String.fromCharCode(input.bytes[i]);

    return {
      data: {
        decodedChars: decodedChars.join('')
      warnings: [],
      errors: []
  } else {
    return {
      data: {},
      warnings: ["No bytes in the input"],
      errors: []

Now you can start to explore and communicate with you physical device using LoRaWAN. However, this configuration works with a M-duino device and the example code provided by our LMIC library. If something goes wrong you can change the parameters and configurations or just register a new device.


For knowing if the connection has gone well, enter on The Things Network and check out if any message has been through the gateway and has arrived at the server. Make sure that the frame is set to 0 as if not, it might provoke an error.

​Search in our Blog

How to work with LoRaWAN and a PLC controller
Boot & Work Corp. S.L., Queralt del Águila Munté February 12, 2024
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.

Industrial PLC comparison >>>