248 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #if (HAS_BME)
 | |
| 
 | |
| #include "bmesensor.h"
 | |
| 
 | |
| // Local logging tag
 | |
| static const char TAG[] = __FILE__;
 | |
| 
 | |
| bmeStatus_t bme_status = {0};
 | |
| 
 | |
| Ticker bmecycler;
 | |
| 
 | |
| #define SEALEVELPRESSURE_HPA (1013.25)
 | |
| 
 | |
| #ifdef HAS_BME680
 | |
| 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,
 | |
| };
 | |
| 
 | |
| uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0};
 | |
| uint16_t stateUpdateCounter = 0;
 | |
| 
 | |
| Bsec iaqSensor;
 | |
| 
 | |
| #elif defined HAS_BME280
 | |
| 
 | |
| Adafruit_BME280 bme; // using I2C interface
 | |
| 
 | |
| // use these alternative constructors for other hw interface types
 | |
| // Adafruit_BME280 bme(BME_CS); // hardware SPI
 | |
| // Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
 | |
| 
 | |
| #elif defined HAS_BMP180
 | |
| 
 | |
| Adafruit_BMP085 bmp; // I2C
 | |
| 
 | |
| #endif
 | |
| 
 | |
| void setBMEIRQ() { xTaskNotify(irqHandlerTask, BME_IRQ, eSetBits); }
 | |
| 
 | |
| // initialize BME680 sensor
 | |
| int bme_init(void) {
 | |
| 
 | |
|   // return = 0 -> error / return = 1 -> success
 | |
|   int rc = 1;
 | |
| 
 | |
| #ifdef HAS_BME680
 | |
|   // block i2c bus access
 | |
|   if (I2C_MUTEX_LOCK()) {
 | |
| 
 | |
|     Wire.begin(HAS_BME680);
 | |
|     iaqSensor.begin(BME680_ADDR, Wire);
 | |
| 
 | |
|     ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major,
 | |
|              iaqSensor.version.minor, iaqSensor.version.major_bugfix,
 | |
|              iaqSensor.version.minor_bugfix);
 | |
| 
 | |
|     iaqSensor.setConfig(bsec_config_iaq);
 | |
| 
 | |
|     if (checkIaqSensorStatus())
 | |
|       ESP_LOGI(TAG, "BME680 sensor found and initialized");
 | |
|     else {
 | |
|       ESP_LOGE(TAG, "BME680 sensor not found");
 | |
|       rc = 0;
 | |
|       goto finish;
 | |
|     }
 | |
| 
 | |
|     loadState();
 | |
| 
 | |
|     iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET);
 | |
|     iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
 | |
| 
 | |
|     if (checkIaqSensorStatus())
 | |
|       ESP_LOGI(TAG, "BSEC subscription succesful");
 | |
|     else {
 | |
|       ESP_LOGE(TAG, "BSEC subscription error");
 | |
|       rc = 0;
 | |
|       goto finish;
 | |
|     }
 | |
|   } else {
 | |
|     ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error");
 | |
|     rc = 0;
 | |
|     goto finish;
 | |
|   }
 | |
| 
 | |
| #elif defined HAS_BME280
 | |
| 
 | |
|   bool status;
 | |
| 
 | |
|   // block i2c bus access
 | |
|   if (I2C_MUTEX_LOCK()) {
 | |
| 
 | |
|     status = bme.begin(BME280_ADDR);
 | |
|     if (!status) {
 | |
|       ESP_LOGE(TAG, "BME280 sensor not found");
 | |
|       rc = 0;
 | |
|       goto finish;
 | |
|     }
 | |
|     ESP_LOGI(TAG, "BME280 sensor found and initialized");
 | |
|   } else {
 | |
|     ESP_LOGE(TAG, "I2c bus busy - BME280 initialization error");
 | |
|     rc = 0;
 | |
|     goto finish;
 | |
|   }
 | |
| 
 | |
| #elif defined HAS_BMP180
 | |
|   bool status;
 | |
|   // block i2c bus access
 | |
|   if (I2C_MUTEX_LOCK()) {
 | |
|     // Wire.begin(21, 22);
 | |
|     status = bmp.begin();
 | |
|     if (!status) {
 | |
|       ESP_LOGE(TAG, "BMP180 sensor not found");
 | |
|       rc = 0;
 | |
|       goto finish;
 | |
|     }
 | |
|     ESP_LOGI(TAG, "BMP180 sensor found and initialized");
 | |
|   } else {
 | |
|     ESP_LOGE(TAG, "I2c bus busy - BMP180 initialization error");
 | |
|     rc = 0;
 | |
|     goto finish;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
| finish:
 | |
|   I2C_MUTEX_UNLOCK(); // release i2c bus access
 | |
|   if (rc)
 | |
|     bmecycler.attach(BMECYCLE, setBMEIRQ);
 | |
|   return rc;
 | |
| 
 | |
| } // bme_init()
 | |
| 
 | |
| #ifdef HAS_BME680
 | |
| 
 | |
| // Helper function definitions
 | |
| int checkIaqSensorStatus(void) {
 | |
|   int rslt = 1; // true = 1 = no error, false = 0 = error
 | |
| 
 | |
|   if (iaqSensor.status != BSEC_OK) {
 | |
|     rslt = 0;
 | |
|     if (iaqSensor.status < BSEC_OK)
 | |
|       ESP_LOGE(TAG, "BSEC error %d", iaqSensor.status);
 | |
|     else
 | |
|       ESP_LOGW(TAG, "BSEC warning %d", iaqSensor.status);
 | |
|   }
 | |
| 
 | |
|   if (iaqSensor.bme680Status != BME680_OK) {
 | |
|     rslt = 0;
 | |
|     if (iaqSensor.bme680Status < BME680_OK)
 | |
|       ESP_LOGE(TAG, "BME680 error %d", iaqSensor.bme680Status);
 | |
|     else
 | |
|       ESP_LOGW(TAG, "BME680 warning %d", iaqSensor.bme680Status);
 | |
|   }
 | |
| 
 | |
|   return rslt;
 | |
| } // checkIaqSensorStatus()
 | |
| #endif
 | |
| 
 | |
| // store current BME sensor data in struct
 | |
| void bme_storedata(bmeStatus_t *bme_store) {
 | |
| 
 | |
|   if ((cfg.payloadmask & MEMS_DATA) &&
 | |
|       (I2C_MUTEX_LOCK())) { // block i2c bus access
 | |
| 
 | |
| #ifdef HAS_BME680
 | |
|     if (iaqSensor.run()) { // if new data is available
 | |
|       bme_store->raw_temperature =
 | |
|           iaqSensor.rawTemperature; // temperature in degree celsius
 | |
|       bme_store->raw_humidity = iaqSensor.rawHumidity;
 | |
|       bme_store->temperature = iaqSensor.temperature;
 | |
|       bme_store->humidity =
 | |
|           iaqSensor.humidity;           // humidity in % relative humidity x1000
 | |
|       bme_store->pressure =             // pressure in Pascal
 | |
|           (iaqSensor.pressure / 100.0); // conversion Pa -> hPa
 | |
|       bme_store->iaq = iaqSensor.iaq;
 | |
|       bme_store->iaq_accuracy = iaqSensor.iaqAccuracy;
 | |
|       bme_store->gas = iaqSensor.gasResistance; // gas resistance in ohms
 | |
|       updateState();
 | |
|     }
 | |
| #elif defined HAS_BME280
 | |
|     bme_store->temperature = bme.readTemperature();
 | |
|     bme_store->pressure = (bme.readPressure() / 100.0); // conversion Pa -> hPa
 | |
|     // bme.readAltitude(SEALEVELPRESSURE_HPA);
 | |
|     bme_store->humidity = bme.readHumidity();
 | |
|     bme_store->iaq = 0; // IAQ feature not present with BME280
 | |
| #elif defined HAS_BMP180
 | |
|     bme_store->temperature = bmp.readTemperature();
 | |
|     bme_store->pressure = (bmp.readPressure() / 100.0); // conversion Pa -> hPa
 | |
|     // bme.readAltitude(SEALEVELPRESSURE_HPA);
 | |
|     bme_store->iaq = 0; // IAQ feature not present with BME280
 | |
| #endif
 | |
| 
 | |
|     I2C_MUTEX_UNLOCK(); // release i2c bus access
 | |
|   }
 | |
| 
 | |
| } // bme_storedata()
 | |
| 
 | |
| #ifdef HAS_BME680
 | |
| void loadState(void) {
 | |
|   if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] == BSEC_MAX_STATE_BLOB_SIZE) {
 | |
|     // Existing state in NVS stored
 | |
|     ESP_LOGI(TAG, "restoring BSEC state from NVRAM");
 | |
|     memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE);
 | |
|     iaqSensor.setState(bsecstate_buffer);
 | |
|     checkIaqSensorStatus();
 | |
|   } else // no state stored
 | |
|     ESP_LOGI(TAG,
 | |
|              "no BSEC state stored in NVRAM, starting sensor with defaults");
 | |
| }
 | |
| 
 | |
| void updateState(void) {
 | |
|   bool update = false;
 | |
| 
 | |
|   if (stateUpdateCounter == 0) {
 | |
|     // first state update when IAQ accuracy is >= 1
 | |
|     if (iaqSensor.iaqAccuracy >= 1) {
 | |
|       update = true;
 | |
|       stateUpdateCounter++;
 | |
|     }
 | |
|   } else {
 | |
| 
 | |
|     /* Update every STATE_SAVE_PERIOD minutes */
 | |
|     if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) {
 | |
|       update = true;
 | |
|       stateUpdateCounter++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (update) {
 | |
|     iaqSensor.getState(bsecstate_buffer);
 | |
|     checkIaqSensorStatus();
 | |
|     memcpy(cfg.bsecstate, bsecstate_buffer, BSEC_MAX_STATE_BLOB_SIZE);
 | |
|     cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = BSEC_MAX_STATE_BLOB_SIZE;
 | |
|     ESP_LOGI(TAG, "saving BSEC state to NVRAM");
 | |
|     saveConfig();
 | |
|   }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #endif // HAS_BME
 |