# Converting a value to a percentage

Hi all!

I have a DIY electric motorbike, which runs a custom BMS system. It pings the pack voltage via MQTT when charging to HA.

The sensor config is as follows

• platform: mqtt
name: ‘3Fazer - Voltage’
state_topic: ‘ev/3fazer’
unit_of_measurement: 'V

I would like to convert this voltage to battery charge % if possible inside HA.

100% is 116.2V
0% 95.2V

The battery drain is more or less linear. Any assistance on how I can do this would be much appreciated. as always.

Have you considered using a template sensor.

``````template:
- sensor:
- name: "battery_sensor"
unique_id: "Battery Sensor"
state: >-
{% set voltage = states('sensor.3fazer_-_voltage') | float(0) %}
{{ ((voltage - 95.2) / 0.21) | int }}
``````

This will give you the % in a truncated integer.

Thank you so much, worked perfectly.

You don’t need a template sensor. The MQTT sensor supports a value template.

``````- platform: mqtt
name: '3Fazer - Voltage'
state_topic: 'ev/3fazer'
value_template: "{{ ((value|float(0) - 95.2) / 0.21)|round(0) }}"
unit_of_measurement: '%'
``````

Also using `|int` truncates the decimal, where as `|round(0)` will round to the nearest whole number.

e.g.

``````70.99|int = 70
70.99|round(0) = 71
``````
1 Like

Also thanks! I did like the seperation so I can monitor voltage as well.

Updated it to use round vs int and that has correct it showing 99% vs 100% at full charge. Thanks

Hi @tom_l

Possibly kind of dumb question - how did you get the value of ‘0.21’ in the example above?

I have a sensor where I measure mm, and want to find the percentage where min are 100 mm and max are 500 mm…?

From this data:

If given two points (x1,y1) (x2,y2) you can work out the equation for the line that passes through them:

y = mx + c

https://content.byui.edu/file/b8b83119-9acc-4a7b-bc84-efacf9043998/1/Math-2-11-2.html

So your two points (0%, 100mm) and (100%, 500mm) gives:

y = 0.25*x - 25

or

% full = 0.25*(x in mm) - 25

1 Like

Damn, @tom_l
Thanx !

@tom_l

I was thinking wrong;

My sensor range are 100 mm (full) to 500 mm (empty) to monitor a water tank.
In my case, when the `states(sensor.water_level)` = 100, it should show 100% and opposite, when at 500 it should show 0%.

How on earth should I calculate this?

To make it worse, I wanted to put this into a gauge. It worked well until I realized it was all opposite… duh…

Are you able to help on this?

Exactly the same way as in the link I provided above.

`%full = -0.25*(x in mm) + 125`

Could you please show me how you calculated the numbers?
Sorry, advanced math ain’t my strong side, I do electronics and ESP32 stuff (using a TOF to measure the distance to the water level)

I am using slider (input_number) as the min & max can change (different tanks to monitor).
Initially I resolved it differently:

``````        state: >-
{% set fill = states('sensor.tof_poc') | float(0) %}
{% set min = states('input_number.mm_min') | float(0) %}
{% set max = states('input_number.mm_max') | float(0) %}
{{ (((fill - min) * 100) / (max-min)) | round(0) }}
``````

How am I going to put that advanced calculation - even the other way where 100 mm = 100% and 500 mm = 0%? And even bring into consideration the input sliders where min and max can change?

Think I’m about to give up this route and look for something else…

I did. Watch the video in the link I posted. It’s high school maths.

You cant use templates with it but it is easy to change the points config. Which really you should not have to once it is set up.

As a mental exercise for the points (0%, `input_number.mm_min`) and (100%, `input_number.mm_max`):

``````        state: >-
{% set distance = states('sensor.tof_poc') | float(0) %}
{% set x1 = states('input_number.mm_min') | float(0) %}
{% set x2 = states('input_number.mm_max') | float(0) %}
{% set m = 100 / (x2 - x1) %}
{% set c = 100 - (m * x2) %}
{{ distance * m  + c }}
``````

this will work for any values of `input_number.mm_min` and `input_number.mm_max`

1 Like

I actually got it with your example I’m passed 50, so I do not remember so much from math classes back in the days

Interesting part - if I changed

``````          {% set x1 = states('input_number.mm_min') | float(0) %}
{% set x2 = states('input_number.mm_max') | float(0) %}
``````

to

``````          {% set x1 = states('input_number.mm_max') | float(0) %}
{% set x2 = states('input_number.mm_min') | float(0) %}
``````

I get the reversed % where 100mm are 100% and 500 mm are 0%.

Thank you so much @tom_l

Um no. All you have to do is change the input number values in the frontend using the sliders.

input_number.mm_min = 100
and
input_number.mm_max = 500

or

input_number.mm_min = 500
and
input_number.mm_max = 100

Will both work the way you want them to. That was the whole point of using input numbers in the template, so you don’t have to change the template.

I noticed that straight away… playing with both scenarios
Need to make sure this way of calculating stick to my brain

Thats my config. Works perfectly. 0.1m = 100%, 1.1m=0%

``````sensor:
- platform: ultrasonic
trigger_pin: 27
echo_pin: 26
unit_of_measurement: "%"
accuracy_decimals: 0
name: "Lenti esoviz tartaly"
update_interval: 10s
filters:
- calibrate_linear:
- 0.1 -> 100
- 1.1 -> 0
``````

That appears to be ESPHome configuration. Not Home Assistant.