ESPHome water level sensor

Hello @mrmuttley I think you have two questions?

One tank Volume
π×r×r x height

Two tank volume
2 x π×r×r x height

Height for both is derived from your existing sensor as you have already set up the depth of the tank through linear filter. You would now set up a template sensor and create a lambada with the formula in it.

I had to do the same BUT my cylinder water tank is on its side and therefore the maths is a pig!

Did you get this problem after installing the second tank? There is no reason I can see why there should be a difference. Your sensor is a throw in pressure sensor. It only knows the height of the water above it.

1 Like

Thanks - I tried to do this as per the code above… would you mind having a look to see if it makes sense?

Problem only started after the second tank was added and updated the code to multiply the total by 2.
Was thinking of perhaps upping the voltage on the sensor but not sure it this would make any difference.

Any further input would greatly be appreciated!

Hi all,

Is anyone able to kindly assist me with adding in filters to my setup.
I’m currently getting values that are greater than the max height, max volume and greater than for 100% for tank percentage.

I’d like to display the last min/max set values and not a NAN value when filtering.

Max volume of both tanks is 4860 Liters
Max height is 1.535 Meters
and Max percentage should ignore anything above 100%

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true
  id: bus_a

ads1115:
 address: 0x48
 i2c_id: bus_a
 continuous_mode: off
       
sensor:
- name: Jojo Tank Height
  id: tank_height
  platform: ads1115
  multiplexer: 'A0_GND'
  update_interval: 60s
  gain: 4.096
  unit_of_measurement: "metres"
  icon: "mdi:gauge"
  accuracy_decimals: 3


  filters:

  - median:
     window_size: 200
     send_every: 10
     send_first_at: 4    


  - calibrate_linear:

    - 0.445 -> 0
    - 1.025 -> 1.535
       
- platform: template
  name: Jojo Tank Volume
  id: tank_volume
  unit_of_measurement: "litres"
  lambda: |-
    return 2 * 3.14159265 * 0.71 * 0.71 * id(tank_height).state * 1000;

- platform: template
  name: Jojo Tank Percentage
  id: tank_percentage
  unit_of_measurement: "%"
  accuracy_decimals: 0
  lambda: |-
    return (id(tank_height).state) / 1.535 * 100;
  

- platform: wifi_signal
  name: "Jojo Volume WiFi Signal Sensor"
  update_interval: 60s

switch:
  - platform: restart
    name: tankvolume

Thanks in advance :slight_smile:

Hello @mrmuttley, first thing is to check what the voltage is when the tank is at the maximum height i.e. full. You may have already done that but it clearly has moved. Easy thing to do is # out the three lines of calibrate _linear, reflash and then reread the new voltage from the logs. Remove the #’s and reenter the calibrate line with the new voltage number i.e. not 1.025

Just need to write some if statement for volume and percentages if you find the base voltage is still wondering around. I can help

Thanks so much for your help with this…

I’ve tried re-calibrating and re-measuring the actual height of the water so many times that I feel like I’m trying to hit a moving target. I’ve even taken the probe out to get a new 0 voltage.

There’s a buck/dc-dc converter installed for both the probe and ESP32 to try keep things stable as suggested by others above.
I’m wondering if perhaps the probe or the 4-20mA to voltage converter is faulty…

For a few days the voltage was 1.025 and now it’s 1.067…

Hence the reason why I’d like to try filter out the variables and set a min and max…
Thanks for the help and input- any additional help would greatly be appreciated!

Hey community,

I wanted to measure my stormwater soak-drain changes (rises quickly, falls slowly, does it overflow?), and solve a rain-water tank problem measurement for a relative.

Journey

There’s a dearth of good water/liquid depth sensors that are pre-integrated into esphome, and certainly none pre-packaged that’ll measure levels that I could find. I think this is mainly because it’s a hard problem to solve in a general sense (how deep, which liquid, etc), but also because the best sensors out there for this purpose are non-trivial to connect to (powered, analog).

I chose the 4-20mA variant sensor immersion sensors after reading way too much here and elsewhere (ultrasonic dead zones, waterproofness, ripples etc and trying to solve for both my use cases). On my research journey I found integrations for current sensors directly onto esp32 boards that required discrete circuitry, but that plus getting the (recommended for this sensor) 24v near the esp32 didn’t seem like a great idea. There are also super-cheap (like $5) industrial sensor->RS-485modbus modules though that can take 2(+) sensor inputs, and are designed to be permanently installed and robust to mistreatment/lightning/etc. So I took that option.

Then there’s RS-485 which has been around forever but I’d not appreciated it as useful for IoT until now. There also esp32 integrations/sub-boards for RS-485. And then there’s the Lilygo T-CAN485 which has an nicely isolated RS-485 interface on it already, and means I didn’t need another board. They do other boards with RS-485 too, but every single one is different.

For this project I decided that the water sensor could be remote, and the esp32 etc could be further away from the water, and then just running 12v to it would be easiest.

Materials

(no affiliate links, but links might be country-dependent)

There are many liquid sensors of this submersible kind. Not all are equal (reports are that some rust) and I believe this store is the OEM and not a re-reseller. These sensors are quite a bit bigger and more hefty than they look in the photos. Ensure the cable length is long enough as it’s got a pressure-equalisation tube inside it that needs to be kept out of the water(discussed above), I guess they can be cut down (but I didn’t) but extending could be problematic. They want 24v but will apparently run on 12v.

Pictures


Testing in my water bottle.


Sensor, 18650 for size reference :slight_smile: Sensor is quite heavy.


Installed, working, with ferrules even. Cable management could be better…

esphome configuration

Modbus configuration of the T-CAN485 board is a little annoying and was undocumented outside of the Arduino examples. It works though, just needs some pins flipped high. Feedback welcome…

Full yaml here

Got the RGB LED working properly too.

Results

It verks!

And installed and on a dashboard.

Final Thoughts

I like using these off-the-shelf components. They’re robust although not that space efficient. I am thinking about why I don’t have an RS-485/modbus bus loop around my house now too. I have no real-world experience with it yet but now I see why there is an RS-485 version of my weather station (Ecowitt), and it looks like I could loop in my aircon and solar inverter too.

The industrial 4-20mA current sensor approach is something I’d do again for remote sensors because after the “why did they make it so complicated?” thoughts subsided I realised that this range stays ~static regardless of the length of the wire to the sensor (unlike say 0-5v), and probably other good reasons too. It’s clearly not a low-power (uA) consumption approach though, so you do need a stable power source. Once 4-20ma sensor integration is solved for one type we can apply this to other types of sensor like this as well as well…

The “12 bit” RS-485 sensor converter is using less than 12 bits because it uses 2621 values for the 4-20mA range of the sensor, which is not 4096 (12 bits). Still enough values for sufficient precision for my purposes. Docs went through Google Translate fine. Can’t beat the price, and there’s space for another sensor.

The sensor is (a few days in) awesome. Came well packaged, calibrated to the values engraved, and just works. It will take some years to prove them out completely, but it looks like the real thing. I could have ordered the RS-485 version (and avoided a box), but I these are more common and replaceable. Seems ~stable across temp and barometric changes at least within 2mm change.

The case probably needs a vent as so the barometric compensation works properly, but it’s not wildly varying (my XT60 hole may be providing this). I’ve ordered some cable glands with vents…which are a thing. TIL.

2 Likes

that is about 4% variability … I am getting 0.45% … what is the rated working depth you purchased? I would have to rerun the numbers when we get to summer and tank lower. How about following:

    filters:
      - lambda: if (x > 1.067) { return 1.067; } else { return x; } 
      - calibrate_linear:
          - 0.028 -> 0
          - 1.067 -> 1.535
      - sliding_window_moving_average:
          window_size: 200
          send_every: 10

I update every second and perhaps with your longer average period that may smooth things out. Otherwise 4% is not the worst thing in the world.

Also you can use the following filter which will ignore any data less than 4% of the last number. You could use combination of filters remembering the order of the filters is important.
- delta: 4%

1 Like

Thanks so much!

I’ve tried this and it’s giving me the 100% value as expected.

Still think something is up with my setup as I re-calibrated everything yesterday and the voltages seem to be stable as per the calibration, then they start to mysteriously increase…

This is the sensor which I’ve been using.
Wondering if I should try buying a new DF Robot Current to Voltage Converter 4-20mA and seeing if this helps - it’s cheaper than buying the whole kit…

The sensor is sitting at the bottom of the tank in an upright position, should I perhaps allow it to float/be suspended mid tank?

Would an increase in temperature possibly cause this?
If so, is there a way to compensate for this…
The temps here have been hovering around 30degrees celcius

Any other suggestions would greatly help…

The raw voltage increases as reported by the ADC? (Not just the output of the filter)

If you have a reasonable meter then do some readings to see if it’s the sensor (so measure the current) or the conversion (voltage on output of the current to voltage) and try and establish which part shows an increase? ie if neither of those it’s the adc. If you’re considering changing the converter then why not get the mA to i2c converter(also DFRobot, “I2C 4-20mA DAC Module (Arduino Compatible)” and collapse one source of error?

I’ve been cycling from 20 to 40C ambient temps on my similar sensor with very little error, and I wouldn’t think that your quantity of water is changing temp that fast anyway? I did see some errors with barometric pressure changes, maybe overlay those graphs too to see if you spot a trend related to that?

1 Like

Hi,
Mr Muttley, I was having simlar issues with the 4-20mA variety. I changed esp boards and added in ADC boards -the list of pieces kept growing.
Then I found Lars Klint posted about a Shelly uni and a sensor that outputs voltage.
I flashed out on more gear and it has been installed for 6 months or more now and I have no issues with the sensor and readings. I am contemplating my power issue (currently a solar panel into a 12v car battery) this at least becomes active once per day and takes my readings required.

1 Like

If you want put a temp sensor in the water tank and then overlay over with your chart above. I would take a week chart to see if it is linked with air pressure and temperatures movements.

Can you remind me how long is the run between the ADS1115 and the current to voltage unit? And can you confirm the rated working pressure range for the pressure sensor.

I do not use current to voltage but ordered the 0-5v variety and have it running over 25 metres straight to the ADS1115. I do get variations but not that much …

You have made me look at my history and I realise my tank has been flooding!!! I am 3.8m inground and water table has been so high that the tank has been gone past the overflow level and filled up to top of turret and the surrounded lawn is now sea level!! I have now a notification from my tank pressure sensor to tell when the garden is flooded!!!

2 Likes

Hi all,

Thanks so much for the very useful input - got me fiddling and fiddling and fiddling yet results came back with no positive results.

I’ve now ordered a new current to voltage module and a new ADS1115.
In addition to this, I’ve ordered a Shelly Uni (first time trying one of these).

If the new current to voltage module and new ADS1115 don’t make a meaningful difference, I’m going to try using the Shelly Uni plus the current to voltage module with my existing pressure sensor.

Current setup:

Shelly proposal:

Not sure if the Shelly Uni idea will work, if not, I’ll order a 0-10V submersible sensor…

Any input as always is appreciated!

What you’ve got should work. Why not move all of your power and circuitry over to the left-hand-side and run the sensor over the wires you have? This is the beauty of 4-20mA sensors, there is no voltage drop issue because you’re not measuring that.

Then you can keep a common earth for everything too, 24v power supply to both regulators, avoid any loss or noise currently being induced in the 0-5v long(?) wire run, and potentially wrap it up in one tidy box.

Then if you’re still seeing oddness get back to basics and measure some baseline values (of the sensor, of the ADC output) with a meter, or at least before esphome filters distort them with filtering and fitting. Maybe turning up the debug level will be enough to see that?

1 Like

No need for extra ADS1115 + Current-to-Voltage converter with an ESP32.
Just use either an INA219 or INA226 DC current sensor.
I have been using an INA226 and the same type of transducer (4-20mA, range 0-5m) for exactly your application scenario for about a year now without any problems. Flawless operation, measured value tolerance < 1 cm. Put the transducer on the high side of the INA

- platform: ina226
    address: 0x40
    shunt_resistance: 0.1 ohm
    current:
      name: "INA226 Current"
      id: raw_current
      filters:
        - multiply: 1000  # conversion to mA
      unit_of_measurement: mA
    bus_voltage:
      name: "INA226 Bus Voltage"
    shunt_voltage:
      name: "INA226 Shunt Voltage"
      filters:
        - multiply: 1000  # conversion to mV
      unit_of_measurement: mV
    max_current: 50mA
    update_interval: 10s

  - platform: template
    name: Water gauge
    unit_of_measurement: cm
    accuracy_decimals: 0
    update_interval: 30s
    filters:
      - sliding_window_moving_average:
          window_size: 10
          send_every: 5
    lambda: |-
      auto current = id(raw_current).state;
      return 100 * current / 5;  // Sensor: 4-20 mA, factor 100 to cm convert, range=5m
2 Likes

Thanks for the input…
After a few days of fiddling, I decided to test the whole system with a new ESP32 and a new ADS1115 plus having 1 power supply…
Things seem to be much more stable but I’m still not yet entirely confident in my current "excuse the pun :smiley: " setup.

My current setup as seen below, I tried using the DFRobot ADS1115 which I had lying around but been struggling to find meaningful info on this device - still not sure if I’ve wired it correctly by connecting the positive from the current to voltage module to the positive on the A0 pin… Any ideas?

captive_portal:

i2c:
  sda: GPIO21
  scl: GPIO22
  scan: true
  id: bus_a

ads1115:
  - address: 0x48
    id: ads1115_48
    i2c_id: bus_a

sensor:
- name: Jojo Tank Height Gravity ADS1115
  id: jojo_tank_voltage_gravity_ADS1115
  ads1115_id: ads1115_48
  multiplexer: 'A0_GND'
  update_interval: 5s  
  gain: 4.096
  platform: ads1115
  unit_of_measurement: "metres"
  icon: "mdi:gauge"  
  accuracy_decimals: 3
  filters:
    - sliding_window_moving_average:
       window_size: 200
       send_every: 10
       send_first_at: 10

#    - median:
#        window_size: 200
#        send_every: 30
#        send_first_at: 30

    - calibrate_linear:
      - 0.210 -> 0
      - 0.800 -> 1.545
       
- platform: template
  name: Jojo Tank Volume
  id: tank_volume
  unit_of_measurement: "litres"
  lambda: |-
    return 2 * 3.14159265 * 0.71 * 0.71 * id(jojo_tank_voltage_gravity_ADS1115).state * 1000;

- platform: template
  name: Jojo Tank Percentage
  id: tank_percentage
  unit_of_measurement: "%"
  accuracy_decimals: 0
  lambda: |-
    return (id(jojo_tank_voltage_gravity_ADS1115).state) / 1.545 * 100;
  

- platform: wifi_signal
  name: "Jojo Volume WiFi Signal Sensor"
  update_interval: 60s

switch:
  - platform: restart
    name: tankvolume

1 Like

Thanks for your input on my dilemma - would you mind sharing a wiring diagram?

Connect the red wire from transducer to -IN, the other one (black or blue) to ground. +IN (R100) from INA2xx to +24V.
That’s it.

1 Like

Pls see here ESPHome water level sensor - #221 by kimocal

Awesome, will deff this a go as soon as I can get a module.
Thanks!

Ah those are i2c? Nice. Mmm, that would have been easier for me too.