# How to do maths in sensor template with esphome on hassio?

Hi, I have not been using Home Assistant for long and have been enjoying using esphome to make my own sensors. I have a BME680 sensor and have used the example at https://esphome.io/cookbook/bme280_environment.html to help me to learn the programming as I am new to yaml and c++.

The example calculates “absolute humidity” using the following equation:

`````` return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) /
(id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) /
((273.15 + id(bme280_temperature).state) * r); // in grams/m^3
``````

so I have adapted the variable names a bit in my project, and I want to have the “dew point” calculated using the equation at https://planetcalc.com/248/.

I am having a problem because the compiler errors on the log function:

``````src/main.cpp:639:46: error: invalid operands of types 'esphome::template_::TemplateSensor*' and 'float' to binary 'operator+'
return ( (b *(dpinter + logf (rh->state)) )/( a - (dpinter + logf (rh->state)) ) );
``````

I have been told I should include the math.h library but am not sure how.

Can some please tell me how to do this - I assume I have to download it from somewhere?

I can provide more info if needed, but have tried to keep the posting short.

I am now calculating the dew point successfully. The necessary functions are available. I did not understand the error message when I posted.

OK

I hope this helps…

``````esphome:
name: ringlight
platform: ESP8266
board: d1_mini
esp8266_restore_from_flash: true

wifi:
ssid: '---'

i2c:
sda: D2
scl: D1

sensor:
- platform: bme680
temperature:
name: "BME680 Temperature"
id: temp
oversampling: 16x
filters:
- offset: -2.8  // odd, but mine was wrong!!
- multiply: 1.0
pressure:
name: "BME680 Pressure"
id: press
unit_of_measurement: "mbar"
filters:
- offset: 8.5  // odd, but mine was wrong!!
- multiply: 1.0
humidity:
name: "BME680 Humidity"
id: rh
gas_resistance:
name: "BME680 Gas Resistance"
update_interval: 15s
heater:
temperature: 200
duration: 0ms

- platform: uptime
name: "ringlight Uptime"

- platform: wifi_signal
name: "ringlight WiFi Signal"
update_interval: 15s

- platform: template
name: "BME680 Absolute Humidity v1"
unit_of_measurement: "g/m^3"
lambda: |-
const float mw = 18.01534;    // molar mass of water g/mol  from bme280 sample in esphome
const float r = 8.31447215;   // Universal gas constant J/mol/K
return (6.112 * powf(2.718281828, (17.67 * id(temp).state) /
(id(temp).state + 243.5)) * id(rh).state * mw) /
((273.15 + id(temp).state) * r); // in grams/m^3
accuracy_decimals: 2
update_interval: 15s

- platform: template
#    name: "BME680 Sat Vap Press"
id: satvappress
unit_of_measurement: "mbar"
lambda: |-
return ( (6.112 * powf(2.718281828, (17.62 * id(temp).state) / (id(temp).state + 243.12)) ) * (1.0016 + (3.15 * powf(10, -6) * id(press).state) - (0.074/id(press).state)) );
accuracy_decimals: 2
update_interval: 15s

- platform: template
name: "BME680 Absolute Humidity"
unit_of_measurement: "kg/m^3"
lambda: |-
const float rv = 461.40000;   // const for water from plantecalc.com/2167
return ( (id(satvappress).state * 100 * id(rh).state/100 ) / ( (273.15 + id(temp).state) * rv) ); // in kg/m^3
accuracy_decimals: 4
update_interval: 15s

- platform: template
name: "BME680 Dew Point"
unit_of_measurement: "°C"
lambda: |-
const float a = 17.27;   // const from https://planetcalc.com/248/
const float b = 237.7;   // const from https://planetcalc.com/248/
return ( (b * ( (id(temp).state * a) / ( b + id(temp).state) + logf (id(rh).state/100) ) )/( a - ( (id(temp).state * a) / ( b + id(temp).state) + logf (id(rh).state/100) ) ) );
accuracy_decimals: 4
update_interval: 15s
``````
10 Likes

It helps, thank you.

This is very interesting and quite an eye opener for me. Did you by any chance try to convert the air pressure at your location to something like QNH? I have done it easily with an RPi but never got around to doing any mathematical functions like you have done because I didn’t know it could be done.

You can do most things with a lambda which is c++. Have a look at following which is not the answer but a flavour. I don’t bother, because I am at sea level. Well just above MHW!

1 Like

Nott that relative pressure is (still) wrong on Esp’shome page for BME280.
BME280’s absolute pressure output has already temperature taken into account, so having it in relative pressure formula again is wrong. I wrote about that years ago and i’m really surprised that noone seems to notice or care…
When i used that formula my relative pressure changed quite a bit from (colf) morning, through (warm) day and into the (again colder) night, although absolute pressure was the same all along ( also compared with high quality device, and with local official weather station’s data)

1 Like

I have mainly been interested in humidity stuff and have found that there is often considerable variation between different sensors. I am located 85m above sea level, am not a pilot, and only just googled QNH.

2 Likes

Thanks for the response. I have a BMP388 and am trying that. My elevation is 574 meters but it was a few hPa out so I used 600 meters for elevation. I will let it run for a few days and keep track of the QNH as we have an airport about 30 kms away that reports it. I had to fiddle with the figures in my Python code on the RPi so it looks similar to that.

I use this code for relative pressure - it’s a formula, taken from BME180 datasheet. On later datasheets it was for some reason removed (but it still works):

``````  - platform: bmp3xx
temperature:
name: "Temperature outside"
oversampling: 16x
pressure:
name: "Absolute pressure outside"
id: abs_pressure
update_interval: 60s

- platform: template
name: "Relative pressure outside"
icon: "mdi:gauge"
lambda: |-
const float STANDARD_ALTITUDE = 315; // in meters, see note
return (id(abs_pressure).state)/powf((1-((float)(STANDARD_ALTITUDE))/44330), 5.255);
update_interval: 60s
unit_of_measurement: 'hPa'
accuracy_decimals: 0
``````

Thanks. I used your version (without temp) and used my altitude and it is only out less than a hPa (around 0.6 hPa and I am about 25 km from the airport). The other version was not so good and it was out by a few hPa.

1 Like

Hi, these lambdas worked perfectly for me with my bme280. With the newest version and switching to bmw280_i2c I get the following compilation errors. What else needs to be changed to get the lambdas working again?

``````  - platform: bme280_i2c
temperature:
name: "BME280 Temperature"
id: bme280_temperature
pressure:
name: "BME280 Pressure"
id: bme280_pressure
humidity:
name: "BME280 Humidity"
id: bme280_humidity
update_interval: 300s
``````
``````/config/esphome/ble-tracker.yaml: In lambda function:
/config/esphome/ble-tracker.yaml:140:65: error: 'class esphome::bme280_i2c::BME280I2CComponent' has no member named 'state'; did you mean 'update'?
(id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) /
^~~~~
update
/config/esphome/ble-tracker.yaml: In lambda function:
/config/esphome/ble-tracker.yaml:149:43: error: 'class esphome::bme280_i2c::BME280I2CComponent' has no member named 'state'; did you mean 'update'?
return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/
^~~~~
update
/config/esphome/ble-tracker.yaml:150:71: error: 'class esphome::bme280_i2c::BME280I2CComponent' has no member named 'state'; did you mean 'update'?
(243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)-
^~~~~
update
``````

Taking a detailed look at my own post, I found the problem. It’s just a formatting error, the bme280_humidity was not indented correctly. Mea culpa

``````    humidity:
name: "BME280 Humidity"
id: bme280_humidity
``````