Build your skills in IoT development by developing a Healthy Habits Tracker
Develop an IoT device and IoT application that uses an IoT developer kit, Python, MQTT, and IBM Watson IoT Platform
When it comes to keeping fit, I need a little extra motivation from time to time. I decided to build a smart device (an IoT device) to help me keep on track with my home exercise program. My IoT device, a healthy habits tracker, takes the form of a friendly pet (which I call my healthy habits pet throughout this tutorial and its videos). I need my pet to encourage me and remind me to get into the habit of taking regular breaks when I am working at my desk and complete exercises from my home exercise program.
The healthy habits pet uses LEDs and a buzzer to get my attention to gently remind me to exercise (see ). I can tap the pet to trigger sending a notification to a service that will keep track of when I completed an exercise, so the data can be used to co-ordinate how often I need to be reminded to establish the habit.
Figure 1. My healthy habits pet
You could use the healthy habits pet to monitor any habits that you want to adopt on a regular basis, whether it is remembering to take medication each day or reminding your kids to floss.
In this tutorial, I’ll step through how I built my healthy habits tracking system, including how I built the IoT device and how I developed the programs to communicate with a cloud application using MQTT on the IBM Watson IoT Platform.
What you’ll need to build this IoT solution
I use a MacBook Pro as my development environment, however any Linux or Windows PC with a standard USB port, wifi, and equivalent software should be suitable. I used the following software and hardware to build my healthy habits tracker system.
- Micro-USB cable (in starter kit)
- Header pins and jumper wires for connecting components (in starter kit, plus you’ll need additional Female-Female jumper wires)
- Tactile switch (i.e. button) (in starter kit)
- Piezo buzzer (in starter kit)
- 12 pixel Neopixel ring
Monochrome 128×64 I2C OLED display
Figure 2. Hardware components for my healthy habits pet
- Access to a 3D printer to print the parts. If you do not have access to a 3D printer, you can build an enclosure from a cardboard box.
- Six 8mm-diameter clear rubber furniture bumpers (or feet), which you can get from your local hardware store
- Four 2.5mm or smaller diameter screws, which you can also get from your local hardware store
- Four small springs (optional), which you use for the “button press” action
- Small Philips head screwdriver
- Soldering iron
- Hobby knife
While developing, I used the following software installed on my laptop:
- Terminal emulator (for example, Screen on Mac or TeraTerm or Putty on Windows)
- Python (with pip)
- Text editor or IDE
- Web Browser (such as Chrome or Firefox)
- Eclipse with the IBM Eclipse Tools for IBM Cloud installed Note: IBM Cloud is now IBM Cloud.
- IBM Cloud CLI
Assembling the device
I selected an IoT development kit – the AdaFruit Feather Huzzah IoT starter kit for this project. The starter kit includes jumper wires, header pins, and button and buzzer components, and I added an extra Neopixel ring to add some colorful lights for notifications and the OLED display to light up the eyes.
The microcontroller included in this development kit is the Feather Huzzah ESP8266. It features on-board wifi, with 4MB flash, an 80MHz processor, and a built-in 100mA LiPo charger. The board has 9 digital I/O pins plus 1 analog I/O pin. Refer to for the placement of the pins. The pins operate on 3.3V logic, and include support for connecting peripheral components using I2C and SPI.
Figure 3. Feather Huzzah ESP8266 pin out. (Source: https://learn.adafruit.com/adafruit-feather-huzzah-esp8266/pinouts)
Inserting components into the enclosure
Follow the steps in this video to insert to the Feather Huzzah ESP8266 and the other components into the enclosure.
I used Meshmixer to design a custom 3D printable enclosure for my device and printed the parts in ABS. I’ve published the 3D models on Thingiverse, so if you have access to a 3D printer, for example, through your local makerspace, you can print your own pet. I used a couple of 8mm diameter clear furniture bumpers from my local hardware store for the eyes, as well as 4 x 2.5mm diameter screws to hold the shell together. You can optionally add some small springs with the screws to make the button press action even smoother.
If you don’t have access to a 3D printer, you could install the components inside a small plastic container or cardboard box, using a hobby knife to cut out holes for the eyes, button and USB cable and using double-sided tape or hot glue to mount the components inside the box, similarly to how I created the enclosure for my smart doorbell and cut a hole in the lid of the container for the PIR sensor. If you are using cardboard box, you can cut one side off the box and replace it with cellophane, paper or thin fabric to act a light diffuser for the Neopixels. The components can be installed inside almost any hollow shell, so why not get creative with the enclosure? You could use a hollow plastic toy and use a dremel tool or hobby knife to create cutouts for the button, screen, and USB cable.
While prototyping, I used the breadboard and jumper wires from the starter kit to make it easy to assemble the circuit and test the code. However, inside the 3D printed shell, there is not enough space for a regular breadboard. Instead, I cut down some of the female-female jumper wires to create short wires to solder on to the buzzer, button, OLED screen and neopixel ring, to connect to the pins on the microcontroller. Alternatively, I could have used thin stranded-core Hookup wire (e.g. 22 – 30 gauge) and soldered the wires directly onto the pins on the microcontroller. I also snapped off five header pins and soldered them together to join the ground wires from each of the peripheral components together so they can all connect to the single ground pin on the microcontroller, and another set of header pins for 3.3V to power the OLED screen and neopixel ring.
Although the power pins on my OLED screen and neopixel ring are labelled “5V”, they can operate with 3.3V without any problems. On some screens and neopixel components, these will be labelled VCC instead, depending on the manufacturer. Check the data sheets for the components you will be using if you are unsure, and be sure to only select components that are 3.3V compatible.
Connecting the components and assembling the IoT device
Follow along with this video to connect the button, buzzer, neopixel ring, and OLED screen to the microcontroller following the circuit in and then to assemble the pet in the enclosure.
I connected the components to the Feather Huzzah ESP8266, following the circuit in .
- Button connected to GND and pin 14
- Buzzer connected to GND and pin 12
- Neopixel ring connected to GND, 3.3V and pin 2
OLED screen connected to GND, 3.3V and the I2C pins (SCA on pin 4 and SCL on pin 5)
Figure 4. Circuit with components connected directly to the microcontroller dev board (see
Preparing the microcontroller
I used MicroPython to develop the programs for my healthy habits pet. MicroPython is an open source python 3 compiler and runtime that runs on microcontrollers including the ESP8266. MicroPython implements a subset of the standard Cpython and the core python libraries as well as additional libraries like the machine library for working with GPIO, and the mqtt library for MQTT communication. It also implements a Read, Eval, Print, Loop (REPL), which is great for interactive prototyping.
I loaded the MicroPython firmware onto the board, connected to the microcontroller, and then uploaded custom python programs to work with the button, neopixels, buzzer, and screen attached to the microcontroller. Use the guide below to prepare your device, including flashing the device for use with MicroPython, connecting to the device, configuring the wifi, and developing programs to use with the device.
Flashing the device with MicroPython
Follow along with this video to see how to flash the board with the MicroPython firmware.
If it’s the first time you’ve used a Feather Huzzah ESP8266, you may need to install the Silicon Labs CP210x USB-serial driver to allow your computer to communicate with the board over USB. Once the driver is installed, you’ll see a device appear when you connect to the board by using USB. On my Mac, this shows up as /dev/tty. SLAB_USBtoUART, and on a Windows machine, you’ll see a COM port (for example, COM4).
To flash the MicroPython firmware onto the board, I used a python-based tool called esptool. You can install the tool using the pip package manager for Python:
pip install esptool
It’s a good idea to completely erase the flash of the microcontroller before uploading the firmware. From the command line, run the esptool utility with the erase_flash command, giving it the port as a parameter. For example, on a MacOS computer, issue this command:
esptool.py ‑‑port /dev/tty.SLAB_USBtoUART erase_flash
Or, on a Windows computer, issue this command:
esptool.py ‑‑port COM4 erase_flash
You’ll need to download MicroPython. The binary (.bin) files for each release of MicroPython are available from GitHub: https://github.com/micropython/micropython/releases. Download the latest stable .bin file and use esptool to upload the firmware file to the board using the write_flash command. This command takes the port, baud rate, and flash size as parameters:
esptool.py ‑‑port /dev/tty.SLAB_USBtoUART ‑‑baud 460800 write_flash ‑‑flash_size=detect 0 ./esp8266‑20170612‑v1.9.1.bin
Connecting to the device
Once MicroPython is running on the device, you’ll need to connect to the device through the UART serial port, through the USB cable, to access the REPL. The default BAUD rate (or, the rate that information is transmitted to the microcontroller) is 115200 bits per second. Use a terminal emulator to connect to the board. If you are on Mac, you can use the GNU screen program from the command line:
screen /dev/tty.SLAB_USBtoUART 115200
On Linux, you can use screen or picocom; on Windows, use a terminal emulator like TeraTerm or Putty.
Once you have connected to the microcontroller, hit enter to see the REPL prompt. You can enter commands in directly, or press control-e to enter paste mode, which will allow you to paste in entire programs (press control-d to exit paste mode).
Configuring the wifi
By default, the ESP8266 is set up to create an adhoc wireless network with the default password of ‘micropythoN’ (with an uppercase ‘N’). To connect your device to an existing wireless network, you can configure the settings from the main.py file which is run just after the device boots. Use your text editor or IDE to create a file named main.py with the following contents (change
import network #disable access point mode ap_if=network.WLAN(network.AP_IF) ap_if.active(False) #configure connection to wireless network sta_if = network.WLAN(network.STA_IF) if not sta_if.isconnected(): sta_if.active(True) sta_if.connect('<essid>', '<password>') while not sta_if.isconnected(): pass
Developing programs using MicroPython and uploading them to the device
The healthy habits pet code is published in my healthy-habits-pet GitHub repo in the micropython directory. This GitHub repo includes the main.py file from the previous section and programs for controlling the lights, sounds, LED display (which requires additional libraries), and using MQTT to send data to Watson IoT Platform.
Follow the steps in the following video to upload libraries and programs to your device.
You can use the MicroPython REPL to type in program statements line by line, or upload complete Python program files that read from sensors or control output devices that are connected to the pins on the microcontroller.
To upload files, you can use ampy from the command line (https://github.com/pycampers/ampy)
ampy ‑‑port /dev/tty.SLAB_USBtoUART put main.py
The settings will take effect next time you boot the microcontroller.
The sections that follow describe some of the code within the Python programs.
There are many third party libraries available for MicroPython to support specialized components. The OLED display used for the eyes of my pet device can be programmed using the SSD1306 library: https://github.com/adafruit/micropython-adafruit-ssd1306
To use the library, download the mpy file (available under the releases tab on the GitHub page), and upload it to the board using ampy from the command line.
ampy ‑‑port /dev/tty.SLAB_USBtoUART put ssd1306.mpy
I’ve used the drawPixel function from the library to draw an image stored as byte arrays (by iterating through the arrays to determine whether to draw a pixel or not). The oled.py program in the healthy-habits-pet git repository includes some example images, including the love hearts that are used to animate the eyes after successful completion of the exercise, and the sleepy eyes that are displayed when the pet has not been activated for a while.
To read from the button connected to pin 14, use the Pin class to set the pin to input mode and then read the button value into a variable:
from machine import Pin button = Pin(14, Pin.IN, Pin.PULL_UP) pressed = button.value()
To detect presses, you can poll the button state, for example, from within a loop. The mqttbluemix.py program in the healthy-habits-pet git repository shows an example of responding to button presses (by publishing MQTT events).
The piezo buzzer can produce tones at different frequencies by using Pulse Width Modulation (PWM) output. To make the piezo buzzer beep at the frequency 440 (the note A above middle C), create an instance of the Pin class in output mode on pin 12, and use the pin object to create an instance of the PWM class to control the PWM frequency and duty cycle. Finally, de-initialize the object to stop the beep:
from machine import Pin, PWM import time piezo = PWM(Pin(12, Pin.OUT), freq=440, duty=512) piezo.freq(440) time.sleep(0.5) piezo.deinit()
You can also write to the pin directly to control the piezo. The soundfx.py program in the healthy-habits-pet git repository contains an example using math functions to control the delay between alternating high and low digital writes to generate interesting sounds (manually creating a PWM-like signal).
def soundFX(amplitude=1000.0, period=1000.0, repeat=100): for i in range(1,repeat): uDelay = math.floor(1.5 + amplitude + amplitude * math.sin(utime.ticks_ms() / period)) p.value(1) utime.sleep_us(uDelay) p.value(0) utime.sleep_us(uDelay)
See the soundfx.py program in the healthy-habits-pet git repository for examples of using this function.
The Neopixel class comes built in to MicroPython. You can use it to individually set pixels in the ring to different colors, using a tuple of red, green and blue color values, each between 0 and 255. For example, to set all of the pixels in the ring connected to pin 2, to red, iterate through the pixels, setting them to (255, 0, 0). Finally use the write method to update the LEDs.
from machine import Pin from neopixel import NeoPixel np = NeoPixel(Pin(2, Pin.OUT), 12) for i in range(np.n): np[i] = (255,0,0) np.write()
You can find more examples of working with the Neopixel class in the lights.py program in the healthy-habits-pet git repository.
Connecting the device to the IBM Watson IoT Platform
The device uses MQTT to publish habit events (which are recorded when the button is pressed) to the IBM Watson IoT Platform, where the events are stored in a Cloudant NoSQL database. A cloud application reads the data and sends update events to the device to trigger the pet to perform a reminder (using lights and sound). I used MQTT for two-way communication to and from the device and to and from the cloud application because it is a very lightweight protocol and because it is supported by the built-in mqtt library in MicroPython. (Read more about networking protocols, including MQTT in my networking guide.) MQTT requires a broker, so I’ll be using a broker running on the IBM Watson IoT Platform. shows this architecture of my IoT app.
Figure 5. Healthy habits tracker system architecture
To get set up to use MQTT with IBM Watson IoT Platform, complete the following steps:
- Create and configure an IoT service and a Cloudant DB serviceRegister a new device type (in our case, ESP8266)
- Register the device
Follow along in the following video as I set up the Cloudant database and IoT Platform service through the IBM Cloud dashboard, and then register the device such that it can send and receive data by using MQTT. (IBM Cloud has been renamed to IBM Cloud, but you’ll see some references to IBM Cloud in the video.) The section below provides additional information for how to complete these steps.
Create and configure an IoT Platform service
Log in to IBM Cloud.
To configure a new IoT Platform service, open the Catalog from within the IBM Cloud dashboard, and select ‘Internet of Things’ from the sidebar on the right-hand side of the screen and then select ‘Internet of Things Platform’. Enter a service name, select a region and plan, and then press the ‘Create’ button to create the service.
Create and configure a Cloudant NoSQL DB service
Create the Cloudant DB from the IBM Cloud Catalog by selecting ‘Data & Analytics’ from the sidebar, and then selecting ‘Cloudant NoSQL DB’. Enter a name for the Cloudant service, select a region and plan and then press the ‘Create’ button.
To persist the device data, I set up the Cloudant DB as a historian service. Read the IBM Cloud documentation on “Connecting and configuring a historian service.” Double click on your Internet of Things Platform service displayed in the IBM Cloud dashboard, then click the Launch button to view the service details. From the IoT Platform dashboard, select Extensions from the sidebar and press the Setup button underneath the Historical Data Storage item on the extensions screen. You will need to enable pop-ups. Configure the historian service by selecting a bucket, timezone and database name and then click Done to complete the configuration of the service.
Then click Confirm in the pop-up that appears after you have configured the historian service.
Register a device type and register the device
To register the device type (ESP8266) and our healthy habits pet, follow the steps in the “How to Register Devices in IBM Watson IoT Platform” recipe. Also, refer to the IBM Cloud documentation on “Connecting Devices.”
If I had wanted to use more than one healthy habits pet, for example, to have one device on my desk to remind me to break to exercise and another in the kitchen to record when I remember to take my vitamins. I’d need to repeat the final step to register each device. The cloud application could then distinguish between the devices based on the device ID or device metadata, or I could create multiple device types instead of a generic ESP8266 device type; for example, I could have a vitamin-tracking-pet type and an exercise-tracking-pet type.
Configure the connection in the MicroPython connection
Once you have registered a device, you’ll need the following pieces of information (which you copied from the final screen when registering a device) to configure the connection in the mqttbluemix.py MicroPython program to run on the device:
- Organization ID (the 6-character identifier)
- Device Type (in our case, ESP8266)
- Device ID for the specific device (for example, I used pet1)
- Authentication Token
You should use TLS to connect securely to the MQTT broker. To create a secure connection to the MQTT broker from MicroPython, set the ssl parameter to True and the port to 8883 when initializing the MQTTClient. Change the
server = "<orgid>.messaging.internetofthings.ibmcloud.com" clientId = "d:<orgid>:<device_type>:<device_id>" client = MQTTClient(clientId, server, port = 8883, ssl = True, user="use‑token‑auth", password=<token>)
By convention, the MQTT topics for applications take the this form:
iot-2/type/<device type>/id/<device id>/evt/<event type>/fmt/<format type>
For devices, the MQTT topics take this form:
iot-2/evt/<event type>/fmt/<format type>
For commands, the convention is:
iot-2/cmd/<command type>/fmt/<format type>
Hence, the pet publishes on the iot-2/evt/habit/fmt/json topic whenever the button is pressed to register the successful completion of the habit that is being tracked. It subscribes to the iot-2/cmd/update-tracker/fmt/json topic to receive update commands from the cloud application, which updates the status to display on the pet (in the eyes of the pet), as well as being used to trigger reminders (using the LEDs and buzzer).
To publish an event use the client.publish method:
See to see the details, include recent events, for our healthy habits pet.
Figure 6. Details of a pet device on the IBM Watson IoT Platform dashboard
Recent events published by the device are displayed through the IoT dashboard, so you can use this dashboard to verify that messages are being sent from the device. Also, you can look at the Connection Log or Diagnostic Log to troubleshoot any problems. The device events are also stored in the Cloudant database that you set up, which shows.
Figure 7. Example device data stored in Cloudant DB
Connect IBM Cloud services
When the deployment process is complete, you will be able to see and administer the app from your Cloud Foundry Apps page (make sure you select the region where you deployed the app at the top-right of the dashboard, which in my case was US South). Double-click on the app name to view the details of the deployed app.
Figure 8. Deployed app details
To use the Cloudant DB and MQTT service that you set up earlier, you’ll need to connect the services to the app. Follow these steps to connect the Cloudant DB to the app:
- Double-click on the application from the Cloud Foundry Apps page to see the app details, and then click on Connect existing under Connections.
- Select the Cloudant NoSQL DB service that you created earlier.
- You will be prompted to restage (and restart) the app. IBM Cloud provides the database credentials to the app using the VCAP_SERVICES environment variable.
Follow the same steps to connect the app with the IoT Platform service. After both services have been connected, you should see both of them when you select Connections from the left-hand sidebar.
Figure 9. Connected services
The VCAP_SERVICES environment variable is only available when the application is running on IBM Cloud. If you want to connect to these services when you are running the app locally, you can update the local code to point to these services by storing the credentials in a properties file, for example:
- In the IBM Cloud dashboard, go to Connections -> Cloudant -> View Credentials.
- Edit the file
src/main/resources/cloudant.properties. Copy the url field from the credentials to the cloudant_url field in the properties file.
Running the cloud application
The cloud application is a Java Cloud Foundry app. To develop the cloud application, I used Eclipse. The source code for the application is published in my healthy-habits-pet GitHub repo in the cloud-app directory.
Follow along the video to see how the device interacts with the cloud app and how to run the cloud app locally using Maven, run the app on IBM Cloud with the command line, or run the app on IBM Cloud by using Eclipse.
Run the app locally using Maven (from the command line)
You can run the application locally. After you have cloned the app from GitHub, use Maven to download the dependencies and build the .war file:
mvn clean install
Then run the app locally with the liberty:run-server command.
mvn install liberty:run‑server
You can access the app at the following URL: http://localhost:9080/HealthyHabitsBackend
Run the app on IBM Cloud (from the command line)
To run the application on IBM Cloud, use the CLI tools to select the IBM Cloud API URL for the region to deploy to (for example, US South is https://api.ng.bluemix.net)):
bluemix api https://api.ng.bluemix.net
Then, log in to IBM Cloud using your IBM id:
bluemix login ‑u <your username> ‑o <your IBM Cloud org name>‑s dev
You can use the single sign-on option if you are using a federated ID:
bluemix login ‑o <your org> ‑s dev –sso
The manifest.yml includes configuration for the app, including the name and location, how much memory to allocate for each instance, and how many instances to create. You can edit these values to customize how your app will be deployed. See the IBM Cloud documentation on “Deploying apps” for details on the application manifest. Use the IBM Cloud CLI to push the app to IBM Cloud, which creates a new Cloud Foundry application.
bluemix app push "Healthy Habits Pet Backend"
Run the app on IBM Cloud (using Eclipse)
If you prefer, you can deploy the app from Eclipse rather than the command line. The IBM Eclipse Tools for IBM Cloud provide features such as remote debugging and incremental updates. Note: IBM Cloud is now called IBM Cloud.
Import the app into Eclipse by selecting File -> Import -> Maven from the menu, and then select Existing Maven Projects.
You’ll need to create an IBM Cloud server definition:
- From the Servers view (to see this view go to Window -> Show View -> Other -> Servers), add a new server.
- Select IBM -> IBM Cloud and follow the wizard steps.
Then you can run your application on IBM Cloud:
- Right click the app, and select Run As -> Run on Server
- Search for and select the server you created and click on Finish.
- The wizard will step you through signing in to IBM Cloud and deploying the app.
Summary and extending the app
I’ve stepped through how I designed my habit tracking device and connected it to the IBM Watson IoT Platform to send and receive data to a NoSQL database and with a cloud application. I described how to configure a Cloudant NoSQL DB service and an IoT Platform service on IBM Cloud, which provides an MQTT broker for sending and receiving data from the habit tracking IoT device, and a data historian service to automatically persist the MQTT messages to the Cloudant DB. I also stepped through how to deploy and connect these services to a cloud application developed in Java.
I outlined how I developed the habit tracking IoT device software with MicroPython, as well as describing how I built the device using a Feather Huzzah ESP8266 IoT development kit. Using the development kit simplified the development of the device and provided the electronic components required to develop the basic device behavior with a button to trigger sending MQTT events, and a piezo buzzer for notification. Using the kit saved time sourcing individual components and removed the issue of whether the components would be compatible with the microcontroller and whether they would work well with MicroPython. I also showed how it was possible to extend the capabilities of the development kit by adding an OLED screen and neopixel ring, which are supported by MicroPython libraries.
The functionality for the tracker is deliberately kept to a minimum for this tutorial, and just focuses on responding to button presses as well as notification using the LEDs, piezo and screen, however here are some of the ways that you can extend this app:
Power management: This allows the pet to run efficiently on battery power and can be achieved by connecting GPIO pin 16 to the RST pin on the Feather Huzzah ESP8266 and then by using MicroPython’s machine library’s real time clock to extend the device program to add deep sleep support, so that the pet would periodically sleep for set intervals to save power, and then re-connect when it wakes.
Analytics: For this tutorial, the cloud app is not being very smart about when to send reminders. Using the IBM Watson IoT Platform to visualize and perform analytics on the data that is collected from the device would be an improvement to the app, to determine the most optimal times, and adjust the frequency of the reminders based on how often the habit was performed in the past, and use these insights to schedule periodic reminders using the Workload Scheduler service.
Automatic device registration: I’ve kept things simple by manually registering my habit-tracking pet device using the IBM Watson IoT Platform Dashboard. For the application to scale to allow many devices owned by many users, the pet devices would need to be registered programmatically. One way to achieve this would be for users to register devices through a custom web app or in bulk through the REST API. You can read more about registering devices in bulk using REST or by using the Java client library. This recipe for using the Java Client library also describes how to simulate multiple devices to get a constant stream of events to use during development and testing.
Mobile app: Another improvement would be to upgrade to an ESP32-based microcontroller (the successor to the ESP8266) and use low energy Bluetooth (BLE) to connect the IoT devices through a phone running a custom mobile app, which would take care of the device registration and allow multiple devices to be coordinated. This approach has been adopted by many other personal health and fitness related devices, including fitness / activity trackers and wireless scales. To track multiple devices for multiple users, the cloud application could also be extended at a later date to manage user accounts and to associate devices with each user.
Gateway devices: Another option to scale this application would be to add gateway devices to the architecture. This solution is appropriate for larger-scale or data intensive applications, for example, within connected cities, or for community-wide applications connecting thousands of devices, or for health applications where devices containing a lot of biometric or activity-related sensors, where edge computing techniques would be applied to filter and pre-process large volumes of data being collected by the devices.
The author used the circuit diagrams from these Fritzing components to create her own circuit diagrams for this tutorial:
- AdaFruit library:
- OLED Frtizing component: