Six Temperature Sensors on a Hot Tank

My home heating system includes a 80L hot water tank, which is heated by a gas boiler. During the summer (i.e. now) it’s set to heat for an hour in the morning and an hour in the evening.
I’ve put 6 equally spaced temperature sensors up the side of the tank, connected to a Sonoff Switch, flashed with TASMOTA.

For your delectation, here is a graph of those sensors over the last 8 hours.
Heating came on at 17:00 and folks took their showers at 17:30, 17:40, 21:40 and 22:00.

I have a great data set from these sensors going back 2 years. I observe a very definite thermocline as the water heats and cools. No real “mixing” of the incoming cold water with the existing hot water.
Has anyone any ideas what can be done with this data?

I am plagued by the eternal question: “How much hot water is there?” That’s the question to which I seek the formula. I accept that “how much” is subjective because “hot” is subjective. So I think I can translate the question as “If we run the shower at typical levels, how long would it last before the user felt ‘cold’?” That’s a question which I think can be answered.

I’m looking forward to a decent bit of conversation and speculation.

HWTD20220824

I won’t go into speculation until I have some extra data:

  1. Where are the intake and output pipes of the tank located? By my limited experience in the field I’d say the water should always flow from bottom to top.
  2. Does the boiler run manually or is it controlled by some thermostat? Is the heating action at around 18:10 automatic or manual?

Thanks for your answers!

What is the flow rate at the shower?
Is inlet temperature constant?

I’d have been interested to hear your speculation on where the pipes might be. They are top and bottom, as you would expect (and have indicated). With respect to the pipes, S6(1) is beside the outlet, S4(6) is beside the inlet.
NB the S number is irrelevant, but the number in brackets is monotonic with respect to height.
The boiler is on a timer and a thermostat. It comes on for an hour in the morning and an hour in the evening, but only if the thermostat demands it.
Still interested in speculation on what further work this might lead to…

I’ve not measured the flow rate at the shower, but it’s variable, depending on the temperature selected by the user.
The inlet temperature is “fairly constant”. It’s colder in winter.

So after staring at that graph for 10 minutes and putting all my imagination to good use, here are my thoughts:

  1. The positioning of the sensors and the pipes is as you described.
  2. The water at the bottom mixes with fresh water quite a lot and it is visible up to the second sensor.
  3. The only way to see how much hot water you actually have (and what hot means is very subjective) you have to shower a bit more, or take a bath. Otherwise I could say that the moment the heating started you still have at least 50% of the initial hot water.
  4. No matter the time of the day, there is constant water movement in there, hence the different temperatures.

So what I would do, to see how much usable hot water I have (I would consider 40 °C water as usable hot water) is to dump the whole quantity in the tub while watching the water meter. When the top sensor reaches 40 °C, I would check the volume.
Do not let it flow too fast (temperature is generally slow to update) or too slow (water would have time to heat up more than when taking a shower).
I hope this helps!

1 Like

I really appreciate your input. I’m hankering for a decent pub conversation about this as I think there’s hidden information in this data!
I’m not sure I agreed with (2). My observation is that the level of “hot” (I accept this is subjective) rises with the heating on, falls with the heating off, and falls rapidly with consumption. I perceive a definite thermocline and very little mixing.
Ha ha! I totally agree with (3). “hot” is subjective. Also “how much” is subjective! I think this is reflected in my original question.
(4) without a doubt there is transfer of heat energy. As the top line and bottom line converge, the principle of convection is very evident. Ref my comments on (2) thought, I’m not sure that’s “movement” (although “movement” is certainly how I normally visualise a convection current in terms of a weather system, for example).
We definitely agree on 40 degrees as the set point. Basically, anything above body temp, for the purposes of a shower is “hot”. The stat mixes in cold to make it tolerable. If I had a tank 100% full of 60 degrees water, there would be “more” than if I had a tank full of 50 degrees water, which is why it’s a difficult question to frame!
Certainly a good debate is helpful, thank you. If it’s any consolation, I have posed the same question to a physics forum, and proposed the data set for analysis in an undergraduate degree course.

Have you seen this topic?

Maybe have a chat with the people there.

1 Like

NOW I have. Thank you!

I have a formula for this which I’ve used for the last year - and very happy with the result.

It’s a lengthy Jinja formula but works out how much 40degC water could be made from the tank when mixed with cold water.

I’m currently on hols but will post it here when I can.

The boost is then able to run until the target quantity is met, rather than for a specific duration.

By some estimation I can display e.g. ‘2.5 baths’ which is a more helpful number for most people than litres.

1 Like

Ok, here’s my yaml for my ‘Hot water litres remaining’ sensor:

 - sensor:
     - name: "Hot water remaining l"
       unit_of_measurement: "l"
       state: "{% with 
traw = [float(states('sensor.temperature1'),0.0), float(states('sensor.temperature2'),0.0), float(states('sensor.temperature3'),0.0), float(states('sensor.temperature4'),0.0), float(states('sensor.temperature5'),0.0), float(states('sensor.temperature6'),0.0), float(states('sensor.temperature'),0.0)] %}
{% with 
tt = 40,
tc = 20,
tlist = [(traw[0]+traw[1])/2, (traw[1]+traw[2])/2, (traw[2]+traw[3])/2, (traw[3]+traw[4])/2, (traw[4]+traw[5])/2, (traw[5]+traw[6])/2],
vlist = [32.7, 34.4, 34.4, 34.4, 34.4, 32.7],
vt=0
%}
{% if tlist[0] > tt -%}
  {%- set i=0 -%}
  {%- set v=(tlist[i]*vlist[i]-tt*vlist[i])/(tt-tc) + vlist[i] -%}
  {%- set vt=vt+v -%}
  {%- set i=1 %}
  {%- if tlist[i] > tt -%}
    {%- set v=(tlist[i]*vlist[i]-tt*vlist[i])/(tt-tc) + vlist[i] -%}
    {%- set vt=vt+v -%}
    {##,v{{i}}={{v}}##}
    {%- set i=2 %}
    {%- if tlist[i] > tt -%}
      {%- set v=(tlist[i]*vlist[i]-tt*vlist[i])/(tt-tc) + vlist[i] -%}
      {%- set vt=vt+v -%}
      {##,v{{i}}={{v}}##}
      {%- set i=3 %}
      {%- if tlist[i] > tt -%}
        {%- set v=(tlist[i]*vlist[i]-tt*vlist[i])/(tt-tc) + vlist[i] -%}
        {%- set vt=vt+v -%}
        {##,v{{i}}={{v}}##}
        {%- set i=4 %}
        {%- if tlist[i] > tt -%}
          {%- set v=(tlist[i]*vlist[i]-tt*vlist[i])/(tt-tc) + vlist[i] -%}
          {%- set vt=vt+v -%}
          {##,v{{i}}={{v}}##}
          {%- set i=5 %}
          {%- if tlist[i] > tt %}
            {%- set v=(tlist[i]*vlist[i]-tt*vlist[i])/(tt-tc) + vlist[i] -%}
            {%- set vt=vt+v -%}
            {##,v{{i}}={{v}}##}
          {%- endif %}
        {%- endif %}
      {%- endif %}
    {%- endif %}
  {%- endif %}
{%- endif %}
{{vt|round(1)}}
{#
traw={{traw}}
tlist = {{tlist}}
vlist = {{vlist}}
#}
{% endwith %}
{% endwith %}"

Might look kind of scary. Not intended to be a code obfuscation competition. Sorry that there aren’t any comments, and there are a few bits of debugging helpers in there.

Basic principle is this:
Define the target temperature, in my case tt=40 (degC)
Define the cold water temperature, in my case tc=20 (degC)

Break up the tank into a series of volumes, with a sensor at the top and bottom of each of them. In my case with 7 sensors, that’s 6 sections, hemispheres at top and bottom, then 4 cylinders in between.

Estimate the geometric volume of each of these in litres (independently using a spreadsheet) and put those into a list (vlist)
Read off the 7 sensor values, and estimate the average temperature of each section using the mean of the top and bottom sensor of that section (tlist).

By this point you have a list of 6 volumes and a list of 6 temperatures.

Now the aim is to calculate section by section (counting down since the tank empties from the top), how much water at could be made at tt degC by mixing that section’s volume of water at that section’s temperature with tc degC water. To do this you use Richmann’s calorimetric mixing formula, to get the amount of cold water you need to add, then add the volume of that section. Adding to a running total vt

Keep doing this section by section, until you find a section that is a lower temperature than tt. At that point you assume that this water is useless (since it’s impossible to mix it with cold water to make it reach tt), then stop.

Then the total volume vt is the accumulated hot water you could make from the tank.

Example: There was some sun (free solar electricity) today but not much. An automation triggered the electric heater a bit but not enough to get any ‘section’ of the tank above 40C. Then later in the day we boosted the water using the gas boiler, which got us up to approx 190L of virtual 40C water.

Displaying number of baths/showers is not shown here (I have that on a separate ESPHome display panel in the house)
My advice: overestimate on your bath/shower volume for the calculation to maximise the WAF.

3 Likes

Can you share the details on “Sonoff Switch, flashed with TASMOTA”? I have local monitoring on the tank, using those little £5 temperature displays, but would like to integrate into HA.

I did something similar then realised that I could get away with just one Dallas temperature sensor connected to the water heater relief line which is about two thirds the way up the tank. The measured temperature at this point is less than it is inside the tank at that point but I found though trial and error that it gave a good indication of the stored heat capacity. I used a gauge card as below with the red/gold/green bands set at 0/25/40 for low/moderate/high capacity.

image

My water heater is electric and comes on before 07:00 when the cheap tariff ends.

On the small graph the large drops represent high usage periods such as baths/showers and the ramp increase is when the water heater comes on. Outside these periods the temperature slowly reduces due to heat losses.

I am using a Shelly 1PM to control the water heater and read the temperature:

image

2 Likes

A good option that I use is ESPHome. I used this guide, only with 6 sensors, to monitor my electric water heater. EPSHome is integrated in HA, i use this to control an Aeotec heavy duty switch connected on the water heaters power input. https://smarthomescene.com/diy/diy-waterproof-double-probe-temperature-sensor-with-an-esp32/

hey hey, saw this and love it - i am hoping to replicate it somewhat, however this is well beyond my knowledge base. I run home assistant on a Rpi, and have an ESPhome 8266 with 5 (the 6th died) Dallas sensors connected to my water tank to monitor what’s there - I’d love to be able to able to show this pictorially on my dashboard or any other smart devices around the house.

So the question is - how to I begin? Any help would be hugely appreciated.

Is your hot water litres remaining yaml on the home assistant side, or esp side? where do i configure the size of my tank? how do i manage to turn that info into a pretty tank picture…

i may have bitten off more than i can chew :rofl:

Hi Craig,

That jinja template sits on home assistant, but could be on the esp side instead in theory, I’ve just never tried it. You can play with the formula and see the result by pasting the above code into the template testing developer tab in HA.

The size of the tank is configured via the vlist variable in the YAML above, it’s a list of sizes in litres, effectively slicing your tank horizontally at each sensor, each size is listed in order from top to bottom. These are not calculated for you, I did them separately on a spreadsheet using geometric hemisphere and cylinder volume formulae.

The cgi script is linked from the GitHub repo above which also has a more complete description, which you should read even if not creating the LCD visualisation. CGI script (python) is here:

Instructions are in the top of the file.
It needs a web server with python enabled, this could maybe be done in an addon, but I did it via a separate raspberry pi that I happened to have already running.
A way more sensible way would be to implement a custom card within HA but I’ve not done that so far.

I would say this is fairly advanced and requires quite a bit of patience to get a good result, rather than copy and paste a few snippets of YAML.

Hopefully this helps!

Dave, thanks so much for the reply! Finally got a bit of time today to tinker with it… I am getting there slowly. Very slowly. I’m still struggling with the jinja template. The more I play with it the more I get lost.

So, I have calculated the volume of the water tank and each individual section - I can see where to alter that. I’m struggling with changing it from a 7 sensor setup to my 5. Renaming the available sensors I have, no problemo - but when removing 2 sensors I am brought up with

UndefinedError: list object has no element 5

I keep playing around with the rest, I’m assuming there are another few blocks I should be removing, but it’s beyond me… any chance I could plead for some more help?

The latter part I have got sorted, like yourself I have a 2nd Pi running another project, thanks for that!

edit: I think I have it! Just going to wait for the water to kick in tonight and hope i see some figures :slight_smile:

Dave, I think I am on the home stretch… I’m having trouble viewing the image on localhost - I’m guessing that particular folder isn’t natively open to apache2? Or am I barking up the wrong tree?

Everything else seems to be working for me now, everything is where it should be - just this last hurdle to overcome…

Once again, any help would be hugely appreciated!

You should be able to view the generated images in a web browser by adding sample temperatures to the URL.

You need to have the script in a folder that apache2 will run, not just display (usually cgi-bin), and python needs to be set up in apache2. Localhost means the local machine (127.0.0.1), so to test it you’ll need to replace that bit of the url with the apache2 machine network name or IP.

have done that, i can see the test pages generated by apache2 on the local machine without issue, but anything in the cgi-bin (or anywhere else) comes up with an internal server error?