project: oil tank level sensor

A heating oil tank level sensor that’s more useful than anything you can buy.

  • Measures oil level in any unit – litres, gallons or days until I need to refill the tank
  • Displays readings on a gauge or time graph (uses Home Assistant gauge & history graph).
  • Receive readings or alerts as an email or phone notification or flashing smart bulb in the house.
  • Uses an ultrasound sensor JSN-SR04T Ultrasonic distance measuring sensor, waterproof (~£6 ebay)
  • Uses an ESP32 wifi chip (~ £6 ebay).
  • With a waterproof housing could work outdoors and on battery power.
  • The project with little modification would monitor the salt level in a water softener or the water in a water barrel. (Ref Dr Zzz – youtube)

Some homes use oil as a fuel for keeping warm in winter. The oil is burned in a central heating boiler in much the same way that many homes in the UK burn methane. Although we call the liquid ‘heating oil’ it’s more runny than the oil you know: it’s more like diesel or white spirits or turps or paraffin or kerosine. Over the course of a winter I might need to order two or three deliveries of oil but till now I’ve no way to predict the day when I’ll need to top it up. And I really don’t ever want to run out of oil.

I asked local firm Shelford Heating to quote for an oil level sensor. Their solution involved drilling and shimming the steel tank to fit an Apollo wireless kit – but the £220 quote seemed excessive for this need. I could also have bought the kit, which sends an oil level to a display unit but I really wanted something that recorded oil levels and could alert me better.

How it connects up

A waterproof ultrasonic sensor, looking like a car bumper sensor, arrives with a long lead and a blue board. Female-female Dupont jumper wires will connect the four pins on the board to an ESP32. Two of the pins connect to ~ 5v power and ground. The other two, labelled TRIG and ECHO go to any suitable GPIO pin on the ESP32. I connected them to GPIO 15 and GPIO 16. Thus far we’ve four wires joining an ESP32 and a sensor board. We now need a lead (from a USB charger) to bring 5v power and GND to the ESP32.

(I used an ESP32-CAM instead of an ESP32 with a USB socket. This meant that I needed to hack a USB cable and make the wiring less elegant. I just happened to have a spare ESP-CAM that had lost its camera).

Underside of the home-made oil cap where the ultrasonic sensor sits, pointing at the oil in the tank

The ultrasound sensor needs to be fixed so that it points down at the surface of the oil in the tank. I used a tank hole that housed the dipstick used for the last 40 years. A suitable cap, as shown below, was made on a 3D printer. You might instead drill a hole for it but I’ve no advice on this.

The sensor installed on an oil tank – it’s messy around here! I lined the sensor holder with sticky felt to ensure it couldn’t slip or shift easily

Program the ESP32

For this step you need an already working Home Assistant installation on a Raspberry Pi as shown in an earlier project. In Home Assistant go to the Esphome plugin and add a new ‘node’. A wizard asks you a few questions after which you can edit your answers. Add the code below but change the items in bold to suit your board, your wifi, your network and the GPIO pins you want to connect to.

# THE FIRST FEW SECTIONS BELOW ARE CREATED BY THE ESPHOME WIZARD SO DON'T DUPLICATE THESE

esphome:
   name: oil
   platform: ESP32
   board: esp-wrover-kit
 
Enable logging
 logger:
 
Enable Home Assistant API
 api:
   password: "Your HA API password"

 ota:
   password: "Any password here"

 wifi:
   ssid: "YOUR WIFI SSID"
   password: "YOUR WIFI PASSWORD"
   manual_ip:
     # Set the IP of the ESP
     static_ip: 192.168.1.14
     # Set this to the IP address of the router. 
     gateway: 192.168.1.1
     # The subnet of the network
     subnet: 255.255.255.0

 # OPTIONAL WEBSERVER - USEFUL WHEN TESTING. IT USES MEMORY SO DELETE THESE TWO LINES. 
 web_server:
 port: 80
 
sensor:
 platform: ultrasonic
 trigger_pin: GPIO15
 echo_pin: GPIO16
 name: "oil level"
 accuracy_decimals: 0
 update_interval: 10s 

The sensor section at the bottom of the code tells the sensor to say how far the sensor is from an object (in cm). The sensor doesn’t work well at distances ~30 cm but at distances up to a couple of metres it’s surprisingly good. A reflective surface nearby might affect your result.

Here is the final code. I call the sensor “oil used” because the number it returns is the amount of oil I need to buy to fill the tank. Next I really don’t need an oil level reading every 10 seconds so I increased the update interval. Lastly, I needed to somehow calibrate the reading so that it gave me a litre volume. My tank has a perfectly regular shape from top to bottom – so by measuring its dipstick, I found that 100 mm of tank depth contains 105.3 litres. The last two lines (filter and lamda) do this calibration. The two lines can be edited or entirely omitted.

sensor:
 platform: ultrasonic
 trigger_pin: GPIO15
 echo_pin: GPIO16
 name: "oil used"
 accuracy_decimals: 0
 update_interval: 60s 
 unit_of_measurement: "litre" 
  filters: 
  lambda: return x * 1053; 
  • In the ESPhome section of Home Assistant VALIDATE your code and then COMPILE it. The compile operation takes a few minutes as ESPhome assembles the code libraries it needs and creates a firmware ‘.bin’ file.
  • Download this bin file. Flash the bin file using the ESPHome-flasher tool (see here).
  • When the flashing is done, power-up the ESP32 and go to Home Assistant > Integrations > + > ESPHome > add node. You might have to enter the IP address you chose in the code. You’ll then see the oil level entity that has been added to Home Assistant.
  • Finally, go to the Home Assistant overview – the page that displays your stuff – and choose Configure UI in the top corner. You might use a history graph and a gauge to display your oil level.

The code for the items above is shown below. You can edit the bold items to suit.

 # THIS IS FOR THE GAUGE 
entity: sensor.oil_level
 max: 1100
 min: 0
 name: heating oil used
 severity:
   green: 100
   red: 800
   yellow: 600
 theme: default
 type: gauge
 # THIS IS FOR THE SMOOTH LINE GRAPH 
entity: sensor.oil_level
 graph: line
 hours_to_show: 96
 name: of 1000 L oil used
 type: sensor
 unit: litres
# THIS IS FOR THE DETAILED HISTORY GRAPH 
entities:
 entity: sensor.oil_level
 hours_to_show: 24
 refresh_interval: 0
 type: history-graph 

So when do I need to order some more oil?

The first nice consequence is that I now know how much oil I need to order and how much I use. And I can see I would need to order an extra 80 litres as it will take 10 days to arrive. As I write I’m thinking about a way to predict the date when I’ll need to order more oil. For the present I’ve put the data in a spreadsheet and it looks like I’ll order in early December – unless I start to use oil faster.

Create a notification that alerts when oil needs to be ordered

I usually order 900 litres of oil and I use 80 litres of oil as I wait for it to be delivered. Therefore I need an alert when the tank has 900 – 80 or 820 litres of oil. Home Assistant offers numerous ways to be alerted including send an email, show a message in the browser or pop-up a ‘toast’ message on your phone. You can set a notification to persist so that you can’t easily swipe it away. You can set an urgent notification to wake up a phone to tell you, or one that waits quietly until you next pick up the phone. Here is the automation code – if you’re starting out, the easiest notification method I found to get working was the email notification:

 # TIME TO ORDER OIL AUTOMATION - HOME ASSISTANT

 alias: heating oil level alert
 trigger:
 above: '820'
 entity_id: sensor.oil_level
 platform: numeric_state
 condition:
 after: 07:00
 condition: time
 action:
 data:
   message: at {{ states ('sensor.time') }}
   title: '{{ states (''sensor.oil_level'') }} L now. 900L oil to be ordered'
 service: notify.notify_html5
 data:
   message: at {{ states ('sensor.time') }}
   title: '{{ states (''sensor.oil_level'') }} L now. 900L oil to be ordered'
 service: notify.email 

Leave a Reply

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