ESPHome water level sensor

I think I’ve linked this video before in this thread (or a similar one).

It shows that the ESP32 has a particularly poor built-in ADC.
That’s why an external one like the ADS1115 is recommended.
Using the ADS1115 and a well suited pressure sensor (in my case one with a range from 0 - 2 meters for a pool that fills up to about 1.35m) I get a precision of about 1-2 millimeters!

Quizzical
Yeah the guy with the swiss accent is on my subscribe list. He also convinced me to purchase the ads1115. I am measuring a 22000 litre water tank - depth about 2.4. I should have it all in a box soon.
Pat

Hi liflitz

  1. The ADS1115 uses an I2C interface to send data to the NodeMCU, therefore the A0 connection is not required at all.
  2. The ADS1115 uses the connection between the ADDR and other pins to set its address so, yes, that connection is correct for the address “0x48”. Other connections and addresses below:
    ADDR → VDD “0x49”
    ADDR → SDA “0x4a”
    ADDR → SCL “0x4b”

This is a very handy feature which allows connection of multiple ADS1115 modules to a single NodeMCU if required. I have 3 water tanks in my RV that each have four outputs “1/4”, “1/2”, “3/4” and “Full”. This is a total of 12 possible water levels. Using 3 x ADS1115 I can configure my tanks to display individually in HA, using one NodeMCU.

  1. The gravity sensor uses current in the range of 4mA - 20mA as its output. This means that the circuit current must flow through the device for it to work. The accompanying module converts the current to a voltage for the ADS1115.

Cheers

1 Like

Hello @iFloris

Can you post your ESPHome config (in its entirety) so that I can have a look at it?

Also, double-check that you are definitely using the correct pins for the SDA and SCL connections on the NodeMCU.

Cheers

Hi Liflitz

No, the picture is correct. The throw-in sensor uses the 24V directly and the 5.2V output of the regulator is used only for powering the NodeMCU and the current to voltage converter.

Cheers

@rusty_away, can you share your config and more detail about the wire; I’m looking for a solution to measure 2 tanks (one next to the other) and your description rang me the bell that I can use a single NodeMCU for that

Hi @bremby

First you have to set up the pins on the NodeMCU that the I2C interface will use:

i2c:
  sda: GPIO4
  scl: GPIO5
  scan: true
  id: bus_a

Then you declare the address the ADS1115 will be using (for example “0x48”) In this case the address is set on the ADS1115 itself by connecting “ADDR” to “GND” of the same module.

ads1115:
  #  continuous_mode : on
 - address: 0x48
   id: ads1115_48
   i2c_id: bus_a

Then you configure each of the inputs on the ADS1115 that you will be connecting:

sensor:
# ads1115-48
  - name: "Tank 1"
    id: ads1115_48_a0
    ads1115_id: ads1115_48
    multiplexer: 'A0_GND'
    update_interval: 60s
    gain: 6.144
    platform: ads1115
    unit_of_measurement: "V"
    icon: "mdi:gauge"
    accuracy_decimals: 2
  - name: "Tank 2"
    id: ads1115_48_a1
    ads1115_id: ads1115_48
    multiplexer: 'A1_GND'
    update_interval: 60s
    gain: 6.144
    platform: ads1115
    unit_of_measurement: "V"
    icon: "mdi:gauge"
    accuracy_decimals: 2

In the above code I have configured the first two analogue inputs of the ADS1115 which is using address 0x48. Read up on the ADS1115 as you will need to use a “gain” value that matches your input voltage range. In the example, above, the ADS1115 input 1 (A0) and input 2 (A1) are referenced to ground (GND) which is the -ve DC rail of the circuit.

So, if you are using throw-in level sensors, connect the output of the first current to voltage module (Tank 1 ??) to A0 and the output of the second current to voltage module (Tank 2 ??) to A1 of the ADS1115.

Hope that helps.

I have just connected all my bits together yesterday and the results look good. I was struggling a bit at first and I believe I found two possible issues.
The board type may be crucial - I had originally flashed my esp32 using the esphome io. It put the board as a esp32 dev board. I changed this to nodemcu-32s.
I also decided to send power from a 3v pin on my esp to the ads1115.
After making these two changes my error with receiving no connection from the ads1115 fixed straight away.
So now a couple more twekas before going into the box. If anyone has advice.
I read in this forum, possibly from hummingbear - that it is better to send the power to the ads1115 through a gpio. Then the ads1115 is only drawing power when you wake from deep sleep otherwise it is sucking 3v all the time?
I am also then considering that my project should all run on a parallel 3 x 18650 battery. Currently I draw .2A through my 24v battery bank (18650). If I tie my smaller 18650 battery to a 5v solar and use deep sleep I should have about 150 days of running without being charged. This is based on the power usage calculator at IOT Battery Life Calculator (thanks Mr swiss man)
I then thought I could use less power by instead of using a 5v relay to send a regular 18v to the sensor that I could use the small battery bank with a dc/dc step up to 18v as the gravity throw in sensor only draws minimal power. This step up would then be switched with a n channel mosfet driven by gpio from the esp32.
Does this make sense?
Pat

Got it - thanks!

Hi rusty_away,

Thansk for all your help, works for me very well now. I took the freedom to slightly modify your diagram based on your instructions and what worked for me:

image

Best wishes,

liflitz

2 Likes

Liflitz
I am wondering - you have sent your voltage to the A1 pin. You are referencing vdd then? Any reason why you do this and not to ground on AO?
Do you know your power usage at work and deep sleep?
Pat

1 Like

Hi Pat,

You are right, A0 not A1, I corrected the diagram.
I do not know the power usage, sorry.

Liflitz

Liflitz,
glad I wasn’t seeing things.
I have just been doing some reading about using proper grounding of components so that there is no fluctuation of signal due to electromagnetic interference. This youtube video posted in an arduino forum though really in depth made me think that my rats nest of wires and cables might be causing some fluctuations to occur. (US) Designing the Signal Return Path Through the PC Board - Susy Webb - Expert Live Training - YouTube
Might see how a good ground base may assist.
Pat

Thank you so much, I will study it

Advice welcome
I have my bits connected and thought I would put it through it’s paces to see how consistent the readings are.
Everything is powered by a bench top supply delivering 14v. I then step this down to 13.3 for the sensor. I have a separate step down to 5v. This power goes to the esp32, the 5v relay (switching power to sensor on upon wake), the current to voltage converter and then to the ADS1115.
All grounds are connected.
Looking at the logs I see that there is fluctuation on readings - is this normal in your setup? see piccy
water level sensor
This is my yaml.

esphome:
  name: "maintankv2"
  platform: esp32
  board: nodemcu-32s
# Send power to sensor by enabling relay on boot
  on_boot:
    then:
      - output.turn_on: water_sensor_power
      - delay: 10s

# Deep sleep
deep_sleep:
  run_duration: 4min
  sleep_duration: 4min
  
# Enable logging
logger:

output:
  - platform: gpio
    pin: 19
    id: water_sensor_power
    inverted: false
# Enable Home Assistant API
api:

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

ads1115:
- address: 0x48
  i2c_id: bus_a

sensor:
- name: maintank
  platform: ads1115
  multiplexer: 'A0_GND'
  update_interval: 6s
  gain: 4.096
  unit_of_measurement: "V"
  icon: "mdi:gauge"
  accuracy_decimals: 3
  
  filters:
  - median:
      window_size: 23
      send_every: 21
      send_first_at: 7
        
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esphome-Web-178238"
    password: "R4e6qBGLoo7Z"

captive_portal:

Patrick

1 Like

I have the exact same setup. But unfortunately I always get 9,7V from the current to voltage converter, no matter what the water level sensor sends.
Could you share a wiring diagram? Maybe I missed something…
Thanks!

Philipp
Here is my just made schematic. You can see that this is my first time using draw.io - maybe I’ll work on it amongst the other 327 jobs.
I get readings that are within +/- .03


Let me know if I have wires missing or in the wrong place.
Pat

1 Like

Hi All,

Thought people here may be interested in a solar ESPhome based water level sensor I recently completed work on. I have a water tank/bladder under the house which I wanted to track for garden watering purposes.

Basically it’s a PCB + battery + sonar sensor + solar panel. I’ve got 3D printed cases/enclosures to go with each of these items too.

The ESP reports back the sonar distance (which I convert to water level in HA) as well as battery voltage and wifi signal strength.

Several iterations were needed to improve/reduce battery usage. The first version had the sonar wired directly to the battery which constantly drained it. The HD-SR04P version it can be powered as/when required from a ESP8266 pin.

The battery is a small 240mAh one I had left over from another hobby. On this it will last roughly a week without sun from a full charge with my deepsleep settings. I’d recommend going with a better battery with proper low power cutoff as I destroyed more than one battery during testing.

This was my first attempt at PCB design so I wouldn’t recommend going out and make clones of this but I can say it works well for me.

Was thinking that it would be cool if this community could put together libraries of known working (and expert reviewed) designs and recommended parts for things like this.

The voltage regulator is a BL9 110-330BPFB which worked better than expected as did the solar/voltage management IC - CN3163.

I’m happy to upload schematic/BOM files for anyone interested.

Code is probably what took me the longest to get working correctly. Hopefully this will help others. Just set your deep sleep settings and the battery voltage settings in the bits below.

esphome:
  name: tanksensor
  on_boot:
    - wait_until:  
        condition:      #  any condition here
          api.connected: 
        timeout: 20s
    - script.execute: read_then_sleep


esp8266:
  board: esp12e

# Enable logging
logger:
  level: DEBUG

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  domain: .mynet.lan
  fast_connect: true

# Enable Home Assistant API
api:
  encryption:
    key: "yeahnah"

ota:
  password: "yeahnah"

output:
  - platform: gpio
    pin: GPIO4
    id: sonar_power

status_led:
  pin: GPIO2


sensor:
  - platform: ultrasonic
    trigger_pin: GPIO14
    echo_pin: GPIO12
    name: "Ultrasonic sensor"
    id: tanklevel_sonar_sensor
    timeout: 4m 
    pulse_time: 15us
    update_interval: never
    unit_of_measurement: "cm"
    accuracy_decimals: 3
    icon: "mdi:water-percent"
    filters:
    - multiply: 100
    - sliding_window_moving_average:
        window_size: 5
        send_every: 5
        send_first_at: 5
    - filter_out: nan
    - filter_out: 0.0
  - platform: adc
    pin: A0
    name: "Battery sensor"
    id: tanklevel_battery_sensor
    update_interval: never
    accuracy_decimals: 3
    icon: "mdi:power"
    filters:
      - calibrate_polynomial:
         degree: 3
         datapoints:
          # Map 0.0 (from sensor) to 0.0 (true value)
          - 0.68945 -> 3.18
          - 0.73047 -> 3.34
          - 0.79785 -> 3.66
          - 0.82715 -> 3.83
          - 0.87402 -> 4.01
          - 0.90332 -> 4.14
          - 0.91797 -> 4.21
  - platform: wifi_signal
    id: tanklevel_wifi_signal
    name: "Wifi Signal sensor"
    icon: "mdi:wifi"
    update_interval: never


script:
  - id: read_then_sleep
    then:
      - output.turn_on: sonar_power
      - delay: 2s
      - component.update: tanklevel_sonar_sensor
      - delay: 1s
      - component.update: tanklevel_sonar_sensor
      - delay: 1s
      - component.update: tanklevel_sonar_sensor
      - delay: 1s
      - component.update: tanklevel_sonar_sensor
      - delay: 1s
      - component.update: tanklevel_sonar_sensor
      - component.update: tanklevel_battery_sensor
      - component.update: tanklevel_wifi_signal
      - delay: 4s
      - script.execute: consider_deep_sleep

  - id: consider_deep_sleep
    then:
      - if:
          condition:
            lambda: 'return id(tanklevel_battery_sensor).state > 3.4;'
          then:
            - logger.log:
                format: "Battery state high"
            - lambda: |-
                id(enter_deep_sleep).set_sleep_duration(XXXXXX);
          else:
            - logger.log:
                format: "Battery state low"
            - lambda: |-
                id(enter_deep_sleep).set_sleep_duration(YYYYYY);
      - deep_sleep.enter:
          id: enter_deep_sleep


deep_sleep:
  id: enter_deep_sleep
  sleep_duration: 2min
    

I have 4 boards left that I probably will not end up using as you have to order with a minimum of 5. If you are in Australia and are interested in something like this feel free to PM me.

Cheers,
Bob

6 Likes

Hi @bobderbuilder thank you for sharing it and sounds a fantastic job
I’m not from Australia, but if you share your schematic, I will be happy to learn from you

regards

Hi Bremby, PM’ed
Cheers,
Bob