Interfacciare il Bosch BME680 con ESP32

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);
}

Hai trovato utile questo articolo?

Questo articolo è stato visto 406 volte (Oggi 1 visite)
5 comments
  1. 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!

    1. 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!

  2. 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

    1. 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!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.