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.

Thanks in advance, Robert

My Bad.

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

I am happy to post more info if anyone is interested.

Please do.

OK

I hope this helps…

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

wifi:
  ssid: '---'
  password: '---'

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"
    address: 0x76
    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
    address: 0x77
    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
    address: 0x76
    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