├── .gitignore ├── src ├── spark-dallas-temperature │ └── spark-dallas-temperature.h ├── spark-dallas-temperature.h └── spark-dallas-temperature.cpp ├── library.properties ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | firmware/test/a.out 2 | -------------------------------------------------------------------------------- /src/spark-dallas-temperature/spark-dallas-temperature.h: -------------------------------------------------------------------------------- 1 | #include "../spark-dallas-temperature.h" -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=spark-dallas-temperature 2 | version=0.0.6 3 | license=MIT 4 | author=Tom de Boer 5 | sentence=A Spark Core ported, but otherwise untouched libary for controlling Dallas Temperature Sensors (DS18B20, DS18S20, DS1822,DS1820) 6 | url=https://github.com/tomdeboer/SparkCoreDallasTemperature 7 | repository=https://github.com/tomdeboer/SparkCoreDallasTemperature.git 8 | architectures=particle-photon,particle-electron,particle-argon,particle-boron,particle-xenon 9 | dependencies.OneWire=2.0.1 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spark Core compatible Dallas Temperature sensor library 2 | === 3 | 4 | This library is a port of the original Arduino compatible Dallas Sensor library. Some includes have been fixed, but the libary is otherwise untouched. 5 | 6 | _**Note:** This library depends on the OneWire library._ 7 | 8 | Original repository by Miles Burton: [Arduino-Temperature-Control-Library](https://github.com/milesburton/Arduino-Temperature-Control-Library). 9 | 10 | ## Getting Started 11 | > This library supports the following devices : 12 | > 13 | > 14 | > * DS18B20 15 | > * DS18S20 - Please note there appears to be an issue with this series. 16 | > * DS1822 17 | > * DS1820 18 | > 19 | > 20 | > You will need a pull-up resistor of about 5 KOhm between the 1-Wire data line 21 | > and your 5V power. If you are using the DS18B20, ground pins 1 and 3. The 22 | > centre pin is the data line '1-wire'. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Joe Goggins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/spark-dallas-temperature.h: -------------------------------------------------------------------------------- 1 | #ifndef DallasTemperature_h 2 | #define DallasTemperature_h 3 | 4 | #define DALLASTEMPLIBVERSION "3.7.2" 5 | 6 | // This library is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU Lesser General Public 8 | // License as published by the Free Software Foundation; either 9 | // version 2.1 of the License, or (at your option) any later version. 10 | 11 | // set to true to include code for new and delete operators 12 | #ifndef REQUIRESNEW 13 | #define REQUIRESNEW false 14 | #endif 15 | 16 | // set to true to include code implementing alarm search functions 17 | #ifndef REQUIRESALARMS 18 | #define REQUIRESALARMS true 19 | #endif 20 | 21 | #include 22 | #include 23 | 24 | // Model IDs 25 | #define DS18S20MODEL 0x10 // also DS1820 26 | #define DS18B20MODEL 0x28 27 | #define DS1822MODEL 0x22 28 | #define DS1825MODEL 0x3B 29 | 30 | // OneWire commands 31 | #define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad 32 | #define COPYSCRATCH 0x48 // Copy EEPROM 33 | #define READSCRATCH 0xBE // Read EEPROM 34 | #define WRITESCRATCH 0x4E // Write to EEPROM 35 | #define RECALLSCRATCH 0xB8 // Reload from last known 36 | #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power 37 | #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition 38 | 39 | // Scratchpad locations 40 | #define TEMP_LSB 0 41 | #define TEMP_MSB 1 42 | #define HIGH_ALARM_TEMP 2 43 | #define LOW_ALARM_TEMP 3 44 | #define CONFIGURATION 4 45 | #define INTERNAL_BYTE 5 46 | #define COUNT_REMAIN 6 47 | #define COUNT_PER_C 7 48 | #define SCRATCHPAD_CRC 8 49 | 50 | // Device resolution 51 | #define TEMP_9_BIT 0x1F // 9 bit 52 | #define TEMP_10_BIT 0x3F // 10 bit 53 | #define TEMP_11_BIT 0x5F // 11 bit 54 | #define TEMP_12_BIT 0x7F // 12 bit 55 | 56 | // Error Codes 57 | #define DEVICE_DISCONNECTED_C -127 58 | #define DEVICE_DISCONNECTED_F -196.6 59 | #define DEVICE_DISCONNECTED_RAW -2032 60 | 61 | typedef uint8_t DeviceAddress[8]; 62 | 63 | class DallasTemperature 64 | { 65 | public: 66 | DallasTemperature(OneWire *); 67 | 68 | // initialise bus 69 | void begin(void); 70 | 71 | // returns the number of devices found on the bus 72 | uint8_t getDeviceCount(void); 73 | 74 | // returns true if address is valid 75 | bool validAddress(const uint8_t *); 76 | 77 | // finds an address at a given index on the bus 78 | bool getAddress(uint8_t *, uint8_t); 79 | 80 | // attempt to determine if the device at the given address is connected to the bus 81 | bool isConnected(const uint8_t *); 82 | 83 | // attempt to determine if the device at the given address is connected to the bus 84 | // also allows for updating the read scratchpad 85 | bool isConnected(const uint8_t *, uint8_t *); 86 | 87 | // read device's scratchpad 88 | void readScratchPad(const uint8_t *, uint8_t *); 89 | 90 | // write device's scratchpad 91 | void writeScratchPad(const uint8_t *, const uint8_t *); 92 | 93 | // read device's power requirements 94 | bool readPowerSupply(const uint8_t *); 95 | 96 | // get global resolution 97 | uint8_t getResolution(); 98 | 99 | // set global resolution to 9, 10, 11, or 12 bits 100 | void setResolution(uint8_t); 101 | 102 | // returns the device resolution: 9, 10, 11, or 12 bits 103 | uint8_t getResolution(const uint8_t *); 104 | 105 | // set resolution of a device to 9, 10, 11, or 12 bits 106 | bool setResolution(const uint8_t *, uint8_t); 107 | 108 | // sets/gets the waitForConversion flag 109 | void setWaitForConversion(bool); 110 | bool getWaitForConversion(void); 111 | 112 | // sets/gets the checkForConversion flag 113 | void setCheckForConversion(bool); 114 | bool getCheckForConversion(void); 115 | 116 | // sends command for all devices on the bus to perform a temperature conversion 117 | void requestTemperatures(void); 118 | 119 | // sends command for one device to perform a temperature conversion by address 120 | bool requestTemperaturesByAddress(const uint8_t *); 121 | 122 | // sends command for one device to perform a temperature conversion by index 123 | bool requestTemperaturesByIndex(uint8_t); 124 | 125 | // returns temperature raw value (12 bit integer of 1/16 degrees C) 126 | int16_t getTemp(const uint8_t *); 127 | 128 | // returns temperature in degrees C 129 | float getTempC(const uint8_t *); 130 | 131 | // returns temperature in degrees F 132 | float getTempF(const uint8_t *); 133 | 134 | // Get temperature for device index (slow) 135 | float getTempCByIndex(uint8_t); 136 | 137 | // Get temperature for device index (slow) 138 | float getTempFByIndex(uint8_t); 139 | 140 | // returns true if the bus requires parasite power 141 | bool isParasitePowerMode(void); 142 | 143 | bool isConversionAvailable(const uint8_t *); 144 | 145 | #if REQUIRESALARMS 146 | 147 | typedef void AlarmHandler(const uint8_t *); 148 | 149 | // sets the high alarm temperature for a device 150 | // accepts a char. valid range is -55C - 125C 151 | void setHighAlarmTemp(const uint8_t *, char); 152 | 153 | // sets the low alarm temperature for a device 154 | // accepts a char. valid range is -55C - 125C 155 | void setLowAlarmTemp(const uint8_t *, char); 156 | 157 | // returns a signed char with the current high alarm temperature for a device 158 | // in the range -55C - 125C 159 | char getHighAlarmTemp(const uint8_t *); 160 | 161 | // returns a signed char with the current low alarm temperature for a device 162 | // in the range -55C - 125C 163 | char getLowAlarmTemp(const uint8_t *); 164 | 165 | // resets internal variables used for the alarm search 166 | void resetAlarmSearch(void); 167 | 168 | // search the wire for devices with active alarms 169 | bool alarmSearch(uint8_t *); 170 | 171 | // returns true if ia specific device has an alarm 172 | bool hasAlarm(const uint8_t *); 173 | 174 | // returns true if any device is reporting an alarm on the bus 175 | bool hasAlarm(void); 176 | 177 | // runs the alarm handler for all devices returned by alarmSearch() 178 | void processAlarms(void); 179 | 180 | // sets the alarm handler 181 | void setAlarmHandler(const AlarmHandler *); 182 | 183 | // The default alarm handler 184 | static void defaultAlarmHandler(const uint8_t *); 185 | 186 | #endif 187 | 188 | // convert from Celsius to Fahrenheit 189 | static float toFahrenheit(float); 190 | 191 | // convert from Fahrenheit to Celsius 192 | static float toCelsius(float); 193 | 194 | // convert from raw to Celsius 195 | static float rawToCelsius(int16_t); 196 | 197 | // convert from raw to Fahrenheit 198 | static float rawToFahrenheit(int16_t); 199 | 200 | #if REQUIRESNEW 201 | 202 | // initialize memory area 203 | void *operator new(unsigned int); 204 | 205 | // delete memory reference 206 | void operator delete(void *); 207 | 208 | #endif 209 | 210 | private: 211 | typedef uint8_t ScratchPad[9]; 212 | 213 | // parasite power on or off 214 | bool parasite; 215 | 216 | // used to determine the delay amount needed to allow for the 217 | // temperature conversion to take place 218 | uint8_t bitResolution; 219 | 220 | // used to requestTemperature with or without delay 221 | bool waitForConversion; 222 | 223 | // used to requestTemperature to dynamically check if a conversion is complete 224 | bool checkForConversion; 225 | 226 | // count of devices on the bus 227 | uint8_t devices; 228 | 229 | // Take a pointer to one wire instance 230 | OneWire *_wire; 231 | 232 | // reads scratchpad and returns the raw temperature 233 | int16_t calculateTemperature(const uint8_t *, uint8_t *); 234 | 235 | int16_t millisToWaitForConversion(uint8_t); 236 | 237 | void blockTillConversionComplete(uint8_t, const uint8_t *); 238 | 239 | #if REQUIRESALARMS 240 | 241 | // required for alarmSearch 242 | uint8_t alarmSearchAddress[8]; 243 | char alarmSearchJunction; 244 | uint8_t alarmSearchExhausted; 245 | 246 | // the alarm handler function pointer 247 | AlarmHandler *_AlarmHandler; 248 | 249 | #endif 250 | }; 251 | #endif 252 | -------------------------------------------------------------------------------- /src/spark-dallas-temperature.cpp: -------------------------------------------------------------------------------- 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 | // Modified by Tom de Boer @ 26-jun-2014 (Spark Core compatibility) 11 | 12 | #include "spark-dallas-temperature.h" 13 | 14 | DallasTemperature::DallasTemperature(OneWire* _oneWire) 15 | #if REQUIRESALARMS 16 | : _AlarmHandler(&defaultAlarmHandler) 17 | #endif 18 | { 19 | _wire = _oneWire; 20 | devices = 0; 21 | parasite = false; 22 | bitResolution = 9; 23 | waitForConversion = true; 24 | checkForConversion = true; 25 | } 26 | 27 | // initialise the bus 28 | void DallasTemperature::begin(void) 29 | { 30 | DeviceAddress deviceAddress; 31 | 32 | _wire->reset_search(); 33 | devices = 0; // Reset the number of devices when we enumerate wire devices 34 | 35 | while (_wire->search(deviceAddress)) 36 | { 37 | if (validAddress(deviceAddress)) 38 | { 39 | if (!parasite && readPowerSupply(deviceAddress)) parasite = true; 40 | 41 | ScratchPad scratchPad; 42 | 43 | readScratchPad(deviceAddress, scratchPad); 44 | 45 | bitResolution = max(bitResolution, getResolution(deviceAddress)); 46 | 47 | devices++; 48 | } 49 | } 50 | } 51 | 52 | // returns the number of devices found on the bus 53 | uint8_t DallasTemperature::getDeviceCount(void) 54 | { 55 | return devices; 56 | } 57 | 58 | // returns true if address is valid 59 | bool DallasTemperature::validAddress(const uint8_t* deviceAddress) 60 | { 61 | return (_wire->crc8((uint8_t*)deviceAddress, 7) == deviceAddress[7]); 62 | } 63 | 64 | // finds an address at a given index on the bus 65 | // returns true if the device was found 66 | bool DallasTemperature::getAddress(uint8_t* deviceAddress, uint8_t index) 67 | { 68 | uint8_t depth = 0; 69 | 70 | _wire->reset_search(); 71 | 72 | while (depth <= index && _wire->search(deviceAddress)) 73 | { 74 | if (depth == index && validAddress(deviceAddress)) return true; 75 | depth++; 76 | } 77 | 78 | return false; 79 | } 80 | 81 | // attempt to determine if the device at the given address is connected to the bus 82 | bool DallasTemperature::isConnected(const uint8_t* deviceAddress) 83 | { 84 | ScratchPad scratchPad; 85 | return isConnected(deviceAddress, scratchPad); 86 | } 87 | 88 | // attempt to determine if the device at the given address is connected to the bus 89 | // also allows for updating the read scratchpad 90 | bool DallasTemperature::isConnected(const uint8_t* deviceAddress, uint8_t* scratchPad) 91 | { 92 | readScratchPad(deviceAddress, scratchPad); 93 | return (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]); 94 | } 95 | 96 | // read device's scratch pad 97 | void DallasTemperature::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad) 98 | { 99 | // send the command 100 | _wire->reset(); 101 | _wire->select(deviceAddress); 102 | _wire->write(READSCRATCH); 103 | 104 | // TODO => collect all comments & use simple loop 105 | // byte 0: temperature LSB 106 | // byte 1: temperature MSB 107 | // byte 2: high alarm temp 108 | // byte 3: low alarm temp 109 | // byte 4: DS18S20: store for crc 110 | // DS18B20 & DS1822: configuration register 111 | // byte 5: internal use & crc 112 | // byte 6: DS18S20: COUNT_REMAIN 113 | // DS18B20 & DS1822: store for crc 114 | // byte 7: DS18S20: COUNT_PER_C 115 | // DS18B20 & DS1822: store for crc 116 | // byte 8: SCRATCHPAD_CRC 117 | // 118 | // for(int i=0; i<9; i++) 119 | // { 120 | // scratchPad[i] = _wire->read(); 121 | // } 122 | 123 | 124 | // read the response 125 | 126 | // byte 0: temperature LSB 127 | scratchPad[TEMP_LSB] = _wire->read(); 128 | 129 | // byte 1: temperature MSB 130 | scratchPad[TEMP_MSB] = _wire->read(); 131 | 132 | // byte 2: high alarm temp 133 | scratchPad[HIGH_ALARM_TEMP] = _wire->read(); 134 | 135 | // byte 3: low alarm temp 136 | scratchPad[LOW_ALARM_TEMP] = _wire->read(); 137 | 138 | // byte 4: 139 | // DS18S20: store for crc 140 | // DS18B20 & DS1822: configuration register 141 | scratchPad[CONFIGURATION] = _wire->read(); 142 | 143 | // byte 5: 144 | // internal use & crc 145 | scratchPad[INTERNAL_BYTE] = _wire->read(); 146 | 147 | // byte 6: 148 | // DS18S20: COUNT_REMAIN 149 | // DS18B20 & DS1822: store for crc 150 | scratchPad[COUNT_REMAIN] = _wire->read(); 151 | 152 | // byte 7: 153 | // DS18S20: COUNT_PER_C 154 | // DS18B20 & DS1822: store for crc 155 | scratchPad[COUNT_PER_C] = _wire->read(); 156 | 157 | // byte 8: 158 | // SCTRACHPAD_CRC 159 | scratchPad[SCRATCHPAD_CRC] = _wire->read(); 160 | 161 | _wire->reset(); 162 | } 163 | 164 | // writes device's scratch pad 165 | void DallasTemperature::writeScratchPad(const uint8_t* deviceAddress, const uint8_t* scratchPad) 166 | { 167 | _wire->reset(); 168 | _wire->select(deviceAddress); 169 | _wire->write(WRITESCRATCH); 170 | _wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp 171 | _wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp 172 | // DS1820 and DS18S20 have no configuration register 173 | if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration 174 | _wire->reset(); 175 | _wire->select(deviceAddress); //<--this line was missing 176 | // save the newly written values to eeprom 177 | _wire->write(COPYSCRATCH, parasite); 178 | if (parasite) delay(10); // 10ms delay 179 | _wire->reset(); 180 | } 181 | 182 | // reads the device's power requirements 183 | bool DallasTemperature::readPowerSupply(const uint8_t* deviceAddress) 184 | { 185 | bool ret = false; 186 | _wire->reset(); 187 | _wire->select(deviceAddress); 188 | _wire->write(READPOWERSUPPLY); 189 | if (_wire->read_bit() == 0) ret = true; 190 | _wire->reset(); 191 | return ret; 192 | } 193 | 194 | 195 | // set resolution of all devices to 9, 10, 11, or 12 bits 196 | // if new resolution is out of range, it is constrained. 197 | void DallasTemperature::setResolution(uint8_t newResolution) 198 | { 199 | bitResolution = constrain(newResolution, 9, 12); 200 | DeviceAddress deviceAddress; 201 | for (int i=0; ireset(); 320 | _wire->skip(); 321 | _wire->write(STARTCONVO, parasite); 322 | 323 | // ASYNC mode? 324 | if (!waitForConversion) return; 325 | blockTillConversionComplete(bitResolution, NULL); 326 | } 327 | 328 | // sends command for one device to perform a temperature by address 329 | // returns FALSE if device is disconnected 330 | // returns TRUE otherwise 331 | bool DallasTemperature::requestTemperaturesByAddress(const uint8_t* deviceAddress) 332 | { 333 | _wire->reset(); 334 | _wire->select(deviceAddress); 335 | _wire->write(STARTCONVO, parasite); 336 | 337 | // check device 338 | ScratchPad scratchPad; 339 | if (!isConnected(deviceAddress, scratchPad)) return false; 340 | 341 | // ASYNC mode? 342 | if (!waitForConversion) return true; 343 | blockTillConversionComplete(getResolution(deviceAddress), deviceAddress); 344 | 345 | return true; 346 | } 347 | 348 | // returns number of milliseconds to wait till conversion is complete (based on IC datasheet) 349 | int16_t DallasTemperature::millisToWaitForConversion(uint8_t bitResolution) 350 | { 351 | switch (bitResolution) 352 | { 353 | case 9: 354 | return 94; 355 | case 10: 356 | return 188; 357 | case 11: 358 | return 375; 359 | default: 360 | return 750; 361 | } 362 | } 363 | 364 | // Continue to check if the IC has responded with a temperature 365 | void DallasTemperature::blockTillConversionComplete(uint8_t bitResolution, const uint8_t* deviceAddress) 366 | { 367 | int delms = millisToWaitForConversion(bitResolution); 368 | if (deviceAddress != NULL && checkForConversion && !parasite) 369 | { 370 | unsigned long timend = millis() + delms; 371 | while(!isConversionAvailable(deviceAddress) && (millis() < timend)); 372 | } 373 | else 374 | { 375 | delay(delms); 376 | } 377 | } 378 | 379 | // sends command for one device to perform a temp conversion by index 380 | bool DallasTemperature::requestTemperaturesByIndex(uint8_t deviceIndex) 381 | { 382 | DeviceAddress deviceAddress; 383 | getAddress(deviceAddress, deviceIndex); 384 | return requestTemperaturesByAddress(deviceAddress); 385 | } 386 | 387 | // Fetch temperature for device index 388 | float DallasTemperature::getTempCByIndex(uint8_t deviceIndex) 389 | { 390 | DeviceAddress deviceAddress; 391 | if (!getAddress(deviceAddress, deviceIndex)) 392 | return DEVICE_DISCONNECTED_C; 393 | return getTempC((uint8_t*)deviceAddress); 394 | } 395 | 396 | // Fetch temperature for device index 397 | float DallasTemperature::getTempFByIndex(uint8_t deviceIndex) 398 | { 399 | DeviceAddress deviceAddress; 400 | if (!getAddress(deviceAddress, deviceIndex)) 401 | return DEVICE_DISCONNECTED_F; 402 | return getTempF((uint8_t*)deviceAddress); 403 | } 404 | 405 | // reads scratchpad and returns fixed-point temperature, scaling factor 2^-7 406 | int16_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, uint8_t* scratchPad) 407 | { 408 | int16_t fpTemperature = 409 | (((int16_t) scratchPad[TEMP_MSB]) << 11) | 410 | (((int16_t) scratchPad[TEMP_LSB]) << 3); 411 | 412 | /* 413 | DS1820 and DS18S20 have a 9-bit temperature register. 414 | 415 | Resolutions greater than 9-bit can be calculated using the data from 416 | the temperature, and COUNT REMAIN and COUNT PER °C registers in the 417 | scratchpad. The resolution of the calculation depends on the model. 418 | 419 | While the COUNT PER °C register is hard-wired to 16 (10h) in a 420 | DS18S20, it changes with temperature in DS1820. 421 | 422 | After reading the scratchpad, the TEMP_READ value is obtained by 423 | truncating the 0.5°C bit (bit 0) from the temperature data. The 424 | extended resolution temperature can then be calculated using the 425 | following equation: 426 | 427 | COUNT_PER_C - COUNT_REMAIN 428 | TEMPERATURE = TEMP_READ - 0.25 + -------------------------- 429 | COUNT_PER_C 430 | 431 | Hagai Shatz simplified this to integer arithmetic for a 12 bits 432 | value for a DS18S20, and James Cameron added legacy DS1820 support. 433 | 434 | See - http://myarduinotoy.blogspot.co.uk/2013/02/12bit-result-from-ds18s20.html 435 | */ 436 | 437 | if (deviceAddress[0] == DS18S20MODEL) 438 | fpTemperature = ((fpTemperature & 0xfff0) << 3) - 16 + 439 | ( 440 | ((scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) << 7) / 441 | scratchPad[COUNT_PER_C] 442 | ); 443 | 444 | return fpTemperature; 445 | } 446 | 447 | 448 | // returns temperature in 1/128 degrees C or DEVICE_DISCONNECTED_RAW if the 449 | // device's scratch pad cannot be read successfully. 450 | // the numeric value of DEVICE_DISCONNECTED_RAW is defined in 451 | // DallasTemperature.h. It is a large negative number outside the 452 | // operating range of the device 453 | int16_t DallasTemperature::getTemp(const uint8_t* deviceAddress) 454 | { 455 | ScratchPad scratchPad; 456 | if (isConnected(deviceAddress, scratchPad)) return calculateTemperature(deviceAddress, scratchPad); 457 | return DEVICE_DISCONNECTED_RAW; 458 | } 459 | 460 | // returns temperature in degrees C or DEVICE_DISCONNECTED_C if the 461 | // device's scratch pad cannot be read successfully. 462 | // the numeric value of DEVICE_DISCONNECTED_C is defined in 463 | // DallasTemperature.h. It is a large negative number outside the 464 | // operating range of the device 465 | float DallasTemperature::getTempC(const uint8_t* deviceAddress) 466 | { 467 | return rawToCelsius(getTemp(deviceAddress)); 468 | } 469 | 470 | // returns temperature in degrees F or DEVICE_DISCONNECTED_F if the 471 | // device's scratch pad cannot be read successfully. 472 | // the numeric value of DEVICE_DISCONNECTED_F is defined in 473 | // DallasTemperature.h. It is a large negative number outside the 474 | // operating range of the device 475 | float DallasTemperature::getTempF(const uint8_t* deviceAddress) 476 | { 477 | return rawToFahrenheit(getTemp(deviceAddress)); 478 | } 479 | 480 | // returns true if the bus requires parasite power 481 | bool DallasTemperature::isParasitePowerMode(void) 482 | { 483 | return parasite; 484 | } 485 | 486 | #if REQUIRESALARMS 487 | 488 | /* 489 | 490 | ALARMS: 491 | 492 | TH and TL Register Format 493 | 494 | BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 495 | S 2^6 2^5 2^4 2^3 2^2 2^1 2^0 496 | 497 | Only bits 11 through 4 of the temperature register are used 498 | in the TH and TL comparison since TH and TL are 8-bit 499 | registers. If the measured temperature is lower than or equal 500 | to TL or higher than or equal to TH, an alarm condition exists 501 | and an alarm flag is set inside the DS18B20. This flag is 502 | updated after every temperature measurement; therefore, if the 503 | alarm condition goes away, the flag will be turned off after 504 | the next temperature conversion. 505 | 506 | */ 507 | 508 | // sets the high alarm temperature for a device in degrees Celsius 509 | // accepts a float, but the alarm resolution will ignore anything 510 | // after a decimal point. valid range is -55C - 125C 511 | void DallasTemperature::setHighAlarmTemp(const uint8_t* deviceAddress, char celsius) 512 | { 513 | // make sure the alarm temperature is within the device's range 514 | if (celsius > 125) celsius = 125; 515 | else if (celsius < -55) celsius = -55; 516 | 517 | ScratchPad scratchPad; 518 | if (isConnected(deviceAddress, scratchPad)) 519 | { 520 | scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius; 521 | writeScratchPad(deviceAddress, scratchPad); 522 | } 523 | } 524 | 525 | // sets the low alarm temperature for a device in degrees Celsius 526 | // accepts a float, but the alarm resolution will ignore anything 527 | // after a decimal point. valid range is -55C - 125C 528 | void DallasTemperature::setLowAlarmTemp(const uint8_t* deviceAddress, char celsius) 529 | { 530 | // make sure the alarm temperature is within the device's range 531 | if (celsius > 125) celsius = 125; 532 | else if (celsius < -55) celsius = -55; 533 | 534 | ScratchPad scratchPad; 535 | if (isConnected(deviceAddress, scratchPad)) 536 | { 537 | scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius; 538 | writeScratchPad(deviceAddress, scratchPad); 539 | } 540 | } 541 | 542 | // returns a char with the current high alarm temperature or 543 | // DEVICE_DISCONNECTED for an address 544 | char DallasTemperature::getHighAlarmTemp(const uint8_t* deviceAddress) 545 | { 546 | ScratchPad scratchPad; 547 | if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[HIGH_ALARM_TEMP]; 548 | return DEVICE_DISCONNECTED_C; 549 | } 550 | 551 | // returns a char with the current low alarm temperature or 552 | // DEVICE_DISCONNECTED for an address 553 | char DallasTemperature::getLowAlarmTemp(const uint8_t* deviceAddress) 554 | { 555 | ScratchPad scratchPad; 556 | if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[LOW_ALARM_TEMP]; 557 | return DEVICE_DISCONNECTED_C; 558 | } 559 | 560 | // resets internal variables used for the alarm search 561 | void DallasTemperature::resetAlarmSearch() 562 | { 563 | alarmSearchJunction = -1; 564 | alarmSearchExhausted = 0; 565 | for(uint8_t i = 0; i < 7; i++) 566 | alarmSearchAddress[i] = 0; 567 | } 568 | 569 | // This is a modified version of the OneWire::search method. 570 | // 571 | // Also added the OneWire search fix documented here: 572 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 573 | // 574 | // Perform an alarm search. If this function returns a '1' then it has 575 | // enumerated the next device and you may retrieve the ROM from the 576 | // OneWire::address variable. If there are no devices, no further 577 | // devices, or something horrible happens in the middle of the 578 | // enumeration then a 0 is returned. If a new device is found then 579 | // its address is copied to newAddr. Use 580 | // DallasTemperature::resetAlarmSearch() to start over. 581 | bool DallasTemperature::alarmSearch(uint8_t* newAddr) 582 | { 583 | uint8_t i; 584 | char lastJunction = -1; 585 | uint8_t done = 1; 586 | 587 | if (alarmSearchExhausted) return false; 588 | if (!_wire->reset()) return false; 589 | 590 | // send the alarm search command 591 | _wire->write(0xEC, 0); 592 | 593 | for(i = 0; i < 64; i++) 594 | { 595 | uint8_t a = _wire->read_bit( ); 596 | uint8_t nota = _wire->read_bit( ); 597 | uint8_t ibyte = i / 8; 598 | uint8_t ibit = 1 << (i & 7); 599 | 600 | // I don't think this should happen, this means nothing responded, but maybe if 601 | // something vanishes during the search it will come up. 602 | if (a && nota) return false; 603 | 604 | if (!a && !nota) 605 | { 606 | if (i == alarmSearchJunction) 607 | { 608 | // this is our time to decide differently, we went zero last time, go one. 609 | a = 1; 610 | alarmSearchJunction = lastJunction; 611 | } 612 | else if (i < alarmSearchJunction) 613 | { 614 | // take whatever we took last time, look in address 615 | if (alarmSearchAddress[ibyte] & ibit) a = 1; 616 | else 617 | { 618 | // Only 0s count as pending junctions, we've already exhausted the 0 side of 1s 619 | a = 0; 620 | done = 0; 621 | lastJunction = i; 622 | } 623 | } 624 | else 625 | { 626 | // we are blazing new tree, take the 0 627 | a = 0; 628 | alarmSearchJunction = i; 629 | done = 0; 630 | } 631 | // OneWire search fix 632 | // See: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 633 | } 634 | 635 | if (a) alarmSearchAddress[ibyte] |= ibit; 636 | else alarmSearchAddress[ibyte] &= ~ibit; 637 | 638 | _wire->write_bit(a); 639 | } 640 | 641 | if (done) alarmSearchExhausted = 1; 642 | for (i = 0; i < 8; i++) newAddr[i] = alarmSearchAddress[i]; 643 | return true; 644 | } 645 | 646 | // returns true if device address might have an alarm condition 647 | // (only an alarm search can verify this) 648 | bool DallasTemperature::hasAlarm(const uint8_t* deviceAddress) 649 | { 650 | ScratchPad scratchPad; 651 | if (isConnected(deviceAddress, scratchPad)) 652 | { 653 | char temp = calculateTemperature(deviceAddress, scratchPad) >> 7; 654 | 655 | // check low alarm 656 | if (temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true; 657 | 658 | // check high alarm 659 | if (temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true; 660 | } 661 | 662 | // no alarm 663 | return false; 664 | } 665 | 666 | // returns true if any device is reporting an alarm condition on the bus 667 | bool DallasTemperature::hasAlarm(void) 668 | { 669 | DeviceAddress deviceAddress; 670 | resetAlarmSearch(); 671 | return alarmSearch(deviceAddress); 672 | } 673 | 674 | // runs the alarm handler for all devices returned by alarmSearch() 675 | void DallasTemperature::processAlarms(void) 676 | { 677 | resetAlarmSearch(); 678 | DeviceAddress alarmAddr; 679 | 680 | while (alarmSearch(alarmAddr)) 681 | { 682 | if (validAddress(alarmAddr)) 683 | _AlarmHandler(alarmAddr); 684 | } 685 | } 686 | 687 | // sets the alarm handler 688 | void DallasTemperature::setAlarmHandler(AlarmHandler *handler) 689 | { 690 | _AlarmHandler = handler; 691 | } 692 | 693 | // The default alarm handler 694 | void DallasTemperature::defaultAlarmHandler(const uint8_t* deviceAddress) 695 | { 696 | } 697 | 698 | #endif 699 | 700 | // Convert float Celsius to Fahrenheit 701 | float DallasTemperature::toFahrenheit(float celsius) 702 | { 703 | return (celsius * 1.8) + 32; 704 | } 705 | 706 | // Convert float Fahrenheit to Celsius 707 | float DallasTemperature::toCelsius(float fahrenheit) 708 | { 709 | return (fahrenheit - 32) * 0.555555556; 710 | } 711 | 712 | // convert from raw to Celsius 713 | float DallasTemperature::rawToCelsius(int16_t raw) 714 | { 715 | if (raw <= DEVICE_DISCONNECTED_RAW) 716 | return DEVICE_DISCONNECTED_C; 717 | // C = RAW/128 718 | return (float)raw * 0.0078125; 719 | } 720 | 721 | // convert from raw to Fahrenheit 722 | float DallasTemperature::rawToFahrenheit(int16_t raw) 723 | { 724 | if (raw <= DEVICE_DISCONNECTED_RAW) 725 | return DEVICE_DISCONNECTED_F; 726 | // C = RAW/128 727 | // F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32 728 | return ((float)raw * 0.0140625) + 32; 729 | } 730 | 731 | #if REQUIRESNEW 732 | 733 | // MnetCS - Allocates memory for DallasTemperature. Allows us to instance a new object 734 | void* DallasTemperature::operator new(unsigned int size) // Implicit NSS obj size 735 | { 736 | void * p; // void pointer 737 | p = malloc(size); // Allocate memory 738 | memset((DallasTemperature*)p,0,size); // Initialise memory 739 | 740 | //!!! CANT EXPLICITLY CALL CONSTRUCTOR - workaround by using an init() methodR - workaround by using an init() method 741 | return (DallasTemperature*) p; // Cast blank region to NSS pointer 742 | } 743 | 744 | // MnetCS 2009 - Free the memory used by this instance 745 | void DallasTemperature::operator delete(void* p) 746 | { 747 | DallasTemperature* pNss = (DallasTemperature*) p; // Cast to NSS pointer 748 | pNss->~DallasTemperature(); // Destruct the object 749 | 750 | free(p); // Free the memory 751 | } 752 | 753 | #endif 754 | --------------------------------------------------------------------------------