Getting started with Arduino MKRWAN1300 & LoRaWan TTN

After making some post on Arduino MKRFOX1200, here I come with the first steps to use MKRWAN1300 board to send your first frame on TTN and also how to use them for discovering the TTN coverage around.

MKRWAN1300 board is a LoRaWan Arduino board based on the Murata CMWX1ZZABZ module. This module is capable for LoRaWan in Europe (868Mhz), NA (915MHz) Asia (923MHz) …. It is also capable for Sigfox in both zone (but actually not with this board as much as I know). Producing 14dB emission and capable for 20dB emission for FCC zone. The price of the Arduino board is about 40€ and it is largely available on Internet.

In this post we are going to see how to make the first steps with this board and create a device to map the TTN network coverage with and without a GPS.

Configure your board – first steps

As for any modern Arduino Board you need to download the right Board and Library. So, once you have started your Arduino application you need to add these elements:

  • Go to Tools >> Boards >> Board Manager menu
  • Search for MKR

  • Select  the last revision and click on Install button.
  • Wait for a while 😉

Then you need to install the associated Library for module communications:

  • Go to Sketch >> Include Library >> Manage Libraries menu
  • Search for MKRWAN

  • Select the last version and click on Install button.

The last step is to update the Murata modem with the last firmware. This is done by executing a sketch provided with the library (should not be a mandatory step).

  • Connect the antenna.
  • Connect Arduino MKRWAN1300 to your computer over USB.
  • Select the board type in menu Tool >> Boards >> Arduino MKR WAN 1300
  • Select the Serial port in menu Tool >> Port >> … (Arduino MKR WAN 1300)
  • Load the MKRWANFWUpdate_standalone sketch from File >> Example >> MKRWAN menu

Now you can upload the sketch on the Arduino board and open the serial console to watch the firmware execution.

Make your first sketch to communicate over LoRaWan

We can start from the File >> Example >> MKRWAN >> LoraSendAndReceive sketch for our first communications.

 /!\ Before powering your board, remove it from the black foam: that one is conductive (!!) so you make your board at risk…

First we need to get the device EUI (kind of MAC address for the LoRaWan device), this can be obtained by uploading the sketch on the Arduino board and run it by opening the Serial Monitor. You get the following print:

Your module version is: ARD-078 1.1.6
Your device EUI is: a8610a3037211111

The device EUI is printed, save this value we will need it later.

We need APP_EUI and APP_KEY for getting our device communicating. For this We will register a new application in TheThingsNetwork console. You need to register if you do not have an account.

Once done you get the APP_EUI value to be used. This one can be copy/paste in the arduino_secret.h file of the sketch.

Now you can click on Register a new device and complete the form. In this form you need to enter the device EUI we have previously obtained and click on Register.

This gives your the AppKey you can copy/paste into the arduino_secret.h file of the sketch.

In the Main file of the Sketch you need to verify the radio settings:

// change this to your regional band (eg. US915, AS923, ...)
if (!modem.begin(EU868)) {
  Serial.println("Failed to start module");
  while (1) {}
};

Then you can compile & upload the sketch on the Arduino board. Open the Serial Monitor and type a word in the input box and send it. A message will be created with the text and send over TTN. You will see the result in the TTN interface in the Data tab of your created device.

If you click on frame detail (clic on the frame containing the payload) you can see information like the spread factor used:

"modulation": "LORA",
"data_rate": "SF12BW125",
"coding_rate": "4/5",

In the serial monitor you get a such result:

Enter a message to send to network
(make sure that end-of-line ‘NL’ is enabled)

Sending: TEST
- 54 45 53 54 0D 
Message sent correctly!
No downlink message received at this time.

TEST is my word, the following line are the corresponding byte of this word.

The frame is sent with a transmission confirmation as indicated by the “true” value passed at andPacker function call.

modem.endPacket(true);

The “Message sent correctly!” in the log is indicating the confirmation reception from the gateway.

Map coverage without GPS

Now we want to see where coverage is. Without GPS we can simply create a Led display when messages are sent and received by the network. For this we will make some change in the source file to simplify it. The first thing is to change the spread factor for have a higher communication frequency and we will send 8 bytes per frame for later use (with GPS).

I chosen SF7 for the frequency of communication, this allowing a frequency of communication every 6s respecting the duty cycle. Basically we can refresh our position every 10 seconds. The way the firmware works makes it a little bit more complicated when requesting for confirmation: If the communication fails at SF7 the firmware send a second frame and a third frame at different SF up to 12. As a consequence this totally kills your duty-cycle timing and force you to wait for a while. As the driver is really bad you have no feedback about this and it make it complex to manage your transmissions. For this I made different wait time and you need to wait 2 minutes (duty cycle rule) in case of missed communication. Clearly that’s a real issue.

The distance with SF7 is lower than what we can achieve with SF12 encoding so the given map will be more secured according to this setting.

So let’s see that sketch:

#include <MKRWAN.h>
LoRaModem modem;

#include "arduino_secrets.h" 
String appEui = SECRET_APP_EUI;
String appKey = SECRET_APP_KEY;

bool connected;
int err_count;

void setup() {
   modem.begin(EU868);
   delay(1000);      // apparently the murata dislike if this tempo is removed...
   connected=false;
   err_count=0;
}

void loop() {
   char msg[12] = {0,1,2,3,4,5,6,7,8,9,10,11};

   if ( !connected ) {
    int ret=modem.joinOTAA(appEui, appKey);
    if ( ret ) {
      connected=true;
      modem.minPollInterval(60);
      modem.dataRate(5);   // switch to SF7
      delay(100);          // because ... more stable
      err_count=0;
    }
  }
  if ( connected ) {
    int err=0;
    modem.beginPacket();
    modem.write(msg,12);
    err = modem.endPacket(true);
    if ( err <= 0 ) {
      // Confirmation not received - jam or coverage fault
      err_count++;
      if ( err_count > 50 ) {
        connected = false;
      }
      // wait for 2min for duty cycle with SF12 - 1.5s frame
      for ( int i = 0 ; i < 120 ; i++ ) {
        delay(1000);
      }
    } else {
      err_count = 0;
      // wait for 10s for duty cycle with SF7 - 55ms frame
      delay(10000);
    }
  }
}

We have a simple sketch managing transmission confirmation, retry and disconnection. It normally sent a frame every 14-15 seconds.

Now we are going to add a RGB led to display the result. I’m using a RGB led with common anode. 3 x 1kohm resistor are added on each of the cathodes for limiting current. The anode is connected to VCC and cathodes are connected to GPIO 3/4/5.

The code is modified to have a green light when the communication is confirmed, a red one when the communication has failed. Blue when we consider the device as disconnected.

You can get the code from this github repository

Add a GPS to send your information into TTN-Mapper

To add a GPS I’ll use the L80 module as I did for this previous LoRaWan tracker. Basically the circuits looks like this:

The system is waiting for the position to be determined with the altitude. This is requiring 4 satellites in view. The board is blinking until the position and altitude are valid. The number of consecutive blinks indicates the number of satellites in view+1.

Once positioned a frame is encoded with the position Lat+Lng, the altitude and the hdop. They are the information required by ttnmapper.org to construct the map of coverage.

When the position becomes invalid a frame is send with a different header to be separated from the coverage information but it keeps the led light on with the right color.

The code of this sketch can be found on GitHub.

Now we need to decode the frame on TTN backend and connect with ttnmapper. For this we need to decode the data in TTN backend by creating a Payload Format function. For this you need to go to the TTN console, then select application and once in the application we have created clic on Payload Format tab.

Once in we can create the javascript function to decode the messages. Only the messages with a 00 header will be proceed. ttnmapper.org service requires a result with different fields completed: latitude, longitude, altitude and hdop.

We are creating a decoder function with the following code:

function Decoder(bytes, port) {
   // Decode an uplink message from a buffer
   // (array) of bytes to an object of fields.
   var decoded = {};
   if (port === 2) {
     if ( bytes[0] === 0 ) {
       decoded.latitude = ((bytes[4]*256.0)+bytes[5])*256.0+bytes[6];
       decoded.latitude = (decoded.latitude / 93206.75) - 90;
    
       decoded.longitude = ((bytes[7])*256+bytes[8])*256+bytes[9];
       decoded.longitude = (decoded.longitude / 46603.375 ) -180;
       
       decoded.altitude = (bytes[1]*256)+bytes[2];
       decoded.hdop = bytes[3]/10.0;
     }

     decoded.raw="";
     for ( var k = 0 ; k < 10 ; k++ )
       decoded.raw += (bytes[k]<16)?"0"+bytes[k].toString(16):bytes[k].toString(16);
     decoded.time=Math.round(new Date().getTime()/1000);
   }
   return decoded;
}

This will create  structure like this:

{
   "altitude": 450,
   "hdop": 1.2,
   "latitude": 45.XXX,
   "longitude": 3.XXX,
   "raw": "00xxxxxxxxxxxxxxx",
   "time": 1535624585
}

Now we need to send this structure to the ttnmapper service. This operation is simple thanks to the prepackaged Integrations existing in TTN. You click on Integration tab

And create a new integration. Then you need to select TTNMapper integration:

Once done you just need to specify a ProcessID and an Email. The other can be left empty. Click on Add Integration and you’re done.

Now your device is starting to push its geolocation data to ttn mapper service and your coverage is added to the map. To see it in real time you need to go to Advanced map Options from the menu and enter your deviceID like in the following screen. Then you can click on Map and show the coverage results:

 

The main map is refreshed differently so you need to wait a bit to see your coverage to appear on it.

Take you a lot jpmeijers for that really useful tool and the support you gave me for debugging getting started 😉 you rocks !

 

Conclusion about Arduino MKRWAN 1300

This board have some nice things : price, accessibility, size, arduino… that’s great. The problem is the same as for MKRFox 1200: these board have some of the worst peace of code I ever seen to make them running. The MKWAN code is durty, with no comments, included in a global .h file… All what you start to learn to not do at school. As a consequence the stability is really bad. Some concrete example:

  • With no delay between init and connect your crash the LoRaWan stack
  • The reset button crash the LoRaWan stack you need to power on/off
  • Once the communication has failed 1 time it won’t be back after.
  • The spread factor is not always respected with no feedback… this create duty-cycle non respect and impacts your code. Assuming there are good reason but not documented.
  • Once start failing the library always failing (even with good coverage) with no explanation.
  • Serial Cable was jamming the GPS. As a consequence the location is false (about 200 meters) and the altitude is totally wrong… Once on a power-bank that was solved. So be careful.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.