calibrate and fit a Vl53L0X time of flight sensor to measure water or oil tank level

Here is a tank level sensor that’s more useful than anything you can buy. This post focuses on my housing and the calibration for a basic sensor to measure oil or water level. The sensor is a VL53L0X time of flight sensor.

When you’ve seen the calibration below you probably want to see the main project page to learn in more detail how to set up, remove noise and manipulate the readings from the Vl53L0X sensor. Alternatively see my very similar oil tank level sensor which uses the ultrasonic sensor JSN-SR04T

time of flight sensor VI53L0X mounting and calibration
time of flight sensor VI53L0X mounting and calibration

what you need for this

  • an infrared based Vl53L0X time of flight sensor (~£5 ebay)
  • project box for sensor 83mm x 58 mm x 33mm IP66 waterproof ABS enclosure / clear cover
  • project box for ESP 63mm x 58 mm x 35mm IP66 waterproof ABS enclosure / clear cover
  • any ESP32 or ESP8266 development board with wifi. I used a nodemcu v3 ESP8266 (~ £6). If you need to use battery power an ESP8266 might be more appropriate than an ESP32 board. The battery power might be 6 x 18650 cells based on this one I made
  • ESPhome and Home Assistant to create the code, collect readings and display the data.
  • USB wire cut and extended to whatever length is needed. I used coloured silicone-covered wire 18 AWG 0.75mm copper conductor.

about the sensor

The Vl53L0X time of flight sensor works by sending infrared blips to a liquid surface and then measuring the ‘time of flight’ to estimate how far away it is. You can find variations of this sensor (VL53L0X, TOF10120, VL53L1X, VL6180X) which work best at different distances (diagram). I chose the Vl53L0X because it’s made for the range 30mm-1200m as suits my tank. The software can also set it in a long distance remote range of 1500 -2000mm. Wonderfully, when the sensor is hooked up it sends a distance value (in metres) and I can multiply that by a number to get readings in mm or litres or kW or even money. The calculation is simple – if your oil tank has an irregular shape I’ve included the code for that below – anything is doable.

wiring the VL53L0X tank level sensor and ESP

The Vl53L0X module has six pin connectors – you need to use four of them. I use Dupont male to female wires because my ESP8266 nodemcu already had pins. I soldered the male pins to the Vl53L0X module and extended the wires with coloured cables (silicone 18 AWG 0.75mm) and covered the join in heat-shrink.

how to protect the components from a damp, wet environment

Getting dirt in the tiny emitter and sensor holes is to be avoided as the emerging pulse or photon can be deflected randomly / cause crosstalk. My sensor and ESP8266 will be attached to the lid of a water tank in a loft so I bought a project box and glued the sensor to its transparent lid. I had a tube of Kafuter K-705 silicone to squeeze over water sensitive parts of the board. Read on to see the oil tank sensor. The sensor will be attached facing downwards from the plastic tank lid as shown. I happened to have some heavy duty Velcro hook & loop tape to help fix the boxes. The ESP8266 has been given its own box – so as not to put all eggs in one basket – in case of failure I’ll be able to replace one or other component.

You can protect the sensor with glass, perspex or polycarbonate. The cover should be as thin, flat, parallel, clear and fitted close to the sensor as possible. ST, the chip maker have a video explaining how a more fussy two-piece glass cover pretty much reduces the crosstalk due to dust. I so wish they’ll create a similarly protected chip. The sensor notes are here.

VL53L0X sensor (on the left)
the plastic box with the VL53L0X sensor has fitting holes. I pushed a plastic wallplug into a hole on the box to provide a screw fitting.
5mm holes drilled in each box for wires. Heat shrink added with hot glue to seal.

My oil tank sensor (below) uses a different fitting to the water tank sensor above. A 3D printed part holds the sensor in place with the help of some hot glue. I don’t yet know if the vapour from the oil will damage the VL53L0X so I’m looking to improve this it it fails. I cut a 30mm circle of acetate film (from a phone case) and glued it to the cap I’d made for the sensor.

Link to STL file for 3D printed holder file – oil-sensor-holder.stl

The oil tank sensor needs to be fixed so that it points down at the surface of the oil in the tank (photo). I used a tank hole that had housed the dipstick. A suitable cap, as shown below, was made on a 3D printer. A container cap might have worked … as long as it doesn’t wobble and thus affect the readings. You might instead drill a hole for it but I’ve no advice on this.

The sensor installed on a messy indoor all-metal oil tank! I lined the sensor holder with sticky felt to ensure it couldn’t slip or shift easily

calibrating the sensor

When ESPhome is installed on the ESP8266 (this detailed post) I receive readings in mm. However wary that I’ve obscured the sensor with a clear plastic cover, I made a calibration graph of readings vs actual distance from the floor. As you see in the graph below that’s only slightly necessary. The graph intercept is at 38mm so I subtract that from each reading.

Vl53L0X time of flight sensor - distance calibration - water tank

The next thing to do is to find eg the volume of liquid represented by a fall in level of 1mm or 1m. In my oil tank a fall of 100 mm is 105 litre. You could instead use percentage full as your unit. In my oil tank I must multiply the reading/result by 1.05. Your oil tank will need a different factor based on its volume per mm. The most basic code is as follows.

adjust the calculation to calibrate the sensor

# WATER SENSOR - THIS WORKS BUT THE DATA IS NOISY

sensor:
  - platform: vl53l0x
    name: "watertank-tof"
    address: 0x29
    update_interval: 10s
    long_range: false
    accuracy_decimals: 0
    unit_of_measurement: "mm"
    id: watertanklevel
    filters:
    - lambda: return x * 1000;

# YOU CAN ADD CALIBRATION FACTORS TO THE WATER SENSOR - THIS WORKS BUT THE DATA IS NOISY 

sensor:
  - platform: vl53l0x
    name: "watertank-tof"
    address: 0x29
    update_interval: 10s
    long_range: false
    accuracy_decimals: 0
    unit_of_measurement: "mm"
    id: watertanklevel
    filters:
    - lambda: return (x - 0.038) * -1050;

# calculation: 38 is the graph intercept so that's - 0.038 in metres x a scaling factor found on graph. If you return a negative value as I have the graph will drop not rise as the tank empties. 

noisey ‘time of flight’ sensor? See the end of my post here.

1 Response

  1. Markus Eckl says:

    Thank your for that great tutorial on how to make the vlx sensor working correctly.
    from my project Phreak87/Oilmeter you can use this Sensor too. But be careful on water
    because this will not always work because of the reflections. For Water the HC04 is way
    more better in my case.

Leave a Reply

Your email address will not be published. Required fields are marked *