Office Weather Station - Internet of Things Project
IoT Project Objective
Our main objective was to build a system that could help us easily monitor the temperature and humidity inside our office building. There were no strong requirements in terms of what the end product should be - an app, a website or some kind of a GUI that could only be used inside the office, so it would be our future task. For the first few months, we focused on the hardware and the firmware. The other inner solution, that was designed by our team, is a safe password manager used for in day-to-day communication.
- can work with batteries or from wall outlet;
- long battery life - at least 1 year;
- potential to add more/different sensors;
- independent devices: when one breaks, others continue to work.
We chose to use Azure as the platform - it’s well established, has features such as MQTT support and we have a lot of positive experience with it. It also has the ability to handle events from IoT devices via Azure Functions, a key element of the structure in our project.
For sending the data we chose MQTT, a lightweight protocol designed for publishing telemetry data. It fits our needs well and has additional features such as subscriptions and topics. Subscriptions are an easy way to link an Azure function to an event. We used it to process the data that comes to the Azure IoT Hub and write it to the database.Topics are essentially channels which can be used to separate the incoming messages. In our project, there is a subscription which triggers a function when a new device sends a message to the default channel. This function creates a new topic for the device, creates a token and sends a message to the device which makes it switch to its own channel.
Bluetooth or WiFi
At the very beginning, we were debating whether the devices should be completely independent and should be connected directly to the internet or not. The other option was having a gateway device on each floor that would gather the sensors information from the devices and send it to Azure. We chose in favor of the WiFi version.
At first, we used one of the most popular temperature + humidity sensors, known as DHT11. It uses 3 pins for power and data connection, draws low current, is small and affordable (< 1$) and widely available. Attractive, but the first tests show a large relative error: when we compared a few devices with the exact same sensors placed side by side, the temperature values varied by a few degrees. Luckily there are some good alternatives. DHT22 costs ~$4 and is marginally larger but it is much more accurate and returns values that are much more precise (it goes into decimals, i.e. 24.3 degrees Celsius). It even uses the same C++ library as DHT11 so we changed just the configuration.
Another good alternative is SHT30, which is available as a shield for easy connectivity and costs about the same (not compatible with DHT sensors and requires a different library).
In the future, we plan to add more sensors: light, noise level, air quality etc.
There were a lot of board options to choose from for our WiFi device. We tried Arduino boards with external WiFi chips and they worked but at some point, it became clear that modern WiFi chips have enough computing power and features and all the connectivity needed to get the data from the sensor and send it over MQTT to Azure. So, the simplified device would consist of the WiFi chip, sensor, battery, and case. We used ESP8266, a widely available WiFi chip.
The main benefit of this design model is that there is no gateway device gathering data from nearby node devices, because all the devices are equal, connected to the Internet and can send the data directly to Azure.
Deep sleep mode
One major feature that led us to believe it would be possible to make WiFi chips last for long periods of time off batteries is Deep Sleep. It’s an internal feature of ESP8266 that lets you send the device to sleep and wake up some time later while not consuming much energy in sleep mode. In deep sleep mode, all the internal circuits are cut off and power is sent only to a clock module which is responsible for waking up the device. And again our test shows the difference with tech specs on paper and device work in reality. The implementation of deep sleep is not great at ESP8266 module, at least on all the boards that we tried some of the circuits continued to consume power. So, all our attempts to optimize the power consumption did not meet our expectations so we made a step back and tried Bluetooth chips.
One option was to find a similar chip with Bluetooth capabilities (ESP8266 only has WiFi) and return to the idea of using node devices that send data to an Internet-connected gateway device. ESP32 fits this idea well but again the first researches show that the deep sleep still would not disable all the circuits and the power consumption would not be as low as needed. So, we take a decision to go ahead with wall outlet version and return to battery mode with upcoming Bluetooth 5 modules. As you surely know, Bluetooth SIG community announced Bluetooth 5 protocol with its benefits:
- range up to 100 meters;
- advanced BLE mode (Bluetooth Low Energy);
- data transmission speed up to 2.0 Mbps;
- wireless coexistence.
The firmware was developed in C++ in Visual Studio. At first we used Arduino Studio for flashing, but later on, we discovered Arduino IDE extension for Visual Studio, which lets you write code and flash it in the same environment. It also has an inbuilt system for installing libraries that are needed to add support for sensors, MQTT etc. You can also set all kinds of settings like board type, firmware upload speed, clock rate etc.
Writing the firmware was a challenging process. First of all, flashing new firmware on a cheap ESP8266 development board is not reliable and sometimes results in bricking the board and making it unusable. It happens quite often even with all the correct settings. And if you chose the wrong settings to break the board is even more likely. It would be very helpful to have an easy process to reset the onboard memory of ESP8266, but unfortunately, when something goes wrong during flashing, the memory cannot be erased and while the device can show signs of life, all you get in the development console is garbage instead of readable output.
Getting messages from Azure wasn’t easy either. The main problem was to find a time window when the device is ready to accept a message, even when the device is powered on. In deep sleep, it obviously can't receive messages.
Our devices work like this:
- wake up;
- connect to WiFi;
- get data from the sensor;
- send data to Azure over MQTT;
- start 30-second countdown;
- be ready to receive messages;
- wait for the countdown to be over;
- go to sleep.
So the device does not accept messages over all of the time when it is powered-on. There're a few seconds when it’s busy getting and sending data.
A queue of messages for a device would be a perfect solution, but there is no easy way to implement it because that’s just not the way MQTT is designed. So the messages to the devices are sent a few seconds after receiving a power-on event. Luckily that fits our needs as our only messages to devices contain instructions to switch topic and are designed to be sent after getting data from the device.
If we wanted the devices to be able to receive messages at any time, we would have to keep them always on, which would increase the power consumption.
MQTT message size
Another challenge was getting the messages delivered, both to and from Azure. Apparently, the MQTT library has an internal setting that defines the size of the message and its content in bytes. The default size was too low and we had overflow issues that were difficult to debug. Our messages to the devices were ignored if they were too long. We managed to fix it by change one of the parameter in the MQTT library.
After taking lots of measurements we had to find a good way to display our data. We wrote a dashboard website that has 2 pages with different types of charts: one with trendlines to show the current data and another one where you can see interactive line charts and have the ability to navigate between previous days. Additionally there is a page with alert history, a page with settings for alerts (for example, admins can set the criteria to send a message to a Slack channel if the battery level falls below a certain point or if one of the devices becomes unresponsive etc.) and a page for editing device names and locations. Technologies used: Angular, ngx-charts, node.js, Express, Azure Functions, Azure IOTHub.
Future plans: beacons
While waiting for boards with Bluetooth 5 that we could use for sending data over BLE channel we discovered a chip by Nordic Semiconductor called nrf51822. It’s a chip widely used in beacons - devices that are most often used as proximity sensors or for notifications/alerts for nearby devices. Other beacon applications include wearables, monitoring with various sensors, RF tags etc. Devices based on this chip have a large working range (up to 30-40 meters), which should be enough to cover an office floor. It is a programmable chip but there are ready-made devices that have inbuilt temperature, ambient light, and atmospheric pressure sensors. This chip has ultra-low power consumption, which is a huge advantage.
The main difference in working with beacons compared to our previous devices is that beacons don’t send data, they advertise it. Essentially they broadcast a message that a device with a unique identifier is available and ready for querying. This broadcast is different from any typical request on the Internet: it is not sent to a specific address or device and there is no response required. Instead, any listener device nearby can receive this message. The message itself does not contain sensor data but lets the listener connect to the beacon and send queries to get needed sensor data.
Our plan is to make a network of beacons and a gateway device on each office floor which queries all the beacons and sends the data to Azure.