#ifndef BME680_H #define BME680_H #include "Adafruit_BME680.h" #include "mqtt.h" class BME680 { Adafruit_BME680 bme; // NOLINT(*-interfaces-global-init) unsigned long last = 0UL; public: const String name; unsigned long intervalMs; explicit BME680(String name, const unsigned long interval_ms = 5000) : name(std::move(name)), intervalMs(interval_ms) { // } void setup() { if (bme.begin()) { Log.printf("BME680 \"%s\": Initialized.\n", name.c_str()); } else { Log.printf("BME680 \"%s\": Failed to initialize.\n", name.c_str()); } 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); } void loop() { const auto now = max(1UL, millis()); if (last == 0 || now - last >= intervalMs) { if (bme.beginReading() == 0) { Log.printf("BME680 \"%s\": Failed to request reading.\n", name.c_str()); setup(); } last = now; } if (bme.remainingReadingMillis() == 0) { if (bme.endReading()) { const auto humidityAbsolute = calculateHumidityAbsolute(bme.temperature, bme.humidity); mqttPublishValue(name + "/temperature", bme.temperature, "TEMPERATURE_C"); mqttPublishValue(name + "/pressure", bme.pressure / 100.0, "PRESSURE_HPA"); mqttPublishValue(name + "/humidity/relative", bme.humidity, "HUMIDITY_RELATIVE_PERCENT"); mqttPublishValue(name + "/humidity/absolute", humidityAbsolute, "HUMIDITY_ABSOLUTE_MGL"); mqttPublishValue(name + "/gas", bme.gas_resistance, "RESISTANCE_OHMS"); mqttPublishValue(name + "/altitude", bme.readAltitude(1013.25), "ALTITUDE_M"); } else { Log.printf("BME680 \"%s\": Failed to complete reading\n", name.c_str()); setup(); } } } static double calculateHumidityAbsolute(const double temperature, const double humidityRelative) { constexpr auto A = 6.112; constexpr auto m = 17.67; constexpr auto Tn = 243.5; constexpr auto Mw = 18.01534; constexpr auto R = 8.314462618; const auto Tk = temperature + 273.15; const auto P_sat = A * exp((m * temperature) / (temperature + Tn)); const auto P_act = P_sat * (humidityRelative / 100.0); return (P_act * Mw) / (R * Tk); } }; #endif