Fix PMSA003 Enables on RAK4631 (#11331)

* Minor fix for PMSA003I

* Remove class from State, make state verbose, sleep after init

* Minor changes to gate some ifdefs and state class

* Make decision tree explicit in AQ Telemetry. Also enable on phone

* Minor change in comment

* Fix issue staying on if failed enable. Minor change in log
This commit is contained in:
oscgonfer
2026-08-03 08:47:09 +00:00
committed by GitHub
parent 41c5c92874
commit 5792e8751b
3 changed files with 70 additions and 45 deletions
+51 -35
View File
@@ -165,58 +165,74 @@ int32_t AirQualityTelemetryModule::runOnce()
return disable();
}
// Wake up the sensors that need it
uint32_t telemetryIntervalMs = Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.air_quality_interval, default_telemetry_broadcast_interval_secs, numOnlineNodes);
uint32_t lastTelemetry =
transmitHistory ? transmitHistory->getLastSentToMeshMillis(TX_HISTORY_KEY_AIR_QUALITY_TELEMETRY) : 0;
bool telemetryAllowed =
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
airTime->isTxAllowedAirUtil();
bool phoneAllowed = service->isToPhoneQueueEmpty();
// Wake up the sensor in either one of these conditions:
// - We can publish the data on the mesh shortly
// - Or we can send it to the phone
// TODO: This will need to be refurbished once we implement separate intervals
LOG_INFO("Waking up sensors...");
for (TelemetrySensor *sensor : sensors) {
LOG_DEBUG("Checking if %s needs to wake up", sensor->sensorName);
if (!sensor->canSleep()) {
LOG_DEBUG("%s sensor doesn't have sleep feature. Skipping", sensor->sensorName);
} else if (((lastTelemetry == 0) || !Throttle::isWithinTimespanMs(lastTelemetry - sensor->wakeUpTimeMs(),
Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.air_quality_interval,
default_telemetry_broadcast_interval_secs,
numOnlineNodes, TrafficType::TELEMETRY))) &&
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
airTime->isTxAllowedAirUtil()) {
if (!sensor->isActive()) {
LOG_DEBUG("Waking up: %s", sensor->sensorName);
return sensor->wakeUp();
} else {
int32_t pendingForReadyMs = sensor->pendingForReadyMs();
LOG_DEBUG("%s. Pending for ready %ums", sensor->sensorName, pendingForReadyMs);
if (pendingForReadyMs) {
return pendingForReadyMs;
}
}
continue;
}
bool telemetryDue = (lastTelemetry == 0) ||
!Throttle::isWithinTimespanMs(lastTelemetry - sensor->wakeUpTimeMs(), telemetryIntervalMs);
bool phoneDue = (lastSentToPhone == 0) ||
!Throttle::isWithinTimespanMs(lastSentToPhone - sensor->wakeUpTimeMs(), sendToPhoneIntervalMs);
bool shouldWake = (telemetryDue && telemetryAllowed) || (phoneDue && phoneAllowed);
if (!shouldWake) {
continue;
}
if (!sensor->isActive()) {
LOG_DEBUG("Waking up: %s", sensor->sensorName);
return sensor->wakeUp();
}
int32_t pending = sensor->pendingForReadyMs();
if (pending) {
LOG_DEBUG("%s pending %dms", sensor->sensorName, pending);
return pending;
}
}
if (((lastTelemetry == 0) || !Throttle::isWithinTimespanMs(lastTelemetry, Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.air_quality_interval,
default_telemetry_broadcast_interval_secs,
numOnlineNodes, TrafficType::TELEMETRY))) &&
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
airTime->isTxAllowedAirUtil()) {
bool telemetryDue = (lastTelemetry == 0) || !Throttle::isWithinTimespanMs(lastTelemetry, telemetryIntervalMs);
bool phoneDue = (lastSentToPhone == 0) || !Throttle::isWithinTimespanMs(lastSentToPhone, sendToPhoneIntervalMs);
if (telemetryDue && telemetryAllowed) {
sendTelemetry();
if (transmitHistory)
if (transmitHistory) {
transmitHistory->setLastSentToMesh(TX_HISTORY_KEY_AIR_QUALITY_TELEMETRY);
} else if (((lastSentToPhone == 0) || !Throttle::isWithinTimespanMs(lastSentToPhone, sendToPhoneIntervalMs)) &&
(service->isToPhoneQueueEmpty())) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
}
} else if (phoneDue && phoneAllowed) {
// Mesh transmission isn't due yet, but we can still update the phone.
sendTelemetry(NODENUM_BROADCAST, true);
lastSentToPhone = millis();
}
// Send to sleep sensors that consume power
// Send to sleep sensors that can be to save power
for (TelemetrySensor *sensor : sensors) {
LOG_DEBUG("Checking if %s can be sent to sleep", sensor->sensorName);
if (sensor->isActive() && sensor->canSleep()) {
if (sensor->wakeUpTimeMs() <
(int32_t)Default::getConfiguredOrDefaultMsScaled(moduleConfig.telemetry.air_quality_interval,
default_telemetry_broadcast_interval_secs, numOnlineNodes,
TrafficType::TELEMETRY)) {
if (sensor->wakeUpTimeMs() < (int32_t)telemetryIntervalMs) {
LOG_DEBUG("Disabling %s until next period", sensor->sensorName);
sensor->sleep();
} else {
@@ -15,10 +15,10 @@ bool PMSA003ISensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
LOG_INFO("%s: Init sensor", sensorName);
#ifdef PMSA003I_ENABLE_PIN
pinMode(PMSA003I_ENABLE_PIN, OUTPUT);
LOG_DEBUG("%s: has enable pin", sensorName);
wakeUp();
#endif
// TODO PMS5003I sometimes get late to the party...
_bus = bus;
_address = dev->address.address;
#ifdef PMSA003I_I2C_CLOCK_SPEED
@@ -36,6 +36,7 @@ bool PMSA003ISensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
LOG_INFO("%s: restoring clock speed", sensorName);
reClockI2C.restoreClock();
#endif /* PMSA003I_I2C_CLOCK_SPEED */
sleep();
return false;
}
@@ -45,7 +46,8 @@ bool PMSA003ISensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
#endif /* PMSA003I_I2C_CLOCK_SPEED */
status = 1;
LOG_INFO("%s Enabled", sensorName);
LOG_INFO("%s: Enabled", sensorName);
sleep();
initI2CSensor();
return true;
@@ -148,7 +150,7 @@ bool PMSA003ISensor::getMetrics(meshtastic_Telemetry *measurement)
bool PMSA003ISensor::isActive()
{
return state == State::ACTIVE;
return state == PMSA003I_ACTIVE;
}
int32_t PMSA003ISensor::wakeUpTimeMs()
@@ -162,7 +164,6 @@ int32_t PMSA003ISensor::wakeUpTimeMs()
int32_t PMSA003ISensor::pendingForReadyMs()
{
#ifdef PMSA003I_ENABLE_PIN
uint32_t now;
now = getTime();
uint32_t sincePmMeasureStarted = (now - pmMeasureStarted) * 1000;
@@ -173,7 +174,6 @@ int32_t PMSA003ISensor::pendingForReadyMs()
return PMSA003I_WARMUP_MS - sincePmMeasureStarted;
}
return 0;
#endif
return 0;
}
@@ -189,8 +189,9 @@ bool PMSA003ISensor::canSleep()
void PMSA003ISensor::sleep()
{
#ifdef PMSA003I_ENABLE_PIN
LOG_INFO("%s: Sleep", sensorName);
digitalWrite(PMSA003I_ENABLE_PIN, LOW);
state = State::IDLE;
state = PMSA003I_IDLE;
pmMeasureStarted = 0;
#endif
}
@@ -200,7 +201,7 @@ uint32_t PMSA003ISensor::wakeUp()
#ifdef PMSA003I_ENABLE_PIN
LOG_INFO("%s: Waking up", sensorName);
digitalWrite(PMSA003I_ENABLE_PIN, HIGH);
state = State::ACTIVE;
state = PMSA003I_ACTIVE;
pmMeasureStarted = getTime();
return PMSA003I_WARMUP_MS;
+10 -2
View File
@@ -7,9 +7,17 @@
#include "TelemetrySensor.h"
#include "gps/RTC.h"
#ifndef PMSA003I_I2C_CLOCK_SPEED
#define PMSA003I_I2C_CLOCK_SPEED 100000
#endif
#ifndef PMSA003I_FRAME_LENGTH
#define PMSA003I_FRAME_LENGTH 32
#endif
#ifndef PMSA003I_WARMUP_MS
#define PMSA003I_WARMUP_MS 30000
#endif
class PMSA003ISensor : public TelemetrySensor
{
@@ -26,8 +34,8 @@ class PMSA003ISensor : public TelemetrySensor
virtual int32_t pendingForReadyMs() override;
private:
enum class State { IDLE, ACTIVE };
State state = State::ACTIVE;
enum PMSA003IState { PMSA003I_IDLE, PMSA003I_ACTIVE };
PMSA003IState state = PMSA003I_ACTIVE;
uint16_t computedChecksum = 0;
uint16_t receivedChecksum = 0;