When I made my initial version of the pellet level monitor for my pellet boiler, many of the comments that I got on the article and the video suggested that I use a VL53L0x, Time Of Flight sensor as supposedly it is a much more reliable and precise than the ultrasonic sensor that I used previously.
To see how the sensor works, I ordered it and in the video below, you can see me recreating the same device, but now we will be using light instead of sound to measure distances.
The video is sponsored by Altium Designer and Altium 365. You can get 25% discount on any new license by using this link: https://www.altium.com/yt/taste_the_code
Overview of the VL53L0X Time of Flight Sensor
The VL53L0X sensor is a laser-based distance measuring sensor, or a so-called Time Of Flight sensor. It uses an infrared laser to shine a light onto the object in front and then measures the reflection using an IR receiver to figure out the time difference between the sent and bounced light.
Since the speed of light is constant, the sensor then calculates the distance based on the time it took the light to travel to the object that we measured and back.
Materials and Tools Needed
The star of the project is the VL53L0x sensor, but we also need a few other components as well. Below are some affiliate links that you can check out and if you purchase through them, you are supporting my work and the channel at no extra cost to you! Any help is much appreciated!
- NodeMCU Development Board - https://s.click.aliexpress.com/e/_oCtXGBs
- NodeMCU with ESP32 - https://s.click.aliexpress.com/e/_mtAWy2e
- VL53L0x ToF Sensor - https://s.click.aliexpress.com/e/_ol0aBhs
- Mini Breadboards - https://s.click.aliexpress.com/e/_m0jPra2
- Jumper Wires - https://s.click.aliexpress.com/e/_mLIY4Om
- Mini PC for Home Assistant - https://s.click.aliexpress.com/e/_ExVyCdH
- Soldering Station - https://s.click.aliexpress.com/e/_mK66lny
- Multimeter - https://s.click.aliexpress.com/e/_m0oU7IS
Connecting the VL53L0X Sensor to a Microcontroller
The VL53L0x sensor uses I2C communication so other than power, we only need two wires to connect it to a microcontroller. The NodeMCU that we are using, uses pins D1 and D2 as defaults for I2C so we will connect D1 to SCL and D2 to SDA pins on the sensor.
For power, I connected the VCC of the sensor to the 3.3V output on the NodeMCU and GND to GND on both.
Programming the VL53L0X Sensor with Arduino
As a first step in making sure that the sensor works, I used the Arduino IDE where I installed the Adafruit library for the VL53L0x sensor.
The library provides an example sketch so I uploaded that and was immediately greeted with the measured distance in millimeters in the Arduino serial console.
The full sketch code is below.
#include "Adafruit_VL53L0X.h"
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
void setup() {
Serial.begin(115200);
// wait until serial port opens for native USB devices
while (! Serial) {
delay(1);
}
Serial.println("Adafruit VL53L0X test");
if (!lox.begin()) {
Serial.println(F("Failed to boot VL53L0X"));
while(1);
}
// power
Serial.println(F("VL53L0X API Simple Ranging example\n\n"));
}
void loop() {
VL53L0X_RangingMeasurementData_t measure;
Serial.print("Reading a measurement... ");
lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
if (measure.RangeStatus != 4) { // phase failures have incorrect data
Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
} else {
Serial.println(" out of range ");
}
delay(100);
}
Integrating VL53L0X with ESPHome
Now that we had the sensor working, it was time to move to use it with ESPHome and luckily, there is already a pre-built component for it. The only requirement is to include the I2C bus component so that communication can be established.
There is no change in the wiring from before so I left it as is from the Arduino version.
i2c:
sda: D2
scl: D1
scan: true
id: bus_a
sensor:
- platform: vl53l0x
id: distance_sensor
name: "VL53L0x Distance"
address: 0x29
update_interval: 1s
long_range: false
- platform: template
id: level
name: Pellet Level TOF
unit_of_measurement: '%'
update_interval: 1s
lambda: |-
if (isnan(id(distance_sensor).state)) return 0;
auto r = (id(distance_sensor).state - 0.8) * (100.0 - 0.0) / (0.1 - 0.8) + 0.0;
if (r > 100) return 100;
if (r < 0) return 0;
return r;
To display the output in a nice card with a needle chart, I used the following code to generate it in the dashboard.
type: gauge
entity: sensor.pellet_level_tof_pellet_level_tof
name: Pellet Level TOF
min: 0
max: 100
needle: true
severity:
green: 30
yellow: 15
red: 0
Future Enhancements and Standalone Version Development
As a next step in developing the sensor, I will add the VL53L0x to the same device with the ultrasonic sensor so I can at least for a while monitor the output of the two sensors in parallel on the same level and compare the values.
Additionally, when people first saw the pellet level monitor, they also asked for a standalone version that they can use at home even if they do not have a Home Assistant setup so I plan to work on that.
If that is something that might be interesting for you or if you want to see some other projects, feel free to subscribe to my YouTube channel to follow my journey.