Enviro: Humidity readings seem to be much to low

Hi there,

I found several older topics concerning strange readings from the BME280-sensor due to the influence of the CPU-Temperature. The Python examples do contain code to compensate for this effect and if I tweak the compensation factor I get fairly good values for the temperature.
However humidity is a different affair. I can’t get any decent readings, all values are far to low. I found some code in the weather-and-light.py example which tries to compensate for CPU temperature and uses the compensated temperature:

def correct_humidity(humidity, temperature, corr_temperature):
    dewpoint = temperature - ((100 - humidity) / 5)
    corr_humidity = 100 - (5 * (corr_temperature - dewpoint))
    return min(100, corr_humidity)`

However, this code looks like guesswork to me and doesn’t produce correct values either. In aforementioned older topics I found several ideas for workarounds but no hint on how to do a simple compensation within the code. Maybe someone has an idea here, would be nice to use a small fleet of pi zeroes to measure room climate and collect the data.

Hi,
I started with Enviro+ end of last year and also got deviations.
According Wikipedia the relative humidity of an air-water mixture is defined as
the ratio of the partial pressure of water vapor in the mixture to the equilibrium vapor pressure of water
over a flat surface of pure water at a given temperature.

Vapor pressure is an exponential funktion of temperature and therefore also relative humidity.

I add to the weather example the correction. I test it together with the “Enviro + Air Quality” directly connected to a Pi Zero WH and alternatively connected to an GPIO extension of a Pi 400. Applying the corrections the deviation from an calibrated hygrometer was 1% humidity, within the tolerance of ±3% accuracy of the sensor.

Here the listing


#!/usr/bin/env python3

import time
import math as m    # add math to allow exponential function
from bme280 import BME280

try:
    from smbus2 import SMBus
except ImportError:
    from smbus import SMBus

import logging

logging.basicConfig(
    format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
    level=logging.INFO,
    datefmt='%Y-%m-%d %H:%M:%S')

logging.info("""weather.py - Print readings from the BME280 weather sensor.

Press Ctrl+C to exit!

""")

bus = SMBus(1)
bme280 = BME280(i2c_dev=bus)


# Get the temperature of the CPU for compensation
def get_cpu_temperature():
    with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
        temp = f.read()
        temp = int(temp) / 1000.0
    return temp

# According Wikipedia the relative humidity of an air-water mixture is defined as
# the ratio of the partial pressure of water vapor in the mixture to the equilibrium vapor pressure of water
# over a flat surface of pure water at a given temperature
# The reading of humidy from sensor is at raw_temp. When we correct the temperature we must als correct the humidy
# by the ratio of equilibrium vapor pressure at raw_temp and reported temperature

#Antoinconstants for Water to calculate vapor pressure or boiling temperature
AntA=18.88579     # pressure in hPa
AntB=-3994.017
AntC=233.874      # Temperature in °C

# Calculate vapor pressure at T of water using Antoine equation
def pvap(T):
    pv=m.exp(AntA+(AntB/(T+AntC)))
    return pv
# Calculate boiling temperature of water using Antoine equation
def tboil(pres):
    tboil=AntB/(m.log(pres)-AntA)-AntC
    return tboil
    
# Tuning factor for compensation. Decrease this number to adjust the
# temperature down, and increase to adjust up
# factor = 2.25 for enviro mounted directly on pi-zero
factor = 12    # value for enviro mounted at an pi400 GPIO extension


cpu_temps = [get_cpu_temperature()] * 5

while True:
    cpu_temp = get_cpu_temperature()
    # Smooth out with some averaging to decrease jitter
    cpu_temps = cpu_temps[1:] + [cpu_temp]
    avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
    raw_temp = bme280.get_temperature()
    temperature = raw_temp - ((avg_cpu_temp - raw_temp) / factor) #compensated temperature
    pressure = bme280.get_pressure()
    raw_humid = bme280.get_humidity()
    dew_point = tboil(raw_humid / 100 * pvap(raw_temp)) # humid is in %, devide by 100 to get factor 
    humidity = raw_humid * pvap(raw_temp) / pvap(temperature) # compensate hum. by ratio of the vapor pressure at Temperatures
    logging.info("""Pressure: {:05.2f} hPa  Temperature: {:05.2f} *C  Humidity: {:05.2f} %
Raw-Temp: {:05.2f} *C Raw-Humid: {:05.2f} %  dew_point: {:05.2f} *C
""".format(pressure, temperature, humidity, raw_temp, raw_humid, dew_point))
    time.sleep(1)


I also add the dew_point, a value that is related to the absolute humidity (g Water per m³ air).
Good look with your setup - Use the correct tuning factor for temperature compensation.

Thanks for the code, I will test this sooner or later. Right now I settled with GPIO-Extension-Ribboncables. The values look good so far, but it is not the nicest of setups …