Programming Narrowband IoT Applications

After looking into some of the details of NBIoT modules an LTE Cat NB as a technology itself it’s about time to get started with programming Narrowband Modules such as the BC68/BC95 from Quectel or uBlox’ SARA N410. Looking at the spec sheets of these modules can be a bit overwhelming, so what’s really necessary to connect an IoT device to a backend service? In this series we’re showing how to get started!

Plain old serial communication..

Basically, programming for and communicating with the Narrowband modem chip means serial communication. In general, most GSM/LTE modules are connected via an Uart, and you can issue textual commands, which the modem parses, processes and responds to. So in this context, nothing much has changed over the last 30 years. The modems nowadays of course have many more commands, more processing power, but it’s still the good old "AT" (for: attention) commands.

A first look into the specs or the AT command guides of an LTE modem are important, as there is no per-se default baud rate for modems, some run at 9600bps, some at 115200, and some support auto-sensing of the baud rate.

The next thing to consider is at what pins of a base board the modem is connected. For custom PCBs and design this is not so important, since the modem can be wired to any of the free hardware Uarts that the controlling MCU offers. For standardized hardware boards such as those from Arduino, Adafruit etc. it’s good to check how many uarts (software serial ok, but hardware uarts are better) the MCU/board supports, if the pins match to the pins of the Narrowband shield and if those pins may interfere with other peripherals of the board. An example of this is the Arduino UNO, where the serial pins 14/15 are identical with the USB serial interface - so you can either use USB serial or Narrowband serial, but not both!

One of the simple sketches we can run is an interactive modem session: The board connects both the Narrowband Modem and USB, everything we type goes to the modem, character-by-character, and vice-versa. That’s also an easy debugging solution. We’re using Tekmodul’s Narrowband Shield with an BC68, which has an Arduino form factor. For Arduino, we’re using an Arduino Leonardo and for ARM mbed we’re using STM’s DISCO L475E-IOT board.

Let’s see:

For Arduino:

#include <Arduino.h>

HardwareSerial& modem_serial = Serial1;     

void setup() {
    Serial.begin(115200);
    modem_serial.begin(9600);
}

void loop() {
    if (modem_serial.available()) {
        int c = modem_serial.read();
        Serial.write(c);
    }

    if ( Serial.available()) {
        int c = Serial.read();

        Serial.write(c);
        modem_serial.write(c);
    }
}

For ARM mbed:

 #include <mbed.h>

Serial pc(USBTX, USBRX); 
RawSerial modem(PA_0, PA_1);

int main() {
    pc.baud(115200);
    modem.baud(9600);

    while(1) {
        if(pc.readable()) { int c = pc.getc(); pc.putc(c); modem.putc(c); }
        if(modem.readable()) { pc.putc(modem.getc()); }
    }
}

Running this sketch we can enter commands, after hitting enter the modem responds:

AT+CGMI
Quectel
OK

So that was easy and playing around with modem commands can be fun - but there are a lot of them! Within IoT devices, communication has to be automated and ideally abstracted away in libraries.

Regarding LTE modems, one can find many examples on the web. Typically it looks like sending over commands using the serial objects, mostly ignoring the responses where it’s not strictly necessary and hoping for the best :)

modem.printf("AT+COPS=0\r\n");
modem.printf("AT+CGATT\r\n");
(…)

Some frameworks offer classes for parsing the responses, such as the ATCommandParser from ARM mbed. They’re really helpful as one can code using scanf like statements for parse the response. Unfortunately, sometimes command responses from modems can be complex and span several lines, sometimes - depending on the configuration - unsolicited messages may appear in between, e.g. when the modem looses cellular connectivity. All that can make it hard for static scanf-like parsing code.

Configuration

Ideally, the combination of LTE module and SIM card have everything on board and pre-defined, so that the modem automatically connects to the cellular network and is ready to go. This is mostly about

  • Band settings (which LTE band(s) to use)
  • PDP Context (definition and activation of APNs)
  • Operator selection (typically mostly automatic)
  • Automatic connection on startup

There are commands for all of these settings, but we prefer to have an abstraction for this and a library. So we decided to work on C++ and (Micro)Python Libraries for modules from Quectel and uBlox.

Libraries

Arduino is doing great work on simplifying programming peripherals and other aspects in embedded devices. For an Arduino-compatible library, developers typically can expect a C++ class with a begin() method to initialize it, some methods for querying and modifying state, and "bridges" to other classes from the Arduino Framework, e.g. EthernetUDP from the networking stack.

Programming Narrowband modules should be comparable to that. So that sending a small UDP packet should be doable with a (sample) code like this:

Narrowband  nb(Serial1, 9600);

void setup() {
    nb.begin();
    while( !nb.attached()) {
        delay(1000);
    }
    Serial.println(nb.signalQuality());
    nb.sendUDP("thingforward.io", 9876, "Sample");
}

Currently, this is in the works. You can take look at the current state of the Arduino Library on github.com/thingforward/nbiot-arduino and on platformio’s library manager:

$ pio lib search narrowband
Found 1 libraries:

nbiot-arduino
=============
#ID: 5975
Arduino Library for accessing Narrowband IoT modules from Quectel (BC68, BC95)

A C++98 Library for ARM mbed OS is also planned. It will have more higher level abstractions and make configuration of modules even easier. Expect a first preview to be ready mid of February.

Python is a great language within the embedded field as well, so we have beed working on this, too. github.com/thingforward/nbiot-python is the current state of our Narrowband Python Library, e.g. to be run on a RaspberryPi or other Linux-based SBCs. You can expect some examples in one of the upcoming posts of this series!

And because our friends at Zerynth are very successfully working on Python on Embedded, we decided to write a port for their Zerynth VM as well.

In the next post, we’re talking a sample walk-through on the Arduino Library show how to connect a Narrowband-device to a backend. See you later!

Andreas