Espruino Pico: Low power ultrasonic sensor with LoRaWAN

Simple LoRaWAN node connected to The Things Network (TTN) using Espruino Pico and Microchip RN2483 LoRa Technology Module. As sensor a MB1242 I2CXL-MaxSonar-EZ4 is used, that is connected via I2C. It returns the distance in centimeter as an array of 2 bytes.

The most prominent goal was to find out how to design a device and its software in order to minimize the energy consumption in order to maximize battery life.


  • In many cases, LoRaWAN nodes are deployed in remote places without a static power supply. So both hardware and software need to be designed in a way that allows battery operation.
  • With battery operation, operation of at least 1 year should be technically feasible these days, given that sending sensor values only a few times per day is good enough for the given use case.
  • The Espruino Pico already has some operational modes for power saving, the goal is to find out how these modes can be used.
  • Also the RN2483 can be sent to sleep in order to minimize power consumption. The goal is how to find out how to send this module to sleep and wake it up again, and what implications this has to the current connection to TTN.

Last but not least …


I use a RN2483A/RN2903A breakout board that I ordered for about €30 at Tindie:

RN2483 Breakout Board Pinout

Level Shifter Option: As the Espruino Pico already operates at 3.3V, there should be no need for a level shifter. However, if you like to play around with this module by simply attaching a (FTDI) Serial-to-UART cable which has 5v levels, then you probably want to have a level shifter and a voltage regulator at hand.

The Espruino Pico gets its power from a 9V battery. It has a built-in voltage regulator that converts the volate to 3.3V. Espruino Pico Pinout

The MaxBotix MB1242 consumes a consiberable amount energy, even in idle mode, so a Adafruit LM3671 3.3V Buck Converter Breakout is used as kind of “switch” to cut-off the power supply for this sensor when it is not in use. Yes, people say that cutting off the power supply is not sufficient to make sure that the MB1242 really no longer consumes any energy, but in my case this trick was very effective.

Wiring on Breadboard

Preparation in TTN Console

Source code: You first need to create an application in TTN console, and create a device within this application.

Select OTAA (Over the Air Activation) as Activation Mode

After creation of the device, copy and paste the values for Device EUIApplication EUI and App Key to the code:

// LoRaWAN Over the Air Activation (OTAA)
// Copy these values from the Device Overview of the TTN console.
const deviceOTAAConfiguration = {
  'deviceEUI': '0000000000000000',
  'applicationEUI': '0000000000000000',
  'appKey': '00000000000000000000000000000000'

Transfer code to Espruino Pico and run it

I won’t explain here how you work in general with Espruino products, you already should be familiar with that or make yourself familiar by other means than this project.

  • Connect the Espruino Pico via USB,
  • use the Espruino Web IDE to transfer the code (I still use the native version for Windows)
  • Run the code by entering onInit(); on the Pico

Note that the Pico won’t go into stop mode until connected to USB. You need to connect a battery (or another power source) to try that out.

Example output

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
 2v06 (c) 2019 G.Williams
["sys get ver\r\n"
] "R"
] "N2483 1.0.5 Oct"
] " 31 2018 15:06:5"
] "2\r\n"
Version: RN2483 1.0.5 Oct 31 2018 15:06:52
["mac reset 868\r\n"
] "o"
] "k\r\n"
["mac set adr on\r\n"
] "o"
] "k\r\n"
["mac set appeui 70B3D57EXXXXXXXX\r\n"
] "o"
] "k\r\n"
["mac set deveui 00022CBFXXXXXXXX\r\n"
] "o"
] "k\r\n"
["mac set appkey 625C109CA95ADA37E9D0EA64XXXXXXXX\r\n"
] "o"
] "k\r\n"
["mac join otaa\r\n"
] "o"
] "k\r\n"
] "a"
] "ccepted\r\n"
Result: accepted
RN2483 go to sleep
["sys sleep 86400000\r\n"
RN2483 sent to sleep
Periodic task started.
RN2483 wake up
] "\u0000"
] "ok\r\n"
] "inv"
] "alid_param\r\n"
wake up finished
["mac tx uncnf 1 42\r\n"
] "o"
] "k\r\n"
] "m"
] "ac_tx_ok\r\n"
RN2483 go to sleep
["sys sleep 86400000\r\n"
Periodic task done.


  • The experiment up to now runs for more than 6 weeks now, longer than any battery powered circuit I did before. Update 2020-12-29: Died after 45 days, which is a little disappointing.
  • Maybe it could be even more power-efficient if we could eliminate the voltage regulator on the Espruino Pico and use an appropriate battery instead
  • The Microchip RN2483 module has quite helpful in keeping the complexity of the LoRaWAN protocol away from the project, especially suprised with its duty cycle enforcing mechanisms and adaptive data rate functionality. It also has a nice functionality to send it to sleep and wake it up when needed again.

To visualize the measurements, I used

Running now for more then 6 weeks, hanging on the ceiling of my garage

Grafana Output - Running 6 weeks

Sending a distance value every 30 minutes (well, there are some few losses)

Grafana Output - Last hours

Some similar project with focus on energy consumption and also using an ultrasonic sensor can be found here:

Flat Rate for NB-IoT: Accessing the 1NCE Management API


1NCE is an IoT connectivity provider with a disruptive pricing model:
The company offers a so-called “IoT Flat Rate”:
For 10 € you get a SIM card with 10 years lifetime and a flat rate traffic volume of 500 MB and 250 SMS.

As a maker of IoT devices communicating using NB-IoT you now question yourself:

  • Would such a flat rate be sufficient for my use-case?
  • What is the current traffic consumption of my device?
  • What effects does it have on the traffic consumption if I change the communication pattern in one or the other way?

Altough some RF modules like the Quectel BG96 offer counters to query the number of bytes sent and received, which already give a good indication about the traffic consumption, these perhaps don’t take into account the traffic on the lower levels of the communication stack, like UDP or TCP.

So why not directly ask 1NCE for the “consumed” traffic volume?

1NCE offers an Application Programming Interface that allows users to implement the most important functions of the Customer Portal into a customer’s environment. The supported functions of the 1NCE API generally enables the customer to manage, control and monitor the 1NCE SIM Cards from an external system.

For example, one can query for a list of SIM cards using a HTTP GET request to

… or get information about the left over flat rate traffic volume with a HTTP GET request to

There is a Swagger UI interface at that lets you play around with the functionality of the Management API.

This example application connects to this Management API, gets the SIM cards and
creates a Round-Robin-Database (RRDB) out of that. Then, the application queries the current traffic consumptions of the cards and enters it as sample into the RRDB.

And, as the final goodie, if you navigate to port 8080 with your web browser, a nice graph with the consumption rate of the last 24 hours is displayed.


How to configure

Find the source code on github at

Put your client-id and client-credentials in configuration file application.yml:

# proxy:
# host: localhost
# port: 3128

client-id: your-client-id
client-secret: your-client-secret

How to build

You need maven and a Java JDK to compile:

$ mvn clean package

How to run

$ java -jar target/1nce-management-api-access-and-rrd4j-graphs-0.0.1-SNAPSHOT.jar

On the first start, you may see something like this:

Tomcat started on port(s): 8080 (http) with context path ''
route=Route{/a.b.c.d:xxxx} response=Response{protocol=http/1.1, code=401, message=, url=}
Request did NOT use an Authorization header.
Requesting a new Access Token by client credentials
Token endpoint returned status 200 OK and tokens OnceAccessTokenService.Tokens(accessToken=206bed3b-11e6-4253-97c4-cb410f6f08ab, tokenType=bearer, expiresIn=3560, scope=all, appToken=eyJhbGc...)
QuotaDataResponse(volume=488.29297, totalVolume=500.0, expiryDate=2028-11-20 00:00:00, lastStatusChangeDate=2018-08-20 11:25:03)
QuotaDataResponse(volume=499.98907, totalVolume=500.0, expiryDate=2028-11-20 00:00:00, lastStatusChangeDate=2018-08-20 11:25:03)
sample=update "./data-traffic-consumption.rrd" 1573889068:1.2275710689279974E7:11460.935679972172

If a RRDB file with name data-traffic-consumption.rrd already exist in the current directory, then it won’t be overriden.
If you explicitly want to start with a new RRDB file, start the application with option –override.

Fun fact: To meet the goal of 500 MB in 10 years, the traffic consumtion rate needs not to exceed the red line at 1.66 bytes/second. So, there is still much to optimize in the communication patterns of this example device.


Espruino on RAK8212: Digital Twin in Bosch IoT Suite

A few weeks ago, I wrote a blog post how to connect a Espruino powered RAK8212 device with AWS IoT. In this posting, I would like to showcase how to connect a RAK8212 device to the Bosch IoT Suite Platform using the Quectel BG96’s built-in MQTT stack.

The example will be a simple data logger, periodically sending sensor values using NB-IoT connectivity.

You can find the source code and other material on the following github repository:

The RAK8212 has quite a few sensors on board:

  • Temperature
  • Humidity
  • Barometeric Pressure
  • Ambient Light
  • Accelerometer
  • Magnetometer
  • Location (GNSS)


You are already familiar with the RAK 8212 and how to program it using Espruino.


This example uses the Asset Communication package of the Bosch IoT Suite. There are quite a few things to configure before you can start, but there is an excellent tutorial that describes the steps in detail:

What you need to do (steps described in the tutorial):

  • Create a Bosch IoT Suite account
  • Subscribe to the Bosch IoT Suite Asset Communications package
  • Configure a namespace for your things (digital twins)
  • Create and configure a technical OAuth2.0 client
  • Generate a test token to access the APIs of the Bosch IoT Suite

About Vorto Information Models

The IoT Suite gives you full freedom how to model the Digital Twin of your physical devices. However, there is an open source project named “Eclipse Vorto” ( that allows you to compose an Information Model of your device from several so-called Function Blocks. So, like with Lego Bricks, you can compose your device from other building blocks that can be shared by different devices.

Actually, to explain the full functionality behind that would go to far here …

The Information Model for the RAK8212 looks as follows:

vortolang 1.0
namespace org.klenk.connectivity.iot
version 1.0.0
displayname "RAK8212"
description "Information Model for RAK8212"

using; 1.1.0
using org.eclipse.vorto.tutorial.Temperature; 1.0.0
using org.eclipse.vorto.Illuminance; 1.0.0
using; 1.1.0
using org.eclipse.vorto.BarometricPressure; 1.0.0
using; 1.1.0
using org.eclipse.vorto.Location; 1.0.0
infomodel RAK8212 {

	functionblocks {
		temperature as Temperature
		barometricPressure as BarometricPressure
		humidity as Humidity
		magnetometer as Magnetometer
		accelerometer as Accelerometer
		illuminance as Illuminance
		location as Location

One of the several advantages to model a device in an Information Model is that you now can generate code or other helpful things from it, like for instance the device provisioning script.

Again, this is out of scope for now, but the provisioning script generated from this Information Model is available in this repository (rak8212-device-provisioning-msg.json)

Have a look at this Youtube channel of Tim Grossmann for more inspiration about Eclipse Vorto.

Device Provisioning

Again, the Bosch tutorial at gives detailed instructions how to register your device with the Bosch IoT Suite.

But, as the RAK8212 has its own Information Model and provisioning script, use this one that is available in this repository:


  "id": "<your namespace>:rak8212",
  "hub": {
    "device": {
      "enabled": true
    "credentials": {
      "type": "hashed-password",
      "secrets": [
          "password": "<your-device-password>"
  "things": {
    "thing": {
      "attributes": {
        "thingName": "RAK8212",
        "definition": "org.klenk.connectivity.iot:RAK8212:1.0.0"
      "features": {
        "temperature": {
          "definition": [
          "properties": {
            "status": {
              "value": 0.0,
              "unit": ""

How to send telemetry data

To send telemetry data and in this way update the Digital Twin, you need to built up a Eclise Ditto message and publish it to topic telemetry.

    + JSON.stringify("telemetry"),
    '{' +
    '  "topic": "org.klenk.connectivity.iot/rak8212/things/twin/commands/modify",' +
    '  "headers": {},' +
    '  "path": "/features/temperature/properties",' +
    '  "value": {' +
    '    "status": {' +
    '      "value": ' + currentTemperature + ',' +
    '      "unit": "Degree Celsius"' +
    '    }' +
    '  }' +
     .then( ... )

Using the Quectal BG96 module’s command AT+QMTPUB to publish a message to a MQTT topic, this code section updates the feature “temperature” of the Digital Twin.

How to subscribe to “modified” events of the Digital Twin

The built-in MQTT client of the Quectel BG96 makes it easy to subscribe to topics: You just need to use the AT+QMTSUB command to subscribe to topic command/+/+/req/#.

sendAtCommand('AT+QMTSUB=0,1,' + JSON.stringify("command/+/+/req/#") + ',1', 15000, '+QMTSUB:')
  .then( ... )

Now, whenever a message is received on this topic, the MQTT client creates an output line starting with +QMTRECV: , like the following one:

] "\r\n+QMTRECV: 0,3,\"command///req/2240e49bdde-57ad-4652-b557-70f2dcf7"
] "41c0replies/modified\",\"{\"topic\":\"org.klenk.connectivity.iot"
] "/rak8212/things/twin/events/modified\",\"headers\":{\"sec-fetch-mode\":\"cors\", 

You can see this output if you put the debug mode on. In case someone changed the device’s digital twin, we will receive a Eclise Ditto “modified” message like the following one:

  "topic": "org.klenk.connectivity.iot/rak8212/things/twin/events/modified",
  "headers": {
    "sec-fetch-mode": "cors",
    "referer": "",
    "sec-fetch-site": "same-site",
    "accept-language": "de-DE, de;q=0.9, en-US;q=0.8, en;q=0.7",
    "correlation-id": "0e49bdde-57ad-4652-b557-70f2dcf741c0",
    "dnt": "1",
    "source": "iot-suite:service:iot-things-eu-1:50058525-a6ed-4401-9984-f678cd509323_things/full-access",
    "version": 2,
    "accept": "application/json",
    "host": "",
    "content-type": "application/vnd.eclipse.ditto+json",
    "accept-encoding": "gzip, deflate, br"
  "path": "/features/temperature/properties",
  "value": {
    "status": {
      "value": 21.61,
      "unit": "Degree Celsius"
  "revision": 525,
  "timestamp": "2019-09-22T10:58:49.666Z"

This one says that the feature “temperature” was modified.

In order to process this message, you just have to write a “handler” that deals with this incoming message.


As the Quectel BG96 module already has built in a MQTT stack, it is simple to communicate with the Bosch IoT Suite using this protocol. Using Espruino, one can efficiently build IoT prototypes without a big learning curve in regards to the programming of embedded devices.

However, it needs to be evaluated if MQTT in combination with this kind of verbose Eclise Ditto messages is actually a viable way for NB-IoT communication, where every transmitted byte counts to save energy and communication costs.

NB-IoT Explorer

Explore Narrowband IoT (NB-IoT) Radio Networks in a comfortable, user-friendly way.

Animated picture

In this project, two extremely powerful components come together:

The Espruino Pixl.js with its built-in JavaScript interpreter is easy to program. The (native) Espruino Web IDE lets you transfer the code to the device using Bluetooth LE, so there isn’t even a USB cable needed to connect the computer with the device. The Espruino Pixl.js device has a large LCD display with 128×64 pixels, and four buttons on each corner of the display allow highly interactive applications.

The Quectel BG96 module module on the NB-IoT Shield provides multi-band support, so it can be used in many different radio networks all around the world. The NB-IoT Shield provides direct access to the serial interface of the BG96 module, so you also can try things out using a FTDI cable, which can be useful if you want to do firmware updates. The BG96 module provides a wide range of AT commands for a lot of purposes, and even provides high-level protocol implementations like HTTPS and MQTT, which can be very useful for IoT applications. Additionally, it provides geo-positioning by its embedded GNSS chip.


  • Espruino Pixl.js – Bluetooth microcontroller programmable in JavaScript with built-in LCD display and Arduino footprint.
  • Dragino Nb-IoT Shield QG96 – Arduino shield that hosts a Quectel BG96 module. This module supports multiple bands for NB-IoT. Except NB-IoT, It also support LTE Cat M1 and EGPRS.
  • A SIM card from a network provider supporting NB-IoT.
  • Micro USB cable for power supply
  • Optional: GNSS Active Patch Antenna
  • Bluetooth Low Energy Dongle for your computer, if it not already supports BLE natively.


  • Get yourself familiar how to connect the (native) Espruino Web IDE with the Espruino Pixel.js board via Bluetooth LE.
  • Play around with the code examples for the Pixl.js.
  • The 5v pin on the on the Pixl.js will be used to power the NB-IoT shield. There is a solder jumper near the LCD connector labelled “3.3 5V Vin”. Short Vin to 5v – the 5v pin will be connected to 5v (when connected via USB) or whatever the voltage provided on Vin is. Read more about shield power at (Using the 3.3v at the output of the power regulator does not provide enough power when the BG96 starts to transmit).
  • If you are good in soldering, you can consider to physically remove the big square socket connector at the reverse side of the NB-IoT shield, because it is in the way when the Pixl.js and NB-IoT shield are connected.
  • Connect the Pixl.js with the NB-IoT shield by its Arduino connectors.
  • Optionally: Attach the GNSS Patch Antenna.
  • Get yourself a SIM card suitable for NB-IoT and insert it into the SIM card holder of the NB-IoT shield. Note: The cut corner of the SIM card has to point in your direction when inserting it. If you don’t take attention, then there is a chance that you insert the SIM card in the wrong orientation.
  • Load the JavaScript code from into the (native) Espruino Web IDE.
  • Check for the JSON structure named connection_options and provide the appropriate settings for the NB-IoT network provider of your choice.var connection_options = { band: “B8”, apn: “”, operator: “26201” };
  • Turn on Minification in Settings -> Minification. Choose Closure (online) – Simple optimizations.
  • Send the application to the Pixl.js.
  • If you want to keep the application in the Pixel.js even after re-booting the Pixl.js, then save it to flash by typingsave();
     ____                 _
    |  __|___ ___ ___ _ _|_|___ ___
    |  __|_ -| . |  _| | | |   | . |
    |____|___|  _|_| |___|_|_|_|___|
     2v01 (c) 2018 G.Williams
    Compacting Flash...
    Calculating Size...
    Compressed 40000 bytes to 20601
    Running onInit()...
    Press RESET button on NB-IoT shield if onInit() was called interactively.
  • To connect to the NB-IoT network, press the RESET button on the NB-IoT shield now. This is not necessary when you boot the device. In this case, the NB-IoT shield will reset by its own. When the application detects that the BG96 module is ready for operation, it will flicker the background light of the LCD display 5 times.
  • Now it is time to wait, as it may take seconds to a few minutes now for the BG96 module to manually register at the NB-IoT radio network. The activity LED should flash in the rhythm “on-off-off-off” periodically to indicate network search.
  • Once the BG96 module is connected, the splash screen on the LCD display will disappear, and other screens will appear. Use the two buttons on the corners of the right side of the display to cycle up/down trough these screens.


The button on the left top corner can be used to toggle the backlight of the LCD display. Use the two buttons on the corners of the right side of the display to cycle up/down trough the following screens.

When taking the screenshots, a NB-IoT SIM card of provider was used.

Screen: Registered Network

Registered Network

Displays the name of the registered network. The “Registered Public Land Mobile Network” (RPLMN) is identified by a globally unique PLMN code, which consists of a MCC (Mobile Country Code) and MNC (Mobile Network Code). The screenshot shows MCC 262 for Germany and MNC 01 for Deutsche Telekom.

Screen: Registration Status

Registration Status

Displays the Network Registration Status and the received signal strength (RSSI). On successful connection to the radio network, the status should be Registered Home Network or Registered Roaming.

Screen: Cell Information

Cell Information

Displays the two-byte tracking area code (TAC) in hexadecimal format, the 3 1/2 byte (28 bit) E-UTRAN cell ID in hexadecimal format, the eNB ID in decimal format (E-UTRAN cell id without 8 bit sector information) and the sector of the base station antenna.

This information can be used to look up the position of the base station tower in a map, with a service like

  • Enter Provider. The input field behaves a little bit strange. If RPLMN for example is “26201”, then you may need to enter “2621”.
  • Enter Network “4G – LTE”
  • In Input Area “Tower Search”, enter eNB ID and press Return

Screen: Network Information

Cell Information

Displays network information such as the access technology selected, the selected band and the Channel ID.

Screen: IP Address

IP Address

Displays the IP address assigned to the BG96 module in the address space applicable to the PDP.

Screen: Geo Position

Geo Position

Displays the current geo position including Longitude, Latitude and Elevation, and the number of satellites received.

Screen: Date and Time

Date and Time

Displays the current date and time in UTC.

Espruino on RAK8212: Create a Digital Twin in AWS IoT

You need a fast, simple and inexpensive way to prototype your IoT use cases?

This article describes how you can achieve this using

In this example, the RAK8212 device is used as a sensor that periodically sends temperature values to its digital twin in AWS IoT Core. For communication with AWS it uses the MQTT protocol over Narrowband IoT (NB-Iot). The state of a LED on the RAK8212 can be controlled by setting it on the digital twin in AWS IoT.

Setting up the thing in AWS Iot Core

Get yourself an account on AWS, navigate to “AWS IoT” and “Create a single thing”. Describing all the steps would go too far in this article, and AWS has good online documentation. So please follow the steps given in the AWS documentation.

In the end, you should have an IoT object (=thing), identified by a name, and a certificate for this object (e.g. 133c075337.cert.pem), a public key (e.g. 133c075337.public.key) and a private key (e.g. 133c075337.private.key). You need to download these three files and activate the certificate.

In the navigation menu of the AWS console, go to “Manage -> Things” and you will see all your things. Select the thing of your choice and, in the navigation menu of the thing, go to “interact”. Note the server address displayed as “Update your Thing Shadow using this Rest API Endpoint”. We will use this as the address of the MQTT server later.

Example Address:

Also notice the MQTT topics below. They all contain the name of your thing:

Example MQTT Topic: $aws/things/klenk-iot-device/shadow/update

This shows that the name of my thing is “klenk-iot-device”.

Setting up the example code for RAK8212

The example code is hosted at github:

Find the JavaScript object that holds the configuration for the NB-IoT radio network connection, e.g.

// NB1 connectivity settings for Vodafone Germany

var connection_options = {
  band: "B20",
  apn: "vgesace.nb.iot",
  operator: "26202",

  debug: false // Print communication with BG96 module to console.


Adapt this to fit to your NB-IoT network of choice.

Find the JavaScript object that holds the configuration for the MQTT connection to AWS IoT:

var mqtt_options = {

  // AWS IoT

  server: '',

  port: 8883,

  client_id: "klenk-iot-device"


Adapt the MQTT server (same as address of API endpoint noted down above) and client_id (name of the thing).

Upload the cryptographical material to the BG96 module

There is still one step missing: As AWS IoT uses bidirectional authentication of the MQTT connection, you need to transfer the thing’s certificate, the private key and the file of trusted root CA certificates to the BG96 module.
This is described in depth in this blog post: Espruino on RAK8212: Uploading cryptographic material to Quectel BG96

To code expects the files uploaded to have the following names:

  • cert.pem – The certificate of the thing
  • key.pem – The private key of the thing
  • cacert.pem – The file holding the trusted root CA certificates

Starting the example code on the RAK8212

Using the Espruino IDE, connect to the RAK8212 via Bluetooth LE, send the JavaScript code to the RAK8212 device, and execute function onInit();

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
 1v99 (c) 2018 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
Entering State Setup External Hardware
External modules connected.
BME280 wiring set up.
Entering State Configure Modem
Entering State Register To Network
Entering State Open MQTT Network
Entering State Connect To Server
Entering State Get Current State
Entering State Subscribe To Delta Updates
Entering State Publish Telemetry Data
Current temperature:  27.42
Entering State Sleep
Entering State Publish Telemetry Data
Current temperature:  27.52
Entering State Sleep
Entering State Publish Telemetry Data
Current temperature:  27.78
Entering State Sleep

The code is using a Finite State Machine, that transitions from state to state and can easily be extended (take care of memory limitations!). In case of a failure, the BG96 module is shut down, and the state machine is restarted.

The Digital Twin representation at AWS IoT

In the AWS IoT console’s navigation menu, go to “Manage -> Things” and you will see all your things. Select the thing of your choice and in the navigation menu of the thing, go to “shadow”.

Example Shadow State:


  "desired": {

    "led": "on"


  "reported": {

    "temperature": "27.57",

    "led": "on"



The code on the RAK8212 device will periodically update the temperature value every 60 seconds, and will also report the current state of the (blue) LED on the RAK8212.

Switching on/off the LED using the Digital Twin

You can switch on/off the (blue) LED on the RAK8212 by changing the LED’s desired state in the Digital Twin representation.

On the AWS IoT console, the is a page called “MQTT Client” that can be used to subscribe to or to publish to a arbitrary MQTT topic.

For switching the LED on and off, we need to public the desired state to the topic $aws/things/klenk-iot-device/shadow/update

Send a JSON object like this:


  "state" : {

    "desired" : {

      "led" : "off"




The RAK8212 should output a line like these on the console and switch on/off the (blue) LED accordingly

+QMTRECV reports message on topic:
  with payload:




Espruino on RAK8212: Getting started

The RAK8212 is a versatile developer board ideally suited for prototyping IoT use-cases. LTE NB-IoT is one option to send telemetry data to a IoT platform or receive configuration data and firmware updates over the air.


The board already includes a lot of sensors to play around with and cover a lot of typical IoT use-cases:

The NB-IoT connectivity is provided by the Quectel BG96 module.

Espruino is an open-source JavaScript interpreter for various microcontrollers (including the RAK8212) created 2012 by Gordon Williams. As JavaScript is used for programming the IoT use-cases and the applications can easily be pushed to the device using a Web IDE, Espruino is an ideal companion for the RAK8212.

In the following sections I try to help you (the reader) to get started with setting up Espruino on a RAK8212 module on a Windows PC.

Wiring up the J-Link Adapter

For initial flashing of the Espruino firmware you need a J-Link Adapter. This adapter has to support the Serial Wire Debug (SWD) interface.
Check the documentation of your J-Link adapter for the SWD connector pinout.
For Segger J-Link adapters, one source of information could be here:

Connect the connector pins of the J-Link adapter with the related pin headers on the RAK8212 adapter board.

Connector SWD pinout | RAK8212 header pin label
VTref                | VDD
SWDIO                | SWDIO
SWCLK                | SWCLK
RESET                | RESET
GND                  | GND

When finished, attach J-Link adapter to the Windows PC using the USB cable.

Don’t worry, you don’t need to have this pricey J-Link adapter shown in the picture. A J-Link Edu Mini for about €20 will do the job, too.


Download the Espruino firmware

You can download the Espruino firmware for the RAK8212 module on Espruino’s download page.

Under “Find a binary” choose the board “iTracker RAK8212”.

Download cutting edge build espruino_1v99_RAK8212.hex
Make sure to “save the link as” a file, and not get the firmware displayed in the browser and saving it from the browser.

Flash the Espruino firmware

Download, install and start Nordic nRFgo Studio on the Windows PC.

Then we select “nRF5x programing” in the Device Manager panel, and the following UI will be shown in front of us:


Press button “Erase all” to erase the firmware which had been programmed into the RAK8212 module before.

Select notepad tab “Program Application”, locate the file espruino_1v99_RAK8212.hex and press button “Program”. Flashing the firmware may take some minutes.


In the “Log” section on the bottom of the nRFgo Studio application, there should now be a statement like “Application espruino_1v99_RAK8212.hex programmed successfully.”

Set up serial terminal session

As you have plugged in the USB connector cable of the RAK8212 adapter board into your PC, a COM port should have been assigned to the serial interface. You can find out the assigned COM port using the Windows Device Manager. In my case, the COM port is COM19.


Setup a serial connection to this COM port using the terminal application “putty”.
Enter the COM port name as “Serial line”, 9600 as “Speed” and “Serial” as “Connection type”.
Press the “Open” button to start the serial terminal session.


After pressing the RESET button the the RAK8212 adapter board, you should get an output in the terminal as follows:


You now no longer need the J-Link adapter and can remove it from the RAK8212 adapter board.

Set up Web IDE

Download the Espruino Web IDE for the Chrome browser following the instructions here:

Run Espruino Web IDE from Chrome’s home screen (or the App Launcher).
Click the orange Connect/Disconnect icon in the Top Left.

You should be asked for the right COM port to use now. If everything goes well, the Web IDE will connect to your RAK8212.

You can now start to play with some JavaScript examples and send them down pressing the button “Send to Espruino”.


Now have fun with trying out some example programs and get familar with JavaScript programming in Espruino!

LTE NB-IoT: Send and receive a UDP message with Quectel BC66

Now that the firmware was updated to revision BC66NAR01A03_BETA0808 I managed to find out how to send a UDP message and receive a response message indication. The Quectel support informed that the “BC66 is not finally released” and there are a lot of hints about features being “preliminary” in the documentation. So, in the end, I had to collect information from different resources, which is currently really a pain point in my opinion.

Again, I used the terminal application “putty” on channel A at a baud rate of 115200 bps.
You have to press the on/off button to wake the module from sleeping.

A note to the NB-IoT SIM card provided by 1NCE: There is a 6-digit pin printed on the backside of the credit card sized SIM card holder. This is a little bit confusing, because I never got error messages regarding that the SIM card is locked. The 1NCE support stated:

“Wir haben Ihre SIM-Karte bereits vorab aktiviert. Eine Eingabe ihrer SIM-Pin ist in keinem Fall notwendig”

Good to know that 🙂

Following you find a list of AT commands that I used to send and receive a UDP message. On a PC visible to the internet I started a small UDP echo server written in Python. A good example can be found here:

Enable full functionality


Set default APN for PDP (only required once, is stored in NVRAM)
Provider: 1NCE


Set to automatically report network registration status, when the module is
registered on the network, a URC will be reported.


Reset the module now to make the APN settings effective

F1: 0000 0000
V0: 0000 0000 [0001]
00: 0006 000C
01: 0000 0000
U0: 0000 0001 [0000]
T0: 0000 00B4
Leaving the BROM

If the module has not registered with the network before, this process can actually take minutes. You can check with

+CEREG: 0,2

The “2” means, that the module is currently trying to attach or searching an operator to register to. “1” means registered to “home network” and “5” means the module is registered in a “roaming network”

+CEREG: 0,5

Once registered, it should only take some seconds to get an IP address from the network


This IP actually matches the IP address reported in the 1NCE customer portal at


Create a UDP socket



Create a UDP socket connection to, port 20001


Send the string “0123456789”


If the UDP message manages to get to the UDP server and back (UDP messages may get lost), you should get the following “unsolicited result code” (URC), indicating that 16 bytes were received by the module.


That’s an issue and possibly a bug. I would have expected something like


Disconnect the UDP socket


Close the UDP socket


Some furtherAT commands of interest:

Query the available mobile network operators

+COPS: 0,2,"26201",9
           |       +-- NB-IoT 
           +---------- Operator is MCC=262/MNC=01 --> T-Mobile/Telekom


Query current network status

+QENG: 0,3740,0,156,"1D6E105",-78,-4,-74,15,8,"D325",0,
                    |                       | +-- Tracking Area Code (?)
                    |                       +---- Serving cell band
                    +---------------------------- Serving cell (hex) 


  • This module currently seems to be immature. The documentation is a mess, and it isn’t even possible to send and receive a UDP message in a communication round trip.
  • T-Mobile’s IoT Network is available, even though I don’t live in an area of high population density.
  • Would be interesting if someone is able to locate this network cell “1D6E105”. I couldn’t find it.
  • With Quectel OpenCPU, it is possible to write a small application and flash it directly into the module. So there is no longer the need to have a separate MCU. This seems very innovative for me. I will probably try out if I can write such a custom application that reads an external sensor and periodically sends the sensor values via NB-IoT.
  • Please leave me a comment if you like to give feedback or share insight.

LTE NB-IoT: First steps with Quectel BC66

Narrowband IoT (NB-IoT) is a Low Power Wide Area Network (LPWAN) radio technology.
NB-IoT focuses specifically on indoor coverage (deep penetration), low cost, long battery life, and high connection density. NB-IoT uses a subset of the LTE standard, but limits the bandwidth to a single narrow-band of 200kHz.

With the Quectel BC66, I decided to try out one of the radio modules that clearly focuses on NB-IoT and does not provide any other 2.5G standards. I purchased a BC66-DVK development kit at for about €35. As this company is located in Germany, the development kit arrived just a few days after ordering.


From the “new” narrowband IoT carrier 1nce I got two NB-IoT SIM cards for free.

As described in the BC66-TE-B User Guide, I connected the development kit via a Micro USB cable to the PC and configured the terminal application “putty” to a baud rate of 115200 bps. After pressing the on/off button, the module actually woke up from sleep:

F1: 0000 0000
V0: 0000 0000 [0001]
00: 0006 000C
01: 0000 0000
U0: 0000 0001 [0000]
T0: 0000 00B4
Leaving the BROM


+CFUN: 0


Time to get some information about the module. There is a preliminary “BC66 AT Commands Manual” (2018-04-23) that provides information on that (ask Quectel Customer Support for it).

Display Product Identification Information

Revision: BC66NAR01A01


Request Manufacturer Identification

Revision: MTK_2625


Request Manufacturer Revision

Revision: BC66NAR01A01


After having some issues with verifying the PIN code on the SIM card I contacted the Quectel support staff, and they recommended to do a firmware update, as the BC66 is still in development process and I possibly had a rather outdated firmware on my module. The support sent me a link to an update program and gave instructions.


Firmware update was successful, firmware revision is now BC66NAR01A03_BETA0808

Revision: BC66NAR01A03_BETA0808


Check the next blog posts to find out how the story goes on …