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
This commit is contained in:
Thomas Göttgens 2025-01-18 14:10:13 +01:00 committed by GitHub
parent c4051c1a7b
commit b353bcc04a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 105 additions and 4 deletions

View File

@ -126,6 +126,7 @@ lib_deps =
mprograms/QMC5883LCompass@1.2.3 mprograms/QMC5883LCompass@1.2.3
dfrobot/DFRobot_RTU@1.0.3 dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
https://github.com/DFRobot/DFRobot_RainfallSensor#38fea5e02b40a5430be6dab39a99a6f6347d667e
robtillaart/INA226@0.6.0 robtillaart/INA226@0.6.0
; Health Sensor Libraries ; Health Sensor Libraries

View File

@ -145,6 +145,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define OPT3001_ADDR_ALT 0x44 #define OPT3001_ADDR_ALT 0x44
#define MLX90632_ADDR 0x3A #define MLX90632_ADDR 0x3A
#define DFROBOT_LARK_ADDR 0x42 #define DFROBOT_LARK_ADDR 0x42
#define DFROBOT_RAIN_ADDR 0x1d
#define NAU7802_ADDR 0x2A #define NAU7802_ADDR 0x2A
#define MAX30102_ADDR 0x57 #define MAX30102_ADDR 0x57
#define MLX90614_ADDR_DEF 0x5A #define MLX90614_ADDR_DEF 0x5A

View File

@ -66,6 +66,7 @@ class ScanI2C
CGRADSENS, CGRADSENS,
INA226, INA226,
NXP_SE050, NXP_SE050,
DFROBOT_RAIN,
} DeviceType; } DeviceType;
// typedef uint8_t DeviceAddress; // typedef uint8_t DeviceAddress;

View File

@ -84,23 +84,33 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
return o_probe; return o_probe;
} }
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation &registerLocation, uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation &registerLocation,
ScanI2CTwoWire::ResponseWidth responseWidth) const ScanI2CTwoWire::ResponseWidth responseWidth, bool zeropad = false) const
{ {
uint16_t value = 0x00; uint16_t value = 0x00;
TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress); TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress);
i2cBus->beginTransmission(registerLocation.i2cAddress.address); i2cBus->beginTransmission(registerLocation.i2cAddress.address);
i2cBus->write(registerLocation.registerAddress); 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(); i2cBus->endTransmission();
delay(20); delay(20);
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth); i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
if (i2cBus->available() == 2) { if (i2cBus->available() > 1) {
// Read MSB, then LSB // Read MSB, then LSB
value = (uint16_t)i2cBus->read() << 8; value = (uint16_t)i2cBus->read() << 8;
value |= i2cBus->read(); value |= i2cBus->read();
} else if (i2cBus->available()) { } else if (i2cBus->available()) {
value = i2cBus->read(); value = i2cBus->read();
} }
// Drain excess bytes
for (uint8_t i = 0; i < responseWidth - 1; i++) {
if (i2cBus->available())
i2cBus->read();
}
return value; return value;
} }
@ -286,7 +296,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
RESPONSE_PAYLOAD 0x01 RESPONSE_PAYLOAD 0x01
RESPONSE_PAYLOAD+1 0x00 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); LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue);
if (registerValue == 0x5305) { if (registerValue == 0x5305) {
logFoundDevice("DFRobot Lark", (uint8_t)addr.address); 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(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (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(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 #ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
#endif #endif

View File

@ -53,7 +53,7 @@ class ScanI2CTwoWire : public ScanI2C
concurrency::Lock lock; concurrency::Lock lock;
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const; uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth, bool) const;
DeviceType probeOLED(ScanI2C::DeviceAddress) const; DeviceType probeOLED(ScanI2C::DeviceAddress) const;

View File

@ -610,6 +610,7 @@ void setup()
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS); scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN);
i2cScanner.reset(); i2cScanner.reset();
#endif #endif

View File

@ -27,6 +27,7 @@
#include "Sensor/BMP280Sensor.h" #include "Sensor/BMP280Sensor.h"
#include "Sensor/BMP3XXSensor.h" #include "Sensor/BMP3XXSensor.h"
#include "Sensor/CGRadSensSensor.h" #include "Sensor/CGRadSensSensor.h"
#include "Sensor/DFRobotGravitySensor.h"
#include "Sensor/DFRobotLarkSensor.h" #include "Sensor/DFRobotLarkSensor.h"
#include "Sensor/LPS22HBSensor.h" #include "Sensor/LPS22HBSensor.h"
#include "Sensor/MCP9808Sensor.h" #include "Sensor/MCP9808Sensor.h"
@ -56,6 +57,7 @@ RCWL9620Sensor rcwl9620Sensor;
AHT10Sensor aht10Sensor; AHT10Sensor aht10Sensor;
MLX90632Sensor mlx90632Sensor; MLX90632Sensor mlx90632Sensor;
DFRobotLarkSensor dfRobotLarkSensor; DFRobotLarkSensor dfRobotLarkSensor;
DFRobotGravitySensor dfRobotGravitySensor;
NAU7802Sensor nau7802Sensor; NAU7802Sensor nau7802Sensor;
BMP3XXSensor bmp3xxSensor; BMP3XXSensor bmp3xxSensor;
CGRadSensSensor cgRadSens; CGRadSensSensor cgRadSens;
@ -115,6 +117,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
#elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL #elif !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL
if (dfRobotLarkSensor.hasSensor()) if (dfRobotLarkSensor.hasSensor())
result = dfRobotLarkSensor.runOnce(); result = dfRobotLarkSensor.runOnce();
if (dfRobotGravitySensor.hasSensor())
result = dfRobotGravitySensor.runOnce();
if (bmp085Sensor.hasSensor()) if (bmp085Sensor.hasSensor())
result = bmp085Sensor.runOnce(); result = bmp085Sensor.runOnce();
if (bmp280Sensor.hasSensor()) if (bmp280Sensor.hasSensor())
@ -368,6 +372,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
valid = valid && dfRobotLarkSensor.getMetrics(m); valid = valid && dfRobotLarkSensor.getMetrics(m);
hasSensor = true; hasSensor = true;
} }
if (dfRobotGravitySensor.hasSensor()) {
valid = valid && dfRobotGravitySensor.getMetrics(m);
hasSensor = true;
}
if (sht31Sensor.hasSensor()) { if (sht31Sensor.hasSensor()) {
valid = valid && sht31Sensor.getMetrics(m); valid = valid && sht31Sensor.getMetrics(m);
hasSensor = true; hasSensor = true;
@ -569,6 +577,11 @@ AdminMessageHandleResult EnvironmentTelemetryModule::handleAdminMessageForModule
if (result != AdminMessageHandleResult::NOT_HANDLED) if (result != AdminMessageHandleResult::NOT_HANDLED)
return result; return result;
} }
if (dfRobotGravitySensor.hasSensor()) {
result = dfRobotGravitySensor.handleAdminMessage(mp, request, response);
if (result != AdminMessageHandleResult::NOT_HANDLED)
return result;
}
if (sht31Sensor.hasSensor()) { if (sht31Sensor.hasSensor()) {
result = sht31Sensor.handleAdminMessage(mp, request, response); result = sht31Sensor.handleAdminMessage(mp, request, response);
if (result != AdminMessageHandleResult::NOT_HANDLED) if (result != AdminMessageHandleResult::NOT_HANDLED)

View File

@ -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 <DFRobot_RainfallSensor.h>
#include <string>
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

View File

@ -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 <DFRobot_RainfallSensor.h>
#include <string>
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