mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-08-01 17:56:12 +00:00
Merge pull request #2634 from NickDunklee/bme680-fixes-consolidation
feat: Integrate BME680 Bosch BSEC support for RAK4631
This commit is contained in:
@@ -12,6 +12,31 @@
|
|||||||
// Sensor library includes and static driver instances
|
// Sensor library includes and static driver instances
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
|
#if ENV_INCLUDE_BME680_BSEC
|
||||||
|
#ifndef TELEM_BME680_ADDRESS
|
||||||
|
#define TELEM_BME680_ADDRESS 0x76
|
||||||
|
#endif
|
||||||
|
#define TELEM_BME680_SEALEVELPRESSURE_HPA (1013.25)
|
||||||
|
#include <bsec.h>
|
||||||
|
#include <Adafruit_LittleFS.h>
|
||||||
|
#include <InternalFileSystem.h>
|
||||||
|
static const uint8_t bsec_config_iaq[] = {
|
||||||
|
#include "config/generic_33v_3s_28d/bsec_iaq.txt" // 3.3v, LP, 28 day background calibration window
|
||||||
|
};
|
||||||
|
static Bsec bsec_iaq;
|
||||||
|
static float bsec_temperature = 0;
|
||||||
|
static float bsec_humidity = 0;
|
||||||
|
static float bsec_pressure_hpa = 0;
|
||||||
|
static float bsec_iaq_val = 0;
|
||||||
|
static uint8_t bsec_accuracy = 0;
|
||||||
|
static bool bsec_active = false;
|
||||||
|
static bool bsec_data_ready = false;
|
||||||
|
static bool bsec_first_save_done = false;
|
||||||
|
static uint32_t bsec_last_save_ms = 0;
|
||||||
|
#define BSEC_STATE_FILE "/bsec_state.bin"
|
||||||
|
#define BSEC_SAVE_INTERVAL_MS (8UL * 60 * 60 * 1000) // 8 hour state-save interval
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENV_INCLUDE_BME680
|
#ifdef ENV_INCLUDE_BME680
|
||||||
#ifndef TELEM_BME680_ADDRESS
|
#ifndef TELEM_BME680_ADDRESS
|
||||||
#define TELEM_BME680_ADDRESS 0x76
|
#define TELEM_BME680_ADDRESS 0x76
|
||||||
@@ -235,9 +260,10 @@ static void query_bme680(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
|||||||
if (BME680.performReading()) {
|
if (BME680.performReading()) {
|
||||||
lpp.addTemperature(ch, BME680.temperature);
|
lpp.addTemperature(ch, BME680.temperature);
|
||||||
lpp.addRelativeHumidity(ch, BME680.humidity);
|
lpp.addRelativeHumidity(ch, BME680.humidity);
|
||||||
lpp.addBarometricPressure(ch, BME680.pressure / 100);
|
const float pressure_hpa = BME680.pressure / 100.0f;
|
||||||
lpp.addAltitude(ch, 44330.0 * (1.0 - pow((BME680.pressure / 100) / TELEM_BME680_SEALEVELPRESSURE_HPA, 0.1903)));
|
lpp.addBarometricPressure(ch, pressure_hpa);
|
||||||
lpp.addAnalogInput(ch, BME680.gas_resistance);
|
lpp.addAltitude(ch, 44330.0f * (1.0f - powf(pressure_hpa / (float)TELEM_BME680_SEALEVELPRESSURE_HPA, 0.1903f)));
|
||||||
|
lpp.addGenericSensor(ch, BME680.gas_resistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -449,6 +475,62 @@ static void query_rak12035(uint8_t ch, uint8_t sub_ch, CayenneLPP& lpp) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENV_INCLUDE_BME680_BSEC
|
||||||
|
static void bsec_load_state() {
|
||||||
|
using namespace Adafruit_LittleFS_Namespace;
|
||||||
|
File f = InternalFS.open(BSEC_STATE_FILE, FILE_O_READ);
|
||||||
|
if (!f) return;
|
||||||
|
uint8_t state[BSEC_MAX_STATE_BLOB_SIZE];
|
||||||
|
f.read(state, BSEC_MAX_STATE_BLOB_SIZE);
|
||||||
|
f.close();
|
||||||
|
bsec_iaq.setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bsec_save_state() {
|
||||||
|
using namespace Adafruit_LittleFS_Namespace;
|
||||||
|
uint8_t state[BSEC_MAX_STATE_BLOB_SIZE];
|
||||||
|
bsec_iaq.getState(state);
|
||||||
|
InternalFS.remove(BSEC_STATE_FILE);
|
||||||
|
File f = InternalFS.open(BSEC_STATE_FILE, FILE_O_WRITE);
|
||||||
|
if (!f) return;
|
||||||
|
f.write(state, BSEC_MAX_STATE_BLOB_SIZE);
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t init_bme680_bsec(TwoWire* wire, uint8_t addr) {
|
||||||
|
bsec_iaq.begin(addr, *wire);
|
||||||
|
if (bsec_iaq.bsecStatus != BSEC_OK) return 0;
|
||||||
|
|
||||||
|
bsec_iaq.setConfig(bsec_config_iaq);
|
||||||
|
if (bsec_iaq.bsecStatus != BSEC_OK) return 0;
|
||||||
|
|
||||||
|
bsec_virtual_sensor_t outputs[] = {
|
||||||
|
BSEC_OUTPUT_IAQ,
|
||||||
|
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
|
||||||
|
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
|
||||||
|
BSEC_OUTPUT_RAW_PRESSURE,
|
||||||
|
BSEC_OUTPUT_STABILIZATION_STATUS,
|
||||||
|
BSEC_OUTPUT_RUN_IN_STATUS,
|
||||||
|
};
|
||||||
|
bsec_iaq.updateSubscription(outputs, 6, BSEC_SAMPLE_RATE_LP);
|
||||||
|
if (bsec_iaq.bsecStatus != BSEC_OK) return 0;
|
||||||
|
|
||||||
|
bsec_load_state();
|
||||||
|
bsec_active = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void query_bme680_bsec(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||||
|
if (!bsec_data_ready) return;
|
||||||
|
lpp.addTemperature(ch, bsec_temperature);
|
||||||
|
lpp.addRelativeHumidity(ch, bsec_humidity);
|
||||||
|
lpp.addBarometricPressure(ch, bsec_pressure_hpa);
|
||||||
|
lpp.addAltitude(ch, 44330.0f * (1.0f - powf(bsec_pressure_hpa / (float)TELEM_BME680_SEALEVELPRESSURE_HPA, 0.1903f)));
|
||||||
|
lpp.addGenericSensor(ch, (uint16_t)bsec_iaq_val);
|
||||||
|
lpp.addAnalogInput(ch, (float)bsec_accuracy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Sensor descriptor table
|
// Sensor descriptor table
|
||||||
//
|
//
|
||||||
@@ -476,6 +558,9 @@ static const SensorDef SENSOR_TABLE[] = {
|
|||||||
#ifdef ENV_INCLUDE_BME680
|
#ifdef ENV_INCLUDE_BME680
|
||||||
{ TELEM_BME680_ADDRESS, "BME680", init_bme680, query_bme680 },
|
{ TELEM_BME680_ADDRESS, "BME680", init_bme680, query_bme680 },
|
||||||
#endif
|
#endif
|
||||||
|
#if ENV_INCLUDE_BME680_BSEC
|
||||||
|
{ TELEM_BME680_ADDRESS, "BME680+BSEC", init_bme680_bsec, query_bme680_bsec },
|
||||||
|
#endif
|
||||||
#if ENV_INCLUDE_BME280
|
#if ENV_INCLUDE_BME280
|
||||||
{ TELEM_BME280_ADDRESS, "BME280", init_bme280, query_bme280 },
|
{ TELEM_BME280_ADDRESS, "BME280", init_bme280, query_bme280 },
|
||||||
#endif
|
#endif
|
||||||
@@ -798,11 +883,13 @@ void EnvironmentSensorManager::stop_gps() {
|
|||||||
MESH_DEBUG_PRINTLN("Stop GPS is N/A on this board. Actual GPS state unchanged");
|
MESH_DEBUG_PRINTLN("Stop GPS is N/A on this board. Actual GPS state unchanged");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // ENV_INCLUDE_GPS
|
||||||
|
|
||||||
|
#if ENV_INCLUDE_GPS || defined(ENV_INCLUDE_BME680_BSEC)
|
||||||
void EnvironmentSensorManager::loop() {
|
void EnvironmentSensorManager::loop() {
|
||||||
static long next_gps_update = 0;
|
|
||||||
|
|
||||||
#if ENV_INCLUDE_GPS
|
#if ENV_INCLUDE_GPS
|
||||||
|
static long next_gps_update = 0;
|
||||||
if (gps_active) {
|
if (gps_active) {
|
||||||
_location->loop();
|
_location->loop();
|
||||||
}
|
}
|
||||||
@@ -830,5 +917,27 @@ void EnvironmentSensorManager::loop() {
|
|||||||
next_gps_update = millis() + (gps_update_interval_sec * 1000);
|
next_gps_update = millis() + (gps_update_interval_sec * 1000);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if ENV_INCLUDE_BME680_BSEC
|
||||||
|
if (bsec_active && bsec_iaq.run()) {
|
||||||
|
uint8_t prev_accuracy = bsec_accuracy;
|
||||||
|
bsec_temperature = bsec_iaq.temperature;
|
||||||
|
bsec_humidity = bsec_iaq.humidity;
|
||||||
|
bsec_pressure_hpa = bsec_iaq.pressure / 100.0f;
|
||||||
|
bsec_iaq_val = bsec_iaq.iaq;
|
||||||
|
bsec_accuracy = bsec_iaq.iaqAccuracy;
|
||||||
|
bsec_data_ready = true;
|
||||||
|
|
||||||
|
if (bsec_accuracy == 3) {
|
||||||
|
if (!bsec_first_save_done) {
|
||||||
|
bsec_save_state();
|
||||||
|
bsec_last_save_ms = millis();
|
||||||
|
bsec_first_save_done = true;
|
||||||
|
} else if ((millis() - bsec_last_save_ms) >= BSEC_SAVE_INTERVAL_MS) {
|
||||||
|
bsec_save_state();
|
||||||
|
bsec_last_save_ms = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENV_INCLUDE_BME680_BSEC
|
||||||
}
|
}
|
||||||
#endif
|
#endif // ENV_INCLUDE_GPS || ENV_INCLUDE_BME680_BSEC
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
bool begin() override;
|
bool begin() override;
|
||||||
bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
|
bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
|
||||||
#if ENV_INCLUDE_GPS
|
#if ENV_INCLUDE_GPS || defined(ENV_INCLUDE_BME680_BSEC)
|
||||||
void loop() override;
|
void loop() override;
|
||||||
#endif
|
#endif
|
||||||
int getNumSettings() const override;
|
int getNumSettings() const override;
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
Import('env')
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Bosch has a goof in their PlatformIO packaging making linking fail.
|
||||||
|
# The BSEC library's extra_script.py selects cortex-m4/libalgobsec.a (soft-float ABI).
|
||||||
|
# nRF52840 compiles with -mfloat-abi=hard, requiring the fpv4-sp-d16-hard blob.
|
||||||
|
# Workaround to prepend the hard-float path so the linker finds it before the
|
||||||
|
# soft-float one.
|
||||||
|
bsec_hard = os.path.join(
|
||||||
|
env.subst('$PROJECT_DIR'),
|
||||||
|
'.pio', 'libdeps', env.subst('$PIOENV'),
|
||||||
|
'BSEC Software Library', 'src',
|
||||||
|
'cortex-m4', 'fpv4-sp-d16-hard'
|
||||||
|
)
|
||||||
|
env.Prepend(LIBPATH=[bsec_hard])
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
extends = nrf52_base
|
extends = nrf52_base
|
||||||
board = rak4631
|
board = rak4631
|
||||||
board_check = true
|
board_check = true
|
||||||
|
extra_scripts = ${nrf52_base.extra_scripts}
|
||||||
|
post:variants/rak4631/fix_bsec_lib.py
|
||||||
build_flags = ${nrf52_base.build_flags}
|
build_flags = ${nrf52_base.build_flags}
|
||||||
${sensor_base.build_flags}
|
${sensor_base.build_flags}
|
||||||
-I variants/rak4631
|
-I variants/rak4631
|
||||||
@@ -21,6 +23,8 @@ build_flags = ${nrf52_base.build_flags}
|
|||||||
-D SX126X_CURRENT_LIMIT=140
|
-D SX126X_CURRENT_LIMIT=140
|
||||||
-D SX126X_RX_BOOSTED_GAIN=1
|
-D SX126X_RX_BOOSTED_GAIN=1
|
||||||
-D ENV_INCLUDE_RAK12035=1
|
-D ENV_INCLUDE_RAK12035=1
|
||||||
|
-UENV_INCLUDE_BME680
|
||||||
|
-D ENV_INCLUDE_BME680_BSEC=1
|
||||||
build_src_filter = ${nrf52_base.build_src_filter}
|
build_src_filter = ${nrf52_base.build_src_filter}
|
||||||
+<../variants/rak4631>
|
+<../variants/rak4631>
|
||||||
+<helpers/sensors>
|
+<helpers/sensors>
|
||||||
@@ -31,6 +35,7 @@ lib_deps =
|
|||||||
${sensor_base.lib_deps}
|
${sensor_base.lib_deps}
|
||||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
adafruit/Adafruit SSD1306 @ ^2.5.13
|
||||||
sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
|
sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
|
||||||
|
boschsensortec/BSEC Software Library @ ^1.8.1492
|
||||||
|
|
||||||
[env:RAK_4631_repeater]
|
[env:RAK_4631_repeater]
|
||||||
extends = rak4631
|
extends = rak4631
|
||||||
|
|||||||
Reference in New Issue
Block a user