Make reclock function aware of screen-set I2C speeds

This commit is contained in:
oscgonfer
2026-06-14 14:48:40 +02:00
parent 1a1f906b7a
commit 0200d45241
12 changed files with 280 additions and 265 deletions
+28 -15
View File
@@ -1,29 +1,42 @@
#include "reClockI2C.h"
#include "ScanI2CTwoWire.h"
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus, bool force)
/* See https://github.com/arduino/Arduino/issues/11457
Currently, only ESP32 can getClock()
While all cores can setClock()
https://github.com/sandeepmistry/arduino-nRF5/blob/master/libraries/Wire/Wire.h#L50
https://github.com/earlephilhower/arduino-pico/blob/master/libraries/Wire/src/Wire.h#L60
https://github.com/stm32duino/Arduino_Core_STM32/blob/main/libraries/Wire/src/Wire.h#L103
For cases when I2C speed is different to the ones defined by sensors (see defines in sensor classes)
we need to reclock I2C and set it back to the previous stablished speed.
Only for cases where we can know it (ESP32 or known screen) we can do this.
*/
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus, ScanI2C::I2CPort port)
{
uint32_t currentClock = 0;
uint32_t screenClock = 0;
ScanI2C::I2CPort screenPort = ScanI2C::I2CPort::NO_I2C;
/* See https://github.com/arduino/Arduino/issues/11457
Currently, only ESP32 can getClock()
While all cores can setClock()
https://github.com/sandeepmistry/arduino-nRF5/blob/master/libraries/Wire/Wire.h#L50
https://github.com/earlephilhower/arduino-pico/blob/master/libraries/Wire/src/Wire.h#L60
https://github.com/stm32duino/Arduino_Core_STM32/blob/main/libraries/Wire/src/Wire.h#L103
For cases when I2C speed is different to the ones defined by sensors (see defines in sensor classes)
we need to reclock I2C and set it back to the previous desired speed.
Only for cases where we can know OR predefine the speed, we can do this.
*/
// TODO add getClock function or return a predefined clock speed per variant?
// Assume that if we can't getClock, or there is no screen, we can set the clock speed at will
#ifdef CAN_RECLOCK_I2C
currentClock = i2cBus->getClock();
LOG_DEBUG("Current I2C frequency: %uHz", currentClock);
#elif HAS_SCREEN
if (screen) {
// If we get a non-zero response here, the screen has set a speed
screenClock = screen->getI2cFrequency();
screenPort = screen->getI2CPort();
// Check if i2c port is the same, and that we got a screenClock back (0 means the screen didn't set it)
if (screenClock && (screenPort == port))
currentClock = screenClock;
LOG_DEBUG("Screen defined I2C frequency: %uHz", screenClock);
}
#endif
if ((currentClock != desiredClock) || force) {
LOG_DEBUG("Changing I2C clock to %u", desiredClock);
if (currentClock != desiredClock) {
LOG_DEBUG("Changing I2C clock to %uHz", desiredClock);
i2cBus->setClock(desiredClock);
}
+4 -1
View File
@@ -2,10 +2,13 @@
#ifndef RECLOCK_I2C_
#define RECLOCK_I2C_
#include "../graphics/Screen.h"
#include "ScanI2CTwoWire.h"
#include <Wire.h>
#include <stdint.h>
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus, bool force);
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus, ScanI2C::I2CPort port);
extern graphics::Screen *screen;
#endif
+17 -22
View File
@@ -20,16 +20,11 @@ bool PMSA003ISensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
_bus = bus;
_address = dev->address.address;
_port = dev->address.port;
#ifdef PMSA003I_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(PMSA003I_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(PMSA003I_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, PMSA003I_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(PMSA003I_I2C_CLOCK_SPEED, _bus, _port);
#endif /* PMSA003I_I2C_CLOCK_SPEED */
_bus->beginTransmission(_address);
@@ -38,9 +33,12 @@ bool PMSA003ISensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
return false;
}
#if defined(PMSA003I_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef PMSA003I_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* PMSA003I_I2C_CLOCK_SPEED */
status = 1;
LOG_INFO("%s Enabled", sensorName);
@@ -57,14 +55,8 @@ bool PMSA003ISensor::getMetrics(meshtastic_Telemetry *measurement)
}
#ifdef PMSA003I_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(PMSA003I_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(PMSA003I_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, PMSA003I_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(PMSA003I_I2C_CLOCK_SPEED, _bus, _port);
#endif /* PMSA003I_I2C_CLOCK_SPEED */
_bus->requestFrom(_address, (uint8_t)PMSA003I_FRAME_LENGTH);
@@ -77,9 +69,12 @@ bool PMSA003ISensor::getMetrics(meshtastic_Telemetry *measurement)
buffer[i] = _bus->read();
}
#if defined(PMSA003I_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef PMSA003I_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* PMSA003I_I2C_CLOCK_SPEED */
if (buffer[0] != 0x42 || buffer[1] != 0x4D) {
LOG_WARN("%s frame header invalid: 0x%02X 0x%02X", sensorName, buffer[0], buffer[1]);
@@ -35,6 +35,7 @@ class PMSA003ISensor : public TelemetrySensor
uint8_t buffer[PMSA003I_FRAME_LENGTH]{};
TwoWire *_bus{};
uint8_t _address{};
ScanI2C::I2CPort _port = ScanI2C::I2CPort::NO_I2C;
};
#endif
+54 -62
View File
@@ -16,25 +16,23 @@ bool SCD30Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
_bus = bus;
_address = dev->address.address;
_port = dev->address.port;
#ifdef SCD30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD30_I2C_CLOCK_SPEED */
scd30.begin(*_bus, _address);
if (!startMeasurement()) {
LOG_ERROR("%s: Failed to start periodic measurement", sensorName);
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
return false;
}
@@ -42,9 +40,12 @@ bool SCD30Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
LOG_WARN("%s: Could not determine ASC state", sensorName);
}
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
if (state == SCD30_MEASUREMENT) {
status = 1;
@@ -62,27 +63,28 @@ bool SCD30Sensor::getMetrics(meshtastic_Telemetry *measurement)
float co2, temperature, humidity;
#ifdef SCD30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD30_I2C_CLOCK_SPEED */
if (scd30.readMeasurementData(co2, temperature, humidity) != SCD30_NO_ERROR) {
LOG_ERROR("SCD30: Failed to read measurement data.");
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
return false;
}
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
if (co2 == 0) {
LOG_ERROR("SCD30: Invalid CO₂ reading.");
@@ -372,23 +374,19 @@ bool SCD30Sensor::isActive()
*/
uint32_t SCD30Sensor::wakeUp()
{
#ifdef SCD30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return 0;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD30_I2C_CLOCK_SPEED */
startMeasurement();
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
return 0;
}
@@ -400,21 +398,18 @@ uint32_t SCD30Sensor::wakeUp()
void SCD30Sensor::sleep()
{
#ifdef SCD30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD30_I2C_CLOCK_SPEED */
stopMeasurement();
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
}
bool SCD30Sensor::canSleep()
@@ -438,14 +433,8 @@ AdminMessageHandleResult SCD30Sensor::handleAdminMessage(const meshtastic_MeshPa
AdminMessageHandleResult result;
#ifdef SCD30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return AdminMessageHandleResult::NOT_HANDLED;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD30_I2C_CLOCK_SPEED */
switch (request->which_payload_variant) {
@@ -501,9 +490,12 @@ AdminMessageHandleResult SCD30Sensor::handleAdminMessage(const meshtastic_MeshPa
result = AdminMessageHandleResult::NOT_HANDLED;
}
#if defined(SCD30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD30_I2C_CLOCK_SPEED */
return result;
}
@@ -14,6 +14,7 @@ class SCD30Sensor : public TelemetrySensor
SensirionI2cScd30 scd30;
TwoWire *_bus{};
uint8_t _address{};
ScanI2C::I2CPort _port = ScanI2C::I2CPort::NO_I2C;
bool performFRC(uint16_t targetCO2);
bool setASC(bool ascEnabled);
+96 -90
View File
@@ -18,14 +18,8 @@ bool SCD4XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
_address = dev->address.address;
#ifdef SCD4X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD4X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD4X_I2C_CLOCK_SPEED */
scd4x.begin(*_bus, _address);
@@ -35,9 +29,12 @@ bool SCD4XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
// Stop periodic measurement
if (!stopMeasurement()) {
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return false;
}
@@ -48,33 +45,45 @@ bool SCD4XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
LOG_INFO("%s: Found SCD41", sensorName);
if (!powerUp()) {
LOG_ERROR("%s: Error trying to execute powerUp()", sensorName);
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return false;
}
}
if (!getASC(ascActive)) {
LOG_ERROR("%s: Unable to check if ASC is enabled", sensorName);
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return false;
}
// Start measurement in selected power mode (low power by default)
if (!startMeasurement()) {
LOG_ERROR("%s: Couldn't start measurement", sensorName);
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return false;
}
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
if (state == SCD4X_MEASUREMENT) {
status = 1;
@@ -99,31 +108,31 @@ bool SCD4XSensor::getMetrics(meshtastic_Telemetry *measurement)
float temperature, humidity;
#ifdef SCD4X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD4X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD4X_I2C_CLOCK_SPEED */
bool dataReady;
error = scd4x.getDataReadyStatus(dataReady);
if (error != SCD4X_NO_ERROR || !dataReady) {
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
LOG_ERROR("SCD4X: Data is not ready");
return false;
}
error = scd4x.readMeasurement(co2, temperature, humidity);
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
LOG_DEBUG("Got %s readings: co2=%u, co2_temp=%.2f, co2_hum%.2f", sensorName, co2, temperature, humidity);
if (error != SCD4X_NO_ERROR) {
@@ -637,34 +646,37 @@ bool SCD4XSensor::powerDown()
}
#ifdef SCD4X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD4X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD4X_I2C_CLOCK_SPEED */
if (!stopMeasurement()) {
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return false;
}
if (scd4x.powerDown() != SCD4X_NO_ERROR) {
LOG_ERROR("%s: Error trying to execute sleep()", sensorName);
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return false;
}
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
state = SCD4X_OFF;
return true;
@@ -711,27 +723,27 @@ uint32_t SCD4XSensor::wakeUp()
{
#ifdef SCD4X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return 0;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD4X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD4X_I2C_CLOCK_SPEED */
if (startMeasurement()) {
co2MeasureStarted = getTime();
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return SCD4X_WARMUP_MS;
}
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return 0;
}
@@ -743,21 +755,18 @@ uint32_t SCD4XSensor::wakeUp()
void SCD4XSensor::sleep()
{
#ifdef SCD4X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD4X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD4X_I2C_CLOCK_SPEED */
stopMeasurement();
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
}
/**
@@ -797,14 +806,8 @@ AdminMessageHandleResult SCD4XSensor::handleAdminMessage(const meshtastic_MeshPa
AdminMessageHandleResult result;
#ifdef SCD4X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return AdminMessageHandleResult::NOT_HANDLED;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SCD4X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SCD4X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SCD4X_I2C_CLOCK_SPEED */
// TODO: potentially add selftest command?
@@ -907,9 +910,12 @@ AdminMessageHandleResult SCD4XSensor::handleAdminMessage(const meshtastic_MeshPa
// Start measurement mode
this->startMeasurement();
#if defined(SCD4X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SCD4X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SCD4X_I2C_CLOCK_SPEED */
return result;
}
@@ -17,6 +17,7 @@ class SCD4XSensor : public TelemetrySensor
SensirionI2cScd4x scd4x;
TwoWire *_bus{};
uint8_t _address{};
ScanI2C::I2CPort _port = ScanI2C::I2CPort::NO_I2C;
bool performFRC(uint32_t targetCO2);
bool setASCBaseline(uint32_t targetCO2);
+18 -22
View File
@@ -134,14 +134,8 @@ bool SEN5XSensor::sendCommand(uint16_t command, uint8_t *buffer, uint8_t byteNum
}
#ifdef SEN5X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SEN5X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SEN5X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SEN5X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SEN5X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SEN5X_I2C_CLOCK_SPEED */
// Transmit the data
@@ -152,9 +146,12 @@ bool SEN5XSensor::sendCommand(uint16_t command, uint8_t *buffer, uint8_t byteNum
size_t writtenBytes = _bus->write(toSend, bufferSize);
uint8_t i2c_error = _bus->endTransmission();
#if defined(SEN5X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SEN5X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SEN5X_I2C_CLOCK_SPEED */
if (writtenBytes != bufferSize) {
LOG_ERROR("SEN5X: Error writting on I2C bus");
@@ -171,14 +168,8 @@ bool SEN5XSensor::sendCommand(uint16_t command, uint8_t *buffer, uint8_t byteNum
uint8_t SEN5XSensor::readBuffer(uint8_t *buffer, uint8_t byteNumber)
{
#ifdef SEN5X_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SEN5X_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SEN5X_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SEN5X_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SEN5X_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SEN5X_I2C_CLOCK_SPEED */
size_t readBytes = _bus->requestFrom(_address, byteNumber);
@@ -201,9 +192,13 @@ uint8_t SEN5XSensor::readBuffer(uint8_t *buffer, uint8_t byteNumber)
readBytes -= 3;
receivedBytes += 2;
}
#if defined(SEN5X_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SEN5X_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SEN5X_I2C_CLOCK_SPEED */
return receivedBytes;
}
@@ -567,6 +562,7 @@ bool SEN5XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
_bus = bus;
_address = dev->address.address;
_port = dev->address.port;
delay(50); // without this there is an error on the deviceReset function
@@ -62,6 +62,7 @@ class SEN5XSensor : public TelemetrySensor
private:
TwoWire *_bus{};
uint8_t _address{};
ScanI2C::I2CPort _port = ScanI2C::I2CPort::NO_I2C;
bool getVersion();
float firmwareVer = -1;
+57 -53
View File
@@ -14,41 +14,45 @@ bool SFA30Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
_bus = bus;
_address = dev->address.address;
_port = dev->address.port;
#ifdef SFA30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SFA30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SFA30_I2C_CLOCK_SPEED */
sfa30.begin(*_bus, _address);
delay(20);
if (this->isError(sfa30.deviceReset())) {
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
return false;
}
state = State::IDLE;
if (this->isError(sfa30.startContinuousMeasurement())) {
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
return false;
}
LOG_INFO("%s starting measurement", sensorName);
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
status = 1;
state = State::ACTIVE;
@@ -72,14 +76,8 @@ bool SFA30Sensor::isError(uint16_t response)
void SFA30Sensor::sleep()
{
#ifdef SFA30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SFA30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SFA30_I2C_CLOCK_SPEED */
// Note - not recommended for this sensor on a periodic basis
@@ -87,9 +85,12 @@ void SFA30Sensor::sleep()
LOG_ERROR("%s: can't stop measurement", sensorName);
};
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
LOG_INFO("%s: stop measurement", sensorName);
state = State::IDLE;
@@ -99,27 +100,27 @@ void SFA30Sensor::sleep()
uint32_t SFA30Sensor::wakeUp()
{
#ifdef SFA30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SFA30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SFA30_I2C_CLOCK_SPEED */
LOG_INFO("Waking up %s", sensorName);
if (this->isError(sfa30.startContinuousMeasurement())) {
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
return 0;
}
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
state = State::ACTIVE;
measureStarted = getTime();
@@ -164,24 +165,27 @@ bool SFA30Sensor::getMetrics(meshtastic_Telemetry *measurement)
float temperature = 0.0;
#ifdef SFA30_I2C_CLOCK_SPEED
#ifdef CAN_RECLOCK_I2C
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, false);
#elif !HAS_SCREEN
reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, true);
#else
LOG_WARN("%s can't be used at this clock speed, with a screen", sensorName);
return false;
#endif /* CAN_RECLOCK_I2C */
LOG_INFO("%s attempting to reclock speed to %uHz", sensorName, SFA30_I2C_CLOCK_SPEED);
uint32_t currentClock = reClockI2C(SFA30_I2C_CLOCK_SPEED, _bus, _port);
#endif /* SFA30_I2C_CLOCK_SPEED */
if (this->isError(sfa30.readMeasuredValues(hcho, humidity, temperature))) {
LOG_WARN("%s: No values", sensorName);
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
return false;
}
#if defined(SFA30_I2C_CLOCK_SPEED) && defined(CAN_RECLOCK_I2C)
reClockI2C(currentClock, _bus, false);
#endif
#ifdef SFA30_I2C_CLOCK_SPEED
if (currentClock) {
LOG_INFO("%s restoring clock speed to %uHz", sensorName, currentClock);
reClockI2C(currentClock, _bus, _port);
}
#endif /* SFA30_I2C_CLOCK_SPEED */
measurement->variant.air_quality_metrics.has_form_temperature = true;
measurement->variant.air_quality_metrics.has_form_humidity = true;
@@ -21,6 +21,8 @@ class SFA30Sensor : public TelemetrySensor
SensirionI2cSfa3x sfa30;
TwoWire *_bus{};
uint8_t _address{};
ScanI2C::I2CPort _port = ScanI2C::I2CPort::NO_I2C;
bool isError(uint16_t response);
public: