Mercurial > code > home > repos > homeauto
comparison service/arduinoNode/arduino-libraries/DallasTemperature/DallasTemperature.cpp @ 970:4f5825a9fc47
some external arduino libs, minus examples and docs
Ignore-this: 444126f11a1755109b3b29cbeaa6b9bd
darcs-hash:20150411084314-312f9-165a2a8d6ee806950c8a7ae2145364d286fd50b4
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sat, 11 Apr 2015 01:43:14 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
969:70a5392b24d3 | 970:4f5825a9fc47 |
---|---|
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 | |
6 // Version 3.7.2 modified on Dec 6, 2011 to support Arduino 1.0 | |
7 // See Includes... | |
8 // Modified by Jordan Hochenbaum | |
9 | |
10 #include "DallasTemperature.h" | |
11 | |
12 #if ARDUINO >= 100 | |
13 #include "Arduino.h" | |
14 #else | |
15 extern "C" { | |
16 #include "WConstants.h" | |
17 } | |
18 #endif | |
19 | |
20 DallasTemperature::DallasTemperature(OneWire* _oneWire) | |
21 #if REQUIRESALARMS | |
22 : _AlarmHandler(&defaultAlarmHandler) | |
23 #endif | |
24 { | |
25 _wire = _oneWire; | |
26 devices = 0; | |
27 parasite = false; | |
28 bitResolution = 9; | |
29 waitForConversion = true; | |
30 checkForConversion = true; | |
31 } | |
32 | |
33 // initialise the bus | |
34 void DallasTemperature::begin(void) | |
35 { | |
36 DeviceAddress deviceAddress; | |
37 | |
38 _wire->reset_search(); | |
39 devices = 0; // Reset the number of devices when we enumerate wire devices | |
40 | |
41 while (_wire->search(deviceAddress)) | |
42 { | |
43 if (validAddress(deviceAddress)) | |
44 { | |
45 if (!parasite && readPowerSupply(deviceAddress)) parasite = true; | |
46 | |
47 ScratchPad scratchPad; | |
48 | |
49 readScratchPad(deviceAddress, scratchPad); | |
50 | |
51 bitResolution = max(bitResolution, getResolution(deviceAddress)); | |
52 | |
53 devices++; | |
54 } | |
55 } | |
56 } | |
57 | |
58 // returns the number of devices found on the bus | |
59 uint8_t DallasTemperature::getDeviceCount(void) | |
60 { | |
61 return devices; | |
62 } | |
63 | |
64 // returns true if address is valid | |
65 bool DallasTemperature::validAddress(const uint8_t* deviceAddress) | |
66 { | |
67 return (_wire->crc8(deviceAddress, 7) == deviceAddress[7]); | |
68 } | |
69 | |
70 // finds an address at a given index on the bus | |
71 // returns true if the device was found | |
72 bool DallasTemperature::getAddress(uint8_t* deviceAddress, uint8_t index) | |
73 { | |
74 uint8_t depth = 0; | |
75 | |
76 _wire->reset_search(); | |
77 | |
78 while (depth <= index && _wire->search(deviceAddress)) | |
79 { | |
80 if (depth == index && validAddress(deviceAddress)) return true; | |
81 depth++; | |
82 } | |
83 | |
84 return false; | |
85 } | |
86 | |
87 // attempt to determine if the device at the given address is connected to the bus | |
88 bool DallasTemperature::isConnected(const uint8_t* deviceAddress) | |
89 { | |
90 ScratchPad scratchPad; | |
91 return isConnected(deviceAddress, scratchPad); | |
92 } | |
93 | |
94 // attempt to determine if the device at the given address is connected to the bus | |
95 // also allows for updating the read scratchpad | |
96 bool DallasTemperature::isConnected(const uint8_t* deviceAddress, uint8_t* scratchPad) | |
97 { | |
98 readScratchPad(deviceAddress, scratchPad); | |
99 return (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]); | |
100 } | |
101 | |
102 // read device's scratch pad | |
103 void DallasTemperature::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad) | |
104 { | |
105 // send the command | |
106 _wire->reset(); | |
107 _wire->select(deviceAddress); | |
108 _wire->write(READSCRATCH); | |
109 | |
110 // TODO => collect all comments & use simple loop | |
111 // byte 0: temperature LSB | |
112 // byte 1: temperature MSB | |
113 // byte 2: high alarm temp | |
114 // byte 3: low alarm temp | |
115 // byte 4: DS18S20: store for crc | |
116 // DS18B20 & DS1822: configuration register | |
117 // byte 5: internal use & crc | |
118 // byte 6: DS18S20: COUNT_REMAIN | |
119 // DS18B20 & DS1822: store for crc | |
120 // byte 7: DS18S20: COUNT_PER_C | |
121 // DS18B20 & DS1822: store for crc | |
122 // byte 8: SCRATCHPAD_CRC | |
123 // | |
124 // for(int i=0; i<9; i++) | |
125 // { | |
126 // scratchPad[i] = _wire->read(); | |
127 // } | |
128 | |
129 | |
130 // read the response | |
131 | |
132 // byte 0: temperature LSB | |
133 scratchPad[TEMP_LSB] = _wire->read(); | |
134 | |
135 // byte 1: temperature MSB | |
136 scratchPad[TEMP_MSB] = _wire->read(); | |
137 | |
138 // byte 2: high alarm temp | |
139 scratchPad[HIGH_ALARM_TEMP] = _wire->read(); | |
140 | |
141 // byte 3: low alarm temp | |
142 scratchPad[LOW_ALARM_TEMP] = _wire->read(); | |
143 | |
144 // byte 4: | |
145 // DS18S20: store for crc | |
146 // DS18B20 & DS1822: configuration register | |
147 scratchPad[CONFIGURATION] = _wire->read(); | |
148 | |
149 // byte 5: | |
150 // internal use & crc | |
151 scratchPad[INTERNAL_BYTE] = _wire->read(); | |
152 | |
153 // byte 6: | |
154 // DS18S20: COUNT_REMAIN | |
155 // DS18B20 & DS1822: store for crc | |
156 scratchPad[COUNT_REMAIN] = _wire->read(); | |
157 | |
158 // byte 7: | |
159 // DS18S20: COUNT_PER_C | |
160 // DS18B20 & DS1822: store for crc | |
161 scratchPad[COUNT_PER_C] = _wire->read(); | |
162 | |
163 // byte 8: | |
164 // SCTRACHPAD_CRC | |
165 scratchPad[SCRATCHPAD_CRC] = _wire->read(); | |
166 | |
167 _wire->reset(); | |
168 } | |
169 | |
170 // writes device's scratch pad | |
171 void DallasTemperature::writeScratchPad(const uint8_t* deviceAddress, const uint8_t* scratchPad) | |
172 { | |
173 _wire->reset(); | |
174 _wire->select(deviceAddress); | |
175 _wire->write(WRITESCRATCH); | |
176 _wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp | |
177 _wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp | |
178 // DS1820 and DS18S20 have no configuration register | |
179 if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration | |
180 _wire->reset(); | |
181 _wire->select(deviceAddress); //<--this line was missing | |
182 // save the newly written values to eeprom | |
183 _wire->write(COPYSCRATCH, parasite); | |
184 delay(20); // <--- added 20ms delay to allow 10ms long EEPROM write operation (as specified by datasheet) | |
185 if (parasite) delay(10); // 10ms delay | |
186 _wire->reset(); | |
187 } | |
188 | |
189 // reads the device's power requirements | |
190 bool DallasTemperature::readPowerSupply(const uint8_t* deviceAddress) | |
191 { | |
192 bool ret = false; | |
193 _wire->reset(); | |
194 _wire->select(deviceAddress); | |
195 _wire->write(READPOWERSUPPLY); | |
196 if (_wire->read_bit() == 0) ret = true; | |
197 _wire->reset(); | |
198 return ret; | |
199 } | |
200 | |
201 | |
202 // set resolution of all devices to 9, 10, 11, or 12 bits | |
203 // if new resolution is out of range, it is constrained. | |
204 void DallasTemperature::setResolution(uint8_t newResolution) | |
205 { | |
206 bitResolution = constrain(newResolution, 9, 12); | |
207 DeviceAddress deviceAddress; | |
208 for (int i=0; i<devices; i++) | |
209 { | |
210 getAddress(deviceAddress, i); | |
211 setResolution(deviceAddress, bitResolution); | |
212 } | |
213 } | |
214 | |
215 // set resolution of a device to 9, 10, 11, or 12 bits | |
216 // if new resolution is out of range, 9 bits is used. | |
217 bool DallasTemperature::setResolution(const uint8_t* deviceAddress, uint8_t newResolution) | |
218 { | |
219 ScratchPad scratchPad; | |
220 if (isConnected(deviceAddress, scratchPad)) | |
221 { | |
222 // DS1820 and DS18S20 have no resolution configuration register | |
223 if (deviceAddress[0] != DS18S20MODEL) | |
224 { | |
225 switch (newResolution) | |
226 { | |
227 case 12: | |
228 scratchPad[CONFIGURATION] = TEMP_12_BIT; | |
229 break; | |
230 case 11: | |
231 scratchPad[CONFIGURATION] = TEMP_11_BIT; | |
232 break; | |
233 case 10: | |
234 scratchPad[CONFIGURATION] = TEMP_10_BIT; | |
235 break; | |
236 case 9: | |
237 default: | |
238 scratchPad[CONFIGURATION] = TEMP_9_BIT; | |
239 break; | |
240 } | |
241 writeScratchPad(deviceAddress, scratchPad); | |
242 } | |
243 return true; // new value set | |
244 } | |
245 return false; | |
246 } | |
247 | |
248 // returns the global resolution | |
249 uint8_t DallasTemperature::getResolution() | |
250 { | |
251 return bitResolution; | |
252 } | |
253 | |
254 // returns the current resolution of the device, 9-12 | |
255 // returns 0 if device not found | |
256 uint8_t DallasTemperature::getResolution(const uint8_t* deviceAddress) | |
257 { | |
258 // DS1820 and DS18S20 have no resolution configuration register | |
259 if (deviceAddress[0] == DS18S20MODEL) return 12; | |
260 | |
261 ScratchPad scratchPad; | |
262 if (isConnected(deviceAddress, scratchPad)) | |
263 { | |
264 switch (scratchPad[CONFIGURATION]) | |
265 { | |
266 case TEMP_12_BIT: | |
267 return 12; | |
268 | |
269 case TEMP_11_BIT: | |
270 return 11; | |
271 | |
272 case TEMP_10_BIT: | |
273 return 10; | |
274 | |
275 case TEMP_9_BIT: | |
276 return 9; | |
277 } | |
278 } | |
279 return 0; | |
280 } | |
281 | |
282 | |
283 // sets the value of the waitForConversion flag | |
284 // TRUE : function requestTemperature() etc returns when conversion is ready | |
285 // FALSE: function requestTemperature() etc returns immediately (USE WITH CARE!!) | |
286 // (1) programmer has to check if the needed delay has passed | |
287 // (2) but the application can do meaningful things in that time | |
288 void DallasTemperature::setWaitForConversion(bool flag) | |
289 { | |
290 waitForConversion = flag; | |
291 } | |
292 | |
293 // gets the value of the waitForConversion flag | |
294 bool DallasTemperature::getWaitForConversion() | |
295 { | |
296 return waitForConversion; | |
297 } | |
298 | |
299 | |
300 // sets the value of the checkForConversion flag | |
301 // TRUE : function requestTemperature() etc will 'listen' to an IC to determine whether a conversion is complete | |
302 // FALSE: function requestTemperature() etc will wait a set time (worst case scenario) for a conversion to complete | |
303 void DallasTemperature::setCheckForConversion(bool flag) | |
304 { | |
305 checkForConversion = flag; | |
306 } | |
307 | |
308 // gets the value of the waitForConversion flag | |
309 bool DallasTemperature::getCheckForConversion() | |
310 { | |
311 return checkForConversion; | |
312 } | |
313 | |
314 bool DallasTemperature::isConversionAvailable(const uint8_t* deviceAddress) | |
315 { | |
316 // Check if the clock has been raised indicating the conversion is complete | |
317 ScratchPad scratchPad; | |
318 readScratchPad(deviceAddress, scratchPad); | |
319 return scratchPad[0]; | |
320 } | |
321 | |
322 | |
323 // sends command for all devices on the bus to perform a temperature conversion | |
324 void DallasTemperature::requestTemperatures() | |
325 { | |
326 _wire->reset(); | |
327 _wire->skip(); | |
328 _wire->write(STARTCONVO, parasite); | |
329 | |
330 // ASYNC mode? | |
331 if (!waitForConversion) return; | |
332 blockTillConversionComplete(bitResolution, NULL); | |
333 } | |
334 | |
335 // sends command for one device to perform a temperature by address | |
336 // returns FALSE if device is disconnected | |
337 // returns TRUE otherwise | |
338 bool DallasTemperature::requestTemperaturesByAddress(const uint8_t* deviceAddress) | |
339 { | |
340 _wire->reset(); | |
341 _wire->select(deviceAddress); | |
342 _wire->write(STARTCONVO, parasite); | |
343 | |
344 // check device | |
345 ScratchPad scratchPad; | |
346 if (!isConnected(deviceAddress, scratchPad)) return false; | |
347 | |
348 // ASYNC mode? | |
349 if (!waitForConversion) return true; | |
350 blockTillConversionComplete(getResolution(deviceAddress), deviceAddress); | |
351 | |
352 return true; | |
353 } | |
354 | |
355 // returns number of milliseconds to wait till conversion is complete (based on IC datasheet) | |
356 int16_t DallasTemperature::millisToWaitForConversion(uint8_t bitResolution) | |
357 { | |
358 switch (bitResolution) | |
359 { | |
360 case 9: | |
361 return 94; | |
362 case 10: | |
363 return 188; | |
364 case 11: | |
365 return 375; | |
366 default: | |
367 return 750; | |
368 } | |
369 } | |
370 | |
371 // Continue to check if the IC has responded with a temperature | |
372 void DallasTemperature::blockTillConversionComplete(uint8_t bitResolution, const uint8_t* deviceAddress) | |
373 { | |
374 int delms = millisToWaitForConversion(bitResolution); | |
375 if (deviceAddress != NULL && checkForConversion && !parasite) | |
376 { | |
377 unsigned long timend = millis() + delms; | |
378 while(!isConversionAvailable(deviceAddress) && (millis() < timend)); | |
379 } | |
380 else | |
381 { | |
382 delay(delms); | |
383 } | |
384 } | |
385 | |
386 // sends command for one device to perform a temp conversion by index | |
387 bool DallasTemperature::requestTemperaturesByIndex(uint8_t deviceIndex) | |
388 { | |
389 DeviceAddress deviceAddress; | |
390 getAddress(deviceAddress, deviceIndex); | |
391 return requestTemperaturesByAddress(deviceAddress); | |
392 } | |
393 | |
394 // Fetch temperature for device index | |
395 float DallasTemperature::getTempCByIndex(uint8_t deviceIndex) | |
396 { | |
397 DeviceAddress deviceAddress; | |
398 if (!getAddress(deviceAddress, deviceIndex)) | |
399 return DEVICE_DISCONNECTED_C; | |
400 return getTempC((uint8_t*)deviceAddress); | |
401 } | |
402 | |
403 // Fetch temperature for device index | |
404 float DallasTemperature::getTempFByIndex(uint8_t deviceIndex) | |
405 { | |
406 DeviceAddress deviceAddress; | |
407 if (!getAddress(deviceAddress, deviceIndex)) | |
408 return DEVICE_DISCONNECTED_F; | |
409 return getTempF((uint8_t*)deviceAddress); | |
410 } | |
411 | |
412 // reads scratchpad and returns fixed-point temperature, scaling factor 2^-7 | |
413 int16_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, uint8_t* scratchPad) | |
414 { | |
415 int16_t fpTemperature = | |
416 (((int16_t) scratchPad[TEMP_MSB]) << 11) | | |
417 (((int16_t) scratchPad[TEMP_LSB]) << 3); | |
418 | |
419 /* | |
420 DS1820 and DS18S20 have a 9-bit temperature register. | |
421 | |
422 Resolutions greater than 9-bit can be calculated using the data from | |
423 the temperature, and COUNT REMAIN and COUNT PER °C registers in the | |
424 scratchpad. The resolution of the calculation depends on the model. | |
425 | |
426 While the COUNT PER °C register is hard-wired to 16 (10h) in a | |
427 DS18S20, it changes with temperature in DS1820. | |
428 | |
429 After reading the scratchpad, the TEMP_READ value is obtained by | |
430 truncating the 0.5°C bit (bit 0) from the temperature data. The | |
431 extended resolution temperature can then be calculated using the | |
432 following equation: | |
433 | |
434 COUNT_PER_C - COUNT_REMAIN | |
435 TEMPERATURE = TEMP_READ - 0.25 + -------------------------- | |
436 COUNT_PER_C | |
437 | |
438 Hagai Shatz simplified this to integer arithmetic for a 12 bits | |
439 value for a DS18S20, and James Cameron added legacy DS1820 support. | |
440 | |
441 See - http://myarduinotoy.blogspot.co.uk/2013/02/12bit-result-from-ds18s20.html | |
442 */ | |
443 | |
444 if (deviceAddress[0] == DS18S20MODEL) | |
445 fpTemperature = ((fpTemperature & 0xfff0) << 3) - 16 + | |
446 ( | |
447 ((scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) << 7) / | |
448 scratchPad[COUNT_PER_C] | |
449 ); | |
450 | |
451 return fpTemperature; | |
452 } | |
453 | |
454 | |
455 // returns temperature in 1/128 degrees C or DEVICE_DISCONNECTED_RAW if the | |
456 // device's scratch pad cannot be read successfully. | |
457 // the numeric value of DEVICE_DISCONNECTED_RAW is defined in | |
458 // DallasTemperature.h. It is a large negative number outside the | |
459 // operating range of the device | |
460 int16_t DallasTemperature::getTemp(const uint8_t* deviceAddress) | |
461 { | |
462 ScratchPad scratchPad; | |
463 if (isConnected(deviceAddress, scratchPad)) return calculateTemperature(deviceAddress, scratchPad); | |
464 return DEVICE_DISCONNECTED_RAW; | |
465 } | |
466 | |
467 // returns temperature in degrees C or DEVICE_DISCONNECTED_C if the | |
468 // device's scratch pad cannot be read successfully. | |
469 // the numeric value of DEVICE_DISCONNECTED_C is defined in | |
470 // DallasTemperature.h. It is a large negative number outside the | |
471 // operating range of the device | |
472 float DallasTemperature::getTempC(const uint8_t* deviceAddress) | |
473 { | |
474 return rawToCelsius(getTemp(deviceAddress)); | |
475 } | |
476 | |
477 // returns temperature in degrees F or DEVICE_DISCONNECTED_F if the | |
478 // device's scratch pad cannot be read successfully. | |
479 // the numeric value of DEVICE_DISCONNECTED_F is defined in | |
480 // DallasTemperature.h. It is a large negative number outside the | |
481 // operating range of the device | |
482 float DallasTemperature::getTempF(const uint8_t* deviceAddress) | |
483 { | |
484 return rawToFahrenheit(getTemp(deviceAddress)); | |
485 } | |
486 | |
487 // returns true if the bus requires parasite power | |
488 bool DallasTemperature::isParasitePowerMode(void) | |
489 { | |
490 return parasite; | |
491 } | |
492 | |
493 #if REQUIRESALARMS | |
494 | |
495 /* | |
496 | |
497 ALARMS: | |
498 | |
499 TH and TL Register Format | |
500 | |
501 BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 | |
502 S 2^6 2^5 2^4 2^3 2^2 2^1 2^0 | |
503 | |
504 Only bits 11 through 4 of the temperature register are used | |
505 in the TH and TL comparison since TH and TL are 8-bit | |
506 registers. If the measured temperature is lower than or equal | |
507 to TL or higher than or equal to TH, an alarm condition exists | |
508 and an alarm flag is set inside the DS18B20. This flag is | |
509 updated after every temperature measurement; therefore, if the | |
510 alarm condition goes away, the flag will be turned off after | |
511 the next temperature conversion. | |
512 | |
513 */ | |
514 | |
515 // sets the high alarm temperature for a device in degrees Celsius | |
516 // accepts a float, but the alarm resolution will ignore anything | |
517 // after a decimal point. valid range is -55C - 125C | |
518 void DallasTemperature::setHighAlarmTemp(const uint8_t* deviceAddress, char celsius) | |
519 { | |
520 // make sure the alarm temperature is within the device's range | |
521 if (celsius > 125) celsius = 125; | |
522 else if (celsius < -55) celsius = -55; | |
523 | |
524 ScratchPad scratchPad; | |
525 if (isConnected(deviceAddress, scratchPad)) | |
526 { | |
527 scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius; | |
528 writeScratchPad(deviceAddress, scratchPad); | |
529 } | |
530 } | |
531 | |
532 // sets the low alarm temperature for a device in degrees Celsius | |
533 // accepts a float, but the alarm resolution will ignore anything | |
534 // after a decimal point. valid range is -55C - 125C | |
535 void DallasTemperature::setLowAlarmTemp(const uint8_t* deviceAddress, char celsius) | |
536 { | |
537 // make sure the alarm temperature is within the device's range | |
538 if (celsius > 125) celsius = 125; | |
539 else if (celsius < -55) celsius = -55; | |
540 | |
541 ScratchPad scratchPad; | |
542 if (isConnected(deviceAddress, scratchPad)) | |
543 { | |
544 scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius; | |
545 writeScratchPad(deviceAddress, scratchPad); | |
546 } | |
547 } | |
548 | |
549 // returns a char with the current high alarm temperature or | |
550 // DEVICE_DISCONNECTED for an address | |
551 char DallasTemperature::getHighAlarmTemp(const uint8_t* deviceAddress) | |
552 { | |
553 ScratchPad scratchPad; | |
554 if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[HIGH_ALARM_TEMP]; | |
555 return DEVICE_DISCONNECTED_C; | |
556 } | |
557 | |
558 // returns a char with the current low alarm temperature or | |
559 // DEVICE_DISCONNECTED for an address | |
560 char DallasTemperature::getLowAlarmTemp(const uint8_t* deviceAddress) | |
561 { | |
562 ScratchPad scratchPad; | |
563 if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[LOW_ALARM_TEMP]; | |
564 return DEVICE_DISCONNECTED_C; | |
565 } | |
566 | |
567 // resets internal variables used for the alarm search | |
568 void DallasTemperature::resetAlarmSearch() | |
569 { | |
570 alarmSearchJunction = -1; | |
571 alarmSearchExhausted = 0; | |
572 for(uint8_t i = 0; i < 7; i++) | |
573 alarmSearchAddress[i] = 0; | |
574 } | |
575 | |
576 // This is a modified version of the OneWire::search method. | |
577 // | |
578 // Also added the OneWire search fix documented here: | |
579 // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 | |
580 // | |
581 // Perform an alarm search. If this function returns a '1' then it has | |
582 // enumerated the next device and you may retrieve the ROM from the | |
583 // OneWire::address variable. If there are no devices, no further | |
584 // devices, or something horrible happens in the middle of the | |
585 // enumeration then a 0 is returned. If a new device is found then | |
586 // its address is copied to newAddr. Use | |
587 // DallasTemperature::resetAlarmSearch() to start over. | |
588 bool DallasTemperature::alarmSearch(uint8_t* newAddr) | |
589 { | |
590 uint8_t i; | |
591 char lastJunction = -1; | |
592 uint8_t done = 1; | |
593 | |
594 if (alarmSearchExhausted) return false; | |
595 if (!_wire->reset()) return false; | |
596 | |
597 // send the alarm search command | |
598 _wire->write(0xEC, 0); | |
599 | |
600 for(i = 0; i < 64; i++) | |
601 { | |
602 uint8_t a = _wire->read_bit( ); | |
603 uint8_t nota = _wire->read_bit( ); | |
604 uint8_t ibyte = i / 8; | |
605 uint8_t ibit = 1 << (i & 7); | |
606 | |
607 // I don't think this should happen, this means nothing responded, but maybe if | |
608 // something vanishes during the search it will come up. | |
609 if (a && nota) return false; | |
610 | |
611 if (!a && !nota) | |
612 { | |
613 if (i == alarmSearchJunction) | |
614 { | |
615 // this is our time to decide differently, we went zero last time, go one. | |
616 a = 1; | |
617 alarmSearchJunction = lastJunction; | |
618 } | |
619 else if (i < alarmSearchJunction) | |
620 { | |
621 // take whatever we took last time, look in address | |
622 if (alarmSearchAddress[ibyte] & ibit) a = 1; | |
623 else | |
624 { | |
625 // Only 0s count as pending junctions, we've already exhausted the 0 side of 1s | |
626 a = 0; | |
627 done = 0; | |
628 lastJunction = i; | |
629 } | |
630 } | |
631 else | |
632 { | |
633 // we are blazing new tree, take the 0 | |
634 a = 0; | |
635 alarmSearchJunction = i; | |
636 done = 0; | |
637 } | |
638 // OneWire search fix | |
639 // See: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 | |
640 } | |
641 | |
642 if (a) alarmSearchAddress[ibyte] |= ibit; | |
643 else alarmSearchAddress[ibyte] &= ~ibit; | |
644 | |
645 _wire->write_bit(a); | |
646 } | |
647 | |
648 if (done) alarmSearchExhausted = 1; | |
649 for (i = 0; i < 8; i++) newAddr[i] = alarmSearchAddress[i]; | |
650 return true; | |
651 } | |
652 | |
653 // returns true if device address might have an alarm condition | |
654 // (only an alarm search can verify this) | |
655 bool DallasTemperature::hasAlarm(const uint8_t* deviceAddress) | |
656 { | |
657 ScratchPad scratchPad; | |
658 if (isConnected(deviceAddress, scratchPad)) | |
659 { | |
660 char temp = calculateTemperature(deviceAddress, scratchPad) >> 7; | |
661 | |
662 // check low alarm | |
663 if (temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true; | |
664 | |
665 // check high alarm | |
666 if (temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true; | |
667 } | |
668 | |
669 // no alarm | |
670 return false; | |
671 } | |
672 | |
673 // returns true if any device is reporting an alarm condition on the bus | |
674 bool DallasTemperature::hasAlarm(void) | |
675 { | |
676 DeviceAddress deviceAddress; | |
677 resetAlarmSearch(); | |
678 return alarmSearch(deviceAddress); | |
679 } | |
680 | |
681 // runs the alarm handler for all devices returned by alarmSearch() | |
682 void DallasTemperature::processAlarms(void) | |
683 { | |
684 resetAlarmSearch(); | |
685 DeviceAddress alarmAddr; | |
686 | |
687 while (alarmSearch(alarmAddr)) | |
688 { | |
689 if (validAddress(alarmAddr)) | |
690 _AlarmHandler(alarmAddr); | |
691 } | |
692 } | |
693 | |
694 // sets the alarm handler | |
695 void DallasTemperature::setAlarmHandler(AlarmHandler *handler) | |
696 { | |
697 _AlarmHandler = handler; | |
698 } | |
699 | |
700 // The default alarm handler | |
701 void DallasTemperature::defaultAlarmHandler(const uint8_t* deviceAddress) | |
702 { | |
703 } | |
704 | |
705 #endif | |
706 | |
707 // Convert float Celsius to Fahrenheit | |
708 float DallasTemperature::toFahrenheit(float celsius) | |
709 { | |
710 return (celsius * 1.8) + 32; | |
711 } | |
712 | |
713 // Convert float Fahrenheit to Celsius | |
714 float DallasTemperature::toCelsius(float fahrenheit) | |
715 { | |
716 return (fahrenheit - 32) * 0.555555556; | |
717 } | |
718 | |
719 // convert from raw to Celsius | |
720 float DallasTemperature::rawToCelsius(int16_t raw) | |
721 { | |
722 if (raw <= DEVICE_DISCONNECTED_RAW) | |
723 return DEVICE_DISCONNECTED_C; | |
724 // C = RAW/128 | |
725 return (float)raw * 0.0078125; | |
726 } | |
727 | |
728 // convert from raw to Fahrenheit | |
729 float DallasTemperature::rawToFahrenheit(int16_t raw) | |
730 { | |
731 if (raw <= DEVICE_DISCONNECTED_RAW) | |
732 return DEVICE_DISCONNECTED_F; | |
733 // C = RAW/128 | |
734 // F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32 | |
735 return ((float)raw * 0.0140625) + 32; | |
736 } | |
737 | |
738 #if REQUIRESNEW | |
739 | |
740 // MnetCS - Allocates memory for DallasTemperature. Allows us to instance a new object | |
741 void* DallasTemperature::operator new(unsigned int size) // Implicit NSS obj size | |
742 { | |
743 void * p; // void pointer | |
744 p = malloc(size); // Allocate memory | |
745 memset((DallasTemperature*)p,0,size); // Initialise memory | |
746 | |
747 //!!! CANT EXPLICITLY CALL CONSTRUCTOR - workaround by using an init() methodR - workaround by using an init() method | |
748 return (DallasTemperature*) p; // Cast blank region to NSS pointer | |
749 } | |
750 | |
751 // MnetCS 2009 - Free the memory used by this instance | |
752 void DallasTemperature::operator delete(void* p) | |
753 { | |
754 DallasTemperature* pNss = (DallasTemperature*) p; // Cast to NSS pointer | |
755 pNss->~DallasTemperature(); // Destruct the object | |
756 | |
757 free(p); // Free the memory | |
758 } | |
759 | |
760 #endif |