7.0 KiB
BME680 module
Since | Origin / Contributor | Maintainer | Source |
---|---|---|---|
2017-10-28 | vsky279 | vsky279 | bme680.c |
This module provides a simple interface to BME680 temperature/air presssure/humidity sensors/air quality sensor (Bosch Sensortec). Compared to the BME280 module the sensor does not support automatic mode which means that it can be setup to perform regular measurements. Every measurement has to be triggered manually.
In order to measure the air quality the sensor needs to be heated first. In the example provided by the manufacturer the sensor is heated to 300 degrees centigrade for a period of 200 ms and then the measurement is taken. These values are taken as default values in this implementation. I have not tested the impact of different temperatures and heating times on the measurement.
This module is able to measure the gas resistance (see Bosch's datasheet). The gas resistance is not the IAQ (Indoor Air Quality) Index. But apparently it can be used as some proxy. The value still should somehow reflect the air quality. It seems that the higher value the air quality is better.
The algorithm for IAQ calculation from the gas restistances (probably measured at different temperatures) is not publicly available. Bosch says that at this point of time the calculations for the Indoor Air Quality index are offered only as a pre-compiled library (see discussion here: BoschSensortec/BME680_driver#6). It is available as the BSEC Library.
The algorithm is implemented in the library bsec/algo/bin/ESP8266/libalgobsec.a
. Unfortunately I did not even manage to run the Bosch BSEC example on ESP8266 using this library.
bme680.altitude()
For given air pressure and sea level air pressure returns the altitude in meters as an integer multiplied with 100, i.e. altimeter function.
Syntax
bme680.altitude(P, QNH)
Parameters
P
measured pressureQNH
current sea level pressure
Returns
altitude in meters of measurement point
bme680.dewpoint()
For given temperature and relative humidity returns the dew point in Celsius as an integer multiplied with 100.
Syntax
bme680.dewpoint(H, T)
Parameters
H
relative humidity in percent multiplied by 1000.T
temperate in Celsius multiplied by 100.
Returns
dew point in Celsius
bme680.qfe2qnh()
For given altitude converts the air pressure to sea level air pressure.
Syntax
bme680.qfe2qnh(P, altitude)
Parameters
P
measured pressurealtitude
altitude in meters of measurement point
Returns
sea level pressure
bme680.read()
Reads the sensor and returns the temperature, the air pressure, the air relative humidity and
Syntax
bme680.read([altitude])
Parameters
- (optional)
altitude
- altitude in meters of measurement point. If provided also the air pressure converted to sea level air pressure is returned.
Returns
T
temperature in Celsius as an integer multiplied with 100P
air pressure in hectopascals multiplied by 100H
relative humidity in percent multiplied by 1000G
gas resistanceQNH
air pressure in hectopascals multiplied by 100 converted to sea level
Any of these variables is nil
if the readout of given measure was not successful.
The measured values can be read only once. Following attempts to read values will return nil. A new startreadout()
needs to be called first before next read()
.
bme680.startreadout()
Starts readout (turns the sensor into forced mode). After the readout the sensor turns to sleep mode.
Syntax
bme680.startreadout(delay, callback)
Parameters
delay
sets sensor to forced mode and calls thecallback
(if provided) after given number of milliseconds. For 0 the default delay is calculated by the formula provided by Bosch. Apparently for certain combinations of oversamplings setup the the delay returned by the formula is not sufficient and the readout is not ready (make sure you are not reading the previous measurement). For default parameters (2x, 16x, 1x) the calculated delay is 121 ms while in reality 150 ms are needed to get the result.callback
if provided it will be invoked after givendelay
. The sensor reading should be finalized by then so.
Returns
nil
bme680.setup()
Initializes module. Initialization is mandatory before read values.
Syntax
bme680.setup([temp_oss, press_oss, humi_oss, heater_temp, heater_duration, IIR_filter, cold_start])
Parameters
- (optional)
temp_oss
- Controls oversampling of temperature data. Default oversampling is 2x. - (optional)
press_oss
- Controls oversampling of pressure data. Default oversampling is 16x. - (optional)
humi_oss
- Controls oversampling of humidity data. Default oversampling is 1x - (optional)
heater_temp
- - (optional)
heater_duration
- - (optional)
IIR_filter
- Controls the time constant of the IIR filter. Default fitler coefficient is 31. - (optional)
cold_start
- If 0 then the bme680 chip is not initialised. Usefull in a battery operated setup when the ESP deep sleeps and on wakeup needs to initialise the driver (the module) but not the chip itself. The chip was kept powered (sleeping too) and is holding the latest reading that should be fetched quickly before another reading starts (bme680.startreadout()
). By default the chip is initialised.
temp_oss , press_oss , humi_oss |
Data oversampling |
---|---|
0 | Skipped (output set to 0x80000) |
1 | oversampling ×1 |
2 | oversampling ×2 |
3 | oversampling ×4 |
4 | oversampling ×8 |
5 | oversampling ×16 |
IIR_filter |
Filter coefficient |
---|---|
0 | Filter off |
1 | 1 |
2 | 3 |
3 | 7 |
4 | 15 |
5 | 31 |
6 | 63 |
7 | 127 |
Returns
nil
if initialization has failed (no sensor connected?)
Example
alt=320 -- altitude of the measurement place
sda, scl = 3, 4
i2c.setup(0, sda, scl, i2c.SLOW) -- call i2c.setup() only once
bme680.setup()
-- delay calculated by formula provided by Bosch: 121 ms, minimum working (empirical): 150 ms
bme680.startreadout(150, function ()
T, P, H, G, QNH = bme680.read(alt)
if T then
local Tsgn = (T < 0 and -1 or 1); T = Tsgn*T
print(string.format("T=%s%d.%02d", Tsgn<0 and "-" or "", T/100, T%100))
print(string.format("QFE=%d.%03d", P/100, P%100))
print(string.format("QNH=%d.%03d", QNH/100, QNH%100))
print(string.format("humidity=%d.%03d%%", H/1000, H%1000))
print(string.format("gas resistance=%d", G))
D = bme680.dewpoint(H, T)
local Dsgn = (D < 0 and -1 or 1); D = Dsgn*D
print(string.format("dew_point=%s%d.%02d", Dsgn<0 and "-" or "", D/100, D%100))
end
end)