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
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.
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.
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.
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.
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.