Enviro+ readings unrealiable

Thanks to nophead working me through it I now have his code working on my setup which a Zero WH ribbon cable and Enviro+. Currently it is indoors by a windowsill waiting for the addition of a fan.
The RH figures seem way off, the temperature a little high and I am still trying to understand the gas and particle numbers.
All the peaks in the particles on my graph coincide with cooking, the kitchen is next door and the hob is gas. With the big storm approaching us here in the UK the drop in pressure is also reflected, I am in the South West and we tend to get them first.


Cool! I’m a sucker for graphs, is there some tutorial to get that?

Perhaps nophead can point you in the direction of a tutorial but if you can ‘teach yourself’ he posted this graphical solution in this thread where I got it from:
As a beginner I can just about read his code but I certainly couldn’t create it, it is a super piece of work.

Bookmarked, I can work with that, thanks 👍🏻

An update from my end with the Enviro+…I did a couple of physical changes which involved separating the Enviro+ and the Pi. I put the Pi in a neat little case that I originally recorded from Pimoroni but never used. I then used a 40-pin header extension block that effectively lifts the Enviro+ about 15mm above the top of the new Pi enclosure. Whatever heat that little CPU generates isn’t going to be effecting the Enviro+ now, that’s for sure, especially as it’s sitting the the breezeway of my little outdoor enclosure.

The results? Way more sensible temp and himidity readings, rendering the scaling factor in the example Luftdaten code redundant. Basically, the raw temp off the chip is a much better representation of the actual temp, and the same for the humidity values. The pressure readings have always been accurate regardless.

I say ‘realistic’ and not ‘spot on’. And I think I know what’s happening. The raw temp is about 2C too high, and the humidity is about 10% too low. The temp effect seems linear, so I just subtract 2C from the raw temp and I’m happy with it. I’ve scaled up the humidity to where it seems to be about +/- 2%. Pretty good for a hack job.

I think I know a path to spot-on figures but I haven’t had time to start playing. There’s a lot on info that suggests different ‘modes’ of the BME280 depending on the application. Weather, indoor, etc etc. Lots of variables, including the read mode (continuous, forced, etc) and how often you read from it. The more you use it, the more it warms up… So, calling the chip in a tight loop is asking it to do more work, so it heats up, and having it in ‘normal’ mode means it’s sampling all the time, basically. Again, more heat. I need to figure out how to set the chip in to the ‘weather configuration’ and see what happens. Here looks promising…


I think I’ve at least partially solved the problem of heat transfer from the RPi to the BME280 as pictured below.
I had a BitScope Uno RPi Blade and an RPI-4 from another project. Mounted the Pi and the Enviro+ hat separately on the blade with a small exhaust fan pulling outside air through a screened inlet across the BME 280 and adjacent to the particulate sensor. The 5VDC fan was fast and loud so I slowed and quieted it using a PWM controller (Green Knob). The unit is mounted outdoors on a wall in a 2L Sistema sandwich box from New Zealand (available at Amazon).
The setup is more expensive than using the downspout material and the hat mounted on an RPi Zero, but better protected from weather and with a more robust power supply (12VDC in/5V regulated out). Better wifi power too, I think. I calibrated it with an analog thermometer by changing the software compensation value and it has been stable and accurate for a week.

Comments welcome.

I tried a ribbon cable and very literally smoked the hat. Obviously, the ribbon cable challenged my ability to visualize the header orientation. Think 3.3V got traded for 5V or GND!

Yes, I triple checked it and took a reference pic with my phone haha
Your setup is indeed beefier. A RPI4 is way more computing power that you need for this, possibly you can use that for some local visualization with Grafana or something en clip a webcam to it to stream to YouTube?
Same goes for the 32gb card, those I’d save for projects that need local storage? 🤔

I successfully corrected the temperature and humidity errors by doing two things. Firstly, I separated the Raspberry Pi Zero and the Pimoroni Enviro+ boards, placed the PMS 5003 between the two boards and used ribbon cable to interconnect them. I’ve designed and built a 3D printed case to hold them. I’ve included a photo of the case.


Secondly, I logged the Enviro+ temperature and humidity readings, along with the temperature and humidity readings from a closely located Aeotec Multisensor. Those logs allowed me to undertake some machine learning using regression analysis, to develop some correction algorithms. I tried polynomial regression but found that linear regression was sufficiently accurate.

I also implemented an algorithm that adjusts the relative humidity to align with the adjusted temperature. I implemented that algorithm using August-Roche-Magnus approximation using https://bmcnoldy.rsmas.miami.edu/Humidity.html

I’m now getting temperature readings with a ±0.4 degree C accuracy and relative humidity readings with ±2% accuracy. I plan to run the ML training on a much larger sample size, with a wider variety of temperature and humidity values to fully verify the algorithms, but the early results are promising. I’ll post the final code, case design and regression analysis when I’ve completed that larger sample size.

In the meantime, here is an extract of the correction code. The corrected temperature is comp_temp and the corrected humidity is comp_hum. It’s possible that the regression compensation variables might need some adjustment if a case that differs from mine is used.

Hope that’s of use to those of you struggling to get some temperature and humidity accuracy.

Set up the regression compensation variables
cpu_temp_factor_slope = 1.038 # Linear Regression to minimise impact of CPU temp on Raw Temp
cpu_temp_factor_intercept = 12.503
comp_temp_slope = 0.623 # Linear Regression to adjust Raw Temp (with impact of CPU Temp removed) to provide compensated temp
comp_temp_intercept = 23.519
comp_hum_slope = 0.966 # Linear Regression to adjust temperature-adjusted raw relative humidity to provide compensated relative humidity
comp_hum_intercept = 15.686

cpu_temp = get_cpu_temperature()
cpu_temps = cpu_temps[1:] + [cpu_temp] # Smooth out with some averaging to decrease jitter
avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
raw_temp = bme280.get_temperature()
cpu_temp_factor = cpu_temp_factor_slope * (avg_cpu_temp - raw_temp) + cpu_temp_factor_intercept
raw_temp_without_cpu_impact = raw_temp - cpu_temp_factor
comp_temp = comp_temp_slope * raw_temp_without_cpu_impact + comp_temp_intercept
raw_hum = bme280.get_humidity()
dew_point = (243.04 * (math.log(raw_hum / 100) + ((17.625 * raw_temp) / (243.04 + raw_temp)))) / (17.625 - math.log(raw_hum / 100) - (17.625 * raw_temp / (243.04 + raw_temp)))
temp_adjusted_hum = 100 * (math.exp((17.625 * dew_point)/(243.04 + dew_point)) / math.exp((17.625 * comp_temp) / (243.04 + comp_temp)))
comp_hum = comp_hum_slope * temp_adjusted_hum + comp_hum_intercept

1 Like

Here’s another photo of the case, this time showing the underside ventilation.

… and with the cover in place.

1 Like

I’ve gone naked, and the results are in. I’m getting much more plausible readings to send to Luftdaten with no temp or humidity compensation necessary. Basically, I’ve removed the Enviro+ and have directly connected a stand-alone BME280 (ironically, a Pimoroni module) and directly connected the PMS5003.

The temperature is pretty-well bang on, and the humidity isn’t far off either. I also got in to the BME280 driver and mauled all of the settings to align it with the recommendations in the BME280 data sheet for weather monitoring: IRR Off, Force mode, x1 oversampling, and 1s sampling rates.

In my weather enclosure, the BME280 module is about 20 cm away from the Pi Zero, so it’s not going to get any heat soak from anywhere except the atmosphere. I also throttled-back the measurement loop to 20 seconds.

I’ve got a few more BME280 modules on the slow boat from China, and a PMS7003 as well. When they turn up I’m going to use the Circuitpython drivers and fiddle with the script to start sending Luftdaten the mean of the previous measurement cycles rather than just the raw data of the last measurement.

So, I’m happy now that I’ve got plausible readings to send up to Luftdaten (I imagine they’re be happier too) but a bit disappointed that the Enviro+ module has some design challenges, especially considering its price.

1 Like

Looks like you’re already executing the plan I had as well ;-) on that same boat are some sensors for me too, though I already received my SDS011. Already have some code / pics to share?

Sensor porn! lol.
Basically the BME280 is hooked up via the Pimoroni breakout board (part # PIM472) to the SDA and SCL (data and clock) pins, plus 3.3v and GND, via some 20cm female-to-female jumpers. The PMS5003 is hooked up via the same jumpers and an interface adapter (part #PIM477) that basically just converts the tiny ribbon connector in to some larger pin terminals. It’s sitting on the TX and RX pins, plus 5v and GND, as well as Reset (to Pin 27) and EN (to Pin 22).

It looks like it sounds - a Pi Zero hooked up to some boards via a bunch of wires. Pretty well all I’ve done is get rid of the Enviro+ hardware and leave all of the code in place.

As for the code - it’s a complete hack job on my part. The Pimoroni driver is coded in a very different style to the circuitpython driver, but it works, so all I did was change some of the parameters according to the ‘weather’ settings that are linked in one of my previous posts in this thread.

I also took the Luftdaten.py script and chopped out all of the unnecessary stuff now that I don’t have the Enviro+, namely the display-related functions and code as well as all of the temperature compensation code. Oh, and I put time.sleep(20) in the main loop to calm it down a bit.

The BME280 driver is in /usr/local/lib/python3.7/dis-packages/pimoroni_bme280-0.0.2-py3.7.egg/bme280/init.py if you’re trying to find it.

For my next iteration, I’ll use the circuitypython drivers for the BME280 and PMSx003 and write my own script to send the date up to Luftdaten. At each loop, I’ll just add the temp, humidity and pressure measurements to a list. When it comes time to sent it up to Luftdaten, I’ll just take the mean of each list, send it, clear the list, and start again. By taking the mean, I’ll be smoothing out the 20-second measurements to better account for how sensitive that little BME280 sensor is!

1 Like

Received the BMP180 today but the protective cap on the sensor seems to lack the protective cap on the sensor itself :-/

That’s pretty well what mine looks like. I have some more good news: My “calibrated” $30 temp/humidity meter turned up this morning (apparently accurate to +/-2% RH and .2C) and according to it, the measurements I’m getting from my stand-alone BME280 are basically spot on. Happy days.

I don’t believe there is supposed to be a cap on the sensor hole. It’s open to the air. My BMP280 had no cover.

Great news Dusty!

That small metal cap was what I expected. Bare chip would probably work just as well, but maybe more fragile? 🤔

Yes, the sensors are tiny and would be prone to damage if they weren’t covered. The hole is the compromise to allow air to flow in. A small bit of micropore filter over the hole would protect against dust.

This unit does have a filter cover. Note the warning at the end.

Another update on going naked: My second generic BME280 turned up this afternoon and I connected it to my spare PI using the CircuitPython BME280 drivers. The result? Amazingly accurate temperature and humidity readings. +/- 1% on humidity and +/- 0.5C for temperature as compared to my $30 handheld hygrometer.
So, I currently have my Pi Zero with a stand-alone Adafruit BME280 and the PMS5003 sending date to Luftdaten utilising the Pimoroni drivers that came with the Enviro+. The results are the same as my Pi3 rig, above - very accurate temp and humidity. I think this conclusively demonstrates that if you are thinking of using an Enviro+ for anything other than a testbed, or you need accurate temp and humidity readings for whatever purpose, consider using just natively-connected devices and the Circuitpython drivers, avoiding the Enviro+