Usermod Temperature: use full 12-bit precision (#4916)

* Usermod Temperature: use full 12-bit precision

* Temperature Usermod: fix DS1822 and DS18B20 family code

* Add Dropdown to select 9 or 12 bit resolution

* Add 10 and 11 bit resolution, Correct rounding towards negativ inf
This commit is contained in:
nename0
2025-12-26 21:32:24 +01:00
committed by GitHub
parent b821e20fd6
commit 8a2a7054ab
2 changed files with 24 additions and 9 deletions

View File

@@ -20,17 +20,19 @@ float UsermodTemperature::readDallas() {
} }
#endif #endif
switch(sensorFound) { switch(sensorFound) {
case 0x10: // DS18S20 has 9-bit precision case 0x10: // DS18S20 has 9-bit precision - 1-bit fraction part
result = (data[1] << 8) | data[0]; result = (data[1] << 8) | data[0];
retVal = float(result) * 0.5f; retVal = float(result) * 0.5f;
break; break;
case 0x22: // DS18B20 case 0x22: // DS1822
case 0x28: // DS1822 case 0x28: // DS18B20
case 0x3B: // DS1825 case 0x3B: // DS1825
case 0x42: // DS28EA00 case 0x42: // DS28EA00
result = (data[1]<<4) | (data[0]>>4); // we only need whole part, we will add fraction when returning // 12-bit precision - 4-bit fraction part
if (data[1] & 0x80) result |= 0xF000; // fix negative value result = (data[1] << 8) | data[0];
retVal = float(result) + ((data[0] & 0x08) ? 0.5f : 0.0f); // Clear LSBs to match desired precision (9/10/11-bit) rounding towards negative infinity
result &= 0xFFFF << (3 - (resolution & 3));
retVal = float(result) * 0.0625f; // 2^(-4)
break; break;
} }
} }
@@ -69,8 +71,8 @@ bool UsermodTemperature::findSensor() {
if (oneWire->crc8(deviceAddress, 7) == deviceAddress[7]) { if (oneWire->crc8(deviceAddress, 7) == deviceAddress[7]) {
switch (deviceAddress[0]) { switch (deviceAddress[0]) {
case 0x10: // DS18S20 case 0x10: // DS18S20
case 0x22: // DS18B20 case 0x22: // DS1822
case 0x28: // DS1822 case 0x28: // DS18B20
case 0x3B: // DS1825 case 0x3B: // DS1825
case 0x42: // DS28EA00 case 0x42: // DS28EA00
DEBUG_PRINTLN(F("Sensor found.")); DEBUG_PRINTLN(F("Sensor found."));
@@ -277,6 +279,7 @@ void UsermodTemperature::addToConfig(JsonObject &root) {
top[FPSTR(_parasite)] = parasite; top[FPSTR(_parasite)] = parasite;
top[FPSTR(_parasitePin)] = parasitePin; top[FPSTR(_parasitePin)] = parasitePin;
top[FPSTR(_domoticzIDX)] = idx; top[FPSTR(_domoticzIDX)] = idx;
top[FPSTR(_resolution)] = resolution;
DEBUG_PRINTLN(F("Temperature config saved.")); DEBUG_PRINTLN(F("Temperature config saved."));
} }
@@ -304,6 +307,7 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
parasite = top[FPSTR(_parasite)] | parasite; parasite = top[FPSTR(_parasite)] | parasite;
parasitePin = top[FPSTR(_parasitePin)] | parasitePin; parasitePin = top[FPSTR(_parasitePin)] | parasitePin;
idx = top[FPSTR(_domoticzIDX)] | idx; idx = top[FPSTR(_domoticzIDX)] | idx;
resolution = top[FPSTR(_resolution)] | resolution;
if (!initDone) { if (!initDone) {
// first run: reading from cfg.json // first run: reading from cfg.json
@@ -324,7 +328,7 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
} }
} }
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features // use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return !top[FPSTR(_domoticzIDX)].isNull(); return !top[FPSTR(_resolution)].isNull();
} }
void UsermodTemperature::appendConfigData() { void UsermodTemperature::appendConfigData() {
@@ -332,6 +336,14 @@ void UsermodTemperature::appendConfigData() {
oappend(F("',1,'<i>(if no Vcc connected)</i>');")); // 0 is field type, 1 is actual field oappend(F("',1,'<i>(if no Vcc connected)</i>');")); // 0 is field type, 1 is actual field
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasitePin)).c_str()); oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
oappend(F("',1,'<i>(for external MOSFET)</i>');")); // 0 is field type, 1 is actual field oappend(F("',1,'<i>(for external MOSFET)</i>');")); // 0 is field type, 1 is actual field
oappend(F("dd=addDD('")); oappend(String(FPSTR(_name)).c_str());
oappend(F("','")); oappend(String(FPSTR(_resolution)).c_str()); oappend(F("');"));
oappend(F("addO(dd,'0.5 °C (9-bit)',0);"));
oappend(F("addO(dd,'0.25°C (10-bit)',1);"));
oappend(F("addO(dd,'0.125°C (11-bit)',2);"));
oappend(F("addO(dd,'0.0625°C (12-bit)',3);"));
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_resolution)).c_str());
oappend(F("',1,'<i>(ignored on DS18S20)</i>');")); // 0 is field type, 1 is actual field
} }
float UsermodTemperature::getTemperature() { float UsermodTemperature::getTemperature() {
@@ -351,6 +363,7 @@ const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s";
const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr"; const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr";
const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin"; const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin";
const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx"; const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx";
const char UsermodTemperature::_resolution[] PROGMEM = "resolution";
const char UsermodTemperature::_sensor[] PROGMEM = "sensor"; const char UsermodTemperature::_sensor[] PROGMEM = "sensor";
const char UsermodTemperature::_temperature[] PROGMEM = "temperature"; const char UsermodTemperature::_temperature[] PROGMEM = "temperature";
const char UsermodTemperature::_Temperature[] PROGMEM = "/temperature"; const char UsermodTemperature::_Temperature[] PROGMEM = "/temperature";

View File

@@ -48,6 +48,7 @@ class UsermodTemperature : public Usermod {
bool HApublished = false; bool HApublished = false;
int16_t idx = -1; // Domoticz virtual sensor idx int16_t idx = -1; // Domoticz virtual sensor idx
uint8_t resolution = 0; // 9bits=0, 10bits=1, 11bits=2, 12bits=3
// strings to reduce flash memory usage (used more than twice) // strings to reduce flash memory usage (used more than twice)
static const char _name[]; static const char _name[];
@@ -56,6 +57,7 @@ class UsermodTemperature : public Usermod {
static const char _parasite[]; static const char _parasite[];
static const char _parasitePin[]; static const char _parasitePin[];
static const char _domoticzIDX[]; static const char _domoticzIDX[];
static const char _resolution[];
static const char _sensor[]; static const char _sensor[];
static const char _temperature[]; static const char _temperature[];
static const char _Temperature[]; static const char _Temperature[];