ESPHome water level sensor

Thanks for the advice,
On the site you found, they indeed connect the Vout- to the converter and have the Vout+ go trough the sensor.
I have been following the schema on the site of DFrobot where they have the Vout+ connected to the converter and the Vout- to the sensor. That could indeed explain the reason my converter catches fire.
My DFRobot current to voltage converter arrived today. I assume I should still connect this one to the Vout+ right (and have the Vout- go trough the sensor and then to the converter), as is depicted on the schema on the DFRobot website?

Looking forward for your experience with DFrobot.
IMO as lomg as you are using completely separate power for sensor than it should not matter where you connect the sensor (either between Vcc and + connector, or GND and - connector - keeping in mind sensor + and -). The chalenge starts when you use setup-up module which (in most cases) hard connects GND of input and output. In that case you can galvanic connection between your sensor power GND and module power GND which has to be taken in consideration.
I woudl first check if ā€œ-ā€ connector of module input is connected to GND of module power supply (as it was in the other module). And in case it is, I would connect sensor between Vcc and + input of module. It should not matter for the sensor as it ā€œcreatesā€ current as a result of itā€™s measure and you are safe that GND of sensor power supply is connected to

1 Like

Iā€™m in the situation where I use one power supply that provides 5V to most of my devices and powers a step-up power supply that delivers the 24V.

I can confirm your statement about the cheap converter: the resistance between GND and the - on the current sensing part is 0.00 Ohm.

For the more expensive DFRobot converter, the resistance is 0.2 Mohm (200 000 Ohm).

I really want to avoid destroying the DFRobot one. Given that the GND and - are not connected, how would you suggest I connect the converter to the sensor and step-up power supply?

This is good sign - meaning that module is more ā€œsecuredā€. IMO there should be no difference in connecting sensor either to Vcc od GND of step-up board. At the same time I think it is always ā€œmore safeā€ to connect it between Vcc and + of the module (in case the GND matters and knowing that GND of your step-up module is connected to GND of power supply).

1 Like

OK so I connected the DFRobot converter according to your suggestions and it works fine!
I then also connected the cheap converter with the burnt ā€˜current signal sampling resistorā€™ in the same manner and it works fine too!
I also have a brand new version of this cheap converter nowā€¦

So I now have the luxury problem that I need to choose between the DFRobot and the cheap converter.
The cheap one has the benefit that I can set for which mA it should output 0V and for which mA it should output 3.3V. It also has many more components on it, which as a layman I would assume means its fancier.

But my number 1 criterium is safety (e.g. not catching fire), I guess the DFRobot one wins in that front, though I have not (and will not) connected it in the ways that made the cheap converter smoke/catch fire.

Which one would you pick?

Thanks a million for all the advice you have given, I donā€™t think I would have figured it out without you!

I integrated it into Home Assistant today and to my surprise the ESPHome code I had written weeks ago works :smiley:
So I figured I might as well share it here (not claiming there arenā€™t better ways of doing it).
Important note is that this code is for when you are using an ESP8266 in combination with an ADS1115 analog to digital converter (costs ā‚¬1 or so and is much more accurate than the built-in ADC in the ESP8266). Slight adjustments would be necessary if you use an ESP32 or donā€™t use the ADS1115.
Hereā€™s the diagram of how I connected everything (a bit messy as I changed it a lot based on the helpfull instructions of @Maco65.

And hereā€™s the code:

# setup ic bus
i2c:
  sda: 4 #for the ESP8266, most often 21 for the ESP32
  scl: 5 #for the ESP8266, most often 22 for the ESP32
  scan: True
#  id: bus_a #I believe this is necessary for the ESP32, but I'm using the ESP8266

# define the ads1115 analog to digital convrerter on the bus
ads1115:
  - address: 0x48 #This is the address used by the ads1115 if you connect ADDR with GND on the board or if you don't connect it to anything. Other addresses can be chosen (if this one is occupied allready) by making a diferent connection.
#    i2c_id: bus_a #This is probably necessary on the ESP32, the way I'm doing it might be incorrect, but in any case it's not necessary for me as I'm using the ESP8266

#These sensors assume one circular tank with the same radius along it's height. I will connect a second tank and to solve that issue I will create additional sensors and sum these with the original sensors into new Total sensors. I need to look at the usable height in the second tank (minimum water level when the siphon connecting the two tanks will start working, assuming that the inlet ofthe pump in the main tank is placed lower than that). I will then define the measured voltage at that level as 0cm. I then need to know the voltage when the second tank is at it's maximum height (i.e. when water in the main tank will start flowing to the drainage citern). I can then do the lineair calibration. Now I have the centimeters. Summing these centimeters with the other one is meaningless. For the liters sensor I need to know the surface mĀ² of the new tank and multiply it with the new height sensor. That result I can indeed sum with the liters of the other tank into a new total. To create the percentage sensor I need to sum the new total liters sensor by the sum of the max liters of both tanks.
sensor:
  - platform: ads1115
    multiplexer: 'A1_GND'
    gain: 4.096
    id: watertank_voltage
    name: "Water Level Sensor Voltage"
    icon: 'mdi:water-well'
    unit_of_measurement: 'V'
    update_interval: 1s #the delta filter will ensure it only sends values when something changes. 
    filters:
      - sliding_window_moving_average:
          window_size: 10 #creates a moving average of the last 10 values
          send_every: 1 #sends the moving average at every measurement (but only if it passes the delta filter below)) 
          send_first_at: 1 #after startup immediately start sending the result rather than wait for the first 10 measurements
      - delta : 0.0015 #only send the result if the voltage difference with the last sent result is higher than this
  - platform: template
    name: "Water Level Sensor usable CM" #first X cm are below pump inlet and thus unuseable.
    id: watertank_cm
    icon: 'mdi:water-well'
    unit_of_measurement: 'cm'
    lambda: |-
        return id(watertank_voltage).state;
    update_interval: 1s #the delta filter will ensure it only sends values when something changes. 
    filters:
      - calibrate_linear:
          # Measured value of X volt maps to y cm
          - 0.0 -> 0
          - 2.5 -> 165.0
      - delta : 0.001 #only send the result if the difference with the last sent result is higher than this
  - platform: template
    name: "Water Level Sensor usable %"
    id: watertank_percent
    icon: 'mdi:water-well'
    unit_of_measurement: '%'
    lambda: |-
        return id(watertank_cm).state / 165.0 * 100; 
      #divide by max water level height to get a percentage
    update_interval: 1s #the delta filter will ensure it only sends values when something changes. 
    filters:
      - delta : 0.001 #only send the result if the difference with the last sent result is higher than this
  - platform: template
    name: "Water Level Sensor usable liters"
    id: watertank_liter
    icon: 'mdi:water-well'
    unit_of_measurement: 'l'
    lambda: |-
        return id(watertank_cm).state / 100 * 3.14159265 * 1.13751599 * 1.13751599 * 1000.0;
      #height (meters) times pi times radius (meters) squared times 1000 gives liters.
    update_interval: 1s #the delta filter will ensure it only sends values when something changes. 
    filters:
      - delta : 0.001 #only send the result if the difference with the last sent result is higher than this

The code is not ideal in that it only sends the Voltage/Cm/Liters/% to ESPHome when there is a change. I would like to to also send the value every hour or every day or so even when there is no change (but send the value immediately if there is a change). I had tried adding the filter - heartbeat : 60m to accomplish this but it creates a very illogical behaviour. The result is that my delta filter is completely ignored and it just sends the value every hour and does not send any values anymore in between those periods even if there is a change.

So it seems like you have to choose between

  • either sending the values at a regular interval (but then you wonā€™t immediately be notified of a change) like every 5 minutes or so.
  • doing the measurements very frequently (e.g. every second) so that Home Assistant immediately is notified of a change, and then prevent spamming home assistant using the delta filter (but then Home Assistant wonā€™t get any values when there is no change for days for example).

I could not find a solution to this, if anybody has a solution, thatā€™s very welcome.

8 Likes

Thank you for that. I got my ADC, but the sensor is a month in transit with no telling when it may arrive. I recognize the D1, ADC, sensor, and buck convertor, what is the other component used?

Itā€™s the cheap current to voltage converter I purchased from Aliexpress.
I also have the more expensive DFRobot one. havenā€™t figured out yet which one I will use in the end. Any advice on that is welcome :slight_smile:

Happy that you have now luxury to choose from! :slight_smile:
To pick one or the other I would consider:

  1. safety. Although the fire in your case IMO is related to the way power is provided still DFRobot seem to be better as itā€™s input terminals does not seem to be connected to either GND or Vcc of the module. So here + for DFRobot. From other hand if you have connected it the way it works I think there is no risk now that it catches the fireā€¦
  2. Power supply impact. In the link I have mentioned earlier it was clearly stated that checp module is sensitive for power supply volatility. I could not find any information how DFRobot is reacting. Would be nice to test what happens with Vout if the water level i s the same but Power supply changes from lets say 5V to 4V. In case the Vout is stable then this will be a BIG + for DFRobot
  3. DFRobot based on product Wiki produces Vout between 0,48 and 2,4 V for currents between 4 and 20 mA. This makes effective Vout range of 1,92 V for measurements. In case your tank is not going to be filled with ā€œfull sensor capacityā€ (I assume 5 meters) the range is getting even smaller. Cheap module can be regulated that for your specific sensor measures (this is my case when I expect min 4mA and max 10mA) you can have full ESP8266 scale used (from 0 to 3,3V).
    So, here the + is for cheap module

Maybe you can connect one for few weeks and then the other and see the difference ? :wink:

It seems that in case you have very stable power supply (5V) and max level of your tank will be much less then 5m, the cheap module has advantages for the range and thus for accurancy. If not, and stability of measures over time are important (and provided that DFRobot conversion is not affected by changes in Power supply) then DFRobot seem to be better choice.

Let us know which one you use and how are the results.

As usual your advice is extremely helpful.

I tested the cheap converter with two different USB power supplies, one outputs 5.21V, the other 4.95V
The output voltage of this cheap converter is 0.597V in one case and 0.708V in the other case.

I then did the same with the DFRobot converter, and the output was 0.668V in both cases.

I could also clearly notice that there was less variation over time in the output voltage.
The DFRobot varies about 0,004V, while the cheap converter varies about 0.008V over time. EDIT: I realise now that I did these tests with the converter that caught fire, so this is not a fair comparison.

So these are strong arguments in favour of the DFRobot converter. It means that you just need to calibrate the voltage to the minimum and maximum levels of the water tank once, while with the cheap sensor if something happens (e.g. you change the power supply), you have to recalibrate.

The downside is as you mention the fact that it can only has an effective Vout range 1,92V for measurements.

Further measures I took to increase accuracy: A higher precision dedicated ADC + my pressure sensor has a range of 2 meters.

I wanted to see how accurate my measurements are with the DFRobot sensor.
Iā€™ve set-up these filters:

    filters:
      - sliding_window_moving_average:
          window_size: 10 #creates a moving average of the last 10 values
          send_every: 1 #sends the moving average at every measurement (but only if it passes the delta filter below)) 
          send_first_at: 1 #after startup immediately start sending the result rather than wait for the first 10 measurements
      - delta : 0.0015 #only send the result if the voltage difference with the last sent result is higher than this

With delta set to 0.0015 I get the impression I donā€™t often get new results due to the random variation in the voltage.
I did a test by slowly adding water in a bucket until I got a new result (0.67120V).
Then I again slowly added water until another new result came in (0.67280V). To achieve this I had to raise the water level by about 0.17cm of water, which for my water citern would mean about 7 liters of water. Thatā€™s a pretty good accuracy :slight_smile:, enough to detect a toilet flushing!

Some math using the above measurements using the effective Vout range of 1,92V (discussed in our previous posts) confirms that these results make sense:
0.17cm/(0.6728V-0.6712V)*1.92V=204cm and my pressure sensor has a measurement range of 200cm!

In conclusion: Iā€™m going to use the DFRobot converter

Searching on Aliexpress I see that they have a sensor (QDY30A) that comes in different versions.
Providing either 4-20mA, 0-5V, 0-10V or even RS485 output.

The 0-5V version combined with a ADS1115 seems to be a very simple solution.

Does anyone have any experience with this sensor?

1 Like

I donā€™t have any experience with this sensor, but the reason there are 4-20mA sensors is that the longer a cable is the lower the voltage will be so if youā€™re measuring amps, the cable length doesnā€™t affect the measurement, and you can detect a broken cable if youā€™re measuring 0 mA

@Syntox Yes, but all the examples here only convert the current to a voltage in order to read it off an analog GPIO on the ESP anyway. So the only advantage then is that you would not have to (re)calibrate for voltage drop in a longer cable.

Is there a convenient way to read the current directly on the ESP? I see there are chips like INA219 - is that an alternative to using the ADS1115?

I guess this Post will help you:

@Syntox Not really.
Iā€™m looking at using the INA219 to read the current directly on the ESP. I cannot see that this is disussed in the thread. My concern is that this has a precision of 0.8mA and that might give a too coarse resolution to be practical with the pressure sensor.

1 Like

For those that might be interested.
I just tested a setup using a ESP32 with a INA219 current sensor module, measuring the the current of a TL-136 water level sensor (0-1 meter version, 4-20mA).

I tested it in the range from 0 to 20cm and it seems to give stable measurements from 4-7.3mA with a precision of ~0.1mA. This fit the INA219 specification with internal gain set to 400mA (div8).

This means that one should be able to monitor water level from 0 to 1 meter with a precision better than 1cm.

Iā€™ll continue testing this and will report my findings.

1 Like

Just for the sake of comparison:
I got a 0-2m pressure sensor which reports in 4-20mA and am using a current to voltage converter and my accuracy is about 1mm. So I have higher accuracy but also a more complex set-up perhaps. More info about that can be found in posts above :wink:

Yes, your set-up might give higher precision, but is also more complex.

The INA219 connects easily to the ESP32 using I2C and is directly supported by ESPHome, so the setup is extremly simple.

With 0.1mA precision it will give you appx. 160 measuring points on a 4-20mA sensor. This is enough for a precision of less than 1cm for a 0-1 meter sensor, and a bit more than 3cm for a 0-5 meter sensor. For my purpose this is more than good enough.

Hi all,

Lots of interesting ideas above!

Iā€™ve finished my water tank level sensor and successfully read level in range, volume/litres, and %. My project is Wemos D1_mini based, and my level sensor is the JSN-SR20 (ultrasonic, waterproof, dual-sensor model of HC-SR04, around AU$8). This sensor has a dead band of ~5cm so can be readily mounted direct to the top of the tank - no cone or spacer required, simplifying installation. It also has a range over 4m, for those with tall tanks! Iā€™ve added a DS18B20 for external air temp, to round things out, and a rainfall sensor to tell me when itā€™s raining.

To get reliability Iā€™ve added the following parameters (not mentioned anywhere above, but in the sensor docs) for the ultrasonic sensor:

  • Pulse_time extended to 20us. The default is 10us, whereas most sensors want a minumum of 20us.
  • Timeout set to 3m. The default is documented as 2m, but my sensor wouldnā€™t reliably report values over 1.80m without this.

I was getting regular ā€œtimeoutā€ and ā€œnanā€ values in my returns prior to adding these; none in the days since.

Others have noted time-of-day variability which would be temperature sensitivity - which Iā€™m also seeing (tank level is currently 3cm overnight but 7cm when air temp is around 18C). There are arduino libraries to reduce temperature sensitivity, but not sure how to implement something like this in ESPHome. Has anyone had success in reducing temperature sensitivity?

1 Like