DallasTemperature.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. // This library is free software; you can redistribute it and/or
  2. // modify it under the terms of the GNU Lesser General Public
  3. // License as published by the Free Software Foundation; either
  4. // version 2.1 of the License, or (at your option) any later version.
  5. // Version 3.7.2 modified on Dec 6, 2011 to support Arduino 1.0
  6. // See Includes...
  7. // Modified by Jordan Hochenbaum
  8. #include "DallasTemperature.h"
  9. #if ARDUINO >= 100
  10. #include "Arduino.h"
  11. #else
  12. extern "C" {
  13. #include "WConstants.h"
  14. }
  15. #endif
  16. DallasTemperature::DallasTemperature(OneWire* _oneWire)
  17. #if REQUIRESALARMS
  18. : _AlarmHandler(&defaultAlarmHandler)
  19. #endif
  20. {
  21. _wire = _oneWire;
  22. devices = 0;
  23. parasite = false;
  24. bitResolution = 9;
  25. waitForConversion = true;
  26. checkForConversion = true;
  27. }
  28. // initialise the bus
  29. void DallasTemperature::begin(void)
  30. {
  31. DeviceAddress deviceAddress;
  32. _wire->reset_search();
  33. devices = 0; // Reset the number of devices when we enumerate wire devices
  34. while (_wire->search(deviceAddress))
  35. {
  36. if (validAddress(deviceAddress))
  37. {
  38. if (!parasite && readPowerSupply(deviceAddress)) parasite = true;
  39. ScratchPad scratchPad;
  40. readScratchPad(deviceAddress, scratchPad);
  41. bitResolution = max(bitResolution, getResolution(deviceAddress));
  42. devices++;
  43. }
  44. }
  45. }
  46. // returns the number of devices found on the bus
  47. uint8_t DallasTemperature::getDeviceCount(void)
  48. {
  49. return devices;
  50. }
  51. // returns true if address is valid
  52. bool DallasTemperature::validAddress(uint8_t* deviceAddress)
  53. {
  54. return (_wire->crc8(deviceAddress, 7) == deviceAddress[7]);
  55. }
  56. // finds an address at a given index on the bus
  57. // returns true if the device was found
  58. bool DallasTemperature::getAddress(uint8_t* deviceAddress, uint8_t index)
  59. {
  60. uint8_t depth = 0;
  61. _wire->reset_search();
  62. while (depth <= index && _wire->search(deviceAddress))
  63. {
  64. if (depth == index && validAddress(deviceAddress)) return true;
  65. depth++;
  66. }
  67. return false;
  68. }
  69. // attempt to determine if the device at the given address is connected to the bus
  70. bool DallasTemperature::isConnected(uint8_t* deviceAddress)
  71. {
  72. ScratchPad scratchPad;
  73. return isConnected(deviceAddress, scratchPad);
  74. }
  75. // attempt to determine if the device at the given address is connected to the bus
  76. // also allows for updating the read scratchpad
  77. bool DallasTemperature::isConnected(uint8_t* deviceAddress, uint8_t* scratchPad)
  78. {
  79. readScratchPad(deviceAddress, scratchPad);
  80. return (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]);
  81. }
  82. // read device's scratch pad
  83. void DallasTemperature::readScratchPad(uint8_t* deviceAddress, uint8_t* scratchPad)
  84. {
  85. // send the command
  86. _wire->reset();
  87. _wire->select(deviceAddress);
  88. _wire->write(READSCRATCH);
  89. // TODO => collect all comments & use simple loop
  90. // byte 0: temperature LSB
  91. // byte 1: temperature MSB
  92. // byte 2: high alarm temp
  93. // byte 3: low alarm temp
  94. // byte 4: DS18S20: store for crc
  95. // DS18B20 & DS1822: configuration register
  96. // byte 5: internal use & crc
  97. // byte 6: DS18S20: COUNT_REMAIN
  98. // DS18B20 & DS1822: store for crc
  99. // byte 7: DS18S20: COUNT_PER_C
  100. // DS18B20 & DS1822: store for crc
  101. // byte 8: SCRATCHPAD_CRC
  102. //
  103. // for(int i=0; i<9; i++)
  104. // {
  105. // scratchPad[i] = _wire->read();
  106. // }
  107. // read the response
  108. // byte 0: temperature LSB
  109. scratchPad[TEMP_LSB] = _wire->read();
  110. // byte 1: temperature MSB
  111. scratchPad[TEMP_MSB] = _wire->read();
  112. // byte 2: high alarm temp
  113. scratchPad[HIGH_ALARM_TEMP] = _wire->read();
  114. // byte 3: low alarm temp
  115. scratchPad[LOW_ALARM_TEMP] = _wire->read();
  116. // byte 4:
  117. // DS18S20: store for crc
  118. // DS18B20 & DS1822: configuration register
  119. scratchPad[CONFIGURATION] = _wire->read();
  120. // byte 5:
  121. // internal use & crc
  122. scratchPad[INTERNAL_BYTE] = _wire->read();
  123. // byte 6:
  124. // DS18S20: COUNT_REMAIN
  125. // DS18B20 & DS1822: store for crc
  126. scratchPad[COUNT_REMAIN] = _wire->read();
  127. // byte 7:
  128. // DS18S20: COUNT_PER_C
  129. // DS18B20 & DS1822: store for crc
  130. scratchPad[COUNT_PER_C] = _wire->read();
  131. // byte 8:
  132. // SCTRACHPAD_CRC
  133. scratchPad[SCRATCHPAD_CRC] = _wire->read();
  134. for (uint8_t i=0; i<8; i++) {
  135. //Serial.print("\n 0x"); Serial.print(scratchPad[i], HEX);
  136. }
  137. _wire->reset();
  138. }
  139. // writes device's scratch pad
  140. void DallasTemperature::writeScratchPad(uint8_t* deviceAddress, const uint8_t* scratchPad)
  141. {
  142. _wire->reset();
  143. _wire->select(deviceAddress);
  144. _wire->write(WRITESCRATCH);
  145. _wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
  146. _wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
  147. // DS18S20 does not use the configuration register
  148. if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration
  149. _wire->reset();
  150. // save the newly written values to eeprom
  151. _wire->write(COPYSCRATCH, parasite);
  152. if (parasite) delay(10); // 10ms delay
  153. _wire->reset();
  154. }
  155. // reads the device's power requirements
  156. bool DallasTemperature::readPowerSupply(uint8_t* deviceAddress)
  157. {
  158. bool ret = false;
  159. _wire->reset();
  160. _wire->select(deviceAddress);
  161. _wire->write(READPOWERSUPPLY);
  162. if (_wire->read_bit() == 0) ret = true;
  163. _wire->reset();
  164. return ret;
  165. }
  166. // set resolution of all devices to 9, 10, 11, or 12 bits
  167. // if new resolution is out of range, it is constrained.
  168. void DallasTemperature::setResolution(uint8_t newResolution)
  169. {
  170. bitResolution = constrain(newResolution, 9, 12);
  171. DeviceAddress deviceAddress;
  172. for (int i=0; i<devices; i++)
  173. {
  174. getAddress(deviceAddress, i);
  175. setResolution(deviceAddress, bitResolution);
  176. }
  177. }
  178. // set resolution of a device to 9, 10, 11, or 12 bits
  179. // if new resolution is out of range, 9 bits is used.
  180. bool DallasTemperature::setResolution(uint8_t* deviceAddress, uint8_t newResolution)
  181. {
  182. ScratchPad scratchPad;
  183. if (isConnected(deviceAddress, scratchPad))
  184. {
  185. // DS18S20 has a fixed 9-bit resolution
  186. if (deviceAddress[0] != DS18S20MODEL)
  187. {
  188. switch (newResolution)
  189. {
  190. case 12:
  191. scratchPad[CONFIGURATION] = TEMP_12_BIT;
  192. break;
  193. case 11:
  194. scratchPad[CONFIGURATION] = TEMP_11_BIT;
  195. break;
  196. case 10:
  197. scratchPad[CONFIGURATION] = TEMP_10_BIT;
  198. break;
  199. case 9:
  200. default:
  201. scratchPad[CONFIGURATION] = TEMP_9_BIT;
  202. break;
  203. }
  204. writeScratchPad(deviceAddress, scratchPad);
  205. }
  206. return true; // new value set
  207. }
  208. return false;
  209. }
  210. // returns the global resolution
  211. uint8_t DallasTemperature::getResolution()
  212. {
  213. return bitResolution;
  214. }
  215. // returns the current resolution of the device, 9-12
  216. // returns 0 if device not found
  217. uint8_t DallasTemperature::getResolution(uint8_t* deviceAddress)
  218. {
  219. if (deviceAddress[0] == DS18S20MODEL) return 9; // this model has a fixed resolution
  220. ScratchPad scratchPad;
  221. if (isConnected(deviceAddress, scratchPad))
  222. {
  223. switch (scratchPad[CONFIGURATION])
  224. {
  225. case TEMP_12_BIT:
  226. return 12;
  227. case TEMP_11_BIT:
  228. return 11;
  229. case TEMP_10_BIT:
  230. return 10;
  231. case TEMP_9_BIT:
  232. return 9;
  233. }
  234. // special exception for MAX31850
  235. if ((scratchPad[CONFIGURATION] & 0xF0) == 0xF0)
  236. return 12;
  237. }
  238. return 0;
  239. }
  240. // sets the value of the waitForConversion flag
  241. // TRUE : function requestTemperature() etc returns when conversion is ready
  242. // FALSE: function requestTemperature() etc returns immediately (USE WITH CARE!!)
  243. // (1) programmer has to check if the needed delay has passed
  244. // (2) but the application can do meaningful things in that time
  245. void DallasTemperature::setWaitForConversion(bool flag)
  246. {
  247. waitForConversion = flag;
  248. }
  249. // gets the value of the waitForConversion flag
  250. bool DallasTemperature::getWaitForConversion()
  251. {
  252. return waitForConversion;
  253. }
  254. // sets the value of the checkForConversion flag
  255. // TRUE : function requestTemperature() etc will 'listen' to an IC to determine whether a conversion is complete
  256. // FALSE: function requestTemperature() etc will wait a set time (worst case scenario) for a conversion to complete
  257. void DallasTemperature::setCheckForConversion(bool flag)
  258. {
  259. checkForConversion = flag;
  260. }
  261. // gets the value of the waitForConversion flag
  262. bool DallasTemperature::getCheckForConversion()
  263. {
  264. return checkForConversion;
  265. }
  266. bool DallasTemperature::isConversionAvailable(uint8_t* deviceAddress)
  267. {
  268. // Check if the clock has been raised indicating the conversion is complete
  269. ScratchPad scratchPad;
  270. readScratchPad(deviceAddress, scratchPad);
  271. return scratchPad[0];
  272. }
  273. // sends command for all devices on the bus to perform a temperature conversion
  274. void DallasTemperature::requestTemperatures()
  275. {
  276. _wire->reset();
  277. _wire->skip();
  278. _wire->write(STARTCONVO, parasite);
  279. // ASYNC mode?
  280. if (!waitForConversion) return;
  281. blockTillConversionComplete(&bitResolution, 0);
  282. return;
  283. }
  284. // sends command for one device to perform a temperature by address
  285. // returns FALSE if device is disconnected
  286. // returns TRUE otherwise
  287. bool DallasTemperature::requestTemperaturesByAddress(uint8_t* deviceAddress)
  288. {
  289. _wire->reset();
  290. _wire->select(deviceAddress);
  291. _wire->write(STARTCONVO, parasite);
  292. // check device
  293. ScratchPad scratchPad;
  294. if (!isConnected(deviceAddress, scratchPad)) return false;
  295. // ASYNC mode?
  296. if (!waitForConversion) return true;
  297. uint8_t bitResolution = getResolution(deviceAddress);
  298. blockTillConversionComplete(&bitResolution, deviceAddress);
  299. return true;
  300. }
  301. void DallasTemperature::blockTillConversionComplete(uint8_t* bitResolution, uint8_t* deviceAddress)
  302. {
  303. if(deviceAddress != 0 && checkForConversion && !parasite)
  304. {
  305. // Continue to check if the IC has responded with a temperature
  306. // NB: Could cause issues with multiple devices (one device may respond faster)
  307. unsigned long start = millis();
  308. while(!isConversionAvailable(0) && ((millis() - start) < 750));
  309. }
  310. // Wait a fix number of cycles till conversion is complete (based on IC datasheet)
  311. switch (*bitResolution)
  312. {
  313. case 9:
  314. delay(94);
  315. break;
  316. case 10:
  317. delay(188);
  318. break;
  319. case 11:
  320. delay(375);
  321. break;
  322. case 12:
  323. default:
  324. delay(750);
  325. break;
  326. }
  327. }
  328. // sends command for one device to perform a temp conversion by index
  329. bool DallasTemperature::requestTemperaturesByIndex(uint8_t deviceIndex)
  330. {
  331. DeviceAddress deviceAddress;
  332. getAddress(deviceAddress, deviceIndex);
  333. return requestTemperaturesByAddress(deviceAddress);
  334. }
  335. // Fetch temperature for device index
  336. float DallasTemperature::getTempCByIndex(uint8_t deviceIndex)
  337. {
  338. DeviceAddress deviceAddress;
  339. getAddress(deviceAddress, deviceIndex);
  340. return getTempC((uint8_t*)deviceAddress);
  341. }
  342. // Fetch temperature for device index
  343. float DallasTemperature::getTempFByIndex(uint8_t deviceIndex)
  344. {
  345. return toFahrenheit(getTempCByIndex(deviceIndex));
  346. }
  347. // reads scratchpad and returns the temperature in degrees C
  348. float DallasTemperature::calculateTemperature(uint8_t* deviceAddress, uint8_t* scratchPad)
  349. {
  350. int16_t rawTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 8) | scratchPad[TEMP_LSB];
  351. switch (deviceAddress[0])
  352. {
  353. case MAX31850MODEL:
  354. if (scratchPad[0] & 0x1) {
  355. return NAN;
  356. } else {
  357. return (float)rawTemperature * 0.0625;
  358. }
  359. break;
  360. case DS18B20MODEL:
  361. case DS1822MODEL:
  362. switch (scratchPad[CONFIGURATION])
  363. {
  364. case TEMP_12_BIT:
  365. return (float)rawTemperature * 0.0625;
  366. break;
  367. case TEMP_11_BIT:
  368. return (float)(rawTemperature >> 1) * 0.125;
  369. break;
  370. case TEMP_10_BIT:
  371. return (float)(rawTemperature >> 2) * 0.25;
  372. break;
  373. case TEMP_9_BIT:
  374. return (float)(rawTemperature >> 3) * 0.5;
  375. break;
  376. }
  377. break;
  378. case DS18S20MODEL:
  379. /*
  380. Resolutions greater than 9 bits can be calculated using the data from
  381. the temperature, COUNT REMAIN and COUNT PER �C registers in the
  382. scratchpad. Note that the COUNT PER �C register is hard-wired to 16
  383. (10h). After reading the scratchpad, the TEMP_READ value is obtained
  384. by truncating the 0.5�C bit (bit 0) from the temperature data. The
  385. extended resolution temperature can then be calculated using the
  386. following equation:
  387. COUNT_PER_C - COUNT_REMAIN
  388. TEMPERATURE = TEMP_READ - 0.25 + --------------------------
  389. COUNT_PER_C
  390. */
  391. // Good spot. Thanks Nic Johns for your contribution
  392. return (float)(rawTemperature >> 1) - 0.25 +((float)(scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) / (float)scratchPad[COUNT_PER_C] );
  393. break;
  394. }
  395. }
  396. // returns temperature in degrees C or DEVICE_DISCONNECTED if the
  397. // device's scratch pad cannot be read successfully.
  398. // the numeric value of DEVICE_DISCONNECTED is defined in
  399. // DallasTemperature.h. It is a large negative number outside the
  400. // operating range of the device
  401. float DallasTemperature::getTempC(uint8_t* deviceAddress)
  402. {
  403. // TODO: Multiple devices (up to 64) on the same bus may take
  404. // some time to negotiate a response
  405. // What happens in case of collision?
  406. ScratchPad scratchPad;
  407. if (isConnected(deviceAddress, scratchPad)) return calculateTemperature(deviceAddress, scratchPad);
  408. return DEVICE_DISCONNECTED;
  409. }
  410. // returns temperature in degrees F
  411. // TODO: - when getTempC returns DEVICE_DISCONNECTED
  412. // -127 gets converted to -196.6 F
  413. float DallasTemperature::getTempF(uint8_t* deviceAddress)
  414. {
  415. return toFahrenheit(getTempC(deviceAddress));
  416. }
  417. // returns true if the bus requires parasite power
  418. bool DallasTemperature::isParasitePowerMode(void)
  419. {
  420. return parasite;
  421. }
  422. #if REQUIRESALARMS
  423. /*
  424. ALARMS:
  425. TH and TL Register Format
  426. BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0
  427. S 2^6 2^5 2^4 2^3 2^2 2^1 2^0
  428. Only bits 11 through 4 of the temperature register are used
  429. in the TH and TL comparison since TH and TL are 8-bit
  430. registers. If the measured temperature is lower than or equal
  431. to TL or higher than or equal to TH, an alarm condition exists
  432. and an alarm flag is set inside the DS18B20. This flag is
  433. updated after every temperature measurement; therefore, if the
  434. alarm condition goes away, the flag will be turned off after
  435. the next temperature conversion.
  436. */
  437. // sets the high alarm temperature for a device in degrees celsius
  438. // accepts a float, but the alarm resolution will ignore anything
  439. // after a decimal point. valid range is -55C - 125C
  440. void DallasTemperature::setHighAlarmTemp(uint8_t* deviceAddress, char celsius)
  441. {
  442. // make sure the alarm temperature is within the device's range
  443. if (celsius > 125) celsius = 125;
  444. else if (celsius < -55) celsius = -55;
  445. ScratchPad scratchPad;
  446. if (isConnected(deviceAddress, scratchPad))
  447. {
  448. scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius;
  449. writeScratchPad(deviceAddress, scratchPad);
  450. }
  451. }
  452. // sets the low alarm temperature for a device in degreed celsius
  453. // accepts a float, but the alarm resolution will ignore anything
  454. // after a decimal point. valid range is -55C - 125C
  455. void DallasTemperature::setLowAlarmTemp(uint8_t* deviceAddress, char celsius)
  456. {
  457. // make sure the alarm temperature is within the device's range
  458. if (celsius > 125) celsius = 125;
  459. else if (celsius < -55) celsius = -55;
  460. ScratchPad scratchPad;
  461. if (isConnected(deviceAddress, scratchPad))
  462. {
  463. scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius;
  464. writeScratchPad(deviceAddress, scratchPad);
  465. }
  466. }
  467. // returns a char with the current high alarm temperature or
  468. // DEVICE_DISCONNECTED for an address
  469. char DallasTemperature::getHighAlarmTemp(uint8_t* deviceAddress)
  470. {
  471. ScratchPad scratchPad;
  472. if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[HIGH_ALARM_TEMP];
  473. return DEVICE_DISCONNECTED;
  474. }
  475. // returns a char with the current low alarm temperature or
  476. // DEVICE_DISCONNECTED for an address
  477. char DallasTemperature::getLowAlarmTemp(uint8_t* deviceAddress)
  478. {
  479. ScratchPad scratchPad;
  480. if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[LOW_ALARM_TEMP];
  481. return DEVICE_DISCONNECTED;
  482. }
  483. // resets internal variables used for the alarm search
  484. void DallasTemperature::resetAlarmSearch()
  485. {
  486. alarmSearchJunction = -1;
  487. alarmSearchExhausted = 0;
  488. for(uint8_t i = 0; i < 7; i++)
  489. alarmSearchAddress[i] = 0;
  490. }
  491. // This is a modified version of the OneWire::search method.
  492. //
  493. // Also added the OneWire search fix documented here:
  494. // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295
  495. //
  496. // Perform an alarm search. If this function returns a '1' then it has
  497. // enumerated the next device and you may retrieve the ROM from the
  498. // OneWire::address variable. If there are no devices, no further
  499. // devices, or something horrible happens in the middle of the
  500. // enumeration then a 0 is returned. If a new device is found then
  501. // its address is copied to newAddr. Use
  502. // DallasTemperature::resetAlarmSearch() to start over.
  503. bool DallasTemperature::alarmSearch(uint8_t* newAddr)
  504. {
  505. uint8_t i;
  506. char lastJunction = -1;
  507. uint8_t done = 1;
  508. if (alarmSearchExhausted) return false;
  509. if (!_wire->reset()) return false;
  510. // send the alarm search command
  511. _wire->write(0xEC, 0);
  512. for(i = 0; i < 64; i++)
  513. {
  514. uint8_t a = _wire->read_bit( );
  515. uint8_t nota = _wire->read_bit( );
  516. uint8_t ibyte = i / 8;
  517. uint8_t ibit = 1 << (i & 7);
  518. // I don't think this should happen, this means nothing responded, but maybe if
  519. // something vanishes during the search it will come up.
  520. if (a && nota) return false;
  521. if (!a && !nota)
  522. {
  523. if (i == alarmSearchJunction)
  524. {
  525. // this is our time to decide differently, we went zero last time, go one.
  526. a = 1;
  527. alarmSearchJunction = lastJunction;
  528. }
  529. else if (i < alarmSearchJunction)
  530. {
  531. // take whatever we took last time, look in address
  532. if (alarmSearchAddress[ibyte] & ibit) a = 1;
  533. else
  534. {
  535. // Only 0s count as pending junctions, we've already exhasuted the 0 side of 1s
  536. a = 0;
  537. done = 0;
  538. lastJunction = i;
  539. }
  540. }
  541. else
  542. {
  543. // we are blazing new tree, take the 0
  544. a = 0;
  545. alarmSearchJunction = i;
  546. done = 0;
  547. }
  548. // OneWire search fix
  549. // See: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295
  550. }
  551. if (a) alarmSearchAddress[ibyte] |= ibit;
  552. else alarmSearchAddress[ibyte] &= ~ibit;
  553. _wire->write_bit(a);
  554. }
  555. if (done) alarmSearchExhausted = 1;
  556. for (i = 0; i < 8; i++) newAddr[i] = alarmSearchAddress[i];
  557. return true;
  558. }
  559. // returns true if device address has an alarm condition
  560. // TODO: can this be done with only TEMP_MSB REGISTER (faster)
  561. // if ((char) scratchPad[TEMP_MSB] <= (char) scratchPad[LOW_ALARM_TEMP]) return true;
  562. // if ((char) scratchPad[TEMP_MSB] >= (char) scratchPad[HIGH_ALARM_TEMP]) return true;
  563. bool DallasTemperature::hasAlarm(uint8_t* deviceAddress)
  564. {
  565. ScratchPad scratchPad;
  566. if (isConnected(deviceAddress, scratchPad))
  567. {
  568. float temp = calculateTemperature(deviceAddress, scratchPad);
  569. // check low alarm
  570. if ((char)temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true;
  571. // check high alarm
  572. if ((char)temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true;
  573. }
  574. // no alarm
  575. return false;
  576. }
  577. // returns true if any device is reporting an alarm condition on the bus
  578. bool DallasTemperature::hasAlarm(void)
  579. {
  580. DeviceAddress deviceAddress;
  581. resetAlarmSearch();
  582. return alarmSearch(deviceAddress);
  583. }
  584. // runs the alarm handler for all devices returned by alarmSearch()
  585. void DallasTemperature::processAlarms(void)
  586. {
  587. resetAlarmSearch();
  588. DeviceAddress alarmAddr;
  589. while (alarmSearch(alarmAddr))
  590. {
  591. if (validAddress(alarmAddr))
  592. _AlarmHandler(alarmAddr);
  593. }
  594. }
  595. // sets the alarm handler
  596. void DallasTemperature::setAlarmHandler(AlarmHandler *handler)
  597. {
  598. _AlarmHandler = handler;
  599. }
  600. // The default alarm handler
  601. void DallasTemperature::defaultAlarmHandler(uint8_t* deviceAddress)
  602. {
  603. }
  604. #endif
  605. // Convert float celsius to fahrenheit
  606. float DallasTemperature::toFahrenheit(float celsius)
  607. {
  608. return (celsius * 1.8) + 32;
  609. }
  610. // Convert float fahrenheit to celsius
  611. float DallasTemperature::toCelsius(float fahrenheit)
  612. {
  613. return (fahrenheit - 32) / 1.8;
  614. }
  615. #if REQUIRESNEW
  616. // MnetCS - Allocates memory for DallasTemperature. Allows us to instance a new object
  617. void* DallasTemperature::operator new(unsigned int size) // Implicit NSS obj size
  618. {
  619. void * p; // void pointer
  620. p = malloc(size); // Allocate memory
  621. memset((DallasTemperature*)p,0,size); // Initalise memory
  622. //!!! CANT EXPLICITLY CALL CONSTRUCTOR - workaround by using an init() methodR - workaround by using an init() method
  623. return (DallasTemperature*) p; // Cast blank region to NSS pointer
  624. }
  625. // MnetCS 2009 - Unallocates the memory used by this instance
  626. void DallasTemperature::operator delete(void* p)
  627. {
  628. DallasTemperature* pNss = (DallasTemperature*) p; // Cast to NSS pointer
  629. pNss->~DallasTemperature(); // Destruct the object
  630. free(p); // Free the memory
  631. }
  632. #endif