PMSA0031 sensors require ~3secs before coming up on I2C (#4743)

* PMSA0031 sensors require ~3secs before coming up on I2C

As reported by @MALAONE1 and debugged by @shodan8192 , PMSA0031s
on a RAK4631 take 3 seconds before they can become detectable on I2c.

Add a delay(4000) before I2C scan if the air quality sensor pin
is defined.

Fixes https://github.com/meshtastic/firmware/issues/3690

* Remove 4 second wait and rescan during air quality init for the sensor

* works without but this triggers my OCD

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
Tom Fifield 2024-09-18 23:12:49 +08:00 committed by GitHub
parent 19c57e8ec6
commit 35e1c401e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 8 deletions

View File

@ -390,7 +390,7 @@ void setup()
#endif #endif
#ifdef AQ_SET_PIN #ifdef AQ_SET_PIN
// RAK-12039 set pin for Air quality sensor // RAK-12039 set pin for Air quality sensor. Detectable on I2C after ~3 seconds, so we need to rescan later
pinMode(AQ_SET_PIN, OUTPUT); pinMode(AQ_SET_PIN, OUTPUT);
digitalWrite(AQ_SET_PIN, HIGH); digitalWrite(AQ_SET_PIN, HIGH);
#endif #endif

View File

@ -10,11 +10,11 @@
#include "PowerFSM.h" #include "PowerFSM.h"
#include "RTC.h" #include "RTC.h"
#include "Router.h" #include "Router.h"
#include "detect/ScanI2CTwoWire.h"
#include "main.h" #include "main.h"
int32_t AirQualityTelemetryModule::runOnce() int32_t AirQualityTelemetryModule::runOnce()
{ {
int32_t result = INT32_MAX;
/* /*
Uncomment the preferences below if you want to use the module Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI. without having to configure it from the PythonAPI or WebUI.
@ -29,21 +29,36 @@ int32_t AirQualityTelemetryModule::runOnce()
if (firstTime) { if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup // This is the first time the OSThread library has called this function, so do some setup
firstTime = 0; firstTime = false;
if (moduleConfig.telemetry.air_quality_enabled) { if (moduleConfig.telemetry.air_quality_enabled) {
LOG_INFO("Air quality Telemetry: Initializing\n"); LOG_INFO("Air quality Telemetry: Initializing\n");
if (!aqi.begin_I2C()) { if (!aqi.begin_I2C()) {
LOG_WARN("Could not establish i2c connection to AQI sensor\n"); LOG_WARN("Could not establish i2c connection to AQI sensor. Rescanning...\n");
// rescan for late arriving sensors. AQI Module starts about 10 seconds into the boot so this is plenty.
uint8_t i2caddr_scan[] = {PMSA0031_ADDR};
uint8_t i2caddr_asize = 1;
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
#if defined(I2C_SDA1)
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1, i2caddr_scan, i2caddr_asize);
#endif
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, i2caddr_scan, i2caddr_asize);
auto found = i2cScanner->find(ScanI2C::DeviceType::PMSA0031);
if (found.type != ScanI2C::DeviceType::NONE) {
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first = found.address.address;
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].second =
i2cScanner->fetchI2CBus(found.address);
return 1000;
}
return disable(); return disable();
} }
return 1000; return 1000;
} }
return result; return disable();
} else { } else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever // if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.air_quality_enabled) if (!moduleConfig.telemetry.air_quality_enabled)
return result; return disable();
uint32_t now = millis(); uint32_t now = millis();
if (((lastSentToMesh == 0) || if (((lastSentToMesh == 0) ||

View File

@ -44,7 +44,7 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf
private: private:
Adafruit_PM25AQI aqi; Adafruit_PM25AQI aqi;
PM25_AQI_Data data = {0}; PM25_AQI_Data data = {0};
bool firstTime = 1; bool firstTime = true;
meshtastic_MeshPacket *lastMeasurementPacket; meshtastic_MeshPacket *lastMeasurementPacket;
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0; uint32_t lastSentToMesh = 0;