Trying out SigFox using Low-Cost Maker Hardware

Lately we’ve examined Arduino’s MKRFOX1200 board to see how it can be programmed and connected to SigFox’ LPWAN network. Thanks to the excellent hardware and software it worked out pretty well and quite fast.

The Arduino MKRFOX1200 is a small 32bit development board, based on an ARM Cortex M0+, and it already includes a SigFox transceiver to communicate with their LPWAN network. It can be programmed using the Arduino Framework, in our case with PlatformIO; but it also works with the Arduino IDE.

And there’s already a SigFox Library from Arduino around, which makes SigFox functionality available through a simple C++ class - perfect. So this is a hassle-free starting point, but it comes with some costs. The Arduino Shop sells it for 35 EUR excl. shipping, and some shops in Germany slightly above that. So we’ve been looking for alternative solutions.

Wisol module

SigFox’ partner portal lists a multitude of developer boards and components. We wanted to integrate a module with the Grove Kit modules we’re using in our trainings and workshops - and found the SigFox Node from LPWAN S.R.O. Arduino-Shop.eu sells it for around 23€. It contains a simple transceiver from WiSOL, the WiSOL SFM10R1 which understands an AT Command set via serial line. „R1“ is the abbreviation for SigFox Zone 1, which includes Europe. Depending on the region you’re in, you’d possibly need a different chip. The price tag is still high given that a standalone module costs around $3 only. But we’re not looking for designing our own PCB, so a breadboard-ready module had to do the job. In the end it sounded easy, so we ordered one and tried it out!

Important notice: Before buying any Sigfox hardware, (1) make sure that the location you’re at is covered by the SigFox network. SigFox' coverage map depicts the coverage quite well. And (2), pick a transceiver module that works in the zone you’re in. Otherwise operating it might not work and/or might not be legal in your country.

Prototyping and training hardware

Regarding our Thingforward.io Trainings and Workshops, we’re using inexpensive, arduino-compatible MCUs with an ESP8266 - the NodeMCU. There’s a base shield available for the Grove Kit system which helps us to easily connect sensors and actuators from the full range of available modules - must be over 100 by now. Using a proper cable, we can connect the WiSOL module to the Grove Base shield. It has a four pin connector: 3.3V, GND, Serial TX and Serial RX. Fits perfectly to a grove cable connector!

So our testing playground consisted of

If you do not like to have all this stuff from Grove around, a simple breadboard with the NodeMCU will also do, as also will smaller ESP8266-based boards such as a WeMos D1 Mini (around $4 from aliexpress). A NodeMCU costs around 8€ from resellers in Germany, but can probably be found for less at online stores shipping from China.

But back to the WiSOL Sigfox module.

AT Command set

As mentioned above this module is controlled by serial line, using an AT command set. This is a set of single line commands, all starting with AT (for „attention“, to help the modem within distinguish between commands and data). For example, sending a message to the SigFox network with the „Send Frame“ command, like so:

AT$SF=00FF

Sends a simple two-byte message containing bytes 0x00,0xFF to the network. LPWAN ships the module with a print out of all AT commands which helps for the firsts steps, and a PDF is available as well. For the first steps, only three commands are really necessary:

  • getting the SigFox Module ID,
  • getting the Module PAC (both are used to register/claim the device)
  • send messages.

Using a SoftwareSerial object from the Arduino Framework makes it easy to connect the module to some GPIO pins, and send commands over the Serial object.

A simple wrapper library

We’re interested in using this module for other boards and embedded frameworks as well, so a library tied to the Arduino Framework does not help. Instead we started a simple C99 library which is independent of the Embedded OS Serial handling, so it can be used it many projects. It abstracts away the commands from the actual serial sending/receiving part. A developer has to write a small adapter function for handling synchronized serial communication (sending a command to the module, waiting for a response or time out). It also includes an example adapter for the Arduino framework.

The Library then offers convenience C functions to trigger commands, such as

void wisol_sigfox__get_id(char *p_id_buf);
void wisol_sigfox__get_pac(char *p_pac_buf);
bool wisol_sigfox__send_frame(const uint8_t *p_payload_buf, size_t payload_size, bool downlink_flag);

and more. So you don’t have to deal with AT commands, simply use the functions. Let’s see how.

Start a new C project

We’re heavy users of PlatformIO, so we decided to publish the above library on PlatformIO’s registry. Let’s start with a simple project on our NodeMCU board. If you’re using another board, please check the -b parameter.

$ mkdir pio-lpwan-sigfox-demo
$ cd pio-lpwan-sigfox-demo
$ platformio init -b nodemcuv2
(…)
Project has been successfully initialized!
(…)

Now, search for the WISOL library and install it:

$ pio lib search wisol
Found 1 libraries:

c99-sigfox-wisol-WSSFM10R1AT
============================
#ID: 1893
C99 library for accessing SigFox modules based on WISOL SFM10R1AT
(…)

Add the name of the library to platformio.ini, under the current environment section, at lib_deps:

(…)
[env:nodemcuv2]
(…)
lib_deps = c99-sigfox-wisol-WSSFM10R1AT

A call to pio run will install the library:

$ pio run
Processing nodemcuv2 (platform: espressif8266; lib_deps: c99-sigfox-wisol-WSSFM10R1AT; board: nodemcuv2; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LibraryManager: Installing id=1893
Downloading  [####################################]  100%
Unpacking  [####################################]  100%
Verbose mode can be enabled via `-v, --verbose` option
Collected 24 compatible libraries
(…) 

First step: Find out Module ID and PAC

As mentioned above, first thing to do is to find out the ID and PAC of this module. Our library includes sample code for Arduino, so we copy it over to our src folder:

$ cp .piolibdeps/c99-sigfox-wisol-WSSFM10R1AT_ID1893/examples/arduino/main.ino ./src/

Let’s look at src/main.ino:

#include <Arduino.h>
#include <SoftwareSerial.h>
#include "wisol_sigfox.h"

// Software Serial to be used to communicate with SigFox module
// Change RX/TX pins according to your setup.
SoftwareSerial  wisol_serial(D1,D2);

It starts with including headers for the Arduino platform of course, the SoftwareSerial class and the wisol_sigfox.h header of our library. When defining a SoftwareSerial, the constructor needs both RX and TX pins as in the last line of the above snippet. We connected to D1/D2 (RX/TX). You’re free to select whatever pins available, just make sure that TX and RX are cross connected.

Meaning: D1 is the RX pin for the SoftwareSerial object, and it has to connect to the TX pins of the WISOL module. Inverse for D2, this needs to be connected to RX at the WiSOL module.

Looking at main.ino again:

/** initialize software serial with proper timeouts */
void wisol_sigfox__serial_init() {
  wisol_serial.begin(9600);
  wisol_serial.setTimeout(100);
}

/** adapter function for synchronous communication with module */
void wisol_sigfox__serial_sync(const char *cmd, char *p_response_buf, int sz_response_buf, int timeout) {
(…)

In this function we initialize the SoftwareSerial, the module understands 9600bps 8N1. Then comes an adapter function which takes an AT command, sends it to the module via wisol_serial, waits up to timeout msecs for a response and puts it into p_response_buf as a 0-terminated string. At present this is done synchronously, we still need an asynchronous interface here for other OSes.

Let’s look at the setup() function, our entry point into this sketch.

void setup() {
(…)
  // initialize serial communication
  wisol_sigfox__serial_init();

  //
  if (wisol_sigfox__ready()) {
    Serial.println("Sigfox module is ready.");

    char buf[32];
    wisol_sigfox__get_id(buf);
    Serial.print("ID="); Serial.println(buf);

    wisol_sigfox__get_pac(buf);
    Serial.print("PAC="); Serial.println(buf);
(…)

The above snippet leaves out some lines so we can concentrate on sigfox commands. First comes a call to initialize the SoftwareSerial. wisol_sigfox__ready() just sends an empty AT command to the module, which should response with OK if it’s ready (and connected correctly). After that come calls to wisol_sigfox__get_id() and wisol_sigfox__get_pac() to retrieve ID and PAC, sending it to the default Serial object as debug messages.

That’s sufficient for a first test!

$ pio run -t upload && pio device monitor

yields:


[Wed Nov 22 13:48:01 2017] Processing nodemcuv2 (platform: espressif8266; lib_deps: c99-sigfox-wisol-WSSFM10R1AT; board: nodemcuv2; framework: arduino)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
Converting main.ino
Collected 24 compatible libraries

(…)
Uploading 232080 bytes from .pioenvs/nodemcuv2/firmware.bin to flash at 0x00000000
................................................................................ [ 35% ]

(…)
— Miniterm on /dev/cu.SLAB_USBtoUART  9600,8,N,1 ---
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
Sigfox module is ready.
ID=
PAC=129…….FE5
FirmwareVersion=1.1
FirmwareVCSVersion=0
LibraryVersion=UDL1-1.8.7
Sending message ...
sent.

The sketch prints out more values on the serial monitor but at present we only need ID and PAC. Visit https://backend.sigfox.com/activate. First you're asked to choose a kit provider from a logo-ish list of many providers. Locate „LPWAN.cz“. Next: Pick your country/network operator, the enter your account details. You'd need to register with a valid email address. If you already registered at the SigFox portal, you can reuse that login. After successful registration you're asked to enter the ID/PAC combination from above. With this step, you're essentially claiming your device, so you're the only one who is able to view messages from the device.

First step: Send messages

After successful registration, your module is ready to send data! The example sketch expects a button connected to D7. The main loop functions looks for the button being pressed, then sends out message.

Please note that this approach is for bare and simple testing only! SigFox allows for sending up to 140 messages per day, that means a single message about every ten minutes, which must be reflected in the sketch. But for now, it’ll do.

char  buf[16];
const char  *format = "SF-%i";
int   counter = 0;

void loop() {
  delay(100);
  if( digitalRead(D7)) {
    Serial.println("Sending message ...");
    counter++;

    int l = snprintf(buf, sizeof(buf), format, counter);

    if (wisol_sigfox__send_frame((const uint8_t*)buf, l, false)) {
      Serial.println("sent.");
    }
  }
}

Once the button is pressed, a message is snprintfed into a buffer, and wisol_sigfox__send_frame(..) is used to send it. wisol_sigfox__send_frame is implemented in a synchronous fashion. Once the „send frame“ command $SF has been sent to the module, the function waits for an „OK“ or Error message to come back from the module, which includes the ca. 6 seconds of air time that is necessary to send the payload off to the SigFox network. So there is a small time lag between „Sending message“ and „sent.“ in the USB Serial output-

If that went well you’re ready to look at SigFox’ dashboard and find your message there:

Message at Sigfox dashboard

That’s about it! Now we have a small sigfox solution, slightly cheaper than the MKRFOX, ready for grove-based prototypes. It’s well suited for our trainings where we make extensive use of Grove’s sensor kits. If you’re into soldering you might consider buying the bare transceiver modules from WiSOL, which cost around 3-4$. Combined with an ESP8266 module makes for a really inexpensive solution.

Andreas

Additional reads