From 09dc9805bc38af06be522a2d81b89439bf7dc47b Mon Sep 17 00:00:00 2001 From: admar Date: Sun, 1 Sep 2024 22:10:53 +0200 Subject: [PATCH] Added BME680 sensor --- .vscode/c_cpp_properties.json | 10 ++-- .vscode/settings.json | 5 ++ include/display.hpp | 2 +- include/sensor_manager.hpp | 55 +++++++++++++++++++ include/wifi_handler.hpp | 6 +- platformio.ini | 1 + src/display.cpp | 30 +++++++++- src/main.cpp | 9 +++ src/sensor_manager.cpp | 100 ++++++++++++++++++++++++++++++++++ 9 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 include/sensor_manager.hpp create mode 100644 src/sensor_manager.cpp diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index ec0e346..e0a9f3a 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -11,6 +11,9 @@ "/home/admar/Documents/Arduino/buienradarklok/Claire/include", "/home/admar/Documents/Arduino/buienradarklok/Claire/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src", + "/home/admar/Documents/Arduino/buienradarklok/Claire/.pio/libdeps/esp32dev/BSEC Software Library/src", + "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src", + "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "/home/admar/Documents/Arduino/buienradarklok/Claire/.pio/libdeps/esp32dev/Adafruit NeoPixel", "/home/admar/Documents/Arduino/buienradarklok/Claire/.pio/libdeps/esp32dev/dESPatch", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Update/src", @@ -237,12 +240,10 @@ "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SD/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src", - "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/USB/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src", - "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src", "" ], "browse": { @@ -251,6 +252,9 @@ "/home/admar/Documents/Arduino/buienradarklok/Claire/include", "/home/admar/Documents/Arduino/buienradarklok/Claire/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src", + "/home/admar/Documents/Arduino/buienradarklok/Claire/.pio/libdeps/esp32dev/BSEC Software Library/src", + "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src", + "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "/home/admar/Documents/Arduino/buienradarklok/Claire/.pio/libdeps/esp32dev/Adafruit NeoPixel", "/home/admar/Documents/Arduino/buienradarklok/Claire/.pio/libdeps/esp32dev/dESPatch", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Update/src", @@ -477,12 +481,10 @@ "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SD/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src", - "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/USB/src", "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src", - "/home/admar/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src", "" ] }, diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a478c1f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "string_view": "cpp" + } +} \ No newline at end of file diff --git a/include/display.hpp b/include/display.hpp index eafc80c..8b2d0f6 100644 --- a/include/display.hpp +++ b/include/display.hpp @@ -16,7 +16,7 @@ class Display { ArduinoJson::V710PB22::JsonArray p_aqi); void setPrecipitationForecastLeds(uint32_t p_current_time, ArduinoJson::V710PB22::JsonArray p_precipitation); void setUVIForecastLed(uint32_t p_current_time, ArduinoJson::V710PB22::JsonArray p_uvi); - void setLocalAirQualityLed(); + void setLocalAirQualityLed(float p_iaq); void setWifiStatusLed(bool p_is_connected); void setErrorLed(bool p_is_error); void setPixelColor(uint32_t p_index, uint8_t p_red, uint8_t p_green, uint8_t p_blue, uint8_t p_white); diff --git a/include/sensor_manager.hpp b/include/sensor_manager.hpp new file mode 100644 index 0000000..d1c39ed --- /dev/null +++ b/include/sensor_manager.hpp @@ -0,0 +1,55 @@ +#ifndef __SENSOR_MANAGER_HPP__ +#define __SENSOR_MANAGER_HPP__ + +#include "bsec.h" + +class SensorManager { + public: + // Public types + struct SensorData { + __typeof__(Bsec::iaq) iaq; + __typeof__(Bsec::iaqAccuracy) iaqAccuracy; + __typeof__(Bsec::staticIaq) staticIaq; + __typeof__(Bsec::co2Equivalent) co2Equivalent; + __typeof__(Bsec::breathVocEquivalent) breathVocEquivalent; + __typeof__(Bsec::rawTemperature) rawTemperature; + __typeof__(Bsec::pressure) pressure; + __typeof__(Bsec::rawHumidity) rawHumidity; + __typeof__(Bsec::gasResistance) gasResistance; + __typeof__(Bsec::stabStatus) stabStatus; + __typeof__(Bsec::runInStatus) runInStatus; + __typeof__(Bsec::temperature) temperature; + __typeof__(Bsec::humidity) humidity; + __typeof__(Bsec::gasPercentage) gasPercentage; + }; + + public: + // Constructor + SensorManager(); + + bool setup(); + + bool read(); + + public: + // Public members + SensorData data; + + private: + bool checkIaqSensorStatus(); + + private: + // Private static members + constexpr static uint16_t m_NUM_LEDS_PROTO_V1 = 29U; + constexpr static int16_t m_DATA_PIN_PROTO_V1 = 14; + constexpr static uint8_t m_BME_CS = 5U; + constexpr static uint8_t m_BSEC_CONFIG_IAQ[] = { +#include "config/generic_33v_3s_4d/bsec_iaq.txt" + }; + + private: + // Private members + Bsec m_iaqSensor; +}; + +#endif // __SENSOR_MANAGER_HPP__ diff --git a/include/wifi_handler.hpp b/include/wifi_handler.hpp index 5141a46..fcb03af 100644 --- a/include/wifi_handler.hpp +++ b/include/wifi_handler.hpp @@ -1,5 +1,5 @@ -#ifndef __WIFIHANDLER_HPP__ -#define __WIFIHANDLER_HPP__ +#ifndef __WIFI_HANDLER_HPP__ +#define __WIFI_HANDLER_HPP__ #include // https://github.com/admarschoonen/WiFiManager @@ -30,4 +30,4 @@ class WifiHandler { WiFiManager m_wifiManager; }; -#endif // __WIFIHANDLER_HPP__ \ No newline at end of file +#endif // __WIFI_HANDLER_HPP__ \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index cea889a..26f5450 100644 --- a/platformio.ini +++ b/platformio.ini @@ -19,3 +19,4 @@ lib_deps = https://github.com/admarschoonen/dESPatch.git#v0.9.5 bblanchon/ArduinoJson@^7.1.0 adafruit/Adafruit NeoPixel@^1.12.3 + boschsensortec/BSEC Software Library@^1.8.1492 diff --git a/src/display.cpp b/src/display.cpp index c7d78e7..f1daa10 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -72,7 +72,35 @@ void Display::setUVIForecastLed(uint32_t p_current_time, ArduinoJson::V710PB22:: } } -void Display::setLocalAirQualityLed() {} +void Display::setLocalAirQualityLed(float p_iaq) { + float value = 0.0f; + + if (p_iaq <= 50.0f) { + value = 1.0f; // Excellent + } else if (p_iaq <= 100.0f) { + value = 2.0f; // Good + } else if (p_iaq <= 125.0f) { + value = 4.0f; + } else if (p_iaq <= 150.0f) { + value = 4.0f; // Lightly polluted + } else if (p_iaq <= 175.0f) { + value = 5.0f; + } else if (p_iaq <= 200.0f) { + value = 6.0f; // Moderately polluted + } else if (p_iaq <= 225.0f) { + value = 7.0f; + } else if (p_iaq <= 250.0f) { + value = 8.0f; // Heavily polluted + } else if (p_iaq <= 300.0f) { + value = 9.0f; + } else if (p_iaq <= 350.0f) { + value = 10.0f; // Severely polluted + } else { + value = 11.0f; // Extremely polluted + } + + setPixelToColorMappedValue(m_local_air_quality_map, value); +} void Display::setWifiStatusLed(bool p_is_connected) { if (p_is_connected) { diff --git a/src/main.cpp b/src/main.cpp index e9efc3d..867ebd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include "../include/backend_communication.hpp" #include "../include/display.hpp" +#include "../include/sensor_manager.hpp" #include "../include/wifi_handler.hpp" #ifndef LED_BUILTIN @@ -28,6 +29,8 @@ WifiHandler wifi_handler(wifiHandlerFeedbackCb); BackendCommunication backend_communication(wifi_handler); +SensorManager sensor_manager; + void wifiHandlerFeedbackCb(WiFiManager::Status p_wifi_status) { static bool state = false; @@ -75,6 +78,8 @@ void setup() { int x = dESPatch.configure(url, true, false, interval, false, root_ca); Serial.println(String(millis()) + " dESPatch.configure() returned with code " + String(x)); + + sensor_manager.setup(); } void loop(void) { @@ -99,9 +104,13 @@ void loop(void) { display.setUVIForecastLed(utc_time, backend_communication.m_weather_data["UVI"].as()); + display.setLocalAirQualityLed(sensor_manager.data.staticIaq); + display.setWifiStatusLed(false); } + sensor_manager.read(); + display.show(); dESPatch.checkForUpdate(true); diff --git a/src/sensor_manager.cpp b/src/sensor_manager.cpp new file mode 100644 index 0000000..3025630 --- /dev/null +++ b/src/sensor_manager.cpp @@ -0,0 +1,100 @@ +#include + +#include "../include/sensor_manager.hpp" + +SensorManager::SensorManager() { + data = {}; + return; +} + +bool SensorManager::setup() { + SPI.begin(); + m_iaqSensor.begin(m_BME_CS, SPI); + String output = "BSEC library version " + String(m_iaqSensor.version.major) + "." + + String(m_iaqSensor.version.minor) + "." + String(m_iaqSensor.version.major_bugfix) + "." + + String(m_iaqSensor.version.minor_bugfix); + Serial.println(output); + + if (not checkIaqSensorStatus()) { + return false; + } + + m_iaqSensor.setConfig(m_BSEC_CONFIG_IAQ); + m_iaqSensor.setTemperatureOffset(13.5f); + + if (not checkIaqSensorStatus()) { + return false; + } + + bsec_virtual_sensor_t sensorList[13] = {BSEC_OUTPUT_IAQ, + BSEC_OUTPUT_STATIC_IAQ, + BSEC_OUTPUT_CO2_EQUIVALENT, + BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, + BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + BSEC_OUTPUT_RAW_HUMIDITY, + BSEC_OUTPUT_RAW_GAS, + BSEC_OUTPUT_STABILIZATION_STATUS, + BSEC_OUTPUT_RUN_IN_STATUS, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, + BSEC_OUTPUT_GAS_PERCENTAGE}; + + m_iaqSensor.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP); + + if (checkIaqSensorStatus()) { + return false; + } + + return true; +} + +bool SensorManager::read() { + if (m_iaqSensor.run()) { // If new data is available + data.iaq = m_iaqSensor.iaq; + data.iaqAccuracy = m_iaqSensor.iaqAccuracy; + data.staticIaq = m_iaqSensor.staticIaq; + data.co2Equivalent = m_iaqSensor.co2Equivalent; + data.breathVocEquivalent = m_iaqSensor.breathVocEquivalent; + data.rawTemperature = m_iaqSensor.rawTemperature; + data.pressure = m_iaqSensor.pressure; + data.rawHumidity = m_iaqSensor.rawHumidity; + data.gasResistance = m_iaqSensor.gasResistance; + data.stabStatus = m_iaqSensor.stabStatus; + data.runInStatus = m_iaqSensor.runInStatus; + data.temperature = m_iaqSensor.temperature; + data.humidity = m_iaqSensor.humidity; + data.gasPercentage = m_iaqSensor.gasPercentage; + } else { + Serial.println("sensor status: " + String(checkIaqSensorStatus())); + } + return true; +} + +bool SensorManager::checkIaqSensorStatus() { + if (m_iaqSensor.bsecStatus != BSEC_OK) { + if (m_iaqSensor.bsecStatus < BSEC_OK) { + Serial.println("BSEC error code: " + String(m_iaqSensor.bsecStatus)); + + return false; + } else { + Serial.println("BSEC warning code: " + String(m_iaqSensor.bsecStatus)); + + return false; + } + } + + if (m_iaqSensor.bme68xStatus != BME68X_OK) { + if (m_iaqSensor.bme68xStatus < BME68X_OK) { + Serial.println("BME68X error code: " + String(m_iaqSensor.bme68xStatus)); + + return false; + } else { + Serial.println("BME68X warning code: " + String(m_iaqSensor.bme68xStatus)); + + return false; + } + } + + return true; +} \ No newline at end of file