Mopeka integration
Template sensor calc for 500 gallon tank based on xls calc found in the included link. Just converted to HA format with some math reduction. Hopefully save others some time. I have only spot checked at my current level. App reads 49% and this calced to 48.74%. If your horizontal tank is different use the xls sheet and copy over the new needed constants.
template:
- sensor:
- name: propane_house_tank_percentage
unit_of_measurement: "%"
state: >
{% set h = (states('sensor.propane_house_tank_level') | float - 0.25) / 12 %}
{# vp = in propane - bottom thick / 12(conv ft) #}
{% set vp= (pi * h ** 2/3) * (4.625 - h) + 6.8333*(2.37673611*acos((1.54166-h)/1.54166)-(1.54166-h)*sqrt(3.08333*h-h**2)) %}
{# propane volume = reduction with h calc from https://github.com/home-assistant/core/issues/87122 #}
{% set vt = 66.37099 %}
{{ ((vp / vt) * 100) | round(2) }}
Has anyone been able to convert this into a cubic meter for usage in the energy dashboard?
For others searching this thread a 30lb vertical tank: min is 1.5in and max is 15in and the multiplier for this sensor is 7.4074.
Also, after filling a tank this sensor formula can result in a percentage greater than 100%. To fix, add the min
filter using brackets around the array as shown below.
{{ [ ((states('sensor.propane_tank_level') | float(1.5) - 1.5) * 7.4074) | round(0), 100] | min }}
Does anyone take the tank temperature into account when calculating the percentage? The apparent volume of propane changes with temperature swings so just using a constant will work as long as your temp is stable, but where I live we can have a 40 degree F swing between low and high temps. Iāve looked for the formula but havenāt had much luck in anything that works.
Terry
Iām curious about this also. Without taking temperature into account, I canāt properly determine consumption due to the swings you mention.
I donāt think youāll ever be able to use one of these sensors and get a reliable consumption value (unless youāre using a LOT of propane). I also donāt think itās simply due to temperature swings, as I see a reasonable bit of noise and general variation in the values all the time. But for having a pretty accurate value of fill level, it works fantastic.
the reading variation can be softened using trend or filter sensors for the most part. still, the fill percentage varies too much each day w/ temperature that filtering/trending wonāt work. iām tempted to figure out a way to keep estimate consumption between peaks, since i rarely see a peak exceeding a previous one. check it out percentage vs temp
Using the constant appears to match the Mopeka app throughout the usage of the tank. That is likely what most users would expect to see when checking their custom sensor and close enough for me even though it fluctuates slightly with temperature as Iām really only concerned with when Iām nearly out of propane and need to take action.
Seems like you might be able to use a derivative sensor to determine your consumption rate with a few different values in the āTime Windowā field to see what smooths it out best. Using the ātank percentageā sensor as I have in my screenshot would show you x% / hour consumption.
I imagine you are looking to take it a step further and estimate āhow much time until I run out of propane?ā For that, there are several different forums posts on battery consumption rates and energy remaining (usually for solar batteries) that seem like they could be modified to work for propane.
For those looking to create one through the GUI:
Settings ā Devices & Services ā Helpers ā Create Helper ā Derivative sensor
I was pretty unhappy with the rudimentary calculations for vertical tanks provided above, so I threw together this customizable template (These are numbers for a 20lb tank, but can be adjusted for any dimension tank you want) for vertical tanks:
{# User supplied variables. Use the same units that the mopeka sensor is configured to report.
I use mm by default (better resolution from the sensor #}
{% set side_length = 203.0 %}
{% set tank_diameter = 304.0 %}
{% set wall_thickness = 3.175 %}
{% set measured_fill_depth = states('sensor.propane_tank_level') | float - wall_thickness%}
{% set R_tank = tank_diameter / 2 %}
{% set H_tank = side_length + R_tank %}
{# A 2:1 Ellipsoid has a c value that is half of its a/b values. A and B are the radius of the tank #}
{% set E_a = R_tank %}
{% set E_b = R_tank %}
{% set E_c = R_tank / 2 %}
{# Vertical tanks are a cylinder capped on either end with half of a 2:1 ellipsoid https://www.vcalc.com/wiki/vCalc/Ellipsoid-Volume #}
{# Calculate max tank volume in mm^3 #}
{% set hemi_ellipsoid_volume = 2 / 3 * pi * E_a * E_b * E_c %}
{% set cylinder_volume = side_length * pi * R_tank**2 %}
{% set max_volume = 2 * hemi_ellipsoid_volume + cylinder_volume %}
{# Fill volume is dependent on which region of the tank the level is in. #}
{# Create a piecewise function which regions for bottom ellipsoid, middle cylinder, or top ellipsoid #}
{% if 0 <= measured_fill_depth and measured_fill_depth <= E_c %}
{# The region where the fill level is in the bottom ellipsoid can be calculated using the volume
for an elipsoidal cap. https://www.vcalc.com/wiki/ellipsoid-cap-volume #}
{% set measured_fill_volume = pi * E_a * E_b * ((2/3 * E_c) - E_c + measured_fill_depth + ((E_c - measured_fill_depth)**3/(3 * E_c**2))) %}
{% elif E_c <= measured_fill_depth and measured_fill_depth <= E_c + side_length %}
{# The region where the fill level is in the middle cylinder can be calculated using the volume
of the bottom ellipsoid plus the filled volume of the cylinder #}
{% set measured_fill_volume = hemi_ellipsoid_volume + (measured_fill_depth - E_c) * pi * R_tank**2 %}
{% elif E_c + side_length <= measured_fill_depth and measured_fill_depth <= H_tank %}
{# The region where the fill level is in the top ellipsoid can be calculated by subtracting the volume
of an elipsoidal cap that has a height of the height of the tank minus the fill level.
https://www.vcalc.com/wiki/ellipsoid-cap-volume #}
{% set measured_fill_volume = max_volume - (pi * E_a * E_b * ((2/3 * E_c) - E_c + H_tank - measured_fill_depth + ((E_c - H_tank + measured_fill_depth)**3/(3 * E_c**2)))) %}
{% else %}
{# All other ranges are invalid, set measured_fill_volume to a value that will result in the template returning -1 #}
{% set measured_fill_volume = -max_volume / 100 %}
{% endif %}
{{ (100 * measured_fill_volume / max_volume) | round(1) }}
I also created a similar configurable template for horizontal tanks.These are numbers for a 500 gal tank, but can be adjusted for any dimension tank you want:
{# User supplied variables. Use the same units that the mopeka sensor is configured to report.
I use mm by default (better resolution from the sensor #}
{% set overall_length = 3022.6 %}
{% set overall_tank_diameter = 952.5 %}
{% set wall_thickness = 6.35 %}
{% set internal_tank_diameter = overall_tank_diameter - 2 * wall_thickness %}
{% set side_length = overall_length - overall_tank_diameter %}
{% set measured_fill_depth = states('sensor.propane_tank_level') | float - wall_thickness %}
{% set R_tank = internal_tank_diameter / 2 %}
{# Horizontal tanks are a cylinder capped on either end with hemispheres #}
{# calculate max tank volume in mm^3 #}
{% set spherical_volume = 4 / 3 * pi * R_tank**3 %}
{% set cylinder_volume = side_length * pi * R_tank**2 %}
{% set max_volume = spherical_volume + cylinder_volume %}
{# Calculate the volume of a spherical cap of height equal to the fill level: https://www.vcalc.com/wiki/Volume-of-a-Sphere-Cap #}
{% set fill_spherical_volume = pi / 3 * measured_fill_depth**2 * (3 * R_tank - measured_fill_depth) %}
{# Calculate the volume of a partial horizontal cylinder: https://www.vcalc.com/wiki/volume-of-horizontal-cylinder #}
{% set fill_cylinder_volume = side_length * (R_tank**2 * acos((R_tank - measured_fill_depth) / R_tank) - (R_tank - measured_fill_depth) * sqrt(2 * R_tank * measured_fill_depth - measured_fill_depth**2)) %}
{% set measured_fill_volume = fill_spherical_volume + fill_cylinder_volume %}
{{ (100 * measured_fill_volume / max_volume) | round(2) }}
Just make sure you enter your user dimensions in the same unit as your sensor is configured or it will not work correctly.
iāll try this, but anytime iāve used a derivative sensor (like electrical energy), if thereās a decrease in the data, then the subsequent increase will make the sensor go nuts. like double the consumption. hope this makes sense the way iām explaining.
i did a quick implementation. your measurements are same as mine with a x25.4 to convert from mm to in (like the sensor). my calculation is much simpler:
{% set full_height = 90 %}
{{ (states('sensor.house_gas_tank_monitor_tank_level')|float(0) / (full_height|float(0) / 2.54) * 100) | round(1) }}
i derived the ā90ā from the sensor when the fill was 58% at 20.7" (20.7/58%x2.54=90ish)
i think your method is a lot more precise for volume and note a delta of ~5.5% between mine and your method. iāll keep monitoring. thanks for thisā¦
Yeah, mine is going to be the exact fill volume.
The linear level based approach described (which is basically assuming that your tank is a rectangle. will become more inaccurate the further you get from the mid level of the tank (Iām assuming youāre referring to a horizontal tank and not a vertical tank. Vertical tanks are a whole different beast)
You can see the effects of this by substituting static values in for your measured fill level. At 50% fill the two methods will be the same, but at 25% fill level your approach will be ~7% higher than the actual fill percentage and at 75% fill level it will be 7% lower.
not sure where I am going wrong hereā¦ I am getting a very āoffā percentage.
I put your code into a template sensor. Please correct me where I am wrongā¦
homeassistant:/config/entities/templates/mopeka# cat house_500gal_2.yaml
- sensor:
- name: "House 500gal Tank Percentage 2"
unit_of_measurement: "%"
state: >
{# User supplied variables. Use the same units that the mopeka sensor is configured to report. #}
{# I use mm by default (better resolution from the sensor #}
{% set overall_length = 3022.6 %}
{% set overall_tank_diameter = 952.5 %}
{% set wall_thickness = 6.35 %}
{% set internal_tank_diameter = overall_tank_diameter - 2 * wall_thickness %}
{% set side_length = overall_length - overall_tank_diameter %}
{% set measured_fill_depth = states('sensor.house_500gal_tank_level') | float - wall_thickness %}
{% set R_tank = internal_tank_diameter / 2 %}
{# Horizontal tanks are a cylinder capped on either end with hemispheres #}
{# calculate max tank volume in mm^3 #}
{% set spherical_volume = 4 / 3 * pi * R_tank**3 %}
{% set cylinder_volume = side_length * pi * R_tank**2 %}
{% set max_volume = spherical_volume + cylinder_volume %}
{# Calculate the volume of a spherical cap of height equal to the fill level: https://www.vcalc.com/wiki/Volume-of-a-Sphere-Cap #}
{% set fill_spherical_volume = pi / 3 * measured_fill_depth**2 * (3 * R_tank - measured_fill_depth) %}
{# Calculate the volume of a partial horizontal cylinder: https://www.vcalc.com/wiki/volume-of-horizontal-cylinder #}
{% set fill_cylinder_volume = side_length * (R_tank**2 * acos((R_tank - measured_fill_depth) / R_tank) - (R_tank - measured_fill_depth) * sqrt(2 * R_tank * measured_fill_depth - measured_fill_depth**2)) %}
{% set measured_fill_volume = fill_spherical_volume + fill_cylinder_volume %}
{{ (100 * measured_fill_volume / max_volume) | round(2) }}
ā¦and if I use this formula, I get something much closer
homeassistant:/config/entities/templates/mopeka# cat house_500gal.yaml
- sensor:
- name: "House 500gal Tank Percentage 1"
unit_of_measurement: "%"
state: >
{% set h = (states('sensor.house_500gal_tank_level') | float - 0.25) / 12 %}
{# vp = in propane - bottom thick / 12(conv ft) #}
{% set vp= (pi * h ** 2/3) * (4.625 - h) + 6.8333*(2.37673611*acos((1.54166-h)/1.54166)-(1.54166-h)*sqrt(3.08333*h-h**2)) %}
{# propane volume = reduction with h calc from https://github.com/home-assistant/core/issues/87122 #}
{% set vt = 66.37099 %}
{{ ((vp / vt) * 100) | round(2) }}
How would you format a template sensor for the Mopeka Pro Universals that can measure things other than propane? For instance I have a 6 gallon marine fuel tank that is hooked up to my diesel heater. Using the Mopeka app I can set the tank to be āArbitraryā and just input the fuel height at the full mark. For me this is 7in when full. Works great in the app, but how do I translate this to HA?
Could anyone provide the calculation for a 250 gallon horizontal tank, please?
Iāve running both sensors for about 3 weeks. i agree that your calculations should be more accurate - makes sense. 3 weeks ago i was reading 43% (my quick method) vs 37% (your more precise method). this is consistent in approach that 7-8% discrepancy you mention. 3 weeks later the readings are 31% vs 23%. but whatās interesting is that 31% is close to the mechanical pressure dial, which is reading ~30%. any idea why? or is the dial just an artifact of the pressure and doesnāt really reflect the actual volume? in any case, i was instructed to call for a fill at ~25%. iām getting close to that.
check out this table:
then you can modify @jrhelbert 's post above (the horizontal tank equation) with the appropriate size for a 250gal
Thanks so much to both of youā¦ this worked great! In case it might help someone else, hereās the template sensor state for a 250 gallon horizontal tank when Mopeka reports depth in inches. Just make sure you change sensor.propane_tank_level to whatever entity that it will listen to for readings:
{# Set three user supplied variables. Use the same units that the mopeka sensor is configured to report.
I am using inches here #}
{% set overall_length = 94.00 %}
{% set overall_tank_diameter = 30.00 %}
{% set wall_thickness = 0.25 %}
{% set internal_tank_diameter = overall_tank_diameter - 2 * wall_thickness %}
{% set side_length = overall_length - overall_tank_diameter %}
{% set measured_fill_depth = states('sensor.propane_tank_level') | float - wall_thickness %}
{% set R_tank = internal_tank_diameter / 2 %}
{# Horizontal tanks are a cylinder capped on either end with hemispheres #}
{# calculate max tank volume in mm^3 #}
{% set spherical_volume = 4 / 3 * pi * R_tank**3 %}
{% set cylinder_volume = side_length * pi * R_tank**2 %}
{% set max_volume = spherical_volume + cylinder_volume %}
{# Calculate the volume of a spherical cap of height equal to the fill level: https://www.vcalc.com/wiki/Volume-of-a-Sphere-Cap #}
{% set fill_spherical_volume = pi / 3 * measured_fill_depth**2 * (3 * R_tank - measured_fill_depth) %}
{# Calculate the volume of a partial horizontal cylinder: https://www.vcalc.com/wiki/volume-of-horizontal-cylinder #}
{% set fill_cylinder_volume = side_length * (R_tank**2 * acos((R_tank - measured_fill_depth) / R_tank) - (R_tank - measured_fill_depth) * sqrt(2 * R_tank * measured_fill_depth - measured_fill_depth**2)) %}
{% set measured_fill_volume = fill_spherical_volume + fill_cylinder_volume %}
{{ (100 * measured_fill_volume / max_volume) | round(2) }}