Build an Industrial Volume & Presence Reader with a MaxBotix Ultrasonic Sensor + ESP32

written by Maria Carlina Hernandez - Ubidots

Learn how to build a robust & waterproof volume and presence reader to create, monitor, and manage insights from Ubidots.

Are you looking to be assemble an Industrial Tank Volume Reader using the precision of ultrasonic sensors, but also keep development and testing simple? Well, we have the solution for you! 

MaxBotix Inc has been innovating in the ultrasonic sensor industry for the last 10+ years, designing affordable sensors to intelligently increase the quality & value of contents within industrial tanks. The MaxBotix sensors most attractive user benefits include:

  • Simple Mounting
  • Low Power Requirements
  • Selection from Multiple Outputs
  • High Reading Stability
  • Calibrated Beam Patterns

The MaxBotix ultrasonic sensors have a wide variety of industry applications apply including but not limited to: 

  • people & unit detection
  • remote bin / tank measurement
  • automated store displayswater level measurementparking sensors and more! 

To give you a general idea of how MaxBotix sensors works, in this guide we're going to cover how to build a tank volume reader using a MaxBotix sensor connected to an ESP32-DevKitC, to then transmit the data read by the sensor to Ubidots over WiFi using MQTT as a communication protocol.


  1. MB7389 HRXL-MaxSonar-WRMT (ultrasonic sensor)
  2. ESP32-DevKitC
  3. Ubidots account


  1. Hardware Setup
  2. Set up the ESP32-DevKitC with the Arduino IDE
  3. Firmware Setup
  4. Analysis and Management of data in Ubidots 
  5. Summary

1. Hardware Setup

Establish the connection between the ultrasonic sensor and the ESP32-DevKitC using the below instructions.

1. Follow the pinouts table below to establish a connection between the ESP32-DevKitC and the MB7389 sensor:

ESP32DevKitC + MB7389
ESP32DevKitC + MB7389

2. [OPTIONAL] For PoC testing and production uses, be sure to enclose the hardware in proper weather casing. The images below is a good reference to viable liquid resistant casings.

Tank Volumen Reader Case

MPORTANT NOTE: Keep in mind that there are many important factors to consider before mounting a sensor in a tank, for this we highly recommend you check this guide  about Tank Level Monitoring in order to avoid any further inconvenience/issues in the sensor readings. 

2. Set up the ESP32 with the Arduino IDE

To start this tutorial, we will begin by connecting your ESP32 to your computers USB port to program the device.

1. Begin by downloading the Arduino IDE, if you have not done so already.

2. Next, install the ESP32 Platform to your Arduino IDE. Please reference the following links depending on your operating system. The following Espressif links will prompt you to install the ESP32 to your computer. 

Note: If you are using Linux or Mac operating systems, an additional step is required as you need to install the ESP32 Platform to the Arduino IDE from your computer's terminal first. Use the below links to execute the required Terminal functions and then return to this guide to continue the ESP32 integration.

Reference image using a MacOS terminal:

mac os 1

3. After installing the ESP32 platform using the above Espressif Systems links, you will be prompted to restart the Arduino IDE - be sure to do so. 

4. After the reboot, select your ESP32 Dev Module from Tools– > Board menu.

5. Additionally, we need to be able to communicate with the ESP32, Let's be sure to select the port communication location. Go to Tools –> Port >  Select the appropriate PORT for your device.

NOTE: If you are using Windows, you need to establish a serial connection between ESP32 and your computer please refer to this link to install the drivers needed and verify the connection. Also, as a MAC or Linux user, the link describes how to verify serial communication should you want to.

6. Next, download and install the PubSubClient Library. For a detailed explanation of how to install libraries using the Arduino IDE, refer to this guide

3. Firmware Setup

With the board and library already configured in the Arduino IDE it's time to program the ESP32-DevKitC.

1. Copy the code below and paste into the Arduino IDE; assigning the correct parameters required: Wi-Fi name and passwordMQTT Client name plus your unique Ubidots TOKEN. If you don't know how to locate your Ubidots TOKEN, please reference this article below. 

* This Example sends hardcoded data to Ubidots using an ESP32-DevKitC. The code sends a distance
* value between an ultrasonic sensor and on the surface of the water detected by an MB7389
* HRXL-MaxSonar-WRMT sensor. Then, the value will be managed in Ubidots to calculate the volume
* of free-flowing substances in the tank.
* This example is given AS IT IS without any warranty.
* Made by María Carlina Hernandez.
* Nov 28, 2018.
* Include Libraries
#include <WiFi.h>
#include <PubSubClient.h>
* Define Constants
namespace {
const char * WIFISSID = "xxxxx"; // Put your WifiSSID here
const char * PASSWORD = "xxxxx"; // Put your wifi password here
const char * TOKEN = "xxxxx"; // Put your Ubidots' TOKEN
const char * MQTT_CLIENT_NAME = "xxxxx"; // MQTT client Name, assign an unique 8-12 alphanumeric character ASCII string;
const char * VARIABLE_LABEL = "distance"; // Assign the variable label
const char * DEVICE_LABEL = "esp32"; // The MAC address of the device will be assigned as device label
const char * MQTT_BROKER = "";
const int ANALOG_PIN_0 = 36; // ADC1_0 GPIO36
int analog_value, distance_mm, distance_cm;
/* Sensor's declarations */
int distance;
/* Space to store the request */
char payload[50];
char topic[50];
* Auxiliar Functions
WiFiClient ubidots;
PubSubClient client(ubidots);
void callback(char* topic, byte* payload, unsigned int length) {
char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
String message(p);
Serial.write(payload, length);
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// Attemp to connect
if (client.connect(MQTT_CLIENT_NAME, TOKEN, "")) {
} else {
Serial.print("Failed, rc=");
Serial.println(" try again in 2 seconds");
// Wait 2 seconds before retrying
* Sensor Functions
int readDistance() {
analog_value = analogRead(ANALOG_PIN_0);
distance_mm = analog_value;
distance_cm = distance_mm / 10;
return distance_cm;
* Main Functions
void setup() {
Serial.print("Wait for WiFi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi Connected");
Serial.println("IP address: ");
client.setServer(MQTT_BROKER, 1883);
void loop() {
if (!client.connected()) {
/* call the funtion readDistance() */
distance = readDistance();
/* Building the Ubidots request */
sprintf(topic, "%s%s", "/v1.6/devices/", DEVICE_LABEL);
sprintf(payload, "%s", ""); // Cleans the payload
sprintf(payload, "{\"%s\": %d}", VARIABLE_LABEL, distance); // Adds the variable label
/* Print the sensor reading to the Serial Monitor */
Serial.println("Publishing values to Ubidots Cloud");
Serial.print("Distance = ");
/* Publish the request to Ubidots */
client.publish(topic, payload);

2. After assigning the parameters required, verify the code in the Arduino IDE by clicking the "Check Mark" icon located at the top left corner of IDE.

Once verified, you will receive a "Done compiling" message in the Arduino IDE.

3. Next, Upload the code into your ESP32 by clicking the "right-arrow" icon beside the check mark icon to upload.

Once uploaded, you'll receive a "Done uploading" message in the Arduino IDE.

Now, your device is transmitting data to Ubidots

4. Analysis and Management of data in Ubidots

If your device is correctly connected you will see a new device automatically created and found the Devices section of your Ubidots account. The name of the device will be "esp32", and after clicking the device, you will see a variable called "distance" along with any other variables in the you're sending to Ubidots.:

If you desire to change your device and variable names to a more friendly one, please reference this article:

NOTE: For an easy scalable deployment of devices we highly recommend you assign the Device MAC Address as device label. For a detailed explanation of how the labels are managed by Ubidotscheck this guide

Now the next step is to calculate the volume of free-flowing substances in the tank. For this, we need to create a Synthetic Variable to calculate a volume value.

Synthetics Variables is a tool which uses the Ubidots Analytics Engine which supports complex mathematical computations. Basically,  a "Synthetic Variable" is a variable that results from the computation of other variables within Ubidots.

In this case,  we are going to apply the volume formula with the characteristic of a cylindrical tank where the sensor is going to be placed. The formula is:


  • Pi = The ratio of a circle's circumference to its diameter (constant)
  • r = The radius of the tank 
  • h = The height of the tank

As a result, we have to subtract the distance value (sensor reading) to the total height of the tank, giving us the following result:

For testing purposes, we are going to use a water tank with the following dimensions: 

  • Diameter = 97 cm
  • Height = 115 cm

1. Now, to create the variable, go to the devices previously created and click on "Add variable" then select "Synthetics":

As you can see at the new window you have to attach the formula in the following field:

Based on the dimensions of the tank to use, the end formula should look like: 

pi * (48.5^2) * (115 - {variable})

Once you've attached the formula with the characteristics of your tank, select the variable "distance." Make sure that the formula expression checker is on green!

To finish with the variable creation, press "Accept" and assign the name desired to the variable. In my case, I called it "volume". The value of the variable should appear automatically after the creation. 

Also, you can assign the units of the resulted value, in this case, "cm3" as you can see below:

2. [OPTIONAL] If it's desired to visualize the volume value in "L" instead of "cm3" you can divide by 1000 the entire formula or you can simply create a new synthetic variable to keep both values inside your device. Having as a result something like this: 

3. Now with the variables created and updating data properly, is time to create a dashboard to visualize the data in a friendly way. 

IMPORTANT NOTE: For a detailed explanation about the features and how Ubidots Dashboards works, we highly recommend you check this guide

To create a new Dashboard, go to the "Data" section of your Ubidots account and press "Dashboard". Then, select the plus icon located at the right upper side of the page, and select the widget desired to display your data. Then, you have to select the variable desired to be displayed and set the configuration desired for the widget. 

In my case, I created two widgets, "tank" and "chart". Having as result the following visualization: 

5. Summary

Thanks to the variety of ultrasonic sensors offered by MaxBotix you are able to build application including but not limited to people detectionremote bin measurementautomated store displayswater level measurementparking sensors and more! 

Now is your time to start creating an IoT Solution that keep you and those who need to know informed and on time!

Back to blog

Lets connect on your project!