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);
  DEBUG_PRINT("\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);
}

(Visitato in totale 91 volte, oggi 1 visite)

Rispondi

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