¿Qué es un BME680?
El BME680 es un sensor de calidad de aire interior del fabricante Bosch que incorpora medición de temperatura, humedad, presión barométrica y contenido en compuestos orgánicos volátiles (VOC) que podemos usar fácilmente junto con un procesador como Arduino.
En sensor puede detectar algunos gases como monóxido de carbono, etanol, o acetona. También es posible calcular parámetros de calidad de aire interior, así como estimar la cantidad de dióxido de carbono equivalente.
Sin embargo, el BEM680 no puede distinguir entre los gases o realizar la medición de forma individual para cada uno de ellos. En su lugar, totaliza el efecto total del VOC para proporcionar una idea cuantitativa de la calidad del aire resultante.
El BME680 tiene una tensión de funcionamiento de 1.2 V a 3.6 V. No obstante, algunos módulos incorporan un regulador de voltaje y un conversor de nivel, que permiten operarlos directamente a 5V.
EL consumo es de 0.15 µA en sleep, 3.7 µA para mediciones de humedad, presión y temperatura, y de 0.09 a 12 mA para medición del gas, en función del modo de operación elegido.
La comunicación se realiza a través de I²C hasta 3.4 MHz, o SPI de 3 o 4 cables hasta 10 MHz. Por tanto, es muy sencillo conectarlo a un procesador como Arduino.
Precio
Podemos encontrar módulo con sensor BME680 por 8-10€, en vendedores internacionales de eBay y AliExpress.
¿Cómo funciona un BME680?
El BME680 está compuesto por un sensor MOX (Metal-oxide). En su funcionamiento, el MOX es calentado y este absorbe moléculas de oxigeno. El Datasheet del componente proporciona los siguientes valores.
Molar fraction | Compound | Production tolerance | Certified accuracy |
---|---|---|---|
5 ppm | Ethane | 20% | 5% |
10 ppm | Isoprene /2-methyl-1,3 Butadiene | 20% | 5% |
10 ppm | Ethanol | 20% | 5% |
50 ppm | Acetone | 20% | 5% |
15 ppm | Carbon Monoxide | 10% | 2% |
Al absorber los VOC el MOX varía su conductividad, por lo que la resistencia del mismo varía. Con el valor de esta resistencia es posible calcular un índice de calidad del aire.
Resistencia | Calidad aire |
---|---|
0 – 50 | Good |
51 – 100 | Average |
101 – 150 | Little bad |
151 – 200 | Bad |
201 – 300 | Worse |
301 – 500 | Very bad |
El sensor proporciona una precisión de 1.0 °C para medición de temperatura, ± 3% para humedad, y ± 1 hPa para presión barométrica, equivalente a una precisión de altura de ± 1 metro.
Al igual que la mayoría de sensores químicos, el BME680 necesita un pre-calentador. El fabricante recomienda que el sensor funcione durante 30 minutos para que las mediciones se estabilicen, y durante 48 horas si se cambia de ubicación.
Esquema de montaje
El control de módulo se realiza a través de I2C, por lo que el conexionado es muy sencillo. Simplemente alimentamos el módulo mediante Gnd y Vdd, y conectamos los pines del I2C SDA y SCL.
La conexión vista desde Arduino sería la siguiente.
Ejemplos de código
Librería Adafruit
Para controlar el BME680 podemos usar la librería desarrollada por Adafruit, cuyo código está disponible en https://github.com/adafruit/Adafruit_BME680.
La librería incorpora ejemplos de su uso, que resulta aconsejable consultar. El siguiente es un resumen extraído de los mismos.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
const int BME_SCK = 13;
const int BME_MISO = 12;
const int BME_MOSI = 11;
const int BME_CS = 10;
const int SEALEVELPRESSURE_HPA = 1013.25;
Adafruit_BME680 bme;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println(F("BME680 test"));
if (!bme.begin()) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
}
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
void loop() {
if (! bme.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
Serial.print("Temperature = ");
Serial.print(bme.temperature);
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bme.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(bme.humidity);
Serial.println(" %");
Serial.print("Gas = ");
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(" KOhms");
Serial.print("Approx. Altitude = ");
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
Serial.println();
delay(2000);
}
Librería Bosch
Otra alternativa es emplear la librería desarrollada por Bosch, disponible en este enlace. Esta librería es algo más compleja que la de Adafruit, pero proporciona más valores del sensor como, por ejemplo, la estimación de CO2 equivalente.
Sin embargo la librería de Bosch ocupa más memoria. Por tanto, no se puede emplear en un Arduino Uno, Nano o similar. Si es compatible con Arduino Mega, ESP8266, ESP32, y otros dispositivo. Consultad la documentación para una lista completa de dispositivos compatibles.
La librería incorpora ejemplos de su uso, que resulta aconsejable consultar. El siguiente es un resumen extraído de los mismos.
#include "bsec.h"
// Helper functions declarations
void checkIaqSensorStatus(void);
void errLeds(void);
// Create an object of the class Bsec
Bsec iaqSensor;
String output;
// Entry point for the example
void setup(void)
{
Serial.begin(115200);
Wire.begin();
iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire);
output = "\nBSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix);
Serial.println(output);
checkIaqSensorStatus();
bsec_virtual_sensor_t sensorList[10] = {
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_STATIC_IAQ,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
};
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
checkIaqSensorStatus();
// Print the header
output = "Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent";
Serial.println(output);
}
// Function that is looped forever
void loop(void)
{
unsigned long time_trigger = millis();
if (iaqSensor.run()) { // If new data is available
output = String(time_trigger);
output += ", " + String(iaqSensor.rawTemperature);
output += ", " + String(iaqSensor.pressure);
output += ", " + String(iaqSensor.rawHumidity);
output += ", " + String(iaqSensor.gasResistance);
output += ", " + String(iaqSensor.iaq);
output += ", " + String(iaqSensor.iaqAccuracy);
output += ", " + String(iaqSensor.temperature);
output += ", " + String(iaqSensor.humidity);
output += ", " + String(iaqSensor.staticIaq);
output += ", " + String(iaqSensor.co2Equivalent);
output += ", " + String(iaqSensor.breathVocEquivalent);
Serial.println(output);
} else {
checkIaqSensorStatus();
}
}
// Helper function definitions
void checkIaqSensorStatus(void)
{
if (iaqSensor.status != BSEC_OK) {
if (iaqSensor.status < BSEC_OK) {
output = "BSEC error code : " + String(iaqSensor.status);
Serial.println(output);
for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BSEC warning code : " + String(iaqSensor.status);
Serial.println(output);
}
}
if (iaqSensor.bme680Status != BME680_OK) {
if (iaqSensor.bme680Status < BME680_OK) {
output = "BME680 error code : " + String(iaqSensor.bme680Status);
Serial.println(output);
for (;;)
errLeds(); /* Halt in case of failure */
} else {
output = "BME680 warning code : " + String(iaqSensor.bme680Status);
Serial.println(output);
}
}
}
void errLeds(void)
{
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
Descarga el código
Todo el código de esta entrada está disponible para su descarga en Github.