Electronics Wednesday - BME280 stuff

The last meeting was well attended (there were 6 people at one time).

The last couple of hours were spent separating Ken’s BMP280 boards from the BME280 ones. I now checked the datasheets and it seems that this should actually be easy with a good magnifying glass.

The U in the UP signifies a BME280. A K should mark a BMP280. We (@Ken_Taylor) need to check the IDs we got from probing the devices against the markings.

On a related matter, I see that the nodeMCU firmware (at least the current dev branch) includes a module for the bme280 so this should be easy to play with.

1 Like

A simple test script (following the example in the doco page) to get started.

local alt=600 -- altitude of the measurement place
local s

local function read_it()
        print("")

s=tmr.now()
        QFE, T = bme280.baro()
s=tmr.now()-s
        print(string.format("%5dus QFE=%d.%03d Temp=%d.%02d", s, QFE/1000, QFE%1000, T/100, T%100))

-- convert measure air pressure to sea level pressure
s=tmr.now()
        QNH = bme280.qfe2qnh(QFE, alt)
s=tmr.now()-s
        print(string.format("%5dus QNH=%d.%03d", s, QNH/1000, QNH%1000))

s=tmr.now()
        H, T = bme280.humi()
s=tmr.now()-s
        print(string.format("%5dus Humidity=%d.%03d%% Temp=%d.%02d", s, H/1000, H%1000, T/100, T%100))

s=tmr.now()
        D = bme280.dewpoint(H, T)
s=tmr.now()-s
        print(string.format("%5dus dew_point=%d.%02d", s, D/100, D%100))

-- altimeter function - calculate altitude based on current sea level pressure (QNH) and measure pressure
s=tmr.now()
        curAlt = bme280.altitude(QFE, QNH)
s=tmr.now()-s
        print(string.format("%5dus Altitude=%d.%02d", s, curAlt/100, curAlt%100))

        bme280.startreadout(1)  -- would prefer 0 but that means 'default' :-(
end

node.setcpufreq(node.CPU160MHZ)

s=tmr.now()
        dev=bme280.init(3, 4, 1, 1, 1, 0, 0, 0) -- sleep mode
s=tmr.now()-s
        print(string.format("%5dus init found %s", s, ({"none","bme280", "bmp280"})[dev]))

tmr.alarm(1, 1000, 1, read_it)  -- read every 1s

The timing for 160MHz is a bit better that at 80MHz.

  At 80MHz
38303us init found bme280
 6795us QFE=937.862 Temp=27.48
  719 QNH=1007.498
 5550us Humidity=30.514% Temp=27.48
  790us dew_point=8.63
  596us Altitude=600.00

 6737us QFE=937.850 Temp=27.57
  432us QNH=1007.485
 5541us Humidity=28.658% Temp=27.57
  784us dew_point=7.79
  685us Altitude=600.00

  At 160MHz
33912us init found bme280
 5842us QFE=937.798 Temp=27.61
  483us QNH=1007.429
 4733us Humidity=30.141% Temp=27.61
  446us dew_point=8.56
  346us Altitude=600.00

 5800us QFE=937.648 Temp=27.48
  244us QNH=1007.268
 4729us Humidity=27.311% Temp=27.48
  444us dew_point=7.00
  448us Altitude=600.00

Moving on. I implemented an extra function in the bme280 module to read all data at once. It also reads the chip registers in burst mode. The timing looks like this now (still at 160MHz)

  108us tmr read
33992us init found bme280
 5845us QFE=939.736 Temp=25.27
  494us QNH=1009.511
 4802us Humidity=31.583% Temp=25.27
  468us dew_point=7.22
  331us Altitude=600.00
 2876us T=25.27 QFE=939.736 QNH=1009.511 H=31.583%

 5828us QFE=939.748 Temp=25.26
  258us QNH=1009.524
 4798us Humidity=31.605% Temp=25.26
  470us dew_point=7.22
  450us Altitude=600.00
 2876us T=25.26 QFE=939.748 QNH=1009.524 H=31.605%

The last line in a block is the new function. As can be seen, it is much faster than the others.

The test program was modified accordingly

local alt=600 -- altitude of the measurement place
local s

local function read_it()
	print("")

s=tmr.now()
	QFE, T = bme280.baro()
s=tmr.now()-s
	if nil == QFE then
		print("no baro")
		return
	end
	print(string.format("%5dus QFE=%d.%03d Temp=%d.%02d", s, QFE/1000, QFE%1000, T/100, T%100))

-- convert measure air pressure to sea level pressure
s=tmr.now()
	QNH = bme280.qfe2qnh(QFE, alt)
s=tmr.now()-s
	print(string.format("%5dus QNH=%d.%03d", s, QNH/1000, QNH%1000))

s=tmr.now()
	H, T = bme280.humi()
s=tmr.now()-s
	print(string.format("%5dus Humidity=%d.%03d%% Temp=%d.%02d", s, H/1000, H%1000, T/100, T%100))

s=tmr.now()
	D = bme280.dewpoint(H, T)
s=tmr.now()-s
	print(string.format("%5dus dew_point=%d.%02d", s, D/100, D%100))

-- altimeter function - calculate altitude based on current sea level pressure (QNH) and measure pressure
s=tmr.now()
	curAlt = bme280.altitude(QFE, QNH)
s=tmr.now()-s
	print(string.format("%5dus Altitude=%d.%02d", s, curAlt/100, curAlt%100))

s=tmr.now()
	T, QFE, H = bme280.read()
s=tmr.now()-s
	QNH = bme280.qfe2qnh(QFE, alt)
	print(string.format("%5dus T=%d.%02d QFE=%d.%03d QNH=%d.%03d H=%d.%03d%%", s,
		T/100, T%100,
		QFE/1000, QFE%1000,
		QNH/1000, QNH%1000,
		H/1000, H%1000))

	bme280.startreadout(1)	-- would prefer 0 but that means 'default' :-(
end

node.setcpufreq(node.CPU160MHZ)

s=tmr.now()
s=tmr.now()-s
	print(string.format("%5dus tmr read", s))

s=tmr.now()
	dev = bme280.init(3, 4, 1, 1, 1, 0, 0, 0)	-- sleep mode
s=tmr.now()-s
	print(string.format("%5dus init found %s", s, ({"none","bme280", "bmp280"})[dev]))

bme280.startreadout(1)
tmr.alarm(1, 1000, 1, read_it)	-- read every 1s

Note how an initial startreadout is done after the init. The time of a tmr read is also printed now.

Lots of progress on what seems a better choice of sensors than the DHT22 and BMP180 combination currently in the MHV weather station. I’ve found the DHT22s too often fail after a while. I also liked Julian Illets idea of mounting BME280s directly on the the screen.

There turned out to be less BMP280s in the bundle than I expected. When we separated them out, the 2 identified as BMP280s were the 2 with rectangular rather than square cans so when @eyal says

should actually be easy with a good magnifying glass.

it turns out, correct identification does not even need the magnifying glass.

Another useful finding from the effort was that the Adafruit BME Arduino library with a modification for the different chip ID also worked with BMP280s.

Slightly OT: an informative sensors comparo
http://www.kandrsmith.org/RJS/Misc/Hygrometers/calib_many.html

I said:

I implemented an extra function in the bme280 module to read all data at once

This extra function is now included in the dev branch.