Weatherhat onboard BME280, elevated readings, external I2C Option

Hi -
I have my raspberry pi 3b+ with the Weatherhat attached fully working, but with one caveat:

The temperature is understandably higher than the ambient outdoor temp, but it’s random in how much it’s higher. I have them in a waterproof box under the eave of my deck, with an exhaust fan and vent holes in the case installed. Temps lowered a bit but are still sporadic in their elevation.

I know you can add external sensors to the hat,and I have an extenal BM280 I2C device on the way, but I’ve read that there’s a jumper I need to flip to disable the onboard so the external one is recognized.

I’ve not been able to find any pictures indicating the jumper (mine is currently inuse so can’t investigate). Any pointers?

Thanks!

You just need to make sure the one you add uses a different i2c address than the onboard one. The one on the hat is using 0x76

Thats done with the address select jumper on the back side of the BME280. Cut the track between the pads to change the address to 0x77

Then edit your code to use the 0x77 BME280.
It will end up being something like this.

from bme280 import BME280
sensor = BreakoutBME280(i2c,0x77)

Might have to go have a look at the BME280 examples for the complete code change needed.
If you get stuck post back and I’ll have a look see in my files and folders. I use a lot of these on Pi’s and PICO’s, and have used two at the same time. I have working code, just have to go find it, lol.

Found some code I have used in the past for indoor and outdoor readings (two BME280’s)

from bme280 import BME280

import smbus
try:
    from smbus2 import SMBus
except ImportError:
    from smbus import SMBus
bus = smbus.SMBus(1)

#bme_in = BME280(0x76)
#bme_out = BME280(0x77)

sensor = BME280(0x77)

Thanks for the info.

I bought a BME280 sensor from Amazon as I liked the weatherproof housing on it. It reports 0x76 is the address, which is in conflict with that on the Weatherhat.

I’m reticent to crack the thing open to see if there’s a trace I can break. Any options other than buying a different one and making a simple case for it?

On a Pico I would use the other I2C port. Are there 2 on a Pi? It’s so long since I used one as I prefer Picos for my current projects.

I2C0 - can be used as an alternate I2C bus, but is typically used by the system to read the HAT EEPROM.

I2C at Raspberry Pi GPIO Pinout

@Tonygo2 I’ve been redoing / replacing quite a few of my Pi builds with Pico equivalents.

Another option is to use an i2c multiplexer.
Adafruit PCA9546 4-Channel I2C Multiplexer - TCA9546A Compatible (pimoroni.com)

I just ordered one of those and a regular BME280. I’ll start with my current BME280 and the multiplexer and if that doesn’t work for some reason - I’ll go with the regular BME280.

I’ll report back for future inquiries.

I have a BME280 in a Stevenson Screen. We’ve had several torrential downpours the last few days that haven’t bothered it. Near as I can tell anyway, it’s still working and giving good readings. It’s mounted on the exterior of my house.

Weatherproof Cover/Enclosure for Outdoor Sensors (Stevenson Screen) (pimoroni.com)

Alright. I got the multiplexer installed with my original sensor connected and I get an I2C address of 0x70. Yay.

But I’m not sure where to put the BME code you referenced below. I’ve searched through the various .py files I’ve pulled down to no avail. Any pointers?

from bme280 import BME280
sensor = BreakoutBME280(i2c,0x77)

Look for a line in your current py file that says
sensor = BreakoutBME280(i2c)
then edit it so its
sensor = BreakoutBME280(i2c,0x70)

Or just post the code your using and I’ll have a look see.

I installed the Pimoroni Weather Hat as described here.

I’m using using Home Assistant and wanted to consume the data via MQTT, so I grabbed the code from the youtube vid here.

That code, which works A-OK, is here:

#!/usr/bin/env python3
from time import sleep
import weatherhat

import json
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish

sensor = weatherhat.WeatherHAT()
#sensor = weatherhat.BreakoutBME280(i2c,0x70)
# We can compensate for the heat of the Pi and other environmental conditions using a simple offset.
# Change this number to adjust temperature compensation!
OFFSET = -7.5

# We're using the Mosquitto HA add-on as our MQTT broker, other setups may vary!
mqtt_client = mqtt.Client()
mqtt_client.username_pw_set(username="hassmqtt",password="hassio")
mqtt_client.connect("192.168.86.30",1883) # you could also use the broker IP here
mqtt_client.loop_start() 

#initial setup of mqtt sensors:
Dict1 = {
"name": "Weather Station Temperature",
"device_class": "temperature",
"state_topic": "homeassistant/sensor/WeatherTemp/state",
"unit_of_measurement": "C",
}
mqtt_client.publish("homeassistant/sensor/WeatherTemp/config",json.dumps(Dict1))

Dict2 = {
"name": "Weather Station Pressure",
"device_class": "pressure",
"state_topic": "homeassistant/sensor/WeatherPres/state",
"unit_of_measurement": "hPa"
}
mqtt_client.publish("homeassistant/sensor/WeatherPres/config",json.dumps(Dict2))

Dict3 = {
"name": "Weather Station Humidity",
"device_class": "humidity",
 "state_topic": "homeassistant/sensor/WeatherHumi/state",
"unit_of_measurement": "%"
}
mqtt_client.publish("homeassistant/sensor/WeatherHumi/config",json.dumps(Dict3))

Dict4 = {
"name": "Weather Station illuminance",
"device_class": "illuminance",
"state_topic": "homeassistant/sensor/WeatherLux/state",
"unit_of_measurement": "lx"
}
mqtt_client.publish("homeassistant/sensor/WeatherLux/config",json.dumps(Dict4))

Dict5 = {
"name": "Weather Station Wind speed",
#"device_class": "none",
"state_topic": "homeassistant/sensor/WeatherWS/state",
"unit_of_measurement": "m/s"
}
mqtt_client.publish("homeassistant/sensor/WeatherWS/config",json.dumps(Dict5))

Dict6 = {
"name": "Weather Station wind gusts",
#"device_class": "none",
"state_topic": "homeassistant/sensor/WeatherWG/state",
"unit_of_measurement": "m/s"
}
#mqtt_client.publish("homeassistant/sensor/WeatherWG/config",json.dumps(Dict6)) #Not done yet

Dict7 = {
"name": "Weather Station wind direction",
#"device_class": "none",
"state_topic": "homeassistant/sensor/WeatherWD/state",
#"unit_of_measurement": "none"
}
mqtt_client.publish("homeassistant/sensor/WeatherWD/config",json.dumps(Dict7))

Dict8 = {
"name": "Weather Station rain",
#"device_class": "none",
"state_topic": "homeassistant/sensor/WeatherRain/state",
"unit_of_measurement": "mm/s"
}
mqtt_client.publish("homeassistant/sensor/WeatherRain/config",json.dumps(Dict8))

#read the BME280 and discard the initial readings
sensor.update(interval=10.0)
sensor.temperature_offset = OFFSET
temperature = sensor.temperature
humidity = sensor.relative_humidity
pressure = sensor.pressure
print("Discarding the first few BME280 readings...")
sleep(10.0)

# Now send some data

while True:
    sensor.update(interval=30.0)

    wind_direction_cardinal = sensor.degrees_to_cardinal(sensor.wind_direction)
           
    temperature = sensor.temperature
    humidity = sensor.relative_humidity
    pressure = sensor.pressure
    light = sensor.lux
    windspeed = sensor.wind_speed
    winddirection = wind_direction_cardinal
    rain = sensor.rain

    try:
        mqtt_client.publish("homeassistant/sensor/WeatherTemp/state", round(temperature,2))	
        mqtt_client.publish("homeassistant/sensor/WeatherPres/state", round(pressure,2))
        mqtt_client.publish("homeassistant/sensor/WeatherHumi/state", round(humidity,2))
        mqtt_client.publish("homeassistant/sensor/WeatherLux/state", round(light,2))	
        mqtt_client.publish("homeassistant/sensor/WeatherWS/state", round(windspeed,2))
        mqtt_client.publish("homeassistant/sensor/WeatherWD/state", winddirection)
        mqtt_client.publish("homeassistant/sensor/WeatherRain/state", round(rain,2))
        print('Data sent to Home Assistant')

    except Exception as e:
        print(e)
    sleep(30.0)

My guess is the BME280 configuration lies elsewhere (within the Pimoroni Weatherhat python library?) but that’s a guess and nothing more.

Perhaps here?

  GNU nano 5.4                                                                                                                                                                          __init__.py                                                                                                                                                                                    
import time
import threading
import math

import RPi.GPIO as GPIO
import ioexpander as io
from bme280 import BME280
from ltr559 import LTR559
from smbus2 import SMBus

from .history import wind_degrees_to_cardinal


__version__ = '0.0.1'


# Wind Vane
PIN_WV = 8     # P0.3 ANE6

# Anemometer
PIN_ANE1 = 5       # P0.0
PIN_ANE2 = 6       # P0.1

ANE_RADIUS = 7  # Radius from center to the center of a cup, in CM
ANE_CIRCUMFERENCE = ANE_RADIUS * 2 * math.pi
ANE_FACTOR = 2.18  # Anemometer factor

# Rain gauge
PIN_R2 = 3         # P1.2
PIN_R3 = 7         # P1.1
PIN_R4 = 2         # P1.0
PIN_R5 = 1         # P1.5
RAIN_MM_PER_TICK = 0.2794

wind_direction_to_degrees = {
    0.9: 0,
    2.0: 45,
    3.0: 90,
    2.8: 135,
    2.5: 180,
    1.5: 225,
    0.3: 270,
    0.6: 315
}


class WeatherHAT:
    def __init__(self):
        self.updated_wind_rain = False
        self._lock = threading.Lock()
        self._i2c_dev = SMBus(1)

        self._bme280 = BME280(i2c_dev=self._i2c_dev)
        self._ltr559 = LTR559(i2c_dev=self._i2c_dev)

        self._ioe = io.IOE(i2c_addr=0x12, interrupt_pin=4)

        # Fudge to enable pull-up on interrupt pin
        self._ioe._gpio.setup(self._ioe._interrupt_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        # Input voltage of IO Expander, this is 3.3 on Breakout Garden
        self._ioe.set_adc_vref(3.3)

        # Wind Vane
        self._ioe.set_mode(PIN_WV, io.ADC)

        # Anemometer
        self._ioe.set_mode(PIN_ANE1, io.OUT)
        self._ioe.output(PIN_ANE1, 0)
        self._ioe.set_pin_interrupt(PIN_ANE2, True)
        self._ioe.setup_switch_counter(PIN_ANE2)

        # Rain Sensor
        self._ioe.set_mode(PIN_R2, io.IN_PU)
        self._ioe.set_mode(PIN_R3, io.OUT)
        self._ioe.set_mode(PIN_R4, io.IN_PU)
        self._ioe.setup_switch_counter(PIN_R4)
        self._ioe.set_mode(PIN_R5, io.IN_PU)
        self._ioe.output(PIN_R3, 0)
        self._ioe.set_pin_interrupt(PIN_R4, True)
        self._ioe.on_interrupt(self.handle_ioe_interrupt)
        self._ioe.clear_interrupt()

        # Data API... kinda
        self.temperature_offset = -7.5
        self.device_temperature = 0
        self.temperature = 0

Two things to note:

Pimoronis BME280 lib puts the sensor in NORMAL_MODE, which the datasheet does not recommend for weather-monitoring. This mode constantly forces a temperature conversion for the sensor, which leads to higher than normal readings. The datasheet recommends FORCED_MODE, which has to be activated for every reading but the sensor then returns automatically to SLEEP_MODE.

You can change the mode with the setup-method.

Second thing: for good temperature readings, your sensor should be far away from any heat-sources. And the Pi is such a heat source and the temperature will creep into the sensor (copper is a great conductor not only for current).

What happen if you change

sensor = weatherhat.WeatherHAT()
#sensor = weatherhat.BreakoutBME280(i2c,0x70)

to

#sensor = weatherhat.WeatherHAT()
sensor = weatherhat.BreakoutBME280(i2c,0x70)

I’ve decided to give up on the multiplexer for the time being. I believe there’s config I need to do with it in order to alert it to the presence of the connected BME280 sensor and I’ve concluded that’s waaaayy deeper than I know how to do.

So…I’ve reverted back to the external/“regular” BME280. I just reconnected it and confirmed it’s on address 0x77

I’m now working to determine where that port change goes within the libraries.

The closest I could find so far is this:

That’s OOTB based on the Pimoroni code I pulled down. The weatherhat onboard is at 0x76 which means I should be good with the external one on 0x77.

Back to weeds I go.

I just do the redirect in my main python file. Just a FYI post.
I change
bme = BreakoutBME280()
to
bme = BreakoutBME280(0x77)

It looks like thats no so easy to in the weather hat setup?

Ended up getting everything working as desired. External BME280 is reading accurate, project looks clean. Thank you to all the input!