In part 1 of this series, we discussed the web tools needed to implement the project and discussed the run-time operation of the sample project.  The goal of Part 2 is to enable you to build the example program yourself.  It reviews

the hardware, how to get the source code, Build an image that will operate as described in Part 1, and how to install and operate.


The project is pretty much self-contained and is easily replicated so there shouldn’t be any real issues, but if there is, please let me know by contacting me via the Element14 web-site.


HW Used

As mentioned in Part 1, the hardware I used is the ‘TELUS LTE-M IoT Starter Kit’:


All the boards fit on-top of each other and connect via the Arduino connectors.  Once you have the board stack assembled, you connect the NUCLEO L496ZG bard to your  development machine via the USB connector.   The BG96 Shield is fitted with a preconfigured Infineon eSIM but if you want to use a removable SIM card, then SW4 must be set accordingly and the SIM should be activated on the carrier’s website.  To insert the SIM card, slide the metal retaining clip in direction of the PWR KEY Push-button switch, then lift this up and inserting the SIM with notched corner facing outwards as shown below. Lock the SIM into place by pressing on the SIM holder and sliding the metal retaining clip back in the other direction.

The other settings that are key to operation are the Rx/Tx selection slide switches. These need to be oriented as showsn below:


All settings for the BG96 expansion board are available in the Telus LTE-M IoT Starter Kit Hardware User Guide.


Required Software Environment

To build the Azure sample program, you must use the Mbed Command Line Interface (CLI) tools because when compiled, the  tool chain needs certain flags enabled/disabled to successfully compile.  These flags and settings are located in the toolchain_debug.json file that is downloaded with the source code.  You also will need to ensure your development machine has the GIT revision control system and the GNU ARM tool chain installed. The URL for all these tools is:



ARM has released an installer for Windows and MAC to simplify the installation of the mbed-cli.  See  for details.


Once all the tools are installed on your development machine, you can download the example program, build it, then load/execute it.


Source Code

The source code is available from  You import this code using the mbed-cli by issuing the command:


mbed import


NOTE: The default location of the compiler/tools is:

 GCC_ARM_PATH = "/usr/local/gcc-arm-none-eabi-7-2018-q2-update/bin/"

If your tools are installed to a different location, you will need to update the file to point to the compiler in your environment.


The mbed-cli will create a directory named 'azure-iot-mbed-client' and import all the program and library source code into that directory. Once this is complete, your directory will resemble:

Build Options

From within the 'azure-iot-mbed-client' directory, you must modify a few files to successfully use the example program.


First, you need to set the connectionString that is located in ' AvnetBG96_azure_client.cpp' on/around source line 66.  This  variable should be set to the Connection string that was highlighted in BLOG 1 when you created your IoT Hub.  The deviceId variable is simply a sub-string within the Connection string, it is just broke out for use separately in the program.


Second, if you need to change the APN for your carrier (it is defaulted to use AT&T with their APN of ""), you will want to add a DEFAULT_APN macro to your mbed_app.json file, e.g


   "macros": [


With these two changes, you can build by issuing the command:


mbed compile –m NUCLEO_L496ZG –t GCC_ARM --profile toolchain_debug.json


This will invoke the compiler to compile and link all the code.  When all is said and done, you will get a result similar to:


From this output you can see that the executable image is located in: ./BUILD/NUCLEO_L496ZG/GCC_ARM/azure-iot-mbed-client.bin


Now copy the executable image to the NUCLEO-L496ZG board that is attached to your PC.  Once the image has finished being copied, it will automatically begin execution.  Of course, you can always manually press the reset button on the board to generate a HW reset and execution from a power-on state.


Program Execution

When the program starts, you will see the standard startup screen on the console:


Console Output

After the startup screen, the sensor data, button press and tilt events will be repetitively collected and sent to Azure.

(0001)Send IoTHubClient Message@20:59:13 - OK. [RSSI=99]
(0002)Send IoTHubClient Message@20:59:25 - OK. [RSSI=17]
(0003)Send IoTHubClient Message@20:59:31 - OK. [RSSI=17]
(0004)Send IoTHubClient Message@20:59:37 - OK. [RSSI=17]
(0005)Send IoTHubClient Message@20:59:43 - OK. [RSSI=17]



  • The first field (xxxx) indicates how many messages has been sent to Azure.
  • The @xx:xx:xx is the time that they message was sent to Azure. This time will match the time in the Azure message.
  • The status of the message.
  • The [RSSI=??] which indicates the current RSSI value when the message was sent.


Monitoring Device output with Azure CLI

If you are using a Linux based PC for development, you will be using the Azure cLI to monitor IoT Hub data and messages (to/from) your device.  Watching data be received by IoT Hub, requires you to issue the command:


az iot hub monitor-events --login "HostName=XXX;SharedAccessKeyName=XXX;SharedAccessKey=XXX"


The XXXX values were provided when registering your device (see step #6 in the section Create an IoT hub).


Once this command is issued, each time Azure receives a message, its contents will be displayed:


"ObjectName": "Avnet NUCLEO-L496ZG+BG96 Azure IoT Client",
"ObjectType": "SensorData",
"Version": "1.0",
"ReportingDevice": "STL496ZG-BG96",
"Temperature": 90.68,
"Humidity": 54,
"Pressure": 1008,
"Tilt": 2,
"ButtonPress": 0,
"TOD": "Thu 2018-09-06 19:36:45 UTC"
---- application properties ----

Note: the TOD stamp in the message will match the time displayed when the message is sent, e.g., the Message@<<>> shown in the device monitor screen will match "TOD" : "<<>>" in the IoT Hub message.

Using Azure CLI to send messages to your Device (via Azure IoT Hub)

The example program understands three basic messages (1) led-on, (2) led-blink, and (3) led-off.  To send the commands to your Device, execute the following command:


az iot device c2d-message send --login "HostName=XXX;SharedAccessKeyName=XXX;SharedAccessKey=XXX" --device-id XXX --data "$*"


were $* is ‘led-on’ or ‘led-off’ or ‘led-blink

The device-id <<XXX>> is the name you used when creating the device, in my case it is STL496ZG-BG96 as reported in the message that is sent to Azure.



When you send these messages to the device, the Console will report the message being received as:

After which the RED LED will react as requested.

Using Device Explorer to Monitoring Device output

If the development machine is Windows based and you have installed Azure Device Explorer, the interaction is similar to that of iothub-explorer only graphically based. When starting, you enter your device information, e.g.


And press the update button. After the credentials have been established, you can go to the Data Tab, click on Monitor and observe the data that is being sent by your device:

Sending messages to your Device using Device Explorer

To send messages to your device, go to the ‘Messages To Device’ tab, enter the Device ID you are sending the message to and enter the Message to be sent (led-on, led-off, led-blink) followed by the ‘Send’ button.  This instructs Azure IoT Hub to send the message to the device:


Again, like with iothub-explorer, the console will reported as previously shown.


Other Configuration Options

The example program uses two JSON configuration files to tailor the program compilation--in addition to what was previously mentioned with regard to the APN.


File: mbed_app.json:

  • Delay time for a cellular network read time-out.  This is the time from when a request for data is sent to when the response is be received.  On the Cellular network, the round-trip time of request-response sometimes takes longer than a standard network so setting this timeout value allows you to account for delays.  It is set by default to 30 seconds.
  • The network-interface to be used.  The example program uses the BG96-Cellular board so this value is set to CELLULAR_BG96.  You can select other values provided you have the necessary hardware configuration.  For ETHERNET, this program was tested with the NXP FRDM K64F board, for CELLULAR_WNC14A2A the board was tested with the Avnet WNC M14A2A LTE-M Modem Module (see
  • The button active state specifies the logic level a button is active at.  The defaults for the NUCLEO_L496ZG is ‘ActiveHigh’ for the K64F, the active state is ‘ActiveLow’.
  • The iksversion setting allows you to specify which version of the X-NUCLEO-IKS01Ax - motion/environment sensor board you are using. Version 2 of this board includes ‘Tilt’ detection and is the preferred version. However, the version 1 board can also be used without the Tilt detection capability.

File: toolchain_debug.json:

This file contains all the flags and compiler/linker settings that are being used.  We are using the GCC_ARM compiler so that section is used for all flag configuration. There are two notes for this file:

  • Errors are generated by the Azure SDK which can be helpful during development but can be optionally disabled to save some ROM/RAM.  To do this, add a definition of "-DNO_LOGGING"  to "common"
  • To save additional space you can disabled blob upload. To do this,
    1. Add the flag -DDONT_USE_UPLOADTOBLOB to "common" and do not compile the files:
      • iothub_client/blob.c
      • iothub_client/iothub_client_ll_uploadtoblob.c


You do not need to modify the toolchain_debug.json file because it is already configured for GCC_ARM as this example program expects, but if you want to use a different compiler be aware of these flags. In Blog #3, I do modify mbed_app.json for different platforms, but even then, changes are minimal.



Previous Blog                                                                                                                                                                            Next Blog