Oil Tank Level Sensor

Recent project that a combination of HA and ESPHome made much easier than I expected. Central heating is oil fired - and our tank has no sight tube. When installed it did have a remote level sensor, but the batteries in the sender died a while back and I hadn’t got round to replacing them - and the inside element was a rather bulky ugly plug.

Time for a proper sensor…a waterproof SR04 compatible sensor TE501 , a D1 mini and a 7 Neopixel disc (left over from previous projects) makes a compact oil level sensor.

SR04 was mounted in the filler cap with plenty of hot glue to seal. D1Mini (powered by an old USB charger) and the Neopixels are in a water proof box on the adjacent garage. The neopixels are bright enough to shine through without a problem. I added a DS1820 temp sensor because why not.

The d1mini converts the distance to a % - I dont allow for the odd shape of the tank just a simple % of distance to empty and luckily that is more or less exactly 25cm to 125cm for this tank so its very simple.

HA converts the % fill to an “OK”/“Alert”/“Critical” badge and turns on the light/sets color when it changes status via NodeRed. The light is also turned for a few minutes when the door/gate adjacent is opened as a reminder of current state.

Capture

Testing…

And Installed…

ESPHome yaml

esphomeyaml:
  name: esp_oilsensor
  platform: ESP8266
  board: d1_mini

wifi:
  domain: .local
  ssid: xxxxx
  password: xxxxxxx
  manual_ip:
    static_ip: 192.168.1.50
    gateway: 192.168.1.254
    subnet: 255.255.255.0

# Enable logging
logger:
# Enable Home Assistant API
api:

ota:

substitutions:
# Unique ID
  esp_id: "esp_oil"

dallas:
  - pin: D1

sensor:
  - platform: ultrasonic
    trigger_pin: D6
    echo_pin: D5
    name: "Oil Tank SR04"
    unit_of_measurement: "cm"
    id: ${esp_id}_sr04
    update_interval: 5s
    accuracy_decimals: 1
    filters:
      - multiply: 100
      - sliding_window_moving_average:
          window_size: 12
          send_every: 12
  - platform: dallas
    address: 0x890008008D53E610
    name: "Oil Tank Temperature"
    id: ${esp_id}_temp
  - platform: template
    name: "Oil Tank Level"
    id: ${esp_id}_level
    accuracy_decimals: 0
    unit_of_measurement: "%"
    icon: "mdi:oil"
    lambda: |-
      if (id(${esp_id}_sr04).state > 160 ) {
        return 999;
      } else if (id(${esp_id}_sr04).state > 125) {
        return 0;
      } else {
        return (125 - (int) id(${esp_id}_sr04).state);
      }
    update_interval: 30s
    

light:
  - platform: neopixelbus
    name: "Oil Tank Light"
    id: ${esp_id}_light
    type: GRB
    method: BIT_BANG
    default_transition_length: 0s
    pin: D2
    num_leds: 7

HA Template Sensor

  - platform: template
    sensors:
      oil_status:
        friendly_name: "Oil Status"
        unit_of_measurement: ""
        value_template: >
          {% if states.sensor.oil_tank_level.state == 999 %}
            Error
          {% elif states.sensor.oil_tank_level.state | int > 15 %}
            OK
          {% elif states.sensor.oil_tank_level.state | int > 7 %}
            Warning
          {% else %} 
            Alert
          {% endif %}
        icon_template: >
          {% if states.sensor.oil_tank_level.state == 999 %}
            mdi:alert-decagram
          {% elif states.sensor.oil_tank_level.state | int > 15 %}
            mdi:check-circle-outline
          {% elif states.sensor.oil_tank_level.state | int > 7 %}
            mdi:alert-circle-outline
          {% else %} 
            mdi:alert-circle
          {% endif %}
        entity_picture_template: >-
          {% if states.sensor.oil_tank_level.state == 999 %}
            /local/cancel.png
          {% elif states.sensor.oil_tank_level.state | int > 15 %}
            /local/ok.png
          {% elif states.sensor.oil_tank_level.state | int > 7 %}
            /local/warning-shield.png
          {% else %} 
            /local/high-priority.png
          {% endif %}
6 Likes

Great write-up, waiting on similar items for a esp32.

Would you have a schematic of how the TE501 and d1mini go together?
Do you need the board that comes with the TE501?

Yes you need the little board. That’s then just 4 pins to the D1mini 5v,Ground, echo and trigger. The latter go straight to a pair of GPIO and you just tell ESPhome which 2 pins you’ve used.

2 Likes

Hi,

Thanks for posting, this is what i am looking to build for a watertank… (just without the light).

I have only recently been introduced to ESPHome (have a lot of components running MQTT), and would like to build your solution. Could i please ask for your guidance and assistance which others could potentially benefit from as well.

  1. I can work out how to get esphome onto the D1Mini (youtube is a lot of help here), and i am guessing the Template Sensor will slot into my configuration.yaml file. Is this all the config which is needed?

  2. Could you please post a schematic of your wiring and the components you used, as i can see what look like two resistors on the breadboard which i need help with.

Thank you in advance for all of your help

Michael

Hi Mikkaat, I’m doing the same project - just waiting on a single part to finalise it. Here’s the resources I used:

Water Softener Salt Level w/ ESPhome & Using a Tablet as a Network Camera - this video shows the D1 Mini and ultrasonic for a similar purpose - start watching at 18:23 I think.

https://randomnerdtutorials.com/power-esp32-esp8266-solar-panels-battery-level-monitoring/ - this is if you want to use a solar setup rather than powered.

And here is my YAML:

esphome:
  name: water_tank_sensor
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: "****"
  password: "****"
  fast_connect: on

# Enable logging
logger:

mqtt:
  broker: 192.168.1.39
  username: ****
  password: ****
  birth_message:
    topic: water_tank_level_sensor/state
    payload: online
  will_message:
    topic: water_tank_level_sensor/state
    payload: online

ota:

sensor:
  - platform: ultrasonic
    trigger_pin: D1
    echo_pin: D2
    name: "Water Tank Level Sensor"
    update_interval: 3h
    filters:
      - offset: -0.15
      - lambda: return (1.0 - (x/2.0)) * 100.0;
    unit_of_measurement: "%"

deep_sleep:
  run_duration: 30s
  sleep_duration: 3h
1 Like

Thank you… will give this a try and let you know how I go.

Thanks to @DeanoX for the inspiration and super simple level sensor.
Up and running @ < €15

Using ESPhome makes it super simple.

Wiring if just level sensor like mine is 4 wires, no resistors etc needed
echo, trigger, vcc and gnd

Many thanks for this @DeanoX! Managed to get it incorporated into Home Assistant without the LED light with no issues apart from a few niggling things - Now I can rest assured that we will never run out of Oil for Heating and Hot Water!

36
The Oil Tank level graph always shows a value of 0 which is I think what it uses for the OK/Warning, is there a way for this to show the percentage graph which clicking on the Oil Tank Level indicator? Funnily enough in the History state, it does show the oil level in percentage.

I just need to wire in the thermometer, didn’t have the required resistor to wire that in, so just awaiting that arriving and it will be fully commissioned.

Again thanks for this, was a breeze to setup!

FWIW, I have this implemented with ESP32, ESPHome and HC-SR04. Getting readings for water tanks as well as my salt softener.

The code in ESPHome is as follows (for the unit measuring 2 water tanks)

esphome:
  name: esp32_2
  platform: ESP32
  board: nodemcu-32s

wifi:
  ssid: "XXXXXXXX"
  password: "XXXXXXXX"

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

sensor:
  - platform: ultrasonic
    trigger_pin: GPIO19
    echo_pin: GPIO18
    name: "House Water"
    accuracy_decimals: 0
    unit_of_measurement: "%"
    update_interval: 30min
    filters:
      - filter_out: nan
      - lambda: return (2.03-x+0.23)/2.03*100;
  - platform: ultrasonic
    trigger_pin: GPIO23
    echo_pin: GPIO22
    name: "Irrigation Water"
    accuracy_decimals: 0
    unit_of_measurement: "%"
    update_interval: 30min
    filters:
      - filter_out: nan
      - lambda: return (1.78-x+0.23)/1.78*100;

In the “lambda” calculation, 2.03 (and 1.78) is the height of my water tanks in meters. 0.23m is the distance between the highest water level and the sensor. From there i calculate roughly the % full right in the NodeMCU.

In lovelace, it looks like this :

Hope this helps ! :slight_smile:

I have had this on for a few months now and it’s been doing its job. One sensor failed (looked rusted a bit) a few weeks back and i have had to replace it…If this happens too often i will look at the suggestion above to replace them with the TE 501 (thanks for the tip !)