Skip to content

Commit 794045d

Browse files
committed
Merge pull request milesburton#18 from quozl/master
restore support for DS1820. Many thanks to Quozi
2 parents e218270 + 9c61459 commit 794045d

File tree

3 files changed

+40
-31
lines changed

3 files changed

+40
-31
lines changed

DallasTemperature.cpp

+38-30
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void DallasTemperature::writeScratchPad(const uint8_t* deviceAddress, const uint
175175
_wire->write(WRITESCRATCH);
176176
_wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
177177
_wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
178-
// DS18S20 does not use the configuration register
178+
// DS1820 and DS18S20 have no configuration register
179179
if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration
180180
_wire->reset();
181181
_wire->select(deviceAddress); //<--this line was missing
@@ -218,7 +218,7 @@ bool DallasTemperature::setResolution(const uint8_t* deviceAddress, uint8_t newR
218218
ScratchPad scratchPad;
219219
if (isConnected(deviceAddress, scratchPad))
220220
{
221-
// DS18S20 has a fixed 9-bit resolution
221+
// DS1820 and DS18S20 have no resolution configuration register
222222
if (deviceAddress[0] != DS18S20MODEL)
223223
{
224224
switch (newResolution)
@@ -254,8 +254,7 @@ uint8_t DallasTemperature::getResolution()
254254
// returns 0 if device not found
255255
uint8_t DallasTemperature::getResolution(const uint8_t* deviceAddress)
256256
{
257-
// this model has a fixed resolution of 9 bits but getTemp calculates
258-
// a full 12 bits resolution and we need 750ms convert time
257+
// DS1820 and DS18S20 have no resolution configuration register
259258
if (deviceAddress[0] == DS18S20MODEL) return 12;
260259

261260
ScratchPad scratchPad;
@@ -409,39 +408,50 @@ float DallasTemperature::getTempFByIndex(uint8_t deviceIndex)
409408
return getTempF((uint8_t*)deviceAddress);
410409
}
411410

412-
// reads scratchpad and returns the raw temperature (12bit)
411+
// reads scratchpad and returns fixed-point temperature, scaling factor 2^-7
413412
int16_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, uint8_t* scratchPad)
414413
{
415-
int16_t rawTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 8) | scratchPad[TEMP_LSB];
414+
int16_t fpTemperature =
415+
(((int16_t) scratchPad[TEMP_MSB]) << 11) |
416+
(((int16_t) scratchPad[TEMP_LSB]) << 3);
416417

417-
/* DS18S20
418-
Resolutions greater than 9 bits can be calculated using the data from
419-
the temperature, COUNT REMAIN and COUNT PER °C registers in the
420-
scratchpad. Note that the COUNT PER °C register is hard-wired to 16
421-
(10h). After reading the scratchpad, the TEMP_READ value is obtained
422-
by truncating the 0.5°C bit (bit 0) from the temperature data. The
418+
/*
419+
DS1820 and DS18S20 have a 9-bit temperature register.
420+
421+
Resolutions greater than 9-bit can be calculated using the data from
422+
the temperature, and COUNT REMAIN and COUNT PER °C registers in the
423+
scratchpad. The resolution of the calculation depends on the model.
424+
425+
While the COUNT PER °C register is hard-wired to 16 (10h) in a
426+
DS18S20, it changes with temperature in DS1820.
427+
428+
After reading the scratchpad, the TEMP_READ value is obtained by
429+
truncating the 0.5°C bit (bit 0) from the temperature data. The
423430
extended resolution temperature can then be calculated using the
424431
following equation:
425432
426433
COUNT_PER_C - COUNT_REMAIN
427434
TEMPERATURE = TEMP_READ - 0.25 + --------------------------
428435
COUNT_PER_C
429436
430-
Simplified to integer arithmetic for a 12 bits value:
431-
432-
TEMPERATURE = ((raw & 0xFFFE) << 3) - 4 + 16 - COUNT_REMAIN
437+
Hagai Shatz simplified this to integer arithmetic for a 12 bits
438+
value for a DS18S20, and James Cameron added legacy DS1820 support.
433439
434440
See - http://myarduinotoy.blogspot.co.uk/2013/02/12bit-result-from-ds18s20.html
435441
*/
436442

437443
if (deviceAddress[0] == DS18S20MODEL)
438-
rawTemperature = ((rawTemperature & 0xFFFE) << 3) + 12 - scratchPad[COUNT_REMAIN];
444+
fpTemperature = ((fpTemperature & 0xfff0) << 3) - 16 +
445+
(
446+
((scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) << 7) /
447+
scratchPad[COUNT_PER_C]
448+
);
439449

440-
return rawTemperature;
450+
return fpTemperature;
441451
}
442452

443453

444-
// returns raw temperature in 1/16 degrees C or DEVICE_DISCONNECTED_RAW if the
454+
// returns temperature in 1/128 degrees C or DEVICE_DISCONNECTED_RAW if the
445455
// device's scratch pad cannot be read successfully.
446456
// the numeric value of DEVICE_DISCONNECTED_RAW is defined in
447457
// DallasTemperature.h. It is a large negative number outside the
@@ -639,22 +649,20 @@ bool DallasTemperature::alarmSearch(uint8_t* newAddr)
639649
return true;
640650
}
641651

642-
// returns true if device address has an alarm condition
643-
// TODO: can this be done with only TEMP_MSB REGISTER (faster)
644-
// if ((char) scratchPad[TEMP_MSB] <= (char) scratchPad[LOW_ALARM_TEMP]) return true;
645-
// if ((char) scratchPad[TEMP_MSB] >= (char) scratchPad[HIGH_ALARM_TEMP]) return true;
652+
// returns true if device address might have an alarm condition
653+
// (only an alarm search can verify this)
646654
bool DallasTemperature::hasAlarm(const uint8_t* deviceAddress)
647655
{
648656
ScratchPad scratchPad;
649657
if (isConnected(deviceAddress, scratchPad))
650658
{
651-
float temp = calculateTemperature(deviceAddress, scratchPad);
659+
char temp = calculateTemperature(deviceAddress, scratchPad) >> 7;
652660

653661
// check low alarm
654-
if ((char)temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true;
662+
if (temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true;
655663

656664
// check high alarm
657-
if ((char)temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true;
665+
if (temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true;
658666
}
659667

660668
// no alarm
@@ -712,18 +720,18 @@ float DallasTemperature::rawToCelsius(int16_t raw)
712720
{
713721
if (raw <= DEVICE_DISCONNECTED_RAW)
714722
return DEVICE_DISCONNECTED_C;
715-
// C = RAW/16
716-
return (float)raw * 0.0625;
723+
// C = RAW/128
724+
return (float)raw * 0.0078125;
717725
}
718726

719727
// convert from raw to Fahrenheit
720728
float DallasTemperature::rawToFahrenheit(int16_t raw)
721729
{
722730
if (raw <= DEVICE_DISCONNECTED_RAW)
723731
return DEVICE_DISCONNECTED_F;
724-
// C = RAW/16
725-
// F = (C*1.8)+32 = (RAW/16*1.8)+32 = (RAW*0.1125)+32
726-
return ((float)raw * 0.1125) + 32;
732+
// C = RAW/128
733+
// F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32
734+
return ((float)raw * 0.0140625) + 32;
727735
}
728736

729737
#if REQUIRESNEW

DallasTemperature.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <OneWire.h>
2323

2424
// Model IDs
25-
#define DS18S20MODEL 0x10
25+
#define DS18S20MODEL 0x10 // also DS1820
2626
#define DS18B20MODEL 0x28
2727
#define DS1822MODEL 0x22
2828
#define DS1825MODEL 0x3B

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This library supports the following devices :
1010
* DS18B20
1111
* DS18S20 - Please note there appears to be an issue with this series.
1212
* DS1822
13+
* DS1820
1314

1415

1516
You will need a pull-up resistor of about 5 KOhm between the 1-Wire data line

0 commit comments

Comments
 (0)