Water Tank Level and Water Volume with ESPHome

yeah, I have that feeling!
These days we have a temp of near 40C outside and I’m doing an experiment related to the ventilation of the tank. I believe that there is a concentration of moisture in the empty space which is affecting the measurements

I recommend using sliding average median, this removes the erroneous readings.

sensor:
  - platform: ultrasonic
    trigger_pin: D1
    echo_pin: D2
    name: "Tank Level Sensor"
    unit_of_measurement: "L"
    device_class: volume_storage
    icon: "mdi:water"
    accuracy_decimals: 0
    update_interval: 1s
    filters:
      - median:
         window_size: 59
         send_every: 60
         send_first_at: 3
      - lambda: return (1-x) * 1000.0 - 55;
      - filter_out: nan
4 Likes

Good morning,
I have indicated your information correctly but it does not work?
I saw that some talk about mqqt?
THANKS

Thank you for this information. After reading about the HopperHawk monitor for pellet grills, I started looking at using an ESP32 device in the same fashion. This is looking at water levels, but I see no reason to think that it won’t work for wood pellets. This looks just like what I need to setup a device to monitor my pellet grill bin.

Wow, this is awesome! Definitely going to use the info in this thread.

I have a water purifier (Berkey). And I want HA to refill the tank when empty. ESPhome will measure the amount of water left and HA will refill. I already have a Zigbee water valve that works. And as a bonus I will be able to monitor when the filters need replacement (they last about 22.000 liters I believe).

Only challange now is ti actually get a waterpipe to the Berkey. But with a little luck, I am able to fix that.

@nawafbana as above - any chances of sharing the solution?

Can you please share your complete setup, which hardware you use, how you connect it and the code?
I’m struggling with getting this working.
I’ve tried a ESP8266 and also a D1 mini, both don’t give any information through.
I don’t know if i have to get a LED signal on the AJ-SR04M board, but I didn’t see that.
Thanks in advance!

1 Like


Check this diagram if you need the code ping me :wink:

1 Like

Thanks for sharing, but this is a different configuration then I have. So I can’t compare it.
I bought a new D1 mini (with 5V) and a new AJ-SR04M sensor (I thought maybe it was broken). But also now after different tries it doesn’t work.

1 Like

can i do this with esp32 ?

@jonasmoreira could you share your code please. This seems to be the perfect setup. Really close to what I had but I’ve lost my configuration in some tests I was doing.
Long story. I would gladly use your code if it’s working as you seem to say.

hmm, seems this hits me again this year.
I used a tf 131 pressure sensor last year, worked perfect. Now wanted to install it for this season - dead. Reading some amazon reviews this is a common problem after 6 month of use - moist is getting in the sensor.
Now may switch back to a ultrasonic sensor.
This drives me nuts.

Hello everyone,

I set up a configuration using an ESP32-CAM AI THINKER along with a security camera near my cistern.

I had an issue with sensor reading errors, generating logs of inexplicable timeouts, so I added a relay that interrupts the GND connection cable to the sensor board for 4 seconds, resetting the sensor every time it obtains a NAN value. It worked! Below is the code:

esphome:
  name: cisterna-espcam
  friendly_name: EspCam Cisterna
  platform: esp32
  board: esp32dev

wifi:
  networks:
  - ssid: xxxxxx
    password: xxxxxx
  - ssid: xxxxxxxx
    password: xxxxxxx
  - ssid: xxxxxx
    password: xxxxxxxx
  ap:
    ssid: "Cisterna-Espcam Hotspot"
    password: "xxxxxxx"

logger:
api:
ota:

esp32_camera:
  external_clock:
    pin: GPIO0
    frequency: 20MHz
  i2c_pins:
    sda: GPIO26
    scl: GPIO27
  data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
  vsync_pin: GPIO25
  href_pin: GPIO23
  pixel_clock_pin: GPIO22
  power_down_pin: GPIO32
  # Image settings
  name: esp32-cam-cisterna
  # resolution: 1024x768
  resolution: FHD
  brightness: 2
  contrast: 2
  jpeg_quality: 18
  vertical_flip: false
  horizontal_mirror: false
  max_framerate: 15 fps

sensor:
  - platform: ultrasonic
    trigger_pin: GPIO12
    echo_pin: GPIO13
    update_interval: 30s     # 5 minutos. Você pode mudar este valor
    timeout: 3.5m
    name: "Agua na Cisterna"
    unit_of_measurement: "L"
    accuracy_decimals: 0
    filters:
      - lambda: |-
          if (std::isnan(x)) {
            id(relay_switch).turn_on();
            delay(4000);
            id(relay_switch).turn_off();
          }
          return (1-((x-.30)/2.86))*10000;
      - median:
         window_size: 5
         send_every: 3
         send_first_at: 2
         
output:
#flashlight
  - platform: gpio
    pin: GPIO4
    id: gpio_4
#relay para resetar sensor
  - platform: gpio
    pin: GPIO2
    id: relay_output

light:
#flashlight
  - platform: binary
    output: gpio_4
    name: Cam Cisterna flash

text_sensor:
  - platform: wifi_info
    ssid:
      name: Cam WiFi

switch:      
  - platform: restart
    name: Cam Cisterna restart
#relay para resetar sensor
  - platform: output
    id: relay_switch
    output: relay_output

Initially, the sensor was presenting reading errors probably due to secondary echoes, always giving the minimum distance as a result. I fixed this by covering the sensor with foam. But now I have a huge fluctuation in readings, generating a variation of up to 800 liters during the day.

Has anyone achieved stable readings by modifying any code in the sensor, such as the pulse time?

If you are having issues, might want to consider using a float sensor - simple and super reliable even in pretty hostile environments. Mine has been working now for over two years without a hiccup. Basically it’s a stainless steel rod with a float outside that changes the resistance as it moves up and down the rod. As much as I wanted to use something like a sonar or pressure sensor, I went for a float sensor as I suspected that otherwise I would be continually replacing sensors… :slight_smile:

1 Like

+1

similarly

Hi,

I find many examples in this topic of yaml configurations where absolute volume and relative volume are calculated in on single instnace. e.g.:

- platform: ultrasonic
    trigger_pin: GPIO1
    echo_pin: GPIO3
    name: "Water Tank Level"
    unit_of_measurement: "%"
    accuracy_decimals: 0
    update_interval: 5s
    filters:
      - lambda: return ((((x*100)-20)-(123-20))/(123-20))*-100;
      - filter_out: nan
      
  - platform: ultrasonic
    trigger_pin: GPIO1
    echo_pin: GPIO3
    update_interval: 5s
    name: "Water Tank Volume"
    unit_of_measurement: "l"
    accuracy_decimals: 0
    filters:
      - lambda: return ((((x*100)-20)-(123-20))/(123-20))*-1000;
      - filter_out: nan

When I do so, I get an error that I just cannot fix?
As if it is not allowed to use the same pins twice to calculate absolute and relative volume?

Can anyone point me in the right direction?

My complete yaml:

esphome:
  name: ibcsensor002
  friendly_name: IBC 
  area: Tuin 
  platform: ESP8266
  board: d1_mini

# Encryptie sleutel: "QEDjdbLjPr7ZosmBBCvYWA="
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.31.132
    gateway: 192.168.31.99
    subnet: 255.255.255.0
    
  ap:
    ssid: "Ibcsensor002 Fallback Hotspot"
    password: "be"

logger:

api:
  encryption:
    key: "QEDjdbLjPr7ZnKfP9tBBCvYWA="

ota:
  - platform: esphome
    password: "1aa73b1d97c3d8eee005c11992ce8573"

web_server:
  port: 80

time:
  - platform: homeassistant
    id: homeassistant_time

text_sensor:
  - platform: version
    name: ibcsensor002 ESPHome Versie
  - platform: wifi_info
    ip_address:
      name: ibcsensor002 IP
    ssid:
      name: ibcsensor002 Wifi
    bssid:
      name: ibcsensor002 MAC

switch:
  - platform: restart
    name: "IBC Aan/Uit"

sensor:
  - platform: uptime
    name: IBC Uptime
    filters:
    - sliding_window_moving_average:
        window_size: 15
        send_every: 15

  - platform: wifi_signal
    name: IBC WiFi
    unit_of_measurement: '%'
    filters:
    - filter_out: nan
    - sliding_window_moving_average:
       window_size: 10 
       send_every: 4 
       send_first_at: 3 
    - delta : 5 
    - lambda: |-
       if (x <= -100) {
         return 0;
       } else {
         if (x >= -50) {
           return 100;
         } else {
           return 2 * (x + 100);
         }
       }              

  - platform: ultrasonic
    trigger_pin: D1
    echo_pin: D2
    name: "Inhoud [l]"
    update_interval: 600s
    unit_of_measurement: "l"
    icon: 'mdi:water'
    accuracy_decimals: 0
    filters:
    # delta : 1 
    - lambda: return ((((x*100)-4)-(98-4))/(98-4))*-900;
    - offset: -17.0
    - filter_out: nan
    - median:
       window_size: 15 
       send_every: 4 
       send_first_at: 1
      
     - platform: ultrasonic
    trigger_pin: D1
    echo_pin: D2
    name: "Inhoud [%]"
    update_interval: 600s
    unit_of_measurement: "%"
    icon: 'mdi:water'
    accuracy_decimals: 0

After some update, using the same pin is no longer possible. Use the copy component.

1 Like

Ran into this issue with my gas meter, that uses a reed switch, with pulse_counter and pulse_meter both using the same reed switch / PIN. See the function of:

allow_other_uses: true

as used below:

  - platform: pulse_counter
    name: "Gas - Pulse Counter"
    id: gas_pulse_counter
    pin:
      number: 32
      allow_other_uses: true
      inverted: true
      mode:
        input: true
        pullup: true


  - platform: pulse_meter
    name: 'Gas - Flow Rate'
    id: "gas_flow_rate"
    unit_of_measurement: "L/min" # "m³/h"
    state_class: measurement
#    device_class: volume  # Disabled to stop this being recorded in HA
    icon: "mdi:pump"
    accuracy_decimals: 3
    pin:
      number: 32
      allow_other_uses: true
      inverted: true
      mode:
        input: true
        pullup: true
    internal_filter_mode: PULSE
    internal_filter: 100ms
    timeout: 3min
    filters:
      - multiply: 10.0     # 1 pulse = 10L

Sorry I didn’t notice your using an ultrasonic sensor. Best option is to use a proper liquid pressure sensor, as used in commercial solutions, especially as your talking ~USD$25 now for one.

If of interest, see: https://www.aliexpress.com/item/33003863661.html just needs the 0-5V version and choose the ‘smallest’ range to suit your tank, as this makes it more accurate. i.e. If you have a 1.2m tall tank get a 2m range model, 2.8m tank get a 3m range model… if you have a 1m tank and get a 5m range model, it will work but it will have less level of granularity.

https://www.aliexpress.com/item/33003863661.html

With this you just need to connect it into an ADC, or just buy a board that’s ready to connect it to, such as: https://www.aliexpress.com/item/1005006976454212.html

If its of use to anyone I can assemble a config you can paste into a device yaml, that pulls all the different senors and packages to give a water tank device with either a ds18b20 (temp) or BME280 (temp/humidity/pressure) sensor. Output is like:

1 Like