33// License as published by the Free Software Foundation; either
44// version 2.1 of the License, or (at your option) any later version.
55
6- // Version 3.7.2 modified on Dec 6, 2011 to support Arduino 1.0
7- // See Includes...
8- // Modified by Jordan Hochenbaum
9-
106#include " DallasTemperature.h"
117
128
@@ -18,6 +14,32 @@ extern "C" {
1814}
1915#endif
2016
17+ // OneWire commands
18+ #define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad
19+ #define COPYSCRATCH 0x48 // Copy EEPROM
20+ #define READSCRATCH 0xBE // Read EEPROM
21+ #define WRITESCRATCH 0x4E // Write to EEPROM
22+ #define RECALLSCRATCH 0xB8 // Reload from last known
23+ #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
24+ #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
25+
26+ // Scratchpad locations
27+ #define TEMP_LSB 0
28+ #define TEMP_MSB 1
29+ #define HIGH_ALARM_TEMP 2
30+ #define LOW_ALARM_TEMP 3
31+ #define CONFIGURATION 4
32+ #define INTERNAL_BYTE 5
33+ #define COUNT_REMAIN 6
34+ #define COUNT_PER_C 7
35+ #define SCRATCHPAD_CRC 8
36+
37+ // Device resolution
38+ #define TEMP_9_BIT 0x1F // 9 bit
39+ #define TEMP_10_BIT 0x3F // 10 bit
40+ #define TEMP_11_BIT 0x5F // 11 bit
41+ #define TEMP_12_BIT 0x7F // 12 bit
42+
2143DallasTemperature::DallasTemperature () {}
2244DallasTemperature::DallasTemperature (OneWire* _oneWire)
2345
@@ -28,6 +50,19 @@ DallasTemperature::DallasTemperature(OneWire* _oneWire)
2850 setOneWire (_oneWire);
2951}
3052
53+ bool DallasTemperature::validFamily (const uint8_t * deviceAddress){
54+ switch (deviceAddress[0 ]){
55+ case DS18S20MODEL:
56+ case DS18B20MODEL:
57+ case DS1822MODEL:
58+ case DS1825MODEL:
59+ case DS28EA00MODEL:
60+ return true ;
61+ default :
62+ return false ;
63+ }
64+ }
65+
3166void DallasTemperature::setOneWire (OneWire* _oneWire){
3267
3368 _wire = _oneWire;
@@ -53,10 +88,6 @@ void DallasTemperature::begin(void){
5388
5489 if (!parasite && readPowerSupply (deviceAddress)) parasite = true ;
5590
56- ScratchPad scratchPad;
57-
58- readScratchPad (deviceAddress, scratchPad);
59-
6091 bitResolution = max (bitResolution, getResolution (deviceAddress));
6192
6293 devices++;
@@ -151,9 +182,9 @@ void DallasTemperature::writeScratchPad(const uint8_t* deviceAddress, const uint
151182 if (deviceAddress[0 ] != DS18S20MODEL) _wire->write (scratchPad[CONFIGURATION]);
152183
153184 _wire->reset ();
154- _wire->select (deviceAddress);
155185
156186 // save the newly written values to eeprom
187+ _wire->select (deviceAddress);
157188 _wire->write (COPYSCRATCH, parasite);
158189 delay (20 ); // <--- added 20ms delay to allow 10ms long EEPROM write operation (as specified by datasheet)
159190
@@ -184,14 +215,20 @@ void DallasTemperature::setResolution(uint8_t newResolution){
184215 for (int i=0 ; i<devices; i++)
185216 {
186217 getAddress (deviceAddress, i);
187- setResolution (deviceAddress, bitResolution);
218+ setResolution (deviceAddress, bitResolution, true );
188219 }
189220
190221}
191222
192223// set resolution of a device to 9, 10, 11, or 12 bits
193224// if new resolution is out of range, 9 bits is used.
194- bool DallasTemperature::setResolution (const uint8_t * deviceAddress, uint8_t newResolution){
225+ bool DallasTemperature::setResolution (const uint8_t * deviceAddress, uint8_t newResolution, bool skipGlobalBitResolutionCalculation){
226+
227+ // ensure same behavior as setResolution(uint8_t newResolution)
228+ newResolution = constrain (newResolution, 9 , 12 );
229+
230+ // return when stored value == new value
231+ if (getResolution (deviceAddress) == newResolution) return true ;
195232
196233 ScratchPad scratchPad;
197234 if (isConnected (deviceAddress, scratchPad)){
@@ -215,6 +252,19 @@ bool DallasTemperature::setResolution(const uint8_t* deviceAddress, uint8_t newR
215252 break ;
216253 }
217254 writeScratchPad (deviceAddress, scratchPad);
255+
256+ // without calculation we can always set it to max
257+ bitResolution = max (bitResolution, newResolution);
258+
259+ if (!skipGlobalBitResolutionCalculation && (bitResolution > newResolution)){
260+ bitResolution = newResolution;
261+ DeviceAddress deviceAddr;
262+ for (int i=0 ; i<devices; i++)
263+ {
264+ getAddress (deviceAddr, i);
265+ bitResolution = max (bitResolution, getResolution (deviceAddr));
266+ }
267+ }
218268 }
219269 return true ; // new value set
220270 }
@@ -285,13 +335,10 @@ bool DallasTemperature::getCheckForConversion(){
285335 return checkForConversion;
286336}
287337
288- bool DallasTemperature::isConversionAvailable (const uint8_t * deviceAddress){
289-
290- // Check if the clock has been raised indicating the conversion is complete
291- ScratchPad scratchPad;
292- readScratchPad (deviceAddress, scratchPad);
293- return scratchPad[0 ];
294-
338+ bool DallasTemperature::isConversionComplete ()
339+ {
340+ uint8_t b = _wire->read_bit ();
341+ return (b == 1 );
295342}
296343
297344// sends command for all devices on the bus to perform a temperature conversion
@@ -303,7 +350,7 @@ void DallasTemperature::requestTemperatures(){
303350
304351 // ASYNC mode?
305352 if (!waitForConversion) return ;
306- blockTillConversionComplete (bitResolution, NULL );
353+ blockTillConversionComplete (bitResolution);
307354
308355}
309356
@@ -317,35 +364,31 @@ bool DallasTemperature::requestTemperaturesByAddress(const uint8_t* deviceAddres
317364 return false ; // Device disconnected
318365 }
319366
320- if (_wire->reset () == 0 ){
321- return false ;
322- }
323-
367+ _wire->reset ();
324368 _wire->select (deviceAddress);
325369 _wire->write (STARTCONVO, parasite);
326370
327-
328371 // ASYNC mode?
329372 if (!waitForConversion) return true ;
330373
331- blockTillConversionComplete (getResolution (deviceAddress), deviceAddress );
374+ blockTillConversionComplete (bitResolution );
332375
333376 return true ;
334377
335378}
336379
337380
338381// Continue to check if the IC has responded with a temperature
339- void DallasTemperature::blockTillConversionComplete (uint8_t bitResolution, const uint8_t * deviceAddress ){
340-
382+ void DallasTemperature::blockTillConversionComplete (uint8_t bitResolution){
383+
341384 int delms = millisToWaitForConversion (bitResolution);
342- if (deviceAddress != NULL && checkForConversion && !parasite){
385+ if (checkForConversion && !parasite){
343386 unsigned long now = millis ();
344- while (!isConversionAvailable (deviceAddress ) && (millis () - delms < now));
387+ while (!isConversionComplete ( ) && (millis () - delms < now));
345388 } else {
346389 delay (delms);
347390 }
348-
391+
349392}
350393
351394// returns number of milliseconds to wait till conversion is complete (based on IC datasheet)
@@ -488,6 +531,9 @@ bool DallasTemperature::isParasitePowerMode(void){
488531// note if device is not connected it will fail writing the data.
489532void DallasTemperature::setUserData (const uint8_t * deviceAddress, int16_t data)
490533{
534+ // return when stored value == new value
535+ if (getUserData (deviceAddress) == data) return ;
536+
491537 ScratchPad scratchPad;
492538 if (isConnected (deviceAddress, scratchPad))
493539 {
@@ -583,6 +629,9 @@ the next temperature conversion.
583629// after a decimal point. valid range is -55C - 125C
584630void DallasTemperature::setHighAlarmTemp (const uint8_t * deviceAddress, char celsius){
585631
632+ // return when stored value == new value
633+ if (getHighAlarmTemp (deviceAddress) == celsius) return ;
634+
586635 // make sure the alarm temperature is within the device's range
587636 if (celsius > 125 ) celsius = 125 ;
588637 else if (celsius < -55 ) celsius = -55 ;
@@ -599,6 +648,10 @@ void DallasTemperature::setHighAlarmTemp(const uint8_t* deviceAddress, char cels
599648// accepts a float, but the alarm resolution will ignore anything
600649// after a decimal point. valid range is -55C - 125C
601650void DallasTemperature::setLowAlarmTemp (const uint8_t * deviceAddress, char celsius){
651+
652+ // return when stored value == new value
653+ if (getLowAlarmTemp (deviceAddress) == celsius) return ;
654+
602655 // make sure the alarm temperature is within the device's range
603656 if (celsius > 125 ) celsius = 125 ;
604657 else if (celsius < -55 ) celsius = -55 ;
0 commit comments