Rainwater tank monitoring without coding
During a MAXWHERE demo, a potential customer asked me how complicated integrating an Industrial IoT device into a MAXWHERE digital twin is. I frankly answered that it could not be more than half an hour from scratch. He smiled widely….
I knew the truth about that because recently, we have integrated a whole bunch of P+F IO-Link sensors through MQTT, so I was pretty confident. To present a double proof, last weekend, I made a quick sprint on my kitchen table and put together a perfect justification: I modeled the IoT monitoring system to my rainwater collector tank using a $20 kit.
Let's see the details…
System architecture
The setup should represent the easiest way of implementing the monitoring. The goal is clear: sampling the water level with some electronics and sending the measurements to a messaging server on an interval basis. In the monitoring app, we then subscribe to the measurements and handle the visualization as we need it.
Regarding the messaging, the way to go (at least for our purpose) is MQTT. This is the quickest possible and lightweight enough IoT messaging platform that can serve a vast majority of use cases even in industrial environment.
Hardware components
For my home projects, I usually use the products of M5 Stack. This company is a rising star from China with supercool components to build almost anything. Since I order M5 Stack stuff regularly, picking all the necessary components from my inventory was easy.
The core of the edge system is an M5 Stack Atom Matrix. A simpler Atom would make it, but I had a Matrix at hand. M5 Atom Matrix is a tiny dev unit with a powerful ESP32 chip with everything I need internally (https://shop.m5stack.com/products/atom-matrix-esp32-development-kit). It can be programmed in multiple environments, such as Platform.IO, Arduino, and MicroPython, but I wanted to use only no-code approaches as much as possible this time, so I used the UIFlow block programming environment.
The easiest way to measure the tank's water level is to use an ultrasonic distance sensor. M5 Stack offers a nice little module (https://shop.m5stack.com/products/ultrasonic-distance-unit-i2c-rcwl-9620) with an I2C interface that can be directly connected to the Atom through a Grove cable (https://wiki.seeedstudio.com/Grove_System).
These are all the hardware we need, at least for a test rig. To make it suitable for the real world, I will put it into a sealed box to protect the stuff from the water. In this post, I just omit such details, but anyone can imagine a 3D-printed case filled with electronics and some silicone.
Implementation
As a quick sprint, I selected the easiest way to make everything up and running without writing code or typing in the console. According to the architectural design, we have three parts: The embedded software, the communication channel, and the PC side software. In this section, I go through the realization of these three components.
MQTT backend
Installing a local Mosquitto server would also be fine, but if you want global access (e.g., to check your water level from the Bahamas), you need a hosted MQTT server. Luckily, some out-of-the-box service providers exist, like HiveMQ, with which we can pull up a globally accessible MQTT backend in a minute free of charge for small projects.
After signing in, we immediately have an instance ready to use. The host URL, port, and user credentials should be copypasted to the MQTT clients, and everything is ready to go!
Embedded logic
The microcontroller program is created using the block-based development environment of M5 Stack called UI-Flow (https://flow.m5stack.com/). This web application enables hobbyists and kids to quickly drop a few blocks together to get something to work. Under the hood, it utilizes a static code generator that translates the blocks into python code which can run on the device thanks to the MicroPython runtime (https://micropython.org/) available on the ESP32 platform.
To learn more about bootstrapping a UIFlow dev environment for your M5Stack device, visit this page: https://docs.m5stack.com/en/quick_start/atom/uiflow
And now, take a look at our actual program! Simple enough, isn't it? We could go didactically block by block, but the figure is self-explaining. The only place when some lines of code were unavoidable was the MQTT client's creation. Due to some HiveMQ specifics related to SSL, the simple MQTT config block did not make it.
MAXWHERE logic
At MAXWHERE, we continuously work on making digital-twin prototyping as easy as possible. Therefore, the Virtual Operations Center Builder (VoC) was created to give a simple tool to connect MAXWHERE to the outer world. It is built around the Node-Red no-code development tool that offers a wide variety of nodes to make data flows and implement filter/modifier logic between data sources and sinks.
A set of MAXWHERE-specific nodes allow the developer to create and access the objects of the space and manipulate them according to the user input events and inputs from the outer world. The MQTT subscriber and publisher nodes are among the most potent elements in the node-red basic palette.
Since the node-red flow is yet simple, it is not as trivial as the UIFlow stuff we go through the flow, node by node.
- MQTT subscriber connected to the HIVEMQ instance. Its output is the measurement in raw string format.
- A "Range" node transforms the raw measurements into the proper range compatible with the virtual counterpart of the water tank.
- The set message.topic node is for setting the message's topic according to the conventions of MAXWHERE's vertical tank node. The message topic on which the level is transmitted to the node should be "setLevel".
- This node represents the virtual water tank. By modifying its height and width parameters, the cylindrically shaped tank can be configured to have a horizontal or vertical positioning without any coding. A debug node is used to track what is going through the lines.
One unique benefit of the MAXWHERE space is that the 3D digital twin can be extended with any web content via the so-called MAXWHERE projects. Here, I included some online rainfall statistics and historical data sources.
Testing
Testing of the model also took place on my dining table. My wife was so kind to provide the test rig in the form of some fought-down plasticware. The fixture that keeps the ultrasonic sensor in place is improvised from my son's LEGO kit. Let's see how it works:
I hope the reader gets an insight into how sensor integrations work in a MAXWHERE digital-twin project. It goes pretty much the same way using industrial-grade devices and IoT backend technologies: Quick and easy.
In complex, industrial digital-twin projects, we usually perform the MAXWHERE-side development in TypeScript using the MAXWHERE APIs. The lower-level development approach allows for implementing any custom logic and even lets us override the standard MAXWHERE UI. This way, a whole industry-specific virtual operation center can be developed with a considerably small team and agile timeframe. In another blog post, we introduce an Intermodal Logistics Terminal Management application which is an illustrative example of how far we can go with the MAXWHERE digital-twin solutions.