mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-05-14 16:55:10 +00:00
Merge pull request #2327 from NickDunklee/fix-environment-sensor-refactor
fix(sensors): improve sensor initialization and handling to prevent hangs and handle growth
This commit is contained in:
@@ -6,6 +6,10 @@
|
||||
#define TELEM_WIRE &Wire // Use default I2C bus for Environment Sensors
|
||||
#endif
|
||||
|
||||
// ============================================================
|
||||
// Sensor library includes and static driver instances
|
||||
// ============================================================
|
||||
|
||||
#ifdef ENV_INCLUDE_BME680
|
||||
#ifndef TELEM_BME680_ADDRESS
|
||||
#define TELEM_BME680_ADDRESS 0x76
|
||||
@@ -31,7 +35,7 @@ static Adafruit_AHTX0 AHTX0;
|
||||
#ifndef TELEM_BME280_ADDRESS
|
||||
#define TELEM_BME280_ADDRESS 0x76 // BME280 environmental sensor I2C address
|
||||
#endif
|
||||
#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level
|
||||
#define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25) // Atmospheric pressure at sea level
|
||||
#include <Adafruit_BME280.h>
|
||||
static Adafruit_BME280 BME280;
|
||||
#endif
|
||||
@@ -40,7 +44,7 @@ static Adafruit_BME280 BME280;
|
||||
#ifndef TELEM_BMP280_ADDRESS
|
||||
#define TELEM_BMP280_ADDRESS 0x76 // BMP280 environmental sensor I2C address
|
||||
#endif
|
||||
#define TELEM_BMP280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level
|
||||
#define TELEM_BMP280_SEALEVELPRESSURE_HPA (1013.25) // Atmospheric pressure at sea level
|
||||
#include <Adafruit_BMP280.h>
|
||||
static Adafruit_BMP280 BMP280(TELEM_WIRE);
|
||||
#endif
|
||||
@@ -51,7 +55,7 @@ static Adafruit_SHTC3 SHTC3;
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_SHT4X
|
||||
#define TELEM_SHT4X_ADDRESS 0x44 //0x44 - 0x46
|
||||
#define TELEM_SHT4X_ADDRESS 0x44
|
||||
#include <SensirionI2cSht4x.h>
|
||||
static SensirionI2cSht4x SHT4X;
|
||||
#endif
|
||||
@@ -63,7 +67,7 @@ LPS22HBClass LPS22HB(*TELEM_WIRE);
|
||||
|
||||
#if ENV_INCLUDE_INA3221
|
||||
#ifndef TELEM_INA3221_ADDRESS
|
||||
#define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address
|
||||
#define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address
|
||||
#endif
|
||||
#ifndef TELEM_INA3221_SHUNT_VALUE
|
||||
#define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts
|
||||
@@ -88,9 +92,9 @@ static Adafruit_INA260 INA260;
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA226
|
||||
#define TELEM_INA226_ADDRESS 0x44
|
||||
#define TELEM_INA226_ADDRESS 0x44
|
||||
#define TELEM_INA226_SHUNT_VALUE 0.100
|
||||
#define TELEM_INA226_MAX_AMP 0.8
|
||||
#define TELEM_INA226_MAX_AMP 0.8
|
||||
#include <INA226.h>
|
||||
static INA226 INA226(TELEM_INA226_ADDRESS, TELEM_WIRE);
|
||||
#endif
|
||||
@@ -161,10 +165,352 @@ public:
|
||||
static RAK12500LocationProvider RAK12500_provider;
|
||||
#endif
|
||||
|
||||
// ============================================================
|
||||
// I2C bus scanner
|
||||
// Probes every valid address and records which ones ACK.
|
||||
// This runs before any sensor library is touched, so a missing
|
||||
// or misbehaving device cannot stall or crash the boot sequence.
|
||||
// ============================================================
|
||||
|
||||
static void scanI2CBus(TwoWire* wire, bool found[128]) {
|
||||
for (uint8_t addr = 0x08; addr < 0x78; addr++) {
|
||||
wire->beginTransmission(addr);
|
||||
found[addr] = (wire->endTransmission() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Per-sensor init and query functions
|
||||
//
|
||||
// init(wire, address) — called only when the address was seen
|
||||
// on the bus. Returns 0 on failure, or the number of
|
||||
// telemetry channels the sensor will consume (1 for all
|
||||
// single-output sensors; INA3221 returns one per enabled
|
||||
// hardware channel; MLX90614 and RAK12035+calibration
|
||||
// return 2).
|
||||
//
|
||||
// query(channel, sub_channel, lpp) — called once per active
|
||||
// sensor entry during querySensors(). sub_channel is always
|
||||
// 0 for single-output sensors.
|
||||
// ============================================================
|
||||
|
||||
#if ENV_INCLUDE_AHTX0
|
||||
static uint8_t init_ahtx0(TwoWire* wire, uint8_t addr) {
|
||||
return AHTX0.begin(wire, 0, addr) ? 1 : 0;
|
||||
}
|
||||
static void query_ahtx0(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
sensors_event_t humidity, temp;
|
||||
AHTX0.getEvent(&humidity, &temp);
|
||||
lpp.addTemperature(ch, temp.temperature);
|
||||
lpp.addRelativeHumidity(ch, humidity.relative_humidity);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENV_INCLUDE_BME680
|
||||
static uint8_t init_bme680(TwoWire*, uint8_t addr) {
|
||||
// Wire was set in the static constructor; begin() takes address only.
|
||||
return BME680.begin(addr) ? 1 : 0;
|
||||
}
|
||||
static void query_bme680(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
if (BME680.performReading()) {
|
||||
lpp.addTemperature(ch, BME680.temperature);
|
||||
lpp.addRelativeHumidity(ch, BME680.humidity);
|
||||
lpp.addBarometricPressure(ch, BME680.pressure / 100);
|
||||
lpp.addAltitude(ch, 44330.0 * (1.0 - pow((BME680.pressure / 100) / TELEM_BME680_SEALEVELPRESSURE_HPA, 0.1903)));
|
||||
lpp.addAnalogInput(ch, BME680.gas_resistance);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME280
|
||||
static uint8_t init_bme280(TwoWire* wire, uint8_t addr) {
|
||||
if (!BME280.begin(addr, wire)) return 0;
|
||||
BME280.setSampling(Adafruit_BME280::MODE_FORCED,
|
||||
Adafruit_BME280::SAMPLING_X1,
|
||||
Adafruit_BME280::SAMPLING_X1,
|
||||
Adafruit_BME280::SAMPLING_X1,
|
||||
Adafruit_BME280::FILTER_OFF,
|
||||
Adafruit_BME280::STANDBY_MS_1000);
|
||||
return 1;
|
||||
}
|
||||
static void query_bme280(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
if (BME280.takeForcedMeasurement()) {
|
||||
lpp.addTemperature(ch, BME280.readTemperature());
|
||||
lpp.addRelativeHumidity(ch, BME280.readHumidity());
|
||||
lpp.addBarometricPressure(ch, BME280.readPressure() / 100);
|
||||
lpp.addAltitude(ch, BME280.readAltitude(TELEM_BME280_SEALEVELPRESSURE_HPA));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BMP280
|
||||
static uint8_t init_bmp280(TwoWire*, uint8_t addr) {
|
||||
// BMP280 static instance was constructed with TELEM_WIRE; begin() uses it.
|
||||
return BMP280.begin(addr) ? 1 : 0;
|
||||
}
|
||||
static void query_bmp280(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
lpp.addTemperature(ch, BMP280.readTemperature());
|
||||
lpp.addBarometricPressure(ch, BMP280.readPressure() / 100);
|
||||
lpp.addAltitude(ch, BMP280.readAltitude(TELEM_BMP280_SEALEVELPRESSURE_HPA));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_SHTC3
|
||||
static uint8_t init_shtc3(TwoWire* wire, uint8_t) {
|
||||
// Adafruit_SHTC3::begin() does not accept an address (fixed at 0x70).
|
||||
return SHTC3.begin(wire) ? 1 : 0;
|
||||
}
|
||||
static void query_shtc3(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
sensors_event_t humidity, temp;
|
||||
SHTC3.getEvent(&humidity, &temp);
|
||||
lpp.addTemperature(ch, temp.temperature);
|
||||
lpp.addRelativeHumidity(ch, humidity.relative_humidity);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_SHT4X
|
||||
static uint8_t init_sht4x(TwoWire* wire, uint8_t addr) {
|
||||
// SensirionI2cSht4x::begin() does not probe the hardware; use serialNumber()
|
||||
// as the actual presence check since it performs a real I2C transaction.
|
||||
SHT4X.begin(*wire, addr);
|
||||
uint32_t serial = 0;
|
||||
return (SHT4X.serialNumber(serial) == 0) ? 1 : 0;
|
||||
}
|
||||
static void query_sht4x(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
float temperature, humidity;
|
||||
if (SHT4X.measureLowestPrecision(temperature, humidity) == 0) {
|
||||
lpp.addTemperature(ch, temperature);
|
||||
lpp.addRelativeHumidity(ch, humidity);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_LPS22HB
|
||||
static uint8_t init_lps22hb(TwoWire*, uint8_t) {
|
||||
// LPS22HBClass is constructed with the wire reference; begin() uses it.
|
||||
return LPS22HB.begin() ? 1 : 0;
|
||||
}
|
||||
static void query_lps22hb(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
lpp.addTemperature(ch, LPS22HB.readTemperature());
|
||||
lpp.addBarometricPressure(ch, LPS22HB.readPressure() * 10); // convert kPa to hPa
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA3221
|
||||
static uint8_t init_ina3221(TwoWire* wire, uint8_t addr) {
|
||||
if (!INA3221.begin(addr, wire)) return 0;
|
||||
for (int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) {
|
||||
INA3221.setShuntResistance(i, TELEM_INA3221_SHUNT_VALUE);
|
||||
}
|
||||
// Each enabled hardware channel becomes its own telemetry channel.
|
||||
uint8_t enabled = 0;
|
||||
for (int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) {
|
||||
if (INA3221.isChannelEnabled(i)) enabled++;
|
||||
}
|
||||
return enabled > 0 ? enabled : 1;
|
||||
}
|
||||
static void query_ina3221(uint8_t ch, uint8_t sub_ch, CayenneLPP& lpp) {
|
||||
// sub_ch is the index of the nth enabled hardware channel.
|
||||
uint8_t seen = 0;
|
||||
for (int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) {
|
||||
if (INA3221.isChannelEnabled(i)) {
|
||||
if (seen == sub_ch) {
|
||||
float v = INA3221.getBusVoltage(i);
|
||||
float c = INA3221.getCurrentAmps(i);
|
||||
lpp.addVoltage(ch, v);
|
||||
lpp.addCurrent(ch, c);
|
||||
lpp.addPower(ch, v * c);
|
||||
return;
|
||||
}
|
||||
seen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA219
|
||||
static uint8_t init_ina219(TwoWire* wire, uint8_t) {
|
||||
// INA219 static instance was constructed with the address; begin() uses it.
|
||||
return INA219.begin(wire) ? 1 : 0;
|
||||
}
|
||||
static void query_ina219(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
lpp.addVoltage(ch, INA219.getBusVoltage_V());
|
||||
lpp.addCurrent(ch, INA219.getCurrent_mA() / 1000.0f);
|
||||
lpp.addPower(ch, INA219.getPower_mW() / 1000.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA260
|
||||
static uint8_t init_ina260(TwoWire* wire, uint8_t addr) {
|
||||
return INA260.begin(addr, wire) ? 1 : 0;
|
||||
}
|
||||
static void query_ina260(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
lpp.addVoltage(ch, INA260.readBusVoltage() / 1000.0f);
|
||||
lpp.addCurrent(ch, INA260.readCurrent() / 1000.0f);
|
||||
lpp.addPower(ch, INA260.readPower() / 1000.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA226
|
||||
static uint8_t init_ina226(TwoWire*, uint8_t) {
|
||||
// INA226 static instance was constructed with address and wire.
|
||||
if (!INA226.begin()) return 0;
|
||||
INA226.setMaxCurrentShunt(TELEM_INA226_MAX_AMP, TELEM_INA226_SHUNT_VALUE);
|
||||
return 1;
|
||||
}
|
||||
static void query_ina226(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
lpp.addVoltage(ch, INA226.getBusVoltage());
|
||||
lpp.addCurrent(ch, INA226.getCurrent_mA() / 1000.0f);
|
||||
lpp.addPower(ch, INA226.getPower_mW() / 1000.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
static uint8_t init_mlx90614(TwoWire* wire, uint8_t addr) {
|
||||
return MLX90614.begin(addr, wire) ? 2 : 0; // 2 channels: object temp, ambient temp
|
||||
}
|
||||
static void query_mlx90614(uint8_t ch, uint8_t sub_ch, CayenneLPP& lpp) {
|
||||
if (sub_ch == 0)
|
||||
lpp.addTemperature(ch, MLX90614.readObjectTempC());
|
||||
else
|
||||
lpp.addTemperature(ch, MLX90614.readAmbientTempC());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
static uint8_t init_vl53l0x(TwoWire* wire, uint8_t addr) {
|
||||
return VL53L0X.begin(addr, false, wire) ? 1 : 0;
|
||||
}
|
||||
static void query_vl53l0x(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
VL53L0X_RangingMeasurementData_t measure;
|
||||
VL53L0X.rangingTest(&measure, false);
|
||||
lpp.addDistance(ch, measure.RangeStatus != 4 ? measure.RangeMilliMeter / 1000.0f : 0.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENV_INCLUDE_BMP085
|
||||
static uint8_t init_bmp085(TwoWire* wire, uint8_t) {
|
||||
return BMP085.begin(0, wire) ? 1 : 0; // mode 0 = ULTRALOWPOWER
|
||||
}
|
||||
static void query_bmp085(uint8_t ch, uint8_t, CayenneLPP& lpp) {
|
||||
lpp.addTemperature(ch, BMP085.readTemperature());
|
||||
lpp.addBarometricPressure(ch, BMP085.readPressure() / 100);
|
||||
lpp.addAltitude(ch, BMP085.readAltitude(TELEM_BMP085_SEALEVELPRESSURE_HPA * 100));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_RAK12035
|
||||
static uint8_t init_rak12035(TwoWire* wire, uint8_t addr) {
|
||||
// RAK12035 requires setup() before begin().
|
||||
RAK12035.setup(*wire);
|
||||
if (!RAK12035.begin(addr)) return 0;
|
||||
#ifdef ENABLE_RAK12035_CALIBRATION
|
||||
return 2; // moisture channel + calibration channel
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
static void query_rak12035(uint8_t ch, uint8_t sub_ch, CayenneLPP& lpp) {
|
||||
if (sub_ch == 0) {
|
||||
lpp.addTemperature(ch, RAK12035.get_sensor_temperature());
|
||||
lpp.addPercentage(ch, RAK12035.get_sensor_moisture());
|
||||
} else {
|
||||
#ifdef ENABLE_RAK12035_CALIBRATION
|
||||
float cap = RAK12035.get_sensor_capacitance();
|
||||
float wet = RAK12035.get_humidity_full();
|
||||
float dry = RAK12035.get_humidity_zero();
|
||||
lpp.addFrequency(ch, cap);
|
||||
lpp.addTemperature(ch, wet);
|
||||
lpp.addPower(ch, dry);
|
||||
if (cap > dry) RAK12035.set_humidity_zero(cap);
|
||||
if (cap < wet) RAK12035.set_humidity_full(cap);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================================================
|
||||
// Sensor descriptor table
|
||||
//
|
||||
// Each entry maps an I2C address to a sensor's init and query
|
||||
// functions. Only entries whose ENV_INCLUDE_* guard is defined
|
||||
// are compiled in. The sentinel at the end keeps the array
|
||||
// non-empty regardless of which sensors are enabled.
|
||||
//
|
||||
// Ordering here determines channel assignment at runtime:
|
||||
// the first detected+initialized sensor gets channel 2, the
|
||||
// next gets channel 3, and so on.
|
||||
// ============================================================
|
||||
|
||||
struct SensorDef {
|
||||
uint8_t address;
|
||||
const char* name;
|
||||
uint8_t (*init)(TwoWire* wire, uint8_t address);
|
||||
void (*query)(uint8_t channel, uint8_t sub_channel, CayenneLPP& telemetry);
|
||||
};
|
||||
|
||||
static const SensorDef SENSOR_TABLE[] = {
|
||||
#if ENV_INCLUDE_AHTX0
|
||||
{ TELEM_AHTX_ADDRESS, "AHT10/AHT20", init_ahtx0, query_ahtx0 },
|
||||
#endif
|
||||
#ifdef ENV_INCLUDE_BME680
|
||||
{ TELEM_BME680_ADDRESS, "BME680", init_bme680, query_bme680 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_BME280
|
||||
{ TELEM_BME280_ADDRESS, "BME280", init_bme280, query_bme280 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_BMP280
|
||||
{ TELEM_BMP280_ADDRESS, "BMP280", init_bmp280, query_bmp280 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_SHTC3
|
||||
{ 0x70, "SHTC3", init_shtc3, query_shtc3 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_SHT4X
|
||||
{ TELEM_SHT4X_ADDRESS, "SHT4X", init_sht4x, query_sht4x },
|
||||
#endif
|
||||
#if ENV_INCLUDE_LPS22HB
|
||||
{ 0x5C, "LPS22HB", init_lps22hb, query_lps22hb },
|
||||
#endif
|
||||
#if ENV_INCLUDE_INA3221
|
||||
{ TELEM_INA3221_ADDRESS, "INA3221", init_ina3221, query_ina3221 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_INA219
|
||||
{ TELEM_INA219_ADDRESS, "INA219", init_ina219, query_ina219 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_INA260
|
||||
{ TELEM_INA260_ADDRESS, "INA260", init_ina260, query_ina260 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_INA226
|
||||
{ TELEM_INA226_ADDRESS, "INA226", init_ina226, query_ina226 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
{ TELEM_MLX90614_ADDRESS,"MLX90614", init_mlx90614, query_mlx90614 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
{ TELEM_VL53L0X_ADDRESS, "VL53L0X", init_vl53l0x, query_vl53l0x },
|
||||
#endif
|
||||
#ifdef ENV_INCLUDE_BMP085
|
||||
{ 0x77, "BMP085", init_bmp085, query_bmp085 },
|
||||
#endif
|
||||
#if ENV_INCLUDE_RAK12035
|
||||
{ TELEM_RAK12035_ADDRESS,"RAK12035", init_rak12035, query_rak12035 },
|
||||
#endif
|
||||
{ 0, nullptr, nullptr, nullptr } // sentinel — keeps the array non-empty
|
||||
};
|
||||
|
||||
static const size_t SENSOR_TABLE_SIZE = (sizeof(SENSOR_TABLE) / sizeof(SENSOR_TABLE[0])) - 1;
|
||||
|
||||
// ============================================================
|
||||
// begin() — scan the I2C bus, then initialize only what was
|
||||
// found. A sensor whose address does not ACK during the scan
|
||||
// is never touched by a library call, preventing hangs or
|
||||
// crashes caused by absent or misbehaving hardware.
|
||||
// ============================================================
|
||||
|
||||
bool EnvironmentSensorManager::begin() {
|
||||
#if ENV_INCLUDE_GPS
|
||||
#ifdef RAK_WISBLOCK_GPS
|
||||
rakGPSInit(); //probe base board/sockets for GPS
|
||||
rakGPSInit();
|
||||
#else
|
||||
initBasicGPS();
|
||||
#endif
|
||||
@@ -181,361 +527,52 @@ bool EnvironmentSensorManager::begin() {
|
||||
MESH_DEBUG_PRINTLN("Second I2C initialized on pins SDA: %d SCL: %d", ENV_PIN_SDA, ENV_PIN_SCL);
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_AHTX0
|
||||
if (AHTX0.begin(TELEM_WIRE, 0, TELEM_AHTX_ADDRESS)) {
|
||||
MESH_DEBUG_PRINTLN("Found AHT10/AHT20 at address: %02X", TELEM_AHTX_ADDRESS);
|
||||
AHTX0_initialized = true;
|
||||
} else {
|
||||
AHTX0_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("AHT10/AHT20 was not found at I2C address %02X", TELEM_AHTX_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
// Scan the I2C bus before touching any sensor library.
|
||||
bool detected[128] = {};
|
||||
scanI2CBus(TELEM_WIRE, detected);
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
if (BME680.begin(TELEM_BME680_ADDRESS)) {
|
||||
MESH_DEBUG_PRINTLN("Found BME680 at address: %02X", TELEM_BME680_ADDRESS);
|
||||
BME680_initialized = true;
|
||||
} else {
|
||||
BME680_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("BME680 was not found at I2C address %02X", TELEM_BME680_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME280
|
||||
if (BME280.begin(TELEM_BME280_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found BME280 at address: %02X", TELEM_BME280_ADDRESS);
|
||||
MESH_DEBUG_PRINTLN("BME sensor ID: %02X", BME280.sensorID());
|
||||
// Reduce self-heating: single-shot conversions, light oversampling, long standby.
|
||||
BME280.setSampling(Adafruit_BME280::MODE_FORCED,
|
||||
Adafruit_BME280::SAMPLING_X1, // temperature
|
||||
Adafruit_BME280::SAMPLING_X1, // pressure
|
||||
Adafruit_BME280::SAMPLING_X1, // humidity
|
||||
Adafruit_BME280::FILTER_OFF,
|
||||
Adafruit_BME280::STANDBY_MS_1000);
|
||||
BME280_initialized = true;
|
||||
} else {
|
||||
BME280_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("BME280 was not found at I2C address %02X", TELEM_BME280_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BMP280
|
||||
if (BMP280.begin(TELEM_BMP280_ADDRESS)) {
|
||||
MESH_DEBUG_PRINTLN("Found BMP280 at address: %02X", TELEM_BMP280_ADDRESS);
|
||||
MESH_DEBUG_PRINTLN("BMP sensor ID: %02X", BMP280.sensorID());
|
||||
BMP280_initialized = true;
|
||||
} else {
|
||||
BMP280_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("BMP280 was not found at I2C address %02X", TELEM_BMP280_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_SHTC3
|
||||
if (SHTC3.begin(TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found sensor: SHTC3");
|
||||
SHTC3_initialized = true;
|
||||
} else {
|
||||
SHTC3_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("SHTC3 was not found at I2C address %02X", 0x70);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if ENV_INCLUDE_SHT4X
|
||||
SHT4X.begin(*TELEM_WIRE, TELEM_SHT4X_ADDRESS);
|
||||
uint32_t serialNumber = 0;
|
||||
int16_t sht4x_error;
|
||||
sht4x_error = SHT4X.serialNumber(serialNumber);
|
||||
if (sht4x_error == 0) {
|
||||
MESH_DEBUG_PRINTLN("Found SHT4X at address: %02X", TELEM_SHT4X_ADDRESS);
|
||||
SHT4X_initialized = true;
|
||||
} else {
|
||||
SHT4X_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("SHT4X was not found at I2C address %02X", TELEM_SHT4X_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_LPS22HB
|
||||
if (LPS22HB.begin()) {
|
||||
MESH_DEBUG_PRINTLN("Found sensor: LPS22HB");
|
||||
LPS22HB_initialized = true;
|
||||
} else {
|
||||
LPS22HB_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("LPS22HB was not found at I2C address %02X", 0x5C);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA3221
|
||||
if (INA3221.begin(TELEM_INA3221_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found INA3221 at address: %02X", TELEM_INA3221_ADDRESS);
|
||||
MESH_DEBUG_PRINTLN("%04X %04X", INA3221.getDieID(), INA3221.getManufacturerID());
|
||||
|
||||
for(int i = 0; i < 3; i++) {
|
||||
INA3221.setShuntResistance(i, TELEM_INA3221_SHUNT_VALUE);
|
||||
// Walk the sensor table and initialize only detected devices.
|
||||
_active_sensor_count = 0;
|
||||
for (size_t i = 0; i < SENSOR_TABLE_SIZE && _active_sensor_count < MAX_ACTIVE_SENSORS; i++) {
|
||||
const SensorDef& def = SENSOR_TABLE[i];
|
||||
if (!detected[def.address]) {
|
||||
MESH_DEBUG_PRINTLN("%s not detected at I2C address %02X", def.name, def.address);
|
||||
continue;
|
||||
}
|
||||
uint8_t n = def.init(TELEM_WIRE, def.address);
|
||||
if (n == 0) {
|
||||
MESH_DEBUG_PRINTLN("%s found at %02X but failed to initialize", def.name, def.address);
|
||||
continue;
|
||||
}
|
||||
MESH_DEBUG_PRINTLN("Found %s at address: %02X", def.name, def.address);
|
||||
for (uint8_t sub = 0; sub < n && _active_sensor_count < MAX_ACTIVE_SENSORS; sub++) {
|
||||
_active_sensors[_active_sensor_count++] = { def.query, sub };
|
||||
}
|
||||
INA3221_initialized = true;
|
||||
} else {
|
||||
INA3221_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("INA3221 was not found at I2C address %02X", TELEM_INA3221_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA219
|
||||
if (INA219.begin(TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found INA219 at address: %02X", TELEM_INA219_ADDRESS);
|
||||
INA219_initialized = true;
|
||||
} else {
|
||||
INA219_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("INA219 was not found at I2C address %02X", TELEM_INA219_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA260
|
||||
if (INA260.begin(TELEM_INA260_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found INA260 at address: %02X", TELEM_INA260_ADDRESS);
|
||||
INA260_initialized = true;
|
||||
} else {
|
||||
INA260_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("INA260 was not found at I2C address %02X", TELEM_INA260_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA226
|
||||
if (INA226.begin()) {
|
||||
MESH_DEBUG_PRINTLN("Found INA226 at address: %02X", TELEM_INA226_ADDRESS);
|
||||
INA226.setMaxCurrentShunt(TELEM_INA226_MAX_AMP, TELEM_INA226_SHUNT_VALUE);
|
||||
INA226_initialized = true;
|
||||
} else {
|
||||
INA226_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("INA226 was not found at I2C address %02X", TELEM_INA226_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
if (MLX90614.begin(TELEM_MLX90614_ADDRESS, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found MLX90614 at address: %02X", TELEM_MLX90614_ADDRESS);
|
||||
MLX90614_initialized = true;
|
||||
} else {
|
||||
MLX90614_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("MLX90614 was not found at I2C address %02X", TELEM_MLX90614_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
if (VL53L0X.begin(TELEM_VL53L0X_ADDRESS, false, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found VL53L0X at address: %02X", TELEM_VL53L0X_ADDRESS);
|
||||
VL53L0X_initialized = true;
|
||||
} else {
|
||||
VL53L0X_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("VL53L0X was not found at I2C address %02X", TELEM_VL53L0X_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BMP085
|
||||
// First argument is MODE (aka oversampling)
|
||||
// choose ULTRALOWPOWER
|
||||
if (BMP085.begin(0, TELEM_WIRE)) {
|
||||
MESH_DEBUG_PRINTLN("Found sensor BMP085");
|
||||
BMP085_initialized = true;
|
||||
} else {
|
||||
BMP085_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("BMP085 was not found at I2C address %02X", 0x77);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_RAK12035
|
||||
RAK12035.setup(*TELEM_WIRE);
|
||||
if (RAK12035.begin(TELEM_RAK12035_ADDRESS)) {
|
||||
MESH_DEBUG_PRINTLN("Found sensor RAK12035 at address: %02X", TELEM_RAK12035_ADDRESS);
|
||||
RAK12035_initialized = true;
|
||||
} else {
|
||||
RAK12035_initialized = false;
|
||||
MESH_DEBUG_PRINTLN("RAK12035 was not found at I2C address %02X", TELEM_RAK12035_ADDRESS);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// querySensors() — GPS stays on channel 1; each active sensor
|
||||
// gets the next available channel in the order it was
|
||||
// initialized.
|
||||
// ============================================================
|
||||
|
||||
bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
|
||||
next_available_channel = TELEM_CHANNEL_SELF + 1;
|
||||
|
||||
if (requester_permissions & TELEM_PERM_LOCATION && gps_active) {
|
||||
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude); // allow lat/lon via telemetry even if no GPS is detected
|
||||
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
|
||||
}
|
||||
|
||||
if (requester_permissions & TELEM_PERM_ENVIRONMENT) {
|
||||
|
||||
#if ENV_INCLUDE_AHTX0
|
||||
if (AHTX0_initialized) {
|
||||
sensors_event_t humidity, temp;
|
||||
AHTX0.getEvent(&humidity, &temp);
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, temp.temperature);
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, humidity.relative_humidity);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME680
|
||||
if (BME680_initialized) {
|
||||
if (BME680.performReading()) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, BME680.temperature);
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, BME680.humidity);
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BME680.pressure / 100);
|
||||
telemetry.addAltitude(TELEM_CHANNEL_SELF, 44330.0 * (1.0 - pow((BME680.pressure / 100) / TELEM_BME680_SEALEVELPRESSURE_HPA, 0.1903)));
|
||||
telemetry.addAnalogInput(next_available_channel, BME680.gas_resistance);
|
||||
next_available_channel++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BME280
|
||||
if (BME280_initialized) {
|
||||
if (BME280.takeForcedMeasurement()) { // trigger a fresh reading in forced mode
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, BME280.readTemperature());
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, BME280.readHumidity());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BME280.readPressure()/100);
|
||||
telemetry.addAltitude(TELEM_CHANNEL_SELF, BME280.readAltitude(TELEM_BME280_SEALEVELPRESSURE_HPA));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BMP280
|
||||
if (BMP280_initialized) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, BMP280.readTemperature());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BMP280.readPressure()/100);
|
||||
telemetry.addAltitude(TELEM_CHANNEL_SELF, BMP280.readAltitude(TELEM_BMP280_SEALEVELPRESSURE_HPA));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_SHTC3
|
||||
if (SHTC3_initialized) {
|
||||
sensors_event_t humidity, temp;
|
||||
SHTC3.getEvent(&humidity, &temp);
|
||||
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, temp.temperature);
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, humidity.relative_humidity);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_SHT4X
|
||||
if (SHT4X_initialized) {
|
||||
float sht4x_humidity, sht4x_temperature;
|
||||
int16_t sht4x_error;
|
||||
sht4x_error = SHT4X.measureLowestPrecision(sht4x_temperature, sht4x_humidity);
|
||||
if (sht4x_error == 0) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, sht4x_temperature);
|
||||
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, sht4x_humidity);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_LPS22HB
|
||||
if (LPS22HB_initialized) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, LPS22HB.readTemperature());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, LPS22HB.readPressure() * 10); // convert kPa to hPa
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA3221
|
||||
if (INA3221_initialized) {
|
||||
for(int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) {
|
||||
// add only enabled INA3221 channels to telemetry
|
||||
if (INA3221.isChannelEnabled(i)) {
|
||||
float voltage = INA3221.getBusVoltage(i);
|
||||
float current = INA3221.getCurrentAmps(i);
|
||||
telemetry.addVoltage(next_available_channel, voltage);
|
||||
telemetry.addCurrent(next_available_channel, current);
|
||||
telemetry.addPower(next_available_channel, voltage * current);
|
||||
next_available_channel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA219
|
||||
if (INA219_initialized) {
|
||||
telemetry.addVoltage(next_available_channel, INA219.getBusVoltage_V());
|
||||
telemetry.addCurrent(next_available_channel, INA219.getCurrent_mA() / 1000);
|
||||
telemetry.addPower(next_available_channel, INA219.getPower_mW() / 1000);
|
||||
for (int i = 0; i < _active_sensor_count; i++) {
|
||||
_active_sensors[i].query(next_available_channel, _active_sensors[i].sub_channel, telemetry);
|
||||
next_available_channel++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA260
|
||||
if (INA260_initialized) {
|
||||
telemetry.addVoltage(next_available_channel, INA260.readBusVoltage() / 1000);
|
||||
telemetry.addCurrent(next_available_channel, INA260.readCurrent() / 1000);
|
||||
telemetry.addPower(next_available_channel, INA260.readPower() / 1000);
|
||||
next_available_channel++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_INA226
|
||||
if (INA226_initialized) {
|
||||
telemetry.addVoltage(next_available_channel, INA226.getBusVoltage());
|
||||
telemetry.addCurrent(next_available_channel, INA226.getCurrent_mA() / 1000.0);
|
||||
telemetry.addPower(next_available_channel, INA226.getPower_mW() / 1000.0);
|
||||
next_available_channel++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_MLX90614
|
||||
if (MLX90614_initialized) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, MLX90614.readObjectTempC());
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF + 1, MLX90614.readAmbientTempC());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_VL53L0X
|
||||
if (VL53L0X_initialized) {
|
||||
VL53L0X_RangingMeasurementData_t measure;
|
||||
VL53L0X.rangingTest(&measure, false); // pass in 'true' to get debug data
|
||||
if (measure.RangeStatus != 4) { // phase failures
|
||||
telemetry.addDistance(TELEM_CHANNEL_SELF, measure.RangeMilliMeter / 1000.0f); // convert mm to m
|
||||
} else {
|
||||
telemetry.addDistance(TELEM_CHANNEL_SELF, 0.0f); // no valid measurement
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_BMP085
|
||||
if (BMP085_initialized) {
|
||||
telemetry.addTemperature(TELEM_CHANNEL_SELF, BMP085.readTemperature());
|
||||
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BMP085.readPressure() / 100);
|
||||
telemetry.addAltitude(TELEM_CHANNEL_SELF, BMP085.readAltitude(TELEM_BMP085_SEALEVELPRESSURE_HPA * 100));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENV_INCLUDE_RAK12035
|
||||
if (RAK12035_initialized) {
|
||||
|
||||
// RAK12035 Telemetry is Channel 2
|
||||
telemetry.addTemperature(2, RAK12035.get_sensor_temperature());
|
||||
telemetry.addPercentage(2, RAK12035.get_sensor_moisture());
|
||||
|
||||
// RAK12035 CALIBRATION Telemetry is Channel 3, if enabled
|
||||
|
||||
#ifdef ENABLE_RAK12035_CALIBRATION
|
||||
// Calibration Data Screen is Channel 3
|
||||
float cap = RAK12035.get_sensor_capacitance();
|
||||
float _wet = RAK12035.get_humidity_full();
|
||||
float _dry = RAK12035.get_humidity_zero();
|
||||
|
||||
telemetry.addFrequency(3, cap);
|
||||
telemetry.addTemperature(3, _wet);
|
||||
telemetry.addPower(3, _dry);
|
||||
|
||||
if(cap > _dry){
|
||||
RAK12035.set_humidity_zero(cap);
|
||||
}
|
||||
|
||||
if(cap < _wet){
|
||||
RAK12035.set_humidity_full(cap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -555,8 +592,6 @@ const char* EnvironmentSensorManager::getSettingName(int i) const {
|
||||
return "gps";
|
||||
}
|
||||
#endif
|
||||
// convenient way to add params (needed for some tests)
|
||||
// if (i == settings++) return "param.2";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -567,8 +602,6 @@ const char* EnvironmentSensorManager::getSettingValue(int i) const {
|
||||
return gps_active ? "1" : "0";
|
||||
}
|
||||
#endif
|
||||
// convenient way to add params ...
|
||||
// if (i == settings++) return "2";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -584,11 +617,7 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val
|
||||
}
|
||||
if (strcmp(name, "gps_interval") == 0) {
|
||||
uint32_t interval_seconds = atoi(value);
|
||||
if (interval_seconds > 0) {
|
||||
gps_update_interval_sec = interval_seconds;
|
||||
} else {
|
||||
gps_update_interval_sec = 1; // Default to 1 second if 0
|
||||
}
|
||||
gps_update_interval_sec = interval_seconds > 0 ? interval_seconds : 1;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -652,16 +681,10 @@ void EnvironmentSensorManager::rakGPSInit(){
|
||||
|
||||
//search for the correct IO standby pin depending on socket used
|
||||
if(gpsIsAwake(WB_IO2)){
|
||||
// MESH_DEBUG_PRINTLN("RAK base board is RAK19007/10");
|
||||
// MESH_DEBUG_PRINTLN("GPS is installed on Socket A");
|
||||
}
|
||||
else if(gpsIsAwake(WB_IO4)){
|
||||
// MESH_DEBUG_PRINTLN("RAK base board is RAK19003/9");
|
||||
// MESH_DEBUG_PRINTLN("GPS is installed on Socket C");
|
||||
}
|
||||
else if(gpsIsAwake(WB_IO5)){
|
||||
// MESH_DEBUG_PRINTLN("RAK base board is RAK19001/11");
|
||||
// MESH_DEBUG_PRINTLN("GPS is installed on Socket F");
|
||||
}
|
||||
else{
|
||||
MESH_DEBUG_PRINTLN("No GPS found");
|
||||
@@ -716,7 +739,7 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){
|
||||
gps_detected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
pinMode(ioPin, INPUT);
|
||||
MESH_DEBUG_PRINTLN("GPS did not init with this IO pin... try the next");
|
||||
return false;
|
||||
|
||||
@@ -6,27 +6,22 @@
|
||||
|
||||
class EnvironmentSensorManager : public SensorManager {
|
||||
protected:
|
||||
int next_available_channel = TELEM_CHANNEL_SELF + 1;
|
||||
static const int MAX_ACTIVE_SENSORS = 16;
|
||||
|
||||
bool AHTX0_initialized = false;
|
||||
bool BME280_initialized = false;
|
||||
bool BMP280_initialized = false;
|
||||
bool INA3221_initialized = false;
|
||||
bool INA219_initialized = false;
|
||||
bool INA260_initialized = false;
|
||||
bool INA226_initialized = false;
|
||||
bool SHTC3_initialized = false;
|
||||
bool LPS22HB_initialized = false;
|
||||
bool MLX90614_initialized = false;
|
||||
bool VL53L0X_initialized = false;
|
||||
bool SHT4X_initialized = false;
|
||||
bool BME680_initialized = false;
|
||||
bool BMP085_initialized = false;
|
||||
bool RAK12035_initialized = false;
|
||||
// Query function pointer + sub-channel index (for multi-channel sensors like INA3221).
|
||||
// Sub-channel is 0 for all single-output sensors.
|
||||
struct ActiveSensor {
|
||||
void (*query)(uint8_t channel, uint8_t sub_channel, CayenneLPP& telemetry);
|
||||
uint8_t sub_channel;
|
||||
};
|
||||
|
||||
bool gps_detected = false;
|
||||
bool gps_active = false;
|
||||
uint32_t gps_update_interval_sec = 1; // Default 1 second
|
||||
ActiveSensor _active_sensors[MAX_ACTIVE_SENSORS];
|
||||
int _active_sensor_count = 0;
|
||||
uint8_t next_available_channel = TELEM_CHANNEL_SELF + 1;
|
||||
|
||||
bool gps_detected = false;
|
||||
bool gps_active = false;
|
||||
uint32_t gps_update_interval_sec = 1;
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
LocationProvider* _location;
|
||||
@@ -39,7 +34,6 @@ protected:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
#if ENV_INCLUDE_GPS
|
||||
EnvironmentSensorManager(LocationProvider &location): _location(&location){};
|
||||
|
||||
Reference in New Issue
Block a user