Skip to main content

Breathe Better Bear- An Air Quality Project. Part 3


Welcome! This is part 3 out of 3 of the articles written about my project, the Breathe Better Bear.

Part 1 introduced the project and talked about challenges and the materials used. Part 2 is a building guide that includes the laser cutting files and the 3D printed part to replicate the project, plus how everything is connected into the Reka:bit board.

In this Part 3, I will be talking about coding the bear. This part of the project was challenging for me as it was the first time I’ve tried making anything around IoT. Fortunately, I had lots of help from the amazing Pete Milne.

The idea for the Breathe Better Bear was that he would have both access to information from the ESDK sensors and an external API that would help make a forecast of the Air Quality Index so the users could choose to have the bear point towards the current (local) conditions as per the sensors, or the regional forecast informed by the API.

Thus coding the bear is divided into parts:

  • Coding the behaviour of the bear
  • Connecting the bear to Wifi
  • Using Mosquitto to test the MQTT connection
  • Installing Node-RED
  • Using Node-RED to get the ESDK sensor data
  • Using Node-RED to connect to an API

Coding the behaviour of the bear

You can access a copy of the bear’s code here. Since I used a Micro:Bit in a Reka:Bit board, I coded the bear with MakeCode. An explanation of the blocks and the code follows.

In the previous article (Part 2) there are instructions on how to create and assemble the bear. To bring him to life there are 4 elements on the bear to control through code: the pointing arm, the left eyebrow, the right eyebrow, the mouth that flips to change his expression.

In addition to that, there is the toggle switch that has the bear change from receiving the local or regional information, the lights that reflect that choice, and the Hazardous Conditions light that will flash when the air quality drops significantly enough.

Bear Faces

We know the bear will have different expressions depending on the 6 Air Quality Index (AQI) levels (for the project I am using USA charts): Good, Moderate, Unhealthy for Sensitive Groups, Unhealthy, Very Unhealthy, and Hazardous. So the set of parameters for the expressions and behaviours for each level are held inside different functions that can be then called by the program. (The functions blocks are found under the Advanced drop-down menu.)


In my code, as talked about in the building instructions, Servo 1 (S1) is the arm, Servo 2 (S2) is the mouth, Servo 3 (S3) is the left eyebrow, and Servo 4 (S4) the right eyebrow. Pin 9 (P9) is the Hazardous exclamation mark, Pin 12 (P12) and P2 are the status lights (not pictured in this part of the code).

Since my project used a Micro:bit v.2, it is able to play simple sounds without having to assign a pin to it. All the orange Servo blocks used here are found under the Reka:Bit extension. (Go to Advanced>Extensions>Rekabit)

The code can be tested by adding a forever loop that calls the different Functions.


The positions of the servos were determined by trial and error. Once the positions reflect the behaviours you want for each AQI level, it’s time to connect the bear to WiFi.

Connecting the bear to Wifi and testing the connection through a test MQTT service

To connect to the Wifi and MQTT server, we need another Makecode extension that will let us use the Wifi Module. If you search under extensions for esp8266, you will find several options. While the module we are using is the Cytron brand, we will use the iot-environment-kit one since that gives us more access to MQTT blocks.



To establish the connection with the Wifi module and then the MQTT broker, the blocks need to be contained in the “on start”. To make it easier to troubleshoot, included in the code are several blocks that test the connections.


First when the Micro:bit starts, show a heart icon. Then set up the connection of the Wifi module to the Pins where it is connected (Rx P16 and Tx P15 in this case). Then add a block with your Wifi credentials (replacing the placeholder text), pause for a few seconds, and test to see if the Wifi connection is true by having an if true block which will then display a checkmark or an x depending on whether it is connected or not. Once that is done, there are blocks to establish the connection with the MQTT server, and when it is connected, it’ll show again a checkmark or an x. For now, the code is using the server, which will be explained further down. This must be changed later when using a different MQTT server.

If you turn on the bear with this code and the Wifi and the MQTT connections are working, it’ll display a heart, then a checkmark followed by another checkmark after a few seconds. If it displays an x after the heart, you need to check your Wifi credentials. If it displays an x after a checkmark, you need to check your MQTT server settings and make sure everything is spelt correctly and it’s using the correct port.

As mentioned before, the way the bear is set up has two modes. One is where it is listening for information from the ESDK sensors and the other for the API. To allow for that, the code for the switch on top of the bear sets the “mode” variable to either “local” or “regional” and turns on the correct indicator light and turns off the incorrect one.


With that done, we can add a “when Topic block” from the MQTT blocks that will be listening for messages sent by the MQTT service on specific Topics. In the bear’s case, he’s listening for messages on two topics. One is regional/aqi (listening to the AQI data from the API server) and the other is local/pm2pt5 (listening to the ESDK PM2.5 sensor data)


The code checks to see first if there is a message on that topic, then checks if it is in the correct “mode” from the variable set by the switch. If it is, then it checks to see if what number is the message (the message content is defined by the user, having it be a number from 1-6 matches the Air Quality Index API’s numbers for the different air quality levels, so that’s why they were kept like that for clarity. Once it receives the specific number, the code then calls the corresponding variable and the bear gets to do the programmed behaviour.

If Makecode doesn’t let you add the numbers as the message, it’s because you need to add them inside a text box block because even though they are numbers, they need to be interpreted as text. The text box block is found at the top of Advanced>Text.


Using Mosquitto to test the MQTT connection

With the bear coded it is time to test it with the Mosquitto test server. Mosquitto is an MQTT broker that has a test server available for developers to check their MQTT settings and such.

The first thing is to install Mosquitto on your computer, so you can “talk” to the server. They have instructions for downloading for different systems on their website:

Once it is downloaded, you can use Mosquitto to send commands to publish messages to the test server on the topic that you want.

(The operating system used when creating the bear was MacOS, so I apologize if the instructions are different if you are using a different OS.)

To send a message on MacOS, open up a Terminal window after Mosquitto was successfully installed, then you can type:

mosquitto_pub -h -t ‘regional/aqi’ -m ‘3’

What that command is saying is to publish to Mosquitto’s host on the topic “regional/aqi” the message “3”. Please note that MacOS Terminal uses the single quote sign ‘ ’ instead of the double quotes “ ” to send messages.

If the bear has been coded correctly at this point and the switch on top is toggled towards the “regional” setting, he should do the behaviour for the Unhealthy for Sensitive Groups category.

Installing Node-RED

From this point, most of the instructions are specific to having an ESDK unit and having followed the basic setup instructions. But if you have a Raspberry Pi with sensors connected to it, you might be able to follow along, but I am afraid I can’t guide you on that.

The ESDK has specific settings that come when you image the card like sending the information from the sensors as MQTT messages under the topic airquality.

Since I’m a visual coder, Peter Milne guided me through installing Node-Red, which is a programming tool that allows for coding the Raspberry Pi (among other things) through your browser using “node” coding.

These are the instructions to install Node-Red written by Peter Milne :

1. Remote login via SSH:

ssh pi@airquality.local

2. Update system:

sudo apt update

sudo apt upgrade

3. Power down using the stop (Bottom) button, remove the power supply, wait for a few seconds, then power on again.

Check the system is still functioning normally.

4. Install Node-RED by running the Raspberry Pi installation script below from Node-RED. Full details can be found on this page:

bash <(curl -sL

The output should look like this:

Running Node-RED install for user pi at /home/pi on Raspbian

This can take 20-30 minutes on the slower Pi versions - please wait.

Stop Node-RED ✔

Remove old version of Node-RED ✔

Remove old version of Node.js ✔

Install Node.js 14 LTS ✔ v14.18.3 Npm 6.14.15

Clean npm cache ✔

Install Node-RED core ✔ 2.2.0

Move global nodes to local -

Npm rebuild existing nodes ✔

Install extra Pi nodes ✔

Add shortcut commands ✔

Update systemd script ✔


Any errors will be logged to /var/log/nodered-install.log

All done.

You can now start Node-RED with the command node-red-start or using the icon under Menu / Programming / Node-RED

Then point your browser to localhost:1880 or http://{your_pi_ip-address}:1880

Started : Tue 1 Feb 11:34:14 GMT 2022

Finished: Tue 1 Feb 11:38:09 GMT 2022

You may want to run node-red admin init to configure your initial options and settings.

5. Start Node-RED


6. Enable auto-startup

sudo systemctl enable nodered.service

7. Re-boot the system and next time Node-RED will start automatically

8. Open a browser and navigate to airquality:1880 - the flow should appear in the browser window

Each time a node is changed it needs re-deploying

Node-RED documentation:

ESDK MQTT message format:

{"hardwareId": "RPI0000000010f6d74f",

"thv": {"vocIndex": 100, "temperature": 23.7, "humidity": 36.5, "sensor": "THV0.2"},

"pm": {"sensor": "PM20.2", "pm1.0": 1, "pm2.5": 1, "pm4.0": 1, "pm10": 1},

"geohash": "u11n9g377406", "co2": {"sensor": "CO20.2", "co2": 720}


Once Node-Red is installed, you can connect to it by going to your browser by typing your pi IP address:1880 (in the case of the bear + ESDK it’s http://airquality.local:1880) and get coding.

At this point, for the bear to be able to talk to the ESDK and receive the MQTT messages from it, you need to change the code inside the connect MQTT broker host block to match the IP address of the ESDK. You can get that from your router's admin page. The connection didn’t work when using the hostname.

Using Node-RED to get the ESDK sensor data

Node-RED uses blocks or nodes as they are called here that you can double click to change the settings and you can connect them to each other by clicking the little grey box on the side and dragging the line that is created to the block you want to connect it to.


This is an overview of my first “flow”, which corresponds to the code to retrieve the sensor data and send it to the bear.

I’ll explain each node below. To find the node you want to use look at the colour and the icons. The names are customizable so you won't find a node already called “pm2pt5_filter” for example. Remember that double-clicking lets you edit the settings.

  • ESDK- This node connects to the ESDK’s MQTT service subscribing to the topic airquality. It’ll read the information from the sensor connected to the ESDK that it’s transmitting. You can edit the specific info on the MQTT broker by clicking the pencil edit button.
  • ESDKNodeEdit ESDKNode
  • Pm2pt5_filter- This node is filtering out the information from the ESDK so it ONLY pays attention to the pm2.5 filter that measures particulates in the air and we’ll be using to calculate the AQI
  • Pm2pt5filter
  • Pm2pt5_rules- This node sets up a set of rules to interpret the sensor data. This says that if the sensor gets values between say 0-12, the air quality is good, so the message sent is “1”. If it is between 13 and 35, then air quality is moderate and the message sent is “2”, and so on. The values used here were calculated on the website which allows you to enter the pollutant (like pm2.5) and tells you which values correspond to what Air Quality Index level.
  • Pm2pt5rules
  • 1,13,36,56,151,252 - These buttons are for testing that the messages are being sent correctly. You press the rounded square on the left of each one and the message or number corresponding to the button is sent. The bear should then receive the message and act accordingly. In this case, each of them corresponds to the lowest number that activates the next AQI level. (Pictured here is the one for 1, which would be Good)
  • InjectNode1
  • Changes- This node will block sending a new message unless the value changes. That way it is not constantly sending the same number over and over.
  • Changes
  • Msg.payload- Is used for debugging
  • Debugging1
  • Local/pm2pt5- This node sends out the MQTT message or number that was determined before, to the topic you specify. This is the topic that the bear is coded to listen for.
  • LocalMQTT

Using Node-RED to connect to an API

The first thing to do to use an API is to decide which API to use. For the bear project, I wanted Air Quality Index data that allowed for forecasting. And of course, I wanted it to be free.

In the USA there is a government website that allows you to subscribe to their API for free as long as you don’t exceed the number of API calls allowed (more on that later). You need to create an account and get your own API key:

Once you have an account you can go to web services and check Forecast by Latitude and Longitude or whatever best works for you and enter the information of the area or region you want the forecast to be from. This will generate an API key you can then use in Node-RED.

In Node-Red, you must create a new flow (assuming you created the sensor flow first) by going to the hamburger menu > Flows > Add



This is the second “flow” in my project and I’ll talk about the nodes used here. Please note again that the nodes were named while coding, so to find the correct ones to use, you should look at the colours and the icons they have. By double-clicking each node you can change the settings on them.

  • Timestamp - In here you can set up how often to check the API website for updates. It is better to not have it too often as your AirNow account could be blocked if it gets too many calls per hour. Since we’ll be using the forecast option, this can be set to repeat at 60-minute intervals or so.
  • Timestamp
  • AirNow- This is an http request node. This connects to the API using your personal key which you enter in the URL section.
  • AirNowRequest
  • Function- This function node checks the API’s response which is a JSON string. it retrieves the Air Quality index directly which is in the “Category”,“Number” element. It is this AQ index from 1 - 6 that is later sent to the Bear.
  • FunctionNode
  • Msg.payload- Is used for debugging
  • debug2
  • Regional/aqi- This one sends out the MQTT message to the specific topic you set. This is the topic that the bear is coded to listen for.
  • RegionalAqi
  • 1,2,3,4,5,6 - These buttons are for testing that the messages are being sent correctly. You press the rounded square on the left of each one and the message or number corresponding to the button is sent. The bear should then receive the message and act accordingly.
  • Inject2


And there you have it, now the Breathe Better Bear is ready for action!

By coding the Micro:Bit inside the bear to connect to the Wifi and to the MQTT broker set up in the Raspberry Pi inside the ESDK, it is now able to point to the Air Quality Index conditions locally by reading the ESDK sensors, or to a forecast in your region by connecting to a free Air Quality API.

I hope you enjoyed the articles and they inspire you to create your own project.

Cecilia is an illustrator, maker, and dreamer. She likes making things that amuse her (mainly involving animals). Cecilia has worked as an educator for several years in different capacities, mainly with students ages 6-14 years old.
DesignSpark Electrical Logolinkedin