Add BME680 and SHTC3 support to meshtasticd and RAK4631

This commit is contained in:
JaeHwan Jin
2025-11-12 17:32:05 +09:00
parent 7212fb9caa
commit 52eb9c9f82
8 changed files with 83 additions and 8 deletions

View File

@@ -30,6 +30,8 @@ lib_deps=
${radiolib_base.lib_deps}
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.3.40408
lib_ignore =
BluetoothOTA

View File

@@ -33,6 +33,8 @@ lib_deps =
adafruit/Adafruit seesaw Library@1.7.9
# renovate: datasource=git-refs depName=RAK12034-BMX160 packageName=https://github.com/RAKWireless/RAK12034-BMX160 gitBranch=main
https://github.com/RAKWireless/RAK12034-BMX160/archive/dcead07ffa267d3c906e9ca4a1330ab989e957e2.zip
# renovate: datasource=custom.pio depName=adafruit/Adafruit BME680 Library packageName=adafruit/library/Adafruit BME680
adafruit/Adafruit BME680 Library@^2.0.5
build_flags =
${arduino_base.build_flags}

View File

@@ -160,6 +160,8 @@ lib_deps =
emotibit/EmotiBit MLX90632@1.0.8
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
adafruit/Adafruit MLX90614 Library@2.1.5
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.2
# renovate: datasource=github-tags depName=INA3221 packageName=sgtwilko/INA3221
https://github.com/sgtwilko/INA3221#bb03d7e9bfcc74fc798838a54f4f99738f29fc6a
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
@@ -192,8 +194,6 @@ lib_deps =
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.2
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
@@ -208,8 +208,6 @@ lib_deps =
ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
boschsensortec/bsec2@1.10.2610
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.3.40408
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core

View File

@@ -53,7 +53,9 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c
#include "Sensor/LTR390UVSensor.h"
#endif
#if __has_include(<bsec2.h>)
#include "Sensor/BME680Generic.h"
#if __has_include(BME680_HEADER)
#include "Sensor/BME680Sensor.h"
#endif
@@ -214,7 +216,7 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
#if __has_include(<Adafruit_LTR390.h>)
addSensor<LTR390UVSensor>(i2cScanner, ScanI2C::DeviceType::LTR390UV);
#endif
#if __has_include(<bsec2.h>)
#if __has_include(BME680_HEADER)
addSensor<BME680Sensor>(i2cScanner, ScanI2C::DeviceType::BME_680);
#endif
#if __has_include(<Adafruit_BMP280.h>)

View File

@@ -0,0 +1,9 @@
#include "configuration.h"
#ifndef BME680_HEADER
#if defined(ARCH_PORTDUINO)
#define BME680_HEADER <Adafruit_BME680.h>
#else
#define BME680_HEADER <bsec2.h>
#endif
#endif

View File

@@ -1,6 +1,8 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<bsec2.h>)
#include "BME680Generic.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(BME680_HEADER)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "BME680Sensor.h"
@@ -10,6 +12,7 @@
BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {}
#if !defined(ARCH_PORTDUINO)
int32_t BME680Sensor::runOnce()
{
if (!bme680.run()) {
@@ -17,10 +20,13 @@ int32_t BME680Sensor::runOnce()
}
return 35;
}
#endif // !defined(ARCH_PORTDUINO)
bool BME680Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
{
status = 0;
#if !defined(ARCH_PORTDUINO)
if (!bme680.begin(dev->address.address, *bus))
checkStatus("begin");
@@ -42,12 +48,25 @@ bool BME680Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
if (status == 0)
LOG_DEBUG("BME680Sensor::runOnce: bme680.status %d", bme680.status);
#else
bme680 = makeBME680(bus);
if (!bme680->begin(dev->address.address)) {
LOG_ERROR("Init sensor: %s failed at begin()", sensorName);
return status;
}
status = 1;
#endif // !defined(ARCH_PORTDUINO)
initI2CSensor();
return status;
}
bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
{
#if !defined(ARCH_PORTDUINO)
if (bme680.getData(BSEC_OUTPUT_RAW_PRESSURE).signal == 0)
return false;
@@ -65,9 +84,27 @@ bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
// Check if we need to save state to filesystem (every STATE_SAVE_PERIOD ms)
measurement->variant.environment_metrics.iaq = bme680.getData(BSEC_OUTPUT_IAQ).signal;
updateState();
#else
if (!bme680->performReading()) {
LOG_ERROR("BME680Sensor::getMetrics: performReading failed");
return false;
}
measurement->variant.environment_metrics.has_temperature = true;
measurement->variant.environment_metrics.has_relative_humidity = true;
measurement->variant.environment_metrics.has_barometric_pressure = true;
measurement->variant.environment_metrics.has_gas_resistance = true;
measurement->variant.environment_metrics.temperature = bme680->readTemperature();
measurement->variant.environment_metrics.relative_humidity = bme680->readHumidity();
measurement->variant.environment_metrics.barometric_pressure = bme680->readPressure() / 100.0F;
measurement->variant.environment_metrics.gas_resistance = bme680->readGas() / 1000.0;
#endif
return true;
}
#if !defined(ARCH_PORTDUINO)
void BME680Sensor::loadState()
{
#ifdef FSCom
@@ -144,5 +181,6 @@ void BME680Sensor::checkStatus(const char *functionName)
else if (bme680.sensor.status > BME68X_OK)
LOG_WARN("%s BME68X code: %d", functionName, bme680.sensor.status);
}
#endif // !defined(ARCH_PORTDUINO)
#endif

View File

@@ -1,23 +1,43 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(<bsec2.h>)
#include "BME680Generic.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include(BME680_HEADER)
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h"
#if defined(ARCH_PORTDUINO)
#include <Adafruit_BME680.h>
#include <memory>
#else // defined(ARCH_PORTDUINO)
#include <bme68xLibrary.h>
#include <bsec2.h>
#endif // defined(ARCH_PORTDUINO)
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // That's 6 hours worth of millis()
#if !defined(ARCH_PORTDUINO)
const uint8_t bsec_config[] = {
#include "config/bme680/bme680_iaq_33v_3s_4d/bsec_iaq.txt"
};
#endif // !defined(ARCH_PORTDUINO)
class BME680Sensor : public TelemetrySensor
{
private:
#if defined(ARCH_PORTDUINO)
using BME680Ptr = std::unique_ptr<Adafruit_BME680>;
static BME680Ptr makeBME680(TwoWire *bus) { return std::make_unique<Adafruit_BME680>(bus); }
BME680Ptr bme680;
#else
Bsec2 bme680;
#endif // defined(ARCH_PORTDUINO)
protected:
#if !defined(ARCH_PORTDUINO)
const char *bsecConfigFileName = "/prefs/bsec.dat";
uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
uint8_t accuracy = 0;
@@ -34,10 +54,13 @@ class BME680Sensor : public TelemetrySensor
void loadState();
void updateState();
void checkStatus(const char *functionName);
#endif // !defined(ARCH_PORTDUINO)
public:
BME680Sensor();
#if !defined(ARCH_PORTDUINO)
virtual int32_t runOnce() override;
#endif // !defined(ARCH_PORTDUINO)
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
};

View File

@@ -5,6 +5,7 @@ board = wiscore_rak4631
board_level = pr
board_check = true
build_flags = ${nrf52840_base.build_flags}
-g
-I variants/nrf52840/rak4631
-D RAK_4631
-DEINK_DISPLAY_MODEL=GxEPD2_213_BN