Multi one wire measurements (#10192)
* First version of DS248X bridge * Add first iteration of DS248X sensor * Supports single readings on DS2484 * Supports readings on ch0 for DS2484_800 * Detection of variant for DS248X * Minor fix on retries for sensor init * Allow multiple channel detect passes on 8-ch version * Always read temperature via ROM matching * Small comment to show how to send all channels * Minor logging changes * Prevent one-wire double definitions * Detect ROMs per round * Fix comment * Prevent skipping on DS2482 ALT3 check * Fix comment (again) * Fix style checks * Remove comment for multiple measurements * Add multi-sensor measurements for one-wire sensors using wildcard message * Move to unpacked measurements in one-wire * Add admin command to set main temperature in 8-channel one-wire bridge. * Fix merge ref * Trunk fmt * Remove unused variable --------- Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
This commit is contained in:
co-authored by
Thomas Göttgens
parent
5d04f86af3
commit
cb557d89a6
4 files changed
+122
-13
No files matched your search
+11
-1
@@ -247,8 +247,18 @@ lib_deps =
|
||||
closedcube/ClosedCube OPT3001@1.1.2
|
||||
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
|
||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
|
||||
# renovate: datasource=github-tags depName=Sensirion Core packageName=sensirion/arduino-core
|
||||
https://github.com/Sensirion/arduino-core/archive/refs/tags/0.7.3.zip
|
||||
# renovate: datasource=github-tags depName=Sensirion I2C SCD4x packageName=sensirion/arduino-i2c-scd4x
|
||||
https://github.com/Sensirion/arduino-i2c-scd4x/archive/refs/tags/1.1.0.zip
|
||||
# renovate: datasource=github-tags depName=Sensirion I2C SFA3x packageName=sensirion/arduino-i2c-sfa3x
|
||||
https://github.com/Sensirion/arduino-i2c-sfa3x/archive/refs/tags/1.0.0.zip
|
||||
# renovate: datasource=github-tags depName=Sensirion I2C SCD30 packageName=sensirion/arduino-i2c-scd30
|
||||
https://github.com/Sensirion/arduino-i2c-scd30/archive/1.1.1.zip
|
||||
# renovate: datasource=github-tags depName=arduino-sht packageName=sensirion/arduino-sht
|
||||
https://github.com/Sensirion/arduino-sht/archive/refs/tags/v1.2.6.zip
|
||||
# renovate: datasource=github-tags depName=Adafruit DS248x packageName=adafruit/Adafruit_DS248x
|
||||
https://github.com/adafruit/Adafruit_DS248x/archive/refs/tags/1.2.0.zip
|
||||
https://github.com/adafruit/Adafruit_DS248x/archive/refs/tags/1.2.0.zip
|
||||
|
||||
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
|
||||
[environmental_extra]
|
||||
|
||||
@@ -743,7 +743,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
|
||||
logFoundDevice("DS2482-800", (uint8_t)addr.address);
|
||||
break;
|
||||
}
|
||||
|
||||
type = HMC5883L;
|
||||
logFoundDevice("HMC5883L", (uint8_t)addr.address);
|
||||
break;
|
||||
|
||||
@@ -78,7 +78,6 @@ bool DS248XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
// Try to init One-Wire with 3 retries. This detects ROMs consistently
|
||||
// on the second one.
|
||||
uint8_t numRetries = 3;
|
||||
uint8_t rom[8]{};
|
||||
|
||||
for (uint8_t retry = 1; retry <= numRetries; retry++) {
|
||||
bool initError = false;
|
||||
@@ -162,12 +161,14 @@ bool DS248XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
|
||||
}
|
||||
|
||||
if (!initError) {
|
||||
LOG_INFO("%s: Started one-wire (%u/%u)", sensorName, retry, numRetries);
|
||||
status = true;
|
||||
// We want to keep searching for ROMs on the DS248X_DS2482_800
|
||||
// and always do the three passes
|
||||
if (_variant == ds248x_variant_t::DS248X_DS2484) {
|
||||
LOG_INFO("%s: Started one-wire (%u/%u)", sensorName, retry, numRetries);
|
||||
break;
|
||||
} else {
|
||||
LOG_INFO("%s: One-wire startup cycle (%u/%u)", sensorName, retry, numRetries);
|
||||
}
|
||||
}
|
||||
// TODO Potentially not needed, but taken from Adafruit's library example
|
||||
@@ -282,18 +283,112 @@ bool DS248XSensor::getMetrics(meshtastic_Telemetry *measurement)
|
||||
return true;
|
||||
}
|
||||
} else if (_variant == ds248x_variant_t::DS248X_DS2482_800) {
|
||||
// Only ch0 is reported, and each populated channel blocks 750ms on its conversion
|
||||
// TODO Support more than one temperature via repeated (3.0)
|
||||
// TODO Select which channel can be reported as main temperature
|
||||
if (readTemperatureChannel(0)) {
|
||||
measurement->variant.environment_metrics.temperature = ds2482800Data.ds248xData[0].temperature;
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
LOG_DEBUG("Got %s readings: temperature=%.2f", sensorName, measurement->variant.environment_metrics.temperature);
|
||||
return true;
|
||||
// If using DS248X_DS2482_800, we read all channels
|
||||
uint8_t channelCount = 0;
|
||||
|
||||
// Note, the reason why we are using an unpacked version of this message
|
||||
// (instead of repeated) it's to save space. With repeated, we have to send all
|
||||
// channels (even if null) or otherwise we don't know where each channel is
|
||||
// being reported
|
||||
for (uint8_t channel = 0; channel < 8; channel++) {
|
||||
if (readTemperatureChannel(channel)) {
|
||||
channelCount += 1;
|
||||
|
||||
if (channel == mainTemperatureChannel) {
|
||||
measurement->variant.environment_metrics.has_temperature = true;
|
||||
measurement->variant.environment_metrics.temperature = ds2482800Data.ds248xData[channel].temperature;
|
||||
}
|
||||
|
||||
switch (channel) {
|
||||
case 0:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch0 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch0 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 1:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch1 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch1 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 2:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch2 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch2 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 3:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch3 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch3 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 4:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch4 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch4 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 5:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch5 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch5 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 6:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch6 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch6 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
case 7:
|
||||
measurement->variant.environment_metrics.has_one_wire_temperature_ch7 = true;
|
||||
measurement->variant.environment_metrics.one_wire_temperature_ch7 =
|
||||
ds2482800Data.ds248xData[channel].temperature;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Got %s readings: temperature_ch%u=%.2f", sensorName, channel,
|
||||
ds2482800Data.ds248xData[channel].temperature);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return channelCount > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DS248XSensor::setMainTemperature(uint8_t channel)
|
||||
{
|
||||
if (channel > 7) {
|
||||
LOG_ERROR("%s: Requested channel (%u) not available", sensorName, channel);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO("%s: Setting requested channel (%u) as main temperature", sensorName, channel);
|
||||
mainTemperatureChannel = channel;
|
||||
return;
|
||||
}
|
||||
|
||||
AdminMessageHandleResult DS248XSensor::handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response)
|
||||
{
|
||||
AdminMessageHandleResult result;
|
||||
result = AdminMessageHandleResult::NOT_HANDLED;
|
||||
|
||||
switch (request->which_payload_variant) {
|
||||
case meshtastic_AdminMessage_sensor_config_tag:
|
||||
if (!request->sensor_config.has_ds248x_config) {
|
||||
result = AdminMessageHandleResult::NOT_HANDLED;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for main temperature channel request
|
||||
if (request->sensor_config.ds248x_config.has_main_temperature_channel) {
|
||||
this->setMainTemperature(request->sensor_config.ds248x_config.main_temperature_channel);
|
||||
}
|
||||
|
||||
result = AdminMessageHandleResult::HANDLED;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = AdminMessageHandleResult::NOT_HANDLED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -66,6 +66,7 @@ class DS248XSensor : public TelemetrySensor
|
||||
ds248x_variant_t _variant = DS248X_UNKNOWN;
|
||||
_DS248XData ds248xData{};
|
||||
_DS2482800Data ds2482800Data{};
|
||||
uint8_t mainTemperatureChannel = 0;
|
||||
#ifdef DS248X_I2C_CLOCK_SPEED
|
||||
ReClockI2C reClockI2C;
|
||||
#endif
|
||||
@@ -73,12 +74,16 @@ class DS248XSensor : public TelemetrySensor
|
||||
bool isValidROM(const uint8_t *rom);
|
||||
float readTemperatureROM(const uint8_t *rom);
|
||||
bool readTemperatureChannel(uint8_t channel);
|
||||
void setMainTemperature(uint8_t channel);
|
||||
|
||||
public:
|
||||
DS248XSensor();
|
||||
ds248x_variant_t detectVariant();
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
|
||||
|
||||
AdminMessageHandleResult handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
|
||||
meshtastic_AdminMessage *response) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user