From b353bcc04acf9eeab7d2f700e7ee977a6a0d7582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sat, 18 Jan 2025 14:10:13 +0100 Subject: [PATCH] fix detection of lark weather station and add rain sensor (#5874) * fix detection of lark weather station * fix unit tests and add support for Dfrobot rain gauge * fix name display on bootup * fix gauge init logic * trunk fmt --- platformio.ini | 1 + src/configuration.h | 1 + src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 17 +++++-- src/detect/ScanI2CTwoWire.h | 2 +- src/main.cpp | 1 + .../Telemetry/EnvironmentTelemetry.cpp | 13 ++++++ .../Telemetry/Sensor/DFRobotGravitySensor.cpp | 44 +++++++++++++++++++ .../Telemetry/Sensor/DFRobotGravitySensor.h | 29 ++++++++++++ 9 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp create mode 100644 src/modules/Telemetry/Sensor/DFRobotGravitySensor.h diff --git a/platformio.ini b/platformio.ini index 217e75631..ea4de4db1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -126,6 +126,7 @@ lib_deps = mprograms/QMC5883LCompass@1.2.3 dfrobot/DFRobot_RTU@1.0.3 https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d + https://github.com/DFRobot/DFRobot_RainfallSensor#38fea5e02b40a5430be6dab39a99a6f6347d667e robtillaart/INA226@0.6.0 ; Health Sensor Libraries diff --git a/src/configuration.h b/src/configuration.h index 2c77b55e3..6f5255ec9 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -145,6 +145,7 @@ along with this program. If not, see . #define OPT3001_ADDR_ALT 0x44 #define MLX90632_ADDR 0x3A #define DFROBOT_LARK_ADDR 0x42 +#define DFROBOT_RAIN_ADDR 0x1d #define NAU7802_ADDR 0x2A #define MAX30102_ADDR 0x57 #define MLX90614_ADDR_DEF 0x5A diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 2561a8e17..faa94c7d3 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -66,6 +66,7 @@ class ScanI2C CGRADSENS, INA226, NXP_SE050, + DFROBOT_RAIN, } DeviceType; // typedef uint8_t DeviceAddress; diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index a786f874d..880e5c131 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -84,23 +84,33 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const return o_probe; } uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation ®isterLocation, - ScanI2CTwoWire::ResponseWidth responseWidth) const + ScanI2CTwoWire::ResponseWidth responseWidth, bool zeropad = false) const { uint16_t value = 0x00; TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress); i2cBus->beginTransmission(registerLocation.i2cAddress.address); i2cBus->write(registerLocation.registerAddress); + if (zeropad) { + // Lark Commands need the argument list length in 2 bytes. + i2cBus->write((int)0); + i2cBus->write((int)0); + } i2cBus->endTransmission(); delay(20); i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth); - if (i2cBus->available() == 2) { + if (i2cBus->available() > 1) { // Read MSB, then LSB value = (uint16_t)i2cBus->read() << 8; value |= i2cBus->read(); } else if (i2cBus->available()) { value = i2cBus->read(); } + // Drain excess bytes + for (uint8_t i = 0; i < responseWidth - 1; i++) { + if (i2cBus->available()) + i2cBus->read(); + } return value; } @@ -286,7 +296,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) RESPONSE_PAYLOAD 0x01 RESPONSE_PAYLOAD+1 0x00 */ - registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2); + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 6, true); LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue); if (registerValue == 0x5305) { logFoundDevice("DFRobot Lark", (uint8_t)addr.address); @@ -402,6 +412,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address); SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address); SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address); #ifdef HAS_TPS65233 SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); #endif diff --git a/src/detect/ScanI2CTwoWire.h b/src/detect/ScanI2CTwoWire.h index d0af7cde6..6988091ad 100644 --- a/src/detect/ScanI2CTwoWire.h +++ b/src/detect/ScanI2CTwoWire.h @@ -53,7 +53,7 @@ class ScanI2CTwoWire : public ScanI2C concurrency::Lock lock; - uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const; + uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth, bool) const; DeviceType probeOLED(ScanI2C::DeviceAddress) const; diff --git a/src/main.cpp b/src/main.cpp index fc9d24e37..24fc71749 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -610,6 +610,7 @@ void setup() scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN); i2cScanner.reset(); #endif diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index fe1d0d2a9..1af6347f2 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -27,6 +27,7 @@ #include "Sensor/BMP280Sensor.h" #include "Sensor/BMP3XXSensor.h" #include "Sensor/CGRadSensSensor.h" +#include "Sensor/DFRobotGravitySensor.h" #include "Sensor/DFRobotLarkSensor.h" #include "Sensor/LPS22HBSensor.h" #include "Sensor/MCP9808Sensor.h" @@ -56,6 +57,7 @@ RCWL9620Sensor rcwl9620Sensor; AHT10Sensor aht10Sensor; MLX90632Sensor mlx90632Sensor; DFRobotLarkSensor dfRobotLarkSensor; +DFRobotGravitySensor dfRobotGravitySensor; NAU7802Sensor nau7802Sensor; BMP3XXSensor bmp3xxSensor; CGRadSensSensor cgRadSens; @@ -115,6 +117,8 @@ int32_t EnvironmentTelemetryModule::runOnce() #elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL if (dfRobotLarkSensor.hasSensor()) result = dfRobotLarkSensor.runOnce(); + if (dfRobotGravitySensor.hasSensor()) + result = dfRobotGravitySensor.runOnce(); if (bmp085Sensor.hasSensor()) result = bmp085Sensor.runOnce(); if (bmp280Sensor.hasSensor()) @@ -368,6 +372,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m valid = valid && dfRobotLarkSensor.getMetrics(m); hasSensor = true; } + if (dfRobotGravitySensor.hasSensor()) { + valid = valid && dfRobotGravitySensor.getMetrics(m); + hasSensor = true; + } if (sht31Sensor.hasSensor()) { valid = valid && sht31Sensor.getMetrics(m); hasSensor = true; @@ -569,6 +577,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule if (result != AdminMessageHandleResult::NOT_HANDLED) return result; } + if (dfRobotGravitySensor.hasSensor()) { + result = dfRobotGravitySensor.handleAdminMessage(mp, request, response); + if (result != AdminMessageHandleResult::NOT_HANDLED) + return result; + } if (sht31Sensor.hasSensor()) { result = sht31Sensor.handleAdminMessage(mp, request, response); if (result != AdminMessageHandleResult::NOT_HANDLED) diff --git a/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp new file mode 100644 index 000000000..c7fa29966 --- /dev/null +++ b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.cpp @@ -0,0 +1,44 @@ +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "DFRobotGravitySensor.h" +#include "TelemetrySensor.h" +#include +#include + +DFRobotGravitySensor::DFRobotGravitySensor() : TelemetrySensor(meshtastic_TelemetrySensorType_DFROBOT_RAIN, "DFROBOT_RAIN") {} + +int32_t DFRobotGravitySensor::runOnce() +{ + LOG_INFO("Init sensor: %s", sensorName); + if (!hasSensor()) { + return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; + } + + gravity = DFRobot_RainfallSensor_I2C(nodeTelemetrySensorsMap[sensorType].second); + status = gravity.begin(); + + return initI2CSensor(); +} + +void DFRobotGravitySensor::setup() +{ + LOG_DEBUG("%s VID: %x, PID: %x, Version: %s", sensorName, gravity.vid, gravity.pid, gravity.getFirmwareVersion().c_str()); +} + +bool DFRobotGravitySensor::getMetrics(meshtastic_Telemetry *measurement) +{ + measurement->variant.environment_metrics.has_rainfall_1h = true; + measurement->variant.environment_metrics.has_rainfall_24h = true; + + measurement->variant.environment_metrics.rainfall_1h = gravity.getRainfall(1); + measurement->variant.environment_metrics.rainfall_24h = gravity.getRainfall(24); + + LOG_INFO("Rain 1h: %f mm", measurement->variant.environment_metrics.rainfall_1h); + LOG_INFO("Rain 24h: %f mm", measurement->variant.environment_metrics.rainfall_24h); + return true; +} + +#endif \ No newline at end of file diff --git a/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h new file mode 100644 index 000000000..8bd7335b5 --- /dev/null +++ b/src/modules/Telemetry/Sensor/DFRobotGravitySensor.h @@ -0,0 +1,29 @@ +#pragma once + +#ifndef _MT_DFROBOTGRAVITYSENSOR_H +#define _MT_DFROBOTGRAVITYSENSOR_H +#include "configuration.h" + +#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR + +#include "../mesh/generated/meshtastic/telemetry.pb.h" +#include "TelemetrySensor.h" +#include +#include + +class DFRobotGravitySensor : public TelemetrySensor +{ + private: + DFRobot_RainfallSensor_I2C gravity = DFRobot_RainfallSensor_I2C(nodeTelemetrySensorsMap[sensorType].second); + + protected: + virtual void setup() override; + + public: + DFRobotGravitySensor(); + virtual int32_t runOnce() override; + virtual bool getMetrics(meshtastic_Telemetry *measurement) override; +}; + +#endif +#endif \ No newline at end of file