Skip to content

Commit 8a2a705

Browse files
authored
Usermod Temperature: use full 12-bit precision (wled#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
1 parent b821e20 commit 8a2a705

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

usermods/Temperature/Temperature.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@ float UsermodTemperature::readDallas() {
2020
}
2121
#endif
2222
switch(sensorFound) {
23-
case 0x10: // DS18S20 has 9-bit precision
23+
case 0x10: // DS18S20 has 9-bit precision - 1-bit fraction part
2424
result = (data[1] << 8) | data[0];
2525
retVal = float(result) * 0.5f;
2626
break;
27-
case 0x22: // DS18B20
28-
case 0x28: // DS1822
27+
case 0x22: // DS1822
28+
case 0x28: // DS18B20
2929
case 0x3B: // DS1825
3030
case 0x42: // DS28EA00
31-
result = (data[1]<<4) | (data[0]>>4); // we only need whole part, we will add fraction when returning
32-
if (data[1] & 0x80) result |= 0xF000; // fix negative value
33-
retVal = float(result) + ((data[0] & 0x08) ? 0.5f : 0.0f);
31+
// 12-bit precision - 4-bit fraction part
32+
result = (data[1] << 8) | data[0];
33+
// Clear LSBs to match desired precision (9/10/11-bit) rounding towards negative infinity
34+
result &= 0xFFFF << (3 - (resolution & 3));
35+
retVal = float(result) * 0.0625f; // 2^(-4)
3436
break;
3537
}
3638
}
@@ -69,8 +71,8 @@ bool UsermodTemperature::findSensor() {
6971
if (oneWire->crc8(deviceAddress, 7) == deviceAddress[7]) {
7072
switch (deviceAddress[0]) {
7173
case 0x10: // DS18S20
72-
case 0x22: // DS18B20
73-
case 0x28: // DS1822
74+
case 0x22: // DS1822
75+
case 0x28: // DS18B20
7476
case 0x3B: // DS1825
7577
case 0x42: // DS28EA00
7678
DEBUG_PRINTLN(F("Sensor found."));
@@ -277,6 +279,7 @@ void UsermodTemperature::addToConfig(JsonObject &root) {
277279
top[FPSTR(_parasite)] = parasite;
278280
top[FPSTR(_parasitePin)] = parasitePin;
279281
top[FPSTR(_domoticzIDX)] = idx;
282+
top[FPSTR(_resolution)] = resolution;
280283
DEBUG_PRINTLN(F("Temperature config saved."));
281284
}
282285

@@ -304,6 +307,7 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
304307
parasite = top[FPSTR(_parasite)] | parasite;
305308
parasitePin = top[FPSTR(_parasitePin)] | parasitePin;
306309
idx = top[FPSTR(_domoticzIDX)] | idx;
310+
resolution = top[FPSTR(_resolution)] | resolution;
307311

308312
if (!initDone) {
309313
// first run: reading from cfg.json
@@ -324,14 +328,22 @@ bool UsermodTemperature::readFromConfig(JsonObject &root) {
324328
}
325329
}
326330
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
327-
return !top[FPSTR(_domoticzIDX)].isNull();
331+
return !top[FPSTR(_resolution)].isNull();
328332
}
329333

330334
void UsermodTemperature::appendConfigData() {
331335
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasite)).c_str());
332336
oappend(F("',1,'<i>(if no Vcc connected)</i>');")); // 0 is field type, 1 is actual field
333337
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_parasitePin)).c_str());
334338
oappend(F("',1,'<i>(for external MOSFET)</i>');")); // 0 is field type, 1 is actual field
339+
oappend(F("dd=addDD('")); oappend(String(FPSTR(_name)).c_str());
340+
oappend(F("','")); oappend(String(FPSTR(_resolution)).c_str()); oappend(F("');"));
341+
oappend(F("addO(dd,'0.5 °C (9-bit)',0);"));
342+
oappend(F("addO(dd,'0.25°C (10-bit)',1);"));
343+
oappend(F("addO(dd,'0.125°C (11-bit)',2);"));
344+
oappend(F("addO(dd,'0.0625°C (12-bit)',3);"));
345+
oappend(F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(F(":")); oappend(String(FPSTR(_resolution)).c_str());
346+
oappend(F("',1,'<i>(ignored on DS18S20)</i>');")); // 0 is field type, 1 is actual field
335347
}
336348

337349
float UsermodTemperature::getTemperature() {
@@ -351,6 +363,7 @@ const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s";
351363
const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr";
352364
const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin";
353365
const char UsermodTemperature::_domoticzIDX[] PROGMEM = "domoticz-idx";
366+
const char UsermodTemperature::_resolution[] PROGMEM = "resolution";
354367
const char UsermodTemperature::_sensor[] PROGMEM = "sensor";
355368
const char UsermodTemperature::_temperature[] PROGMEM = "temperature";
356369
const char UsermodTemperature::_Temperature[] PROGMEM = "/temperature";

usermods/Temperature/UsermodTemperature.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class UsermodTemperature : public Usermod {
4848

4949
bool HApublished = false;
5050
int16_t idx = -1; // Domoticz virtual sensor idx
51+
uint8_t resolution = 0; // 9bits=0, 10bits=1, 11bits=2, 12bits=3
5152

5253
// strings to reduce flash memory usage (used more than twice)
5354
static const char _name[];
@@ -56,6 +57,7 @@ class UsermodTemperature : public Usermod {
5657
static const char _parasite[];
5758
static const char _parasitePin[];
5859
static const char _domoticzIDX[];
60+
static const char _resolution[];
5961
static const char _sensor[];
6062
static const char _temperature[];
6163
static const char _Temperature[];

0 commit comments

Comments
 (0)