Overview

Skill Level: Any Skill Level

This recipe is all about sending data from the TELUS IoT device (sensor, any electronic circuit board, any digital or analog input) to the IBM bluemix platform so that the user can view and use the data as required.

How to easily set up an IBM Cloud application, built using Node-RED, that will receive temperature and humidity data using the TELUS IoT Starter Kit and store it in a Cloudant DB.

Ingredients

The TELUS Internet of Things (IoT) starter kit

Usb cable to connect the Nucleo-64 board with a laptop.

Mbed system compiler using the¬†‚ÄúTELUS_BG96_IBM-QuickStart‚ÄĚ sample

Active TELUS IoT SIM for the NB IoT/LTE CAT M1 Quectel BG 96 Avnet shield

Step-by-step

  1. Introduction

    The TELUS Internet of Things (IoT) starter kit is comprised of a Nucleo-64 (STM32 based Cortex-M4) L476RG MCU, a Nucleo IKS01A2 sensor expansion board with on board HTS221, LPS22HB, LSM6DSL, and LSM303AGR sensors, and a NB IoT/LTE CAT M1 Quectel BG 96 Avnet shield. For convenience, we will refer to the assembled kit as the TIoT device (TELUS IoT device).

    In this tutorial, we will demonstrate how to easily set up an IBM Cloud application, built using Node-RED, that will receive temperature and humidity data from the TIoT device and store it in a Cloudant DB. A video of this tutorial can also be found here.

  2. Hardware

    Figure 1 shows the physical device when assembled, and Figures 2, 3, and 4 are the disassembled MCU, sensor board, and modem shield respectively. The idea of the TIoT device is to combine cellular network connection as well as on-board sensor I/O and processing to provide developers with the utility to configure it for IoT applications.

    Figure 1: Telus LTE-M IoT Starter Devkit

    Figure 1: Telus LTE-M IoT Starter Devkit

    Figure 2Figure 3Figure 4

    Figures 2, 3, 4: Cellular Shield (BG96), Sensor Board (Nucleo IKS01A2), and L476RG Nucleo 64 MCU

     

    Figure 5 shows the L476RG MCU’s pin layout for the Arduino headers, and Figure 6 shows the pin layout for Morpho headers. The board is compatible with both systems.

    Figure 5

     

    Figure 5: Nucleo L476RG with Arduino headers labelled

    Figure 6

    Figure 6: Nucleo L476RG with Morpho headers labelled

  3. Watson IoT

    The TIoT device works with the Watson IoT platform to enable to MQTT connection between it and IBM Cloud servers. The platform allows features such as monitoring published data from the device.

    Firstly, an account must be made on IBM cloud. US South was selected as the server (default). The main console is where all the applications, services, containers, and virtual servers are displayed, see in Figure 7.

     

    Figure 7

    Figure 7: The IBM cloud dashboard view

     

    Resources can be created by clicking the create resource button, and various boilerplates are available to get started quickly. One of the boilerplates is the Internet of Things Platform Starter. So, create the new app, assign an app name, for example ‚ÄúIoT-Telus-Sample‚ÄĚ, and a region for deployment (US South). Note that app names are unique on Bluemix, so the same name should not be in use. A new Cloud Foundry App, Cloudant DB, and IoT service should have been initiated. If not, wait a couple of minutes and they should show up in the main Bluemix console. Starting with the IoT service, click on the name of the service, and then ‚Äúlaunch‚ÄĚ to enter the Watson IoT Platform dashboard.

    The first thing after arriving at the Watson IoT dashboard is to add the TIoT as a device. The lite version works with up to 20 devices. In order to add a device, a device type must be defined, see Figure 8 and Figure 9. The device type is a selectable template for new devices which are added. In this case, the TIoT is defined as a new device type: ‚ÄúTELUS-IOT-Start-Kit‚ÄĚ.

     

    Figure 8

    Figure 8: Watson IoT Platform Dashboard

     

    Figure 9

    Figure 9: Defining a new device type

     

    Following this, the MAC address of the TIoT can be used as its Device ID to add it as a new device. This is not necessarily the only viable device ID, but it is one which is convenient and unique to the device. If the MAC address is unknown, one option is to use another arbitrary Device ID temporarily, and after the device connects to Watson IoT for the first time the MAC address should be printed to serial as programmed in the sample embedded code. All other metadata can be filled at this point or left blank.

    Finally, the last window once the device is added is very important, and should contain the following information:

    Organization ID

    Device Type

    Device ID

    Authentication Method

    Authentication Token

    These parameters should be recorded and used to update the definitions in main.cpp through the Mbed compiler. The auth token can never be recovered if lost and the process of setting up a new device will have to be repeated. After the TIoT has been added as a new device, it should show up under devices as shown in Figure 10.

    Figure 10

    Figure 10: TIoT device shows up under list of devices on the IoT platform

     

    There are many ways to access to the device connected through Watson IoT, including using API keys generated from the platform itself. The advantage of using a Cloud Foundry App (Node-RED on Bluemix) though, is that internal authentication through ‚ÄúBluemix Service‚ÄĚ is done in an easier, more convenient manner such that API keys do not need to be generated.

  4. Embedded Software

    The L476RG MCU can be programmed through the Mbed system. The URL to the compiler is ‚Äúos.mbed.com/compiler‚ÄĚ and the appropriate board ‚ÄúNUCLEO-L476RG‚ÄĚ must be selected. Appendix A contains the default library code for defining the pin addresses for the L476RG. It is useful for referencing and defining I/O but should not be modified. The MCU runs on embedded C++ code. The ‚ÄúTELUS_BG96_IBM-QuickStart‚ÄĚ sample (https://os.mbed.com/teams/Avnet/code/TELUS_BG96_IBM_QuickStart/) can be imported into the compiler and has all the appropriate libraries and dependencies included. In main.cpp, Lines 46 to 50 contain the definitions for connecting the device to Watson, which needs to be updated to the appropriate values. Line 60, the APN, should be changed to match the APN settings of the SIM card, in this case ‚Äúpp.telus.com‚ÄĚ. And, line 321 should be deleted. Then, the code can be compiled and the resulting .bin file will be automatically downloaded to the pre-defined default file download location on the computer (local system).

    Once the MCU is plugged in via the USB Mini-B interface, it will appear under devices as a USB disk, as shown in Figure 11. One simply has to copy/drag-and-drop the compiled .bin file into this USB disk to ‚Äúflash‚ÄĚ the code onto the MCU. That is the advantage of using the Mbed OS ecosystem. The disk will appear as ejected and reconnect again to signal the end of the embedded software update.

     

    Figure 11

    Figure 11: TIoT under ‚Äúdevices‚ÄĚ as NODE_ L476RG

  5. Node-RED

    A Node-RED instance should have been created with the IoT Platform Starter, to enable flows of commands/data between different services on the IBM cloud. This Cloud Foundry web app runs on a virtual server and is accessible for editing via a URL endpoint. Node-RED is a useful visual tool for ‚Äúwiring‚ÄĚ or linking together hardware devices, services, processing functions, and databases. From the main IBM Cloud console, the Node-RED app with the boilerplate <app name> defined previously should be visible. Upon clicking on the app, the webpage will be directed to the application administrative console. Figure 12 shows the app console page, the link ‚ÄúVisit App URL‚ÄĚ is used to visit the Node-RED development page.

     

    Figure 12

    Figure 12: Node-RED application console page

  6. Cloudant Database

    In the main IBM cloud console, a Cloudant NoSQL DB should already be there from when the node-RED app was created. The default service name is <app name>-cloudantNoSQLDB. Launch the database, and view databases as seen in Figure 13. The database ‚Äúnodered‚ÄĚ was created by the node-RED app by default. A new database for storing the sensor data will need to be created, the ‚ÄúCreate Database‚ÄĚ button is found at the top right of the Cloudant DB dashboard. No documents are initially present, only a name is required to interface with the database through the Cloud Foundry application.

     

     

    Picture13

    Figure 13: List of databases in Cloudant DB web interface

  7. Node-RED Flow

    At the Node-RED page, at <yourappname>.mybluemix.net, set up a password to the flow editor and go to the flow editor. Inside the flow editor, a list of inputs, outputs, functions, etc. can be seen on the left. On the right is the information and debug panel. The center is the work space for making ‚Äúflows‚ÄĚ based on available inputs and outputs. To avoid having to set up the entire flow from scratch, simply go to import -> clipboard (shown in Figure 14) and copy paste the code found in Appendix B. The complete flow can be seen in Figure 15. Before the app can be deployed, some settings for the IoT device (ibmiot module) and the database (cloudant module) must first be updated. See Figures 16 and 17 for guidance on the appropriate parameters.

     

    Figure 14

    Figure 14: Importing flows into Node-RED editor

     

    Figure 15

    Figure 15: Complete sample flow

     

    Figure 16Figure 17

    Figures 16, 17: Changes necessary to the imported flow depending on Watson IoT and Cloudant DB setup

     

    To deploy the app, simply log into the editor (if not already) and click deploy in the top right corner. A couple seconds later, the app should be live online and publishing to the database.

  8. Conclusion

    This document detailed a simple example on how to interface the TIoT device with Watson IoT and taking advantage of IBM Cloud’s Internet of Things Platform Starter boilerplate to incorporate Node-RED and Cloudant DB. Based on this example, it is possible to expand upon the introduced concepts and unlock the vast IoT applications development space with the Telus IoT Starter kit and Watson IoT. 

  9. Appendix A (L496RG default library pin definitions)

    /* mbed Microcontroller Library

     *******************************************************************************

     * Copyright (c) 2016, STMicroelectronics

     * All rights reserved.

     *

     * Redistribution and use in source and binary forms, with or without

     * modification, are permitted provided that the following conditions are met:

     *

     * 1. Redistributions of source code must retain the above copyright notice,

     *    this list of conditions and the following disclaimer.

     * 2. Redistributions in binary form must reproduce the above copyright notice,

     *    this list of conditions and the following disclaimer in the documentation

     *    and/or other materials provided with the distribution.

     * 3. Neither the name of STMicroelectronics nor the names of its contributors

     *    may be used to endorse or promote products derived from this software

     *    without specific prior written permission.

     *

    ¬†*¬†THIS¬†SOFTWARE¬†IS¬†PROVIDED¬†BY¬†THE¬†COPYRIGHT¬†HOLDERS¬†AND¬†CONTRIBUTORS¬†“AS¬†IS”

     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE

     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR

     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER

     * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

     *******************************************************************************

     */

     

    #ifndef MBED_PINNAMES_H

    #define MBED_PINNAMES_H

     

    #include¬†“cmsis.h”

    #include¬†“PinNamesTypes.h”

     

    #ifdef __cplusplus

    extern¬†“C”¬†{

    #endif

     

    typedef enum {

        PA_0  = 0x00,

        PA_1  = 0x01,

        PA_2  = 0x02,

        PA_3  = 0x03,

        PA_4  = 0x04,

        PA_5  = 0x05,

        PA_6  = 0x06,

        PA_7  = 0x07,

        PA_8  = 0x08,

        PA_9  = 0x09,

        PA_10 = 0x0A,

        PA_11 = 0x0B,

        PA_12 = 0x0C,

        PA_13 = 0x0D,

        PA_14 = 0x0E,

        PA_15 = 0x0F,

     

        PB_0  = 0x10,

        PB_1  = 0x11,

        PB_2  = 0x12,

        PB_3  = 0x13,

        PB_4  = 0x14,

        PB_5  = 0x15,

        PB_6  = 0x16,

        PB_7  = 0x17,

        PB_8  = 0x18,

        PB_9  = 0x19,

        PB_10 = 0x1A,

        PB_11 = 0x1B,

        PB_12 = 0x1C,

        PB_13 = 0x1D,

        PB_14 = 0x1E,

        PB_15 = 0x1F,

     

        PC_0  = 0x20,

        PC_1  = 0x21,

        PC_2  = 0x22,

        PC_3  = 0x23,

        PC_4  = 0x24,

        PC_5  = 0x25,

        PC_6  = 0x26,

        PC_7  = 0x27,

        PC_8  = 0x28,

        PC_9  = 0x29,

        PC_10 = 0x2A,

        PC_11 = 0x2B,

        PC_12 = 0x2C,

        PC_13 = 0x2D,

        PC_14 = 0x2E,

        PC_15 = 0x2F,

     

        PD_2  = 0x32,

     

        PH_0  = 0x70,

        PH_1  = 0x71,

     

        // ADC internal channels

        ADC_TEMP = 0xF0,

        ADC_VREF = 0xF1,

        ADC_VBAT = 0xF2,

     

        // Arduino connector namings

        A0          = PA_0,

        A1          = PA_1,

        A2          = PA_4,

        A3          = PB_0,

        A4          = PC_1,

        A5          = PC_0,

        D0          = PA_3,

        D1          = PA_2,

        D2          = PA_10,

        D3          = PB_3,

        D4          = PB_5,

        D5          = PB_4,

        D6          = PB_10,

        D7          = PA_8,

        D8          = PA_9,

        D9          = PC_7,

        D10         = PB_6,

        D11         = PA_7,

        D12         = PA_6,

        D13         = PA_5,

        D14         = PB_9,

        D15         = PB_8,

     

        // STDIO for console print

    #ifdef MBED_CONF_TARGET_STDIO_UART_TX

        STDIO_UART_TX = MBED_CONF_TARGET_STDIO_UART_TX,

    #else

        STDIO_UART_TX = PA_2,

    #endif

    #ifdef MBED_CONF_TARGET_STDIO_UART_RX

        STDIO_UART_RX = MBED_CONF_TARGET_STDIO_UART_RX,

    #else

        STDIO_UART_RX = PA_3,

    #endif

     

        // Generic signals namings

        LED1        = PA_5,

        LED2        = PA_5,

        LED3        = PA_5,

        LED4        = PA_5,

        USER_BUTTON = PC_13,

        // Standardized button names

        BUTTON1 = USER_BUTTON,

        SERIAL_TX   = STDIO_UART_TX,

        SERIAL_RX   = STDIO_UART_RX,

        USBTX       = STDIO_UART_TX,

        USBRX       = STDIO_UART_RX,

        I2C_SCL     = PB_8,

        I2C_SDA     = PB_9,

        SPI_MOSI    = PA_7,

        SPI_MISO    = PA_6,

        SPI_SCK     = PA_5,

        SPI_CS      = PB_6,

        PWM_OUT     = PB_3,

     

        //USB pins

        USB_OTG_FS_SOF = PA_8,

        USB_OTG_FS_VBUS = PA_9,

        USB_OTG_FS_ID = PA_10,

        USB_OTG_FS_DM = PA_11,

        USB_OTG_FS_DP = PA_12,

        USB_OTG_FS_NOE_ALT = PA_13,

        USB_OTG_FS_NOE = PC_9,

     

        // Not connected

        NC = (int)0xFFFFFFFF

    } PinName;

     

    #ifdef __cplusplus

    }

    #endif

     

    #endif

  10. Appendix B (Node-RED flow)

    [

        {

    ¬†¬†¬†¬†¬†¬†¬† “id”: “b64eb727.39b738”,

    ¬†¬†¬†¬†¬†¬†¬† “type”: “ibmiot in”,

    ¬†¬†¬†¬†¬†¬†¬† “z”: “deb0d57.1c46528”,

    ¬†¬†¬†¬†¬†¬†¬† “authentication”: “boundService”,

    ¬†¬†¬†¬†¬†¬†¬† “apiKey”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “inputType”: “evt”,

    ¬†¬†¬†¬†¬†¬†¬† “logicalInterface”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “ruleId”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “deviceId”: “testid”,

    ¬†¬†¬†¬†¬†¬†¬† “applicationId”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “deviceType”: “+”,

    ¬†¬†¬†¬†¬†¬†¬† “eventType”: “+”,

    ¬†¬†¬†¬†¬†¬†¬† “commandType”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “format”: “json”,

    ¬†¬†¬†¬†¬†¬†¬† “name”: “IBM IoT”,

    ¬†¬†¬†¬†¬†¬†¬† “service”: “registered”,

    ¬†¬†¬†¬†¬†¬†¬† “allDevices”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “allApplications”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “allDeviceTypes”: true,

    ¬†¬†¬†¬†¬†¬†¬† “allLogicalInterfaces”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “allEvents”: true,

    ¬†¬†¬†¬†¬†¬†¬† “allCommands”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “allFormats”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “qos”: 0,

    ¬†¬†¬†¬†¬†¬†¬† “x”: 300,

    ¬†¬†¬†¬†¬†¬†¬† “y”: 200,

    ¬†¬†¬†¬†¬†¬†¬† “wires”: [

                [

    ¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† “b917cb83.6c97f8”

                ]

            ]

        },

        {

    ¬†¬†¬†¬†¬†¬†¬† “id”: “b917cb83.6c97f8”,

    ¬†¬†¬†¬†¬†¬†¬† “type”: “cloudant out”,

    ¬†¬†¬†¬†¬†¬†¬† “z”: “deb0d57.1c46528”,

    ¬†¬†¬†¬†¬†¬†¬† “name”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “cloudant”: “”,

    ¬†¬†¬†¬†¬†¬†¬† “database”: “sensor”,

    ¬†¬†¬† ¬†¬†¬†¬†“service”: “telus-iot-sample-application-cloudantNoSQLDB”,

    ¬†¬†¬†¬†¬†¬†¬† “payonly”: false,

    ¬†¬†¬†¬†¬†¬†¬† “operation”: “insert”,

    ¬†¬†¬†¬†¬†¬†¬† “x”: 450,

    ¬†¬†¬†¬†¬†¬†¬† “y”: 200,

    ¬†¬†¬†¬†¬†¬†¬† “wires”: []

        }

    ]

Join The Discussion