Il BME680 è il nuovo sensore ambientale sviluppato dall’azienda Bosch Sensortech che incorpora, in aggiunta al sensore di pressione, temperatura e umidità, anche un sensore di gas capace di rilevare anche VOCs – Volatile Organic Compounds – come formaldeide, solventi, detersivi, adesivi e alcool. In generale, questo sensore è capace di misurare la qualità dell’aria, restituendo un valore resistivo proporzionale.
Per noi semplici hobbysti, le ridotte dimensioni del BME680 (3mm x 3mm) rischiano di essere proibitive: per fortuna ci sono aziende che producono moduli già pronti per essere interfacciati e che si possono reperire sui siti di elettronica. Tra le scelte disponibili, ho acquistato il modulo CJMCU 680, attualmente in vendita ad un prezzo di poco inferiore a 10€.
Il modulo può essere interfacciato usando l’interfaccia SPI o il bus I2C, che personalmente preferisco per il ridotto cablaggio necessario: SDA(5), SCL(4), 3.3V e GND.
A differenza dei precedenti BME280 e BMP280, il BME680 esprime tutto il suo potenziale utilizzando la libreria BSEC, sviluppata dal produttore Bosch Sensortec e disponibile gratuitamente solo in forma binaria. Attraverso questa libreria è possibile ottenere il calcolo dell’indice IAQ e il valore CO2 equivalent per determinare la qualità dell’aria.
La libreria, con le istruzioni di installazione su SDK Arduino, è su github.com/BoschSensortec/BSEC-Arduino-library/
Per alcune board ESP32 è necessario fare attenzione ai PIN del bus I2C, perché le impostazioni di default potrebbero non riflettere le scelte progettuali fatte in fase di prototipazione.
I miei primi esperimenti con il BME680 sono stati realizzati su una scheda WeMos Lolin32 con display OLED da 0,96″ integrato, dove visualizzare i valori ambientali individuati (per il display si può usare la libreria github.com/ThingPulse/esp8266-oled-ssd1306):
#include <Wire.h>
#include <SPI.h>
#include "bsec.h"
#include <Adafruit_GFX.h>
#include "SSD1306.h"
/* i2c bus pins */
#define I2C_SDA_PIN 5
#define I2C_SCL_PIN 4
/* i2c OLED display */
#define SDD_ADDRESS 0x3C
SSD1306Wire display(SDD_ADDRESS, I2C_SDA_PIN, I2C_SCL_PIN);
/* i2c BME680 */
#define BME680_ADDRESS 0x77
Bsec iaqSensor;
si passa poi all’inizializzazione del sensore BME680:
void setup() {
Wire.begin( I2C_SDA_PIN, I2C_SCL_PIN );
iaqSensor.begin(BME680_ADDRESS, Wire);
// Serial.println("\nBSEC library version " + String(iaqSensor.version.major) + "." + String(iaqSensor.version.minor) + "." + String(iaqSensor.version.major_bugfix) + "." + String(iaqSensor.version.minor_bugfix));
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);
[...]
e nel loop() prelevare e visualizzare i parametri:
void loop() {
if (iaqSensor.run()) { // If new data is available
display.clear();
display.drawString(0,10,"Temp: "+String(iaqSensor.temperature)+" *C");
display.drawString(0,20,"Pres: "+String(iaqSensor.pressure / 100.0)+" hPa");
display.drawString(0,30,"Hum: "+String(iaqSensor.humidity)+" %");
/* CO2
* 300-600 Excellent
* 601-800 Good
* 801-1001 Fair
* 1001-1500 Mediocre
* 1501-2000 Bad
* >2000 Insane
*/
float co2 = iaqSensor.co2Equivalent;
String co2Quality;
if(co2 < 600) {
co2Quality = "Excellent";
} else if((co2 > 600)&&(co2 < 800)) {
co2Quality = "Good";
} else if((co2 > 800)&&(co2 < 1000)) {
co2Quality = "Fair";
} else if((co2 > 1001)&&(co2 < 1500)) {
co2Quality = "Bad";
} else if((co2 > 1500)&&(co2 < 2000)) {
co2Quality = "Worse";
} else if(co2 > 200) {
co2Quality = "Insane";
}
display.drawString(0,40,"eCO2 is "+String(co2Quality)+" ("+String(iaqSensor.co2Equivalent)+"ppm)");
/*IAQ Index Classification
0 .. 50 Good
51 .. 100 Average
101 .. 150 Little bad
151 .. 200 Bad
201 .. 300 Worse
301 .. 500 Very bad
*/
float iaq = iaqSensor.staticIaq;
String airQuality;
if((iaq > 0)&&(iaq < 50)) {
airQuality = "Good";
} else if((iaq > 50)&&(iaq < 100)) {
airQuality = "Average";
} else if((iaq > 100)&&(iaq < 150)) {
airQuality = "Little bad";
} else if((iaq > 150)&&(iaq < 200)) {
airQuality = "Bad";
} else if((iaq > 200)&&(iaq < 300)) {
airQuality = "Worse";
} else if(iaq > 300) {
airQuality = "Very bad";
}
display.drawString(0,50,"Air is "+String(airQuality)+" (IAQ:"+String(iaqSensor.staticIaq)+")");
}
// Update display
display.display();
delay(2000);
}
5 comments
Buona sera Michele,
nel compilare il codice, l’IDE di Arduino (1.8.13( mi dà errore alla linea
DEBUG_PRINT(“\nBSEC library version ……..(ecc)
dicendo che non è dichiarata.
Come fare?
Grazie!
Buonasera Andrea,
grazie per la segnalazione: DEBUG_PRINT è una macro che uso per il debugging, un semplice Serial.printl(…). Puoi tranquillamente cancellare la riga incriminata, che serve solo a stampare a video la versione della libreria.
Happy coding!
Grazie!
..Però…magari una chiacchierata sul debug…potrebbe sempre starci bene!
Buon pomeriggio Michele,
Ho realizzato un sensore con d1 mini e Bme680. Ho scritto uno sketch che funziona correttamente da almeno 5 mesi. Ho deciso così di crearne degli altri, ma questa volta una volta saldati è caricato lo stesso e identico sketch appena accesi mi restituiscono Error code – 2.
Ho provato a cambiare l’indirizzo da primary a Secondary ma il risultato non cambia. Sapresti indicarmi da cosa può dipendere?
Grazie
Ciao Jordan982,
con così poche informazioni è difficile stabilire la causa dell’errore. Hai provato ad aggiungere allo sketch un I2C bus scanner tipo questo?
/* I2C Bus Scanner */
void i2c_scanner() {
unsigned char error, address;
uint8_t nDevices = 0;
for(address = 1; address < 127; address++ ) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } } Così da individuare l'indirizzo esatto del modulo BME680? Talvolta, alcuni moduli cinesi usato indirizzi non standard... Buona fortuna!