Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
7f042a0
Move PMSA003I to separate class and update AQ telemetry
oscgonfer Jul 1, 2025
835adb2
AirQualityTelemetry module not depend on PM sensor presence
oscgonfer Jul 1, 2025
3b470b7
Remove commented line
oscgonfer Jul 2, 2025
2f68458
Fixes on PMS class
oscgonfer Jul 2, 2025
e4903eb
Add missing warmup period to wakeUp function
oscgonfer Jul 2, 2025
9111f88
Fixes on compilation for different variants
oscgonfer Jul 6, 2025
40af7b8
Add functions to check for I2C bus speed and set it
oscgonfer Jul 11, 2025
ff8691d
Add ScreenFonts.h
oscgonfer Jul 12, 2025
0dda175
PMSA003I 1st round test
Nashui-Yan Jul 22, 2025
14eaa3e
Fix I2C scan speed
oscgonfer Jul 23, 2025
8a811b2
Fix minor issues and bring back I2C SPEED def
oscgonfer Jul 23, 2025
ec5a752
Remove PMSA003I library as its no longer needed
oscgonfer Jul 25, 2025
f7a9e27
Merge branch 'master' into enhancement/air-quality-module
oscgonfer Aug 4, 2025
b23605a
Merge branch 'master' into enhancement/air-quality-module
thebentern Aug 5, 2025
a129441
Remove unused I2C speed functions and cleanup
oscgonfer Aug 6, 2025
3f9bf06
SEN5X first pass
oscgonfer Jul 6, 2025
dc0ab1f
WIP Sen5X functions
oscgonfer Jul 7, 2025
9e82c8c
Further (non-working) progress in SEN5X
oscgonfer Jul 8, 2025
aee86f6
WIP Sen5X functions
oscgonfer Jul 7, 2025
c82e042
Changes on SEN5X library - removing pm_env as well
oscgonfer Jul 15, 2025
0e97e7d
Small cleanup of SEN5X sensors
oscgonfer Jul 15, 2025
a7ea11b
Minor change for SEN5X detection
oscgonfer Jul 15, 2025
f9de802
Remove dup code
oscgonfer Jul 15, 2025
3abd2a2
Enable PM sensor before sending telemetry.
oscgonfer Jul 17, 2025
bab6fdd
Small cleanups in SEN5X sensor
oscgonfer Jul 17, 2025
72d7544
Add dynamic measurement interval for SEN5X
oscgonfer Jul 17, 2025
89e1532
Only disable SEN5X if enough time after reading.
oscgonfer Jul 17, 2025
e3f345c
Idle for SEN5X on communication error
oscgonfer Jul 17, 2025
a374bb5
Cleanup of logs and remove unnecessary delays
oscgonfer Jul 18, 2025
886866d
Small TODO
oscgonfer Jul 22, 2025
21d21af
Settle on uint16_t for SEN5X PM data
oscgonfer Jul 23, 2025
76cffe8
Add logic for sleep/wakeUp of PMS.
oscgonfer Jul 23, 2025
561daa0
Make AQTelemetry sensors non-exclusive
oscgonfer Jul 23, 2025
c408d9c
Implementation of cleaning in FS prefs and cleanup
oscgonfer Aug 5, 2025
b876b9a
Bring back detection code for SEN5X after branch rebase
oscgonfer Aug 6, 2025
b3107fd
Add placeholder for admin message
oscgonfer Aug 7, 2025
7d1deaf
Add VOC measurements and persistence (WIP)
oscgonfer Aug 7, 2025
c321312
Add one-shot mode config flag to SEN5X
oscgonfer Aug 26, 2025
d583991
Add nan checks on sensor data from SEN5X
oscgonfer Aug 26, 2025
1038765
Working implementation on VOCState
oscgonfer Aug 30, 2025
181ed14
Merge branch 'master' into feat/add-sen5x
oscgonfer Aug 30, 2025
bb3ec31
Merge branch 'master' into enhancement/air-quality-module
oscgonfer Aug 30, 2025
8ec036a
Merge branch 'master' into enhancement/air-quality-module
thebentern Sep 9, 2025
6d45a86
Merge branch 'master' into enhancement/air-quality-module
thebentern Sep 10, 2025
86e31b6
Merge branch 'enhancement/air-quality-module' into feat/add-sen5x
oscgonfer Sep 14, 2025
24b3a22
Unify build epoch to add flag in platformio-custom.py (#7917)
thebentern Sep 10, 2025
0827bd0
Fix build error in rak_wismesh_tap_v2 (#7905)
fifieldt Sep 8, 2025
0b900dd
Put guards in place around debug heap operations (#7955)
thebentern Sep 11, 2025
7b75468
Cleanup
thebentern Sep 11, 2025
d7ef19b
Fix memory leak in NextHopRouter: always free packet copy when removi…
compumike Sep 12, 2025
ab09d9b
Formatting
thebentern Sep 12, 2025
4aa5e91
Only queue 2 client notification
thebentern Sep 12, 2025
8468bf9
Merge pull request #7965 from compumike/compumike/fix-nrf52-bluetooth…
thebentern Sep 12, 2025
8d1b20d
Merge pull request #7964 from compumike/compumike/fix-nimble-bluetoot…
thebentern Sep 12, 2025
9f25738
Update protobufs (#7973)
github-actions[bot] Sep 13, 2025
a5876f8
T-Lora Pager: Support LR1121 and SX1280 models (#7956)
WillyJL Sep 13, 2025
1d757ba
Trunk
thebentern Sep 13, 2025
375ab36
Trunk
thebentern Sep 13, 2025
33ffa8d
Static memory pool allocation (#7966)
thebentern Sep 13, 2025
55b42b9
Portduino dynamic alloc
thebentern Sep 13, 2025
1da6d28
Missed
thebentern Sep 13, 2025
3092ec7
Drop the limit
thebentern Sep 13, 2025
569c0d2
Update meshtastic-esp8266-oled-ssd1306 digest to 0cbc26b (#7977)
renovate[bot] Sep 13, 2025
2fe065d
Fix json report crashes on esp32 (#7978)
thebentern Sep 13, 2025
d9eb18f
Tweak maximums
thebentern Sep 13, 2025
9fdd31a
Fix DRAM overflow on old esp32 targets
thebentern Sep 14, 2025
e9fb1b5
Guard bad time warning logs using GPS_DEBUG (#7897)
fifieldt Sep 8, 2025
4b4609f
Scale probe buffer size based on current baud rate (#7975)
thebentern Sep 14, 2025
aea2072
Fix GPS gm_mktime memory leak (#7981)
compumike Sep 14, 2025
520c479
Fix overflow of time value (#7984)
thebentern Sep 14, 2025
cb5ccfd
Merge branch 'enhancement/air-quality-module' into feat/add-sen5x
oscgonfer Sep 14, 2025
2315e1b
Fixes on VOC state and mode swtiching
oscgonfer Sep 14, 2025
7c1fea0
Remove PMSA003 include from modules
oscgonfer Sep 14, 2025
e9752a2
Merge branch 'enhancement/air-quality-module' into feat/add-sen5x
oscgonfer Sep 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .github/actions/setup-base/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ runs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}

- name: Uncomment build epoch
shell: bash
run: |
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini

- name: Install dependencies
shell: bash
run: |
Expand Down
2 changes: 0 additions & 2 deletions bin/build-firmware.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env bash

sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini

export PIP_BREAK_SYSTEM_PACKAGES=1

if (echo $2 | grep -q "esp32"); then
Expand Down
7 changes: 7 additions & 0 deletions bin/platformio-custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import subprocess
import json
import re
import time
from datetime import datetime

from readprops import readProps

Expand Down Expand Up @@ -125,11 +127,16 @@ def esp32_create_combined_bin(source, target, env):
pref_flags.append("-D" + pref + "=" + env.StringifyMacro(userPrefs[pref]) + "")

# General options that are passed to the C and C++ compilers
# Calculate unix epoch for current day (midnight)
current_date = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
build_epoch = int(current_date.timestamp())

flags = [
"-DAPP_VERSION=" + verObj["long"],
"-DAPP_VERSION_SHORT=" + verObj["short"],
"-DAPP_ENV=" + env.get("PIOENV"),
"-DAPP_REPO=" + repo_owner,
"-DBUILD_EPOCH=" + str(build_epoch),
] + pref_flags

print ("Using flags:")
Expand Down
8 changes: 3 additions & 5 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ build_flags = -Wno-missing-field-initializers
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
-DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
#-DBUILD_EPOCH=$UNIX_TIME
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
#-D OLED_PL=1

monitor_speed = 115200
monitor_filters = direct
lib_deps =
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/9573abb64dc9c94f3051348f2bf4fc5cedf03c22.zip
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0cbc26b1f8f61957af0475f486b362eafe7cc4e2.zip
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
Expand Down Expand Up @@ -141,8 +141,6 @@ lib_deps =
adafruit/Adafruit INA260 [email protected]
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
adafruit/Adafruit [email protected]
# renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor
adafruit/Adafruit PM25 AQI [email protected]
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
adafruit/Adafruit [email protected]
# renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH
Expand Down Expand Up @@ -210,4 +208,4 @@ lib_deps =
# renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core
sensirion/Sensirion [email protected]
# renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x
sensirion/Sensirion I2C [email protected]
sensirion/Sensirion I2C [email protected]
2 changes: 1 addition & 1 deletion protobufs
19 changes: 19 additions & 0 deletions src/DebugConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

#include "configuration.h"

// Forward declarations
#if defined(DEBUG_HEAP)
class MemGet;
extern MemGet memGet;
#endif

// DEBUG LED
#ifndef LED_STATE_ON
#define LED_STATE_ON 1
Expand Down Expand Up @@ -65,8 +71,21 @@

#if defined(DEBUG_HEAP)
#define LOG_HEAP(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_HEAP, __VA_ARGS__)

// Macro-based heap debugging
#define DEBUG_HEAP_BEFORE auto heapBefore = memGet.getFreeHeap();
#define DEBUG_HEAP_AFTER(context, ptr) \
do { \
auto heapAfter = memGet.getFreeHeap(); \
if (heapBefore != heapAfter) { \
LOG_HEAP("Alloc in %s pointer 0x%x, size: %u, free: %u", context, ptr, heapBefore - heapAfter, heapAfter); \
} \
} while (0)

#else
#define LOG_HEAP(...)
#define DEBUG_HEAP_BEFORE
#define DEBUG_HEAP_AFTER(context, ptr)
#endif

/// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic
Expand Down
1 change: 1 addition & 0 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BQ27220_ADDR 0x55 // same address as TDECK_KB
#define BQ25896_ADDR 0x6B
#define LTR553ALS_ADDR 0x23
#define SEN5X_ADDR 0x69

// -----------------------------------------------------------------------------
// ACCELEROMETER
Expand Down
1 change: 1 addition & 0 deletions src/detect/ScanI2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ScanI2C
BHI260AP,
BMM150,
TSL2561,
SEN5X,
DRV2605
} DeviceType;

Expand Down
71 changes: 63 additions & 8 deletions src/detect/ScanI2CTwoWire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "meshUtils.h" // vformat

#endif

bool in_array(uint8_t *array, int size, uint8_t lookfor)
Expand Down Expand Up @@ -109,6 +110,42 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
return value;
}

/// for SEN5X detection
// Note, this code needs to be called before setting the I2C bus speed
// for the screen at high speed. The speed needs to be at 100kHz, otherwise
// detection will not work
String readSEN5xProductName(TwoWire* i2cBus, uint8_t address) {
uint8_t cmd[] = { 0xD0, 0x14 };
uint8_t response[48] = {0};

i2cBus->beginTransmission(address);
i2cBus->write(cmd, 2);
if (i2cBus->endTransmission() != 0) return "";

delay(20);
if (i2cBus->requestFrom(address, (uint8_t)48) != 48) return "";

for (int i = 0; i < 48 && i2cBus->available(); ++i) {
response[i] = i2cBus->read();
}

char productName[33] = {0};
int j = 0;
for (int i = 0; i < 48 && j < 32; i += 3) {
if (response[i] >= 32 && response[i] <= 126)
productName[j++] = response[i];
else
break;

if (response[i + 1] >= 32 && response[i + 1] <= 126)
productName[j++] = response[i + 1];
else
break;
}

return String(productName);
}

#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
case ADDR: \
logFoundDevice(__VA_ARGS__); \
Expand Down Expand Up @@ -504,21 +541,39 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
}
break;

case ICM20948_ADDR: // same as BMX160_ADDR
case ICM20948_ADDR: // same as BMX160_ADDR and SEN5X_ADDR
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
// ICM20948 Register check
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
if (registerValue == 0xEA) {
type = ICM20948;
logFoundDevice("ICM20948", (uint8_t)addr.address);
break;
} else if (addr.address == BMX160_ADDR) {
type = BMX160;
logFoundDevice("BMX160", (uint8_t)addr.address);
break;
} else {
type = MPU6050;
logFoundDevice("MPU6050", (uint8_t)addr.address);
break;
String prod = "";
prod = readSEN5xProductName(i2cBus, addr.address);
if (prod.startsWith("SEN55")) {
type = SEN5X;
logFoundDevice("Sensirion SEN55", addr.address);
break;
} else if (prod.startsWith("SEN54")) {
type = SEN5X;
logFoundDevice("Sensirion SEN54", addr.address);
break;
} else if (prod.startsWith("SEN50")) {
type = SEN5X;
logFoundDevice("Sensirion SEN50", addr.address);
break;
}
if (addr.address == BMX160_ADDR) {
type = BMX160;
logFoundDevice("BMX160", (uint8_t)addr.address);
break;
} else {
type = MPU6050;
logFoundDevice("MPU6050", (uint8_t)addr.address);
break;
}
}
break;

Expand Down
19 changes: 15 additions & 4 deletions src/gps/GPS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,7 @@ static const char *DETECTED_MESSAGE = "%s detected";
LOG_DEBUG(PROBE_MESSAGE, COMMAND, FAMILY_NAME); \
clearBuffer(); \
_serial_gps->write(COMMAND "\r\n"); \
GnssModel_t detectedDriver = getProbeResponse(TIMEOUT, RESPONSE_MAP); \
GnssModel_t detectedDriver = getProbeResponse(TIMEOUT, RESPONSE_MAP, serialSpeed); \
if (detectedDriver != GNSS_MODEL_UNKNOWN) { \
return detectedDriver; \
} \
Expand Down Expand Up @@ -1367,17 +1367,26 @@ GnssModel_t GPS::probe(int serialSpeed)
return GNSS_MODEL_UNKNOWN;
}

GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipInfo> &responseMap)
GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipInfo> &responseMap, int serialSpeed)
{
char response[256] = {0}; // Fixed buffer instead of String
// Calculate buffer size based on baud rate - 256 bytes for 9600 baud as baseline
// Higher baud rates get proportionally larger buffers to handle more data
int bufferSize = (serialSpeed * 256) / 9600;
// Clamp buffer size between reasonable limits
if (bufferSize < 128)
bufferSize = 128;
if (bufferSize > 2048)
bufferSize = 2048;

char *response = new char[bufferSize](); // Dynamically allocate based on baud rate
uint16_t responseLen = 0;
unsigned long start = millis();
while (millis() - start < timeout) {
if (_serial_gps->available()) {
char c = _serial_gps->read();

// Add char to buffer if there's space
if (responseLen < sizeof(response) - 1) {
if (responseLen < bufferSize - 1) {
response[responseLen++] = c;
response[responseLen] = '\0';
}
Expand All @@ -1390,6 +1399,7 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
for (const auto &chipInfo : responseMap) {
if (strstr(response, chipInfo.detectionString.c_str()) != nullptr) {
LOG_INFO("%s detected", chipInfo.chipName.c_str());
delete[] response; // Cleanup before return
return chipInfo.driver;
}
}
Expand All @@ -1404,6 +1414,7 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
#ifdef GPS_DEBUG
LOG_DEBUG(response);
#endif
delete[] response; // Cleanup before return
return GNSS_MODEL_UNKNOWN; // Return unknown on timeout
}

Expand Down
2 changes: 1 addition & 1 deletion src/gps/GPS.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ class GPS : private concurrency::OSThread

virtual int32_t runOnce() override;

GnssModel_t getProbeResponse(unsigned long timeout, const std::vector<ChipInfo> &responseMap);
GnssModel_t getProbeResponse(unsigned long timeout, const std::vector<ChipInfo> &responseMap, int serialSpeed);

// Get GNSS model
GnssModel_t probe(int serialSpeed);
Expand Down
Loading
Loading