From 5841c889ba439dff335a5460759f084dbe9d5f62 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Tue, 1 Jul 2025 19:34:03 +1000 Subject: [PATCH 1/4] Add detection code for SCD4X (#7185) * Add detection code for SCD4X This patch adds I2C detection support SCD40/SDC41 CO2 sensors. It's a start to get #4601 over the line :) Co-Authored-By: @Coloradohusky * Remove SCD4X from Portduino --- platformio.ini | 3 ++- src/configuration.h | 1 + src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 3 ++- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 0143038af..c7b728d6a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -195,4 +195,5 @@ lib_deps = # 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 \ No newline at end of file + https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip + sensirion/Sensirion I2C SCD4x@^0.4.0 diff --git a/src/configuration.h b/src/configuration.h index 89257ff2f..cddc7ba7a 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -189,6 +189,7 @@ along with this program. If not, see . #define DFROBOT_RAIN_ADDR 0x1d #define NAU7802_ADDR 0x2A #define MAX30102_ADDR 0x57 +#define SCD4X_ADDR 0x62 #define MLX90614_ADDR_DEF 0x5A #define CGRADSENS_ADDR 0x66 #define LTR390UV_ADDR 0x53 diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 90467abd0..fc0b7c5a6 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -61,6 +61,7 @@ class ScanI2C FT6336U, STK8BAXX, ICM20948, + SCD4X, MAX30102, TPS65233, MPR121KB, diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index fd3d1c80b..9e9441123 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -447,6 +447,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address); SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address); SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(SCD4X_ADDR, SCD4X, "SCD4X", (uint8_t)addr.address); SCAN_SIMPLE_CASE(BMM150_ADDR, BMM150, "BMM150", (uint8_t)addr.address); #ifdef HAS_TPS65233 SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); @@ -556,4 +557,4 @@ void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address) { LOG_INFO("%s found at address 0x%x", device, address); } -#endif \ No newline at end of file +#endif From 598eebfb1084dc4423ada754e73942ba61edd3e4 Mon Sep 17 00:00:00 2001 From: dylanli Date: Tue, 1 Jul 2025 18:16:48 +0800 Subject: [PATCH 2/4] fix t1000-e battery level map (#7186) --- src/power.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/power.h b/src/power.h index 33a356d92..e7193dd07 100644 --- a/src/power.h +++ b/src/power.h @@ -25,7 +25,7 @@ #elif defined(CELL_TYPE_LTO) #define OCV_ARRAY 2700, 2560, 2540, 2520, 2500, 2460, 2420, 2400, 2380, 2320, 1500 #elif defined(TRACKER_T1000_E) -#define OCV_ARRAY 4190, 4078, 4017, 3969, 3887, 3818, 3798, 3791, 3766, 3712, 3100 +#define OCV_ARRAY 4190, 4042, 3957, 3885, 3820, 3776, 3746, 3725, 3696, 3644, 3100 #elif defined(HELTEC_MESH_POCKET_BATTERY_5000) #define OCV_ARRAY 4300, 4240, 4120, 4000, 3888, 3800, 3740, 3698, 3655, 3580, 3400 #elif defined(HELTEC_MESH_POCKET_BATTERY_10000) From baf0e9c7e6987be7b872b6c7a92d9ec0725a1f01 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Tue, 1 Jul 2025 21:27:44 +1000 Subject: [PATCH 3/4] Add detection framework for multiple AirQuality sensors (#7187) * Add detection framework for multiple AirQuality sensors Now we have the ability to detect multiple AirQualitySensors, follow the lead of other sensor types and create supporting methods and objects for using this information. Continued cherry-picking to get #4601 over the line :) Co-Authored-By: @Coloradohusky * Update src/main.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/detect/ScanI2C.cpp | 8 +++++++- src/detect/ScanI2C.h | 2 ++ src/main.cpp | 6 ++++++ src/main.h | 3 ++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/detect/ScanI2C.cpp b/src/detect/ScanI2C.cpp index e6236251c..170bef3a6 100644 --- a/src/detect/ScanI2C.cpp +++ b/src/detect/ScanI2C.cpp @@ -41,6 +41,12 @@ ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const return firstOfOrNONE(9, types); } +ScanI2C::FoundDevice ScanI2C::firstAQI() const +{ + ScanI2C::DeviceType types[] = {PMSA0031, SCD4X}; + return firstOfOrNONE(2, types); +} + ScanI2C::FoundDevice ScanI2C::firstRGBLED() const { ScanI2C::DeviceType types[] = {NCP5623, LP5562}; @@ -80,4 +86,4 @@ bool ScanI2C::DeviceAddress::operator<(const ScanI2C::DeviceAddress &other) cons || (port != NO_I2C && other.port != NO_I2C && (address < other.address)); } -ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {} \ No newline at end of file +ScanI2C::FoundDevice::FoundDevice(ScanI2C::DeviceType type, ScanI2C::DeviceAddress address) : type(type), address(address) {} diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index fc0b7c5a6..dd290db98 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -127,6 +127,8 @@ class ScanI2C FoundDevice firstAccelerometer() const; + FoundDevice firstAQI() const; + FoundDevice firstRGBLED() const; virtual FoundDevice find(DeviceType) const; diff --git a/src/main.cpp b/src/main.cpp index 4b64a78ea..9e0985a3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -195,6 +195,8 @@ ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE; ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE; // The I2C address of the RGB LED (if found) ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE); +/// The I2C address of our Air Quality Indicator (if found) +ScanI2C::DeviceAddress aqi_found = ScanI2C::ADDRESS_NONE; #ifdef T_WATCH_S3 Adafruit_DRV2605 drv; @@ -622,6 +624,9 @@ void setup() pmu_found = i2cScanner->exists(ScanI2C::DeviceType::PMU_AXP192_AXP2101); + auto aqiInfo = i2cScanner->firstAQI(); + aqi_found = aqiInfo.type != ScanI2C::DeviceType::NONE ? aqiInfo.address : ScanI2C::ADDRESS_NONE; + /* * There are a bunch of sensors that have no further logic than to be found and stuffed into the * nodeTelemetrySensorsMap singleton. This wraps that logic in a temporary scope to declare the temporary field @@ -690,6 +695,7 @@ void setup() scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DPS310, meshtastic_TelemetrySensorType_DPS310); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RAK12035, meshtastic_TelemetrySensorType_RAK12035); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SCD4X, meshtastic_TelemetrySensorType_SCD4X); i2cScanner.reset(); #endif diff --git a/src/main.h b/src/main.h index 79094e2d3..7105bd62b 100644 --- a/src/main.h +++ b/src/main.h @@ -35,6 +35,7 @@ extern bool kb_found; extern ScanI2C::DeviceAddress rtc_found; extern ScanI2C::DeviceAddress accelerometer_found; extern ScanI2C::FoundDevice rgb_found; +extern ScanI2C::DeviceAddress aqi_found; extern bool eink_found; extern bool pmu_found; @@ -92,4 +93,4 @@ void scannerToSensorsMap(const std::unique_ptr &i2cScanner, Scan #endif // We default to 4MHz SPI, SPI mode 0 -extern SPISettings spiSettings; \ No newline at end of file +extern SPISettings spiSettings; From 3ea96bb6e164a5ee61e6983b537cfb8d517ef747 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 1 Jul 2025 16:47:42 +0300 Subject: [PATCH 4/4] Log TX power after limits applyng and store it in config (#7065) * Log and save in config lora tx_power after limits applyng * Log and save in config lora tx_power after limits applyng * Trunk fmt * Remove duplicate logic --------- Co-authored-by: Ben Meadors --- src/mesh/LR11x0Interface.cpp | 5 +---- src/mesh/RF95Interface.cpp | 5 +---- src/mesh/RadioInterface.cpp | 9 ++++++++- src/mesh/RadioInterface.h | 2 +- src/mesh/STM32WLE5JCInterface.cpp | 5 +---- src/mesh/SX126xInterface.cpp | 5 +---- src/mesh/SX128xInterface.cpp | 5 +---- 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index 8cc05994c..a20db808e 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -71,10 +71,7 @@ template bool LR11x0Interface::init() RadioLibInterface::init(); - limitPower(); - - if (power > LR1110_MAX_POWER) // Clamp power to maximum defined level - power = LR1110_MAX_POWER; + limitPower(LR1110_MAX_POWER); if ((power > LR1120_MAX_POWER) && (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { // clamp again if wide freq range diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 943a79a5f..97f21fc34 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -122,10 +122,7 @@ bool RF95Interface::init() power = dacDbValues.db; #endif - limitPower(); - - if (power > RF95_MAX_POWER) // This chip has lower power limits than some - power = RF95_MAX_POWER; + limitPower(RF95_MAX_POWER); iface = lora = new RadioLibRF95(&module); diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index f7cd6f4c1..91a4d0632 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -611,7 +611,7 @@ uint32_t RadioInterface::computeSlotTimeMsec() * Some regulatory regions limit xmit power. * This function should be called by subclasses after setting their desired power. It might lower it */ -void RadioInterface::limitPower() +void RadioInterface::limitPower(int8_t loraMaxPower) { uint8_t maxPower = 255; // No limit @@ -628,6 +628,13 @@ void RadioInterface::limitPower() power -= TX_GAIN_LORA; } + if (power > loraMaxPower) // Clamp power to maximum defined level + power = loraMaxPower; + + if (TX_GAIN_LORA == 0) { // Setting power in config with defined TX_GAIN_LORA will cause decreasing power on each reboot + config.lora.tx_power = power; // Set limited power in config + } + LOG_INFO("Final Tx power: %d dBm", power); } diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 68ae09635..c9e71cfa8 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -230,7 +230,7 @@ class RadioInterface * Some regulatory regions limit xmit power. * This function should be called by subclasses after setting their desired power. It might lower it */ - void limitPower(); + void limitPower(int8_t MAX_POWER); /** * Save the frequency we selected for later reuse. diff --git a/src/mesh/STM32WLE5JCInterface.cpp b/src/mesh/STM32WLE5JCInterface.cpp index 3c8bf89c3..d7bc37466 100644 --- a/src/mesh/STM32WLE5JCInterface.cpp +++ b/src/mesh/STM32WLE5JCInterface.cpp @@ -25,10 +25,7 @@ bool STM32WLE5JCInterface::init() lora.setRfSwitchTable(rfswitch_pins, rfswitch_table); - limitPower(); - - if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some - power = STM32WLx_MAX_POWER; + limitPower(STM32WLx_MAX_POWER); int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage); diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index e5ecd9302..729c1abc6 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -69,10 +69,7 @@ template bool SX126xInterface::init() RadioLibInterface::init(); - limitPower(); - - if (power > SX126X_MAX_POWER) // Clamp power to maximum defined level - power = SX126X_MAX_POWER; + limitPower(SX126X_MAX_POWER); int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO); // \todo Display actual typename of the adapter, not just `SX126x` diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 2b17543fc..866426872 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -62,10 +62,7 @@ template bool SX128xInterface::init() RadioLibInterface::init(); - limitPower(); - - if (power > SX128X_MAX_POWER) // This chip has lower power limits than some - power = SX128X_MAX_POWER; + limitPower(SX128X_MAX_POWER); preambleLength = 12; // 12 is the default for this chip, 32 does not RX at all