fix(sensors): probe BMP/BME at both 0x76 and 0x77

Grove and other Bosch modules strap SDO high, so the 0x76-only table
never initialized them. Add an alternate-address entry per Bosch sensor;
the bus scan still gates every probe, and all four drivers verify a chip
ID before claiming an address.

Each sensor type has a single static driver instance, so skip an entry
whose query is already active: the alternate address is a fallback, not
a second device.
This commit is contained in:
agessaman
2026-08-17 14:59:59 -07:00
parent 2b0ed00004
commit 2a6eabe120
@@ -539,6 +539,8 @@ static void query_bme680_bsec(uint8_t ch, uint8_t, CayenneLPP& lpp) {
// are compiled in. The sentinel at the end keeps the array // are compiled in. The sentinel at the end keeps the array
// non-empty regardless of which sensors are enabled. // non-empty regardless of which sensors are enabled.
// //
// Bosch BMP/BME SDO selects 0x76 or 0x77; probe both.
//
// Ordering here determines channel assignment at runtime: // Ordering here determines channel assignment at runtime:
// the first detected+initialized sensor gets channel 2, the // the first detected+initialized sensor gets channel 2, the
// next gets channel 3, and so on. // next gets channel 3, and so on.
@@ -551,21 +553,27 @@ struct SensorDef {
void (*query)(uint8_t channel, uint8_t sub_channel, CayenneLPP& telemetry); void (*query)(uint8_t channel, uint8_t sub_channel, CayenneLPP& telemetry);
}; };
#define TELEM_BOSCH_ALT_ADDR(addr) ((uint8_t)((addr) == 0x76 ? 0x77 : 0x76))
static const SensorDef SENSOR_TABLE[] = { static const SensorDef SENSOR_TABLE[] = {
#if ENV_INCLUDE_AHTX0 #if ENV_INCLUDE_AHTX0
{ TELEM_AHTX_ADDRESS, "AHT10/AHT20", init_ahtx0, query_ahtx0 }, { TELEM_AHTX_ADDRESS, "AHT10/AHT20", init_ahtx0, query_ahtx0 },
#endif #endif
#ifdef ENV_INCLUDE_BME680 #ifdef ENV_INCLUDE_BME680
{ TELEM_BME680_ADDRESS, "BME680", init_bme680, query_bme680 }, { TELEM_BME680_ADDRESS, "BME680", init_bme680, query_bme680 },
{ TELEM_BOSCH_ALT_ADDR(TELEM_BME680_ADDRESS), "BME680", init_bme680, query_bme680 },
#endif #endif
#if ENV_INCLUDE_BME680_BSEC #if ENV_INCLUDE_BME680_BSEC
{ TELEM_BME680_ADDRESS, "BME680+BSEC", init_bme680_bsec, query_bme680_bsec }, { TELEM_BME680_ADDRESS, "BME680+BSEC", init_bme680_bsec, query_bme680_bsec },
{ TELEM_BOSCH_ALT_ADDR(TELEM_BME680_ADDRESS), "BME680+BSEC", init_bme680_bsec, query_bme680_bsec },
#endif #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 },
{ TELEM_BOSCH_ALT_ADDR(TELEM_BME280_ADDRESS), "BME280", init_bme280, query_bme280 },
#endif #endif
#if ENV_INCLUDE_BMP280 #if ENV_INCLUDE_BMP280
{ TELEM_BMP280_ADDRESS, "BMP280", init_bmp280, query_bmp280 }, { TELEM_BMP280_ADDRESS, "BMP280", init_bmp280, query_bmp280 },
{ TELEM_BOSCH_ALT_ADDR(TELEM_BMP280_ADDRESS), "BMP280", init_bmp280, query_bmp280 },
#endif #endif
#if ENV_INCLUDE_SHTC3 #if ENV_INCLUDE_SHTC3
{ 0x70, "SHTC3", init_shtc3, query_shtc3 }, { 0x70, "SHTC3", init_shtc3, query_shtc3 },
@@ -603,6 +611,8 @@ static const SensorDef SENSOR_TABLE[] = {
{ 0, nullptr, nullptr, nullptr } // sentinel — keeps the array non-empty { 0, nullptr, nullptr, nullptr } // sentinel — keeps the array non-empty
}; };
#undef TELEM_BOSCH_ALT_ADDR
static const size_t SENSOR_TABLE_SIZE = (sizeof(SENSOR_TABLE) / sizeof(SENSOR_TABLE[0])) - 1; static const size_t SENSOR_TABLE_SIZE = (sizeof(SENSOR_TABLE) / sizeof(SENSOR_TABLE[0])) - 1;
// ============================================================ // ============================================================
@@ -640,6 +650,12 @@ bool EnvironmentSensorManager::begin() {
_active_sensor_count = 0; _active_sensor_count = 0;
for (size_t i = 0; i < SENSOR_TABLE_SIZE && _active_sensor_count < MAX_ACTIVE_SENSORS; i++) { for (size_t i = 0; i < SENSOR_TABLE_SIZE && _active_sensor_count < MAX_ACTIVE_SENSORS; i++) {
const SensorDef& def = SENSOR_TABLE[i]; const SensorDef& def = SENSOR_TABLE[i];
// One static driver instance per type: an alternate address is a fallback, not a second device.
bool already_active = false;
for (int j = 0; j < _active_sensor_count; j++) {
if (_active_sensors[j].query == def.query) { already_active = true; break; }
}
if (already_active) continue;
if (!detected[def.address]) { if (!detected[def.address]) {
MESH_DEBUG_PRINTLN("%s not detected at I2C address %02X", def.name, def.address); MESH_DEBUG_PRINTLN("%s not detected at I2C address %02X", def.name, def.address);
continue; continue;