├── DS18B20_DS2482.cpp ├── DS18B20_DS2482.h ├── DS2482.cpp ├── DS2482.h ├── README.md └── examples └── DS2482_DEMO └── DS2482_DEMO.ino /DS18B20_DS2482.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.7 modified on Mar 12, 2017 7 | // Modified by Nuno Chaveiro - nchaveiro(at)gmail.com 8 | 9 | #include "DS18B20_DS2482.h" 10 | 11 | 12 | #if ARDUINO >= 100 13 | #include "Arduino.h" 14 | #else 15 | extern "C" { 16 | #include "WConstants.h" 17 | } 18 | #endif 19 | 20 | DS18B20_DS2482::DS18B20_DS2482() {} 21 | DS18B20_DS2482::DS18B20_DS2482(DS2482* _DS2482) 22 | 23 | #if REQUIRESALARMS 24 | : _AlarmHandler(&defaultAlarmHandler) 25 | #endif 26 | { 27 | setOneWire(_DS2482); 28 | } 29 | 30 | bool DS18B20_DS2482::validFamily(const uint8_t* deviceAddress){ 31 | switch (deviceAddress[0]){ 32 | case DS18S20MODEL: 33 | case DS18B20MODEL: 34 | case DS1822MODEL: 35 | case DS1825MODEL: 36 | case DS28EA00MODEL: 37 | return true; 38 | default: 39 | return false; 40 | } 41 | } 42 | 43 | void DS18B20_DS2482::setOneWire(DS2482* _DS2482){ 44 | 45 | _wire = _DS2482; 46 | devices = 0; 47 | parasite = false; 48 | bitResolution = 9; 49 | waitForConversion = true; 50 | checkForConversion = true; 51 | 52 | } 53 | 54 | // initialise the bus 55 | void DS18B20_DS2482::begin(void){ 56 | 57 | DeviceAddress deviceAddress; 58 | 59 | _wire->wireResetSearch(); 60 | devices = 0; // Reset the number of devices when we enumerate wire devices 61 | 62 | while (_wire->wireSearch(deviceAddress)){ 63 | 64 | if (validAddress(deviceAddress)){ 65 | 66 | if (!parasite && readPowerSupply(deviceAddress)) parasite = true; 67 | 68 | // ScratchPad scratchPad; 69 | 70 | // readScratchPad(deviceAddress, scratchPad); 71 | 72 | bitResolution = max(bitResolution, getResolution(deviceAddress)); 73 | 74 | devices++; 75 | } 76 | } 77 | 78 | } 79 | 80 | // returns the number of devices found on the bus 81 | uint8_t DS18B20_DS2482::getDeviceCount(void){ 82 | return devices; 83 | } 84 | 85 | // returns true if address is valid 86 | bool DS18B20_DS2482::validAddress(const uint8_t* deviceAddress){ 87 | return (_wire->crc8(deviceAddress, 7) == deviceAddress[7]); 88 | } 89 | 90 | // finds an address at a given index on the bus 91 | // returns true if the device was found 92 | bool DS18B20_DS2482::getAddress(uint8_t* deviceAddress, uint8_t index){ 93 | 94 | uint8_t depth = 0; 95 | 96 | _wire->wireResetSearch(); 97 | 98 | while (depth <= index && _wire->wireSearch(deviceAddress)) { 99 | if (depth == index && validAddress(deviceAddress)) return true; 100 | depth++; 101 | } 102 | 103 | return false; 104 | 105 | } 106 | 107 | // attempt to determine if the device at the given address is connected to the bus 108 | bool DS18B20_DS2482::isConnected(const uint8_t* deviceAddress){ 109 | 110 | ScratchPad scratchPad; 111 | return isConnected(deviceAddress, scratchPad); 112 | 113 | } 114 | 115 | // attempt to determine if the device at the given address is connected to the bus 116 | // also allows for updating the read scratchpad 117 | bool DS18B20_DS2482::isConnected(const uint8_t* deviceAddress, uint8_t* scratchPad) 118 | { 119 | bool b = readScratchPad(deviceAddress, scratchPad); 120 | return b && (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]); 121 | } 122 | 123 | bool DS18B20_DS2482::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad){ 124 | 125 | // send the reset command and fail fast 126 | int b = _wire->reset(); 127 | if (b == 0) return false; 128 | 129 | _wire->wireSelect(deviceAddress); 130 | _wire->wireWriteByte(READSCRATCH); 131 | 132 | // Read all registers in a simple loop 133 | // byte 0: temperature LSB 134 | // byte 1: temperature MSB 135 | // byte 2: high alarm temp 136 | // byte 3: low alarm temp 137 | // byte 4: DS18S20: store for crc 138 | // DS18B20 & DS1822: configuration register 139 | // byte 5: internal use & crc 140 | // byte 6: DS18S20: COUNT_REMAIN 141 | // DS18B20 & DS1822: store for crc 142 | // byte 7: DS18S20: COUNT_PER_C 143 | // DS18B20 & DS1822: store for crc 144 | // byte 8: SCRATCHPAD_CRC 145 | for(uint8_t i = 0; i < 9; i++){ 146 | scratchPad[i] = _wire->wireReadByte(); 147 | } 148 | 149 | b = _wire->reset(); 150 | return (b == 1); 151 | } 152 | 153 | 154 | void DS18B20_DS2482::writeScratchPad(const uint8_t* deviceAddress, const uint8_t* scratchPad){ 155 | 156 | _wire->reset(); 157 | _wire->wireSelect(deviceAddress); 158 | _wire->wireWriteByte(WRITESCRATCH); 159 | _wire->wireWriteByte(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp 160 | _wire->wireWriteByte(scratchPad[LOW_ALARM_TEMP]); // low alarm temp 161 | 162 | // DS1820 and DS18S20 have no configuration register 163 | if (deviceAddress[0] != DS18S20MODEL) _wire->wireWriteByte(scratchPad[CONFIGURATION]); 164 | 165 | _wire->reset(); 166 | 167 | // save the newly written values to eeprom 168 | _wire->wireSelect(deviceAddress); 169 | //_wire->wireWriteByte(COPYSCRATCH, parasite); 170 | _wire->wireWriteByte(COPYSCRATCH); 171 | delay(20); // <--- added 20ms delay to allow 10ms long EEPROM write operation (as specified by datasheet) 172 | 173 | if (parasite) delay(10); // 10ms delay 174 | _wire->reset(); 175 | 176 | } 177 | 178 | bool DS18B20_DS2482::readPowerSupply(const uint8_t* deviceAddress){ 179 | 180 | bool ret = false; 181 | _wire->reset(); 182 | _wire->wireSelect(deviceAddress); 183 | _wire->wireWriteByte(READPOWERSUPPLY); 184 | if (_wire->wireReadBit() == 0) ret = true; 185 | _wire->reset(); 186 | return ret; 187 | 188 | } 189 | 190 | 191 | // set resolution of all devices to 9, 10, 11, or 12 bits 192 | // if new resolution is out of range, it is constrained. 193 | void DS18B20_DS2482::setResolution(uint8_t newResolution){ 194 | 195 | bitResolution = constrain(newResolution, 9, 12); 196 | DeviceAddress deviceAddress; 197 | for (int i=0; i newResolution)){ 242 | bitResolution = newResolution; 243 | DeviceAddress deviceAddr; 244 | for (int i=0; iwireReadBit(); 323 | return (b == 1); 324 | } 325 | 326 | // sends command for all devices on the bus to perform a temperature conversion 327 | void DS18B20_DS2482::requestTemperatures(){ 328 | 329 | _wire->reset(); 330 | _wire->wireSkip(); 331 | //_wire->wireWriteByte(STARTCONVO, parasite); 332 | _wire->wireWriteByte(STARTCONVO); 333 | 334 | // ASYNC mode? 335 | if (!waitForConversion) return; 336 | blockTillConversionComplete(bitResolution); 337 | 338 | } 339 | 340 | // sends command for one device to perform a temperature by address 341 | // returns FALSE if device is disconnected 342 | // returns TRUE otherwise 343 | bool DS18B20_DS2482::requestTemperaturesByAddress(const uint8_t* deviceAddress){ 344 | 345 | uint8_t bitResolution = getResolution(deviceAddress); 346 | if (bitResolution == 0){ 347 | return false; //Device disconnected 348 | } 349 | 350 | if (_wire->reset() == 0){ 351 | return false; 352 | } 353 | 354 | _wire->wireSelect(deviceAddress); 355 | //_wire->wireWriteByte(STARTCONVO, parasite); 356 | _wire->wireWriteByte(STARTCONVO); 357 | 358 | 359 | // ASYNC mode? 360 | if (!waitForConversion) return true; 361 | 362 | blockTillConversionComplete(bitResolution); 363 | 364 | return true; 365 | 366 | } 367 | 368 | 369 | // Continue to check if the IC has responded with a temperature 370 | void DS18B20_DS2482::blockTillConversionComplete(uint8_t bitResolution){ 371 | 372 | int delms = millisToWaitForConversion(bitResolution); 373 | if (checkForConversion && !parasite){ 374 | unsigned long now = millis(); 375 | while(!isConversionComplete() && (millis() - delms < now)); 376 | } else { 377 | delay(delms); 378 | } 379 | 380 | } 381 | 382 | // returns number of milliseconds to wait till conversion is complete (based on IC datasheet) 383 | int16_t DS18B20_DS2482::millisToWaitForConversion(uint8_t bitResolution){ 384 | 385 | switch (bitResolution){ 386 | case 9: 387 | return 94; 388 | case 10: 389 | return 188; 390 | case 11: 391 | return 375; 392 | default: 393 | return 750; 394 | } 395 | 396 | } 397 | 398 | 399 | // sends command for one device to perform a temp conversion by index 400 | bool DS18B20_DS2482::requestTemperaturesByIndex(uint8_t deviceIndex){ 401 | 402 | DeviceAddress deviceAddress; 403 | getAddress(deviceAddress, deviceIndex); 404 | 405 | return requestTemperaturesByAddress(deviceAddress); 406 | 407 | } 408 | 409 | // Fetch temperature for device index 410 | float DS18B20_DS2482::getTempCByIndex(uint8_t deviceIndex){ 411 | 412 | DeviceAddress deviceAddress; 413 | if (!getAddress(deviceAddress, deviceIndex)){ 414 | return DEVICE_DISCONNECTED_C; 415 | } 416 | 417 | return getTempC((uint8_t*)deviceAddress); 418 | 419 | } 420 | 421 | // Fetch temperature for device index 422 | float DS18B20_DS2482::getTempFByIndex(uint8_t deviceIndex){ 423 | 424 | DeviceAddress deviceAddress; 425 | 426 | if (!getAddress(deviceAddress, deviceIndex)){ 427 | return DEVICE_DISCONNECTED_F; 428 | } 429 | 430 | return getTempF((uint8_t*)deviceAddress); 431 | 432 | } 433 | 434 | // reads scratchpad and returns fixed-point temperature, scaling factor 2^-7 435 | int16_t DS18B20_DS2482::calculateTemperature(const uint8_t* deviceAddress, uint8_t* scratchPad){ 436 | 437 | int16_t fpTemperature = 438 | (((int16_t) scratchPad[TEMP_MSB]) << 11) | 439 | (((int16_t) scratchPad[TEMP_LSB]) << 3); 440 | 441 | /* 442 | DS1820 and DS18S20 have a 9-bit temperature register. 443 | 444 | Resolutions greater than 9-bit can be calculated using the data from 445 | the temperature, and COUNT REMAIN and COUNT PER °C registers in the 446 | scratchpad. The resolution of the calculation depends on the model. 447 | 448 | While the COUNT PER °C register is hard-wired to 16 (10h) in a 449 | DS18S20, it changes with temperature in DS1820. 450 | 451 | After reading the scratchpad, the TEMP_READ value is obtained by 452 | truncating the 0.5°C bit (bit 0) from the temperature data. The 453 | extended resolution temperature can then be calculated using the 454 | following equation: 455 | 456 | COUNT_PER_C - COUNT_REMAIN 457 | TEMPERATURE = TEMP_READ - 0.25 + -------------------------- 458 | COUNT_PER_C 459 | 460 | Hagai Shatz simplified this to integer arithmetic for a 12 bits 461 | value for a DS18S20, and James Cameron added legacy DS1820 support. 462 | 463 | See - http://myarduinotoy.blogspot.co.uk/2013/02/12bit-result-from-ds18s20.html 464 | */ 465 | 466 | if (deviceAddress[0] == DS18S20MODEL){ 467 | fpTemperature = ((fpTemperature & 0xfff0) << 3) - 16 + 468 | ( 469 | ((scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) << 7) / 470 | scratchPad[COUNT_PER_C] 471 | ); 472 | } 473 | 474 | return fpTemperature; 475 | } 476 | 477 | 478 | // returns temperature in 1/128 degrees C or DEVICE_DISCONNECTED_RAW if the 479 | // device's scratch pad cannot be read successfully. 480 | // the numeric value of DEVICE_DISCONNECTED_RAW is defined in 481 | // DS18B20_DS2482.h. It is a large negative number outside the 482 | // operating range of the device 483 | int16_t DS18B20_DS2482::getTemp(const uint8_t* deviceAddress){ 484 | 485 | ScratchPad scratchPad; 486 | if (isConnected(deviceAddress, scratchPad)) return calculateTemperature(deviceAddress, scratchPad); 487 | return DEVICE_DISCONNECTED_RAW; 488 | 489 | } 490 | 491 | // returns temperature in degrees C or DEVICE_DISCONNECTED_C if the 492 | // device's scratch pad cannot be read successfully. 493 | // the numeric value of DEVICE_DISCONNECTED_C is defined in 494 | // DS18B20_DS2482.h. It is a large negative number outside the 495 | // operating range of the device 496 | float DS18B20_DS2482::getTempC(const uint8_t* deviceAddress){ 497 | return rawToCelsius(getTemp(deviceAddress)); 498 | } 499 | 500 | // returns temperature in degrees F or DEVICE_DISCONNECTED_F if the 501 | // device's scratch pad cannot be read successfully. 502 | // the numeric value of DEVICE_DISCONNECTED_F is defined in 503 | // DS18B20_DS2482.h. It is a large negative number outside the 504 | // operating range of the device 505 | float DS18B20_DS2482::getTempF(const uint8_t* deviceAddress){ 506 | return rawToFahrenheit(getTemp(deviceAddress)); 507 | } 508 | 509 | // returns true if the bus requires parasite power 510 | bool DS18B20_DS2482::isParasitePowerMode(void){ 511 | return parasite; 512 | } 513 | 514 | 515 | // IF alarm is not used one can store a 16 bit int of userdata in the alarm 516 | // registers. E.g. an ID of the sensor. 517 | // See github issue #29 518 | 519 | // note if device is not connected it will fail writing the data. 520 | void DS18B20_DS2482::setUserData(const uint8_t* deviceAddress, int16_t data) 521 | { 522 | // return when stored value == new value 523 | if(getUserData(deviceAddress) == data) return; 524 | 525 | ScratchPad scratchPad; 526 | if (isConnected(deviceAddress, scratchPad)) 527 | { 528 | scratchPad[HIGH_ALARM_TEMP] = data >> 8; 529 | scratchPad[LOW_ALARM_TEMP] = data & 255; 530 | writeScratchPad(deviceAddress, scratchPad); 531 | } 532 | } 533 | 534 | int16_t DS18B20_DS2482::getUserData(const uint8_t* deviceAddress) 535 | { 536 | int16_t data = 0; 537 | ScratchPad scratchPad; 538 | if (isConnected(deviceAddress, scratchPad)) 539 | { 540 | data = scratchPad[HIGH_ALARM_TEMP] << 8; 541 | data += scratchPad[LOW_ALARM_TEMP]; 542 | } 543 | return data; 544 | } 545 | 546 | // note If address cannot be found no error will be reported. 547 | int16_t DS18B20_DS2482::getUserDataByIndex(uint8_t deviceIndex) 548 | { 549 | DeviceAddress deviceAddress; 550 | getAddress(deviceAddress, deviceIndex); 551 | return getUserData((uint8_t*) deviceAddress); 552 | } 553 | 554 | void DS18B20_DS2482::setUserDataByIndex(uint8_t deviceIndex, int16_t data) 555 | { 556 | DeviceAddress deviceAddress; 557 | getAddress(deviceAddress, deviceIndex); 558 | setUserData((uint8_t*) deviceAddress, data); 559 | } 560 | 561 | 562 | // Convert float Celsius to Fahrenheit 563 | float DS18B20_DS2482::toFahrenheit(float celsius){ 564 | return (celsius * 1.8) + 32; 565 | } 566 | 567 | // Convert float Fahrenheit to Celsius 568 | float DS18B20_DS2482::toCelsius(float fahrenheit){ 569 | return (fahrenheit - 32) * 0.555555556; 570 | } 571 | 572 | // convert from raw to Celsius 573 | float DS18B20_DS2482::rawToCelsius(int16_t raw){ 574 | 575 | if (raw <= DEVICE_DISCONNECTED_RAW) 576 | return DEVICE_DISCONNECTED_C; 577 | // C = RAW/128 578 | return (float)raw * 0.0078125; 579 | 580 | } 581 | 582 | // convert from raw to Fahrenheit 583 | float DS18B20_DS2482::rawToFahrenheit(int16_t raw){ 584 | 585 | if (raw <= DEVICE_DISCONNECTED_RAW) 586 | return DEVICE_DISCONNECTED_F; 587 | // C = RAW/128 588 | // F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32 589 | return ((float)raw * 0.0140625) + 32; 590 | 591 | } 592 | 593 | #if REQUIRESALARMS 594 | 595 | /* 596 | 597 | ALARMS: 598 | 599 | TH and TL Register Format 600 | 601 | BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0 602 | S 2^6 2^5 2^4 2^3 2^2 2^1 2^0 603 | 604 | Only bits 11 through 4 of the temperature register are used 605 | in the TH and TL comparison since TH and TL are 8-bit 606 | registers. If the measured temperature is lower than or equal 607 | to TL or higher than or equal to TH, an alarm condition exists 608 | and an alarm flag is set inside the DS18B20. This flag is 609 | updated after every temperature measurement; therefore, if the 610 | alarm condition goes away, the flag will be turned off after 611 | the next temperature conversion. 612 | 613 | */ 614 | 615 | // sets the high alarm temperature for a device in degrees Celsius 616 | // accepts a float, but the alarm resolution will ignore anything 617 | // after a decimal point. valid range is -55C - 125C 618 | void DS18B20_DS2482::setHighAlarmTemp(const uint8_t* deviceAddress, char celsius){ 619 | 620 | // return when stored value == new value 621 | if(getHighAlarmTemp(deviceAddress) == celsius) return; 622 | 623 | // make sure the alarm temperature is within the device's range 624 | if (celsius > 125) celsius = 125; 625 | else if (celsius < -55) celsius = -55; 626 | 627 | ScratchPad scratchPad; 628 | if (isConnected(deviceAddress, scratchPad)){ 629 | scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius; 630 | writeScratchPad(deviceAddress, scratchPad); 631 | } 632 | 633 | } 634 | 635 | // sets the low alarm temperature for a device in degrees Celsius 636 | // accepts a float, but the alarm resolution will ignore anything 637 | // after a decimal point. valid range is -55C - 125C 638 | void DS18B20_DS2482::setLowAlarmTemp(const uint8_t* deviceAddress, char celsius){ 639 | 640 | // return when stored value == new value 641 | if(getLowAlarmTemp(deviceAddress) == celsius) return; 642 | 643 | // make sure the alarm temperature is within the device's range 644 | if (celsius > 125) celsius = 125; 645 | else if (celsius < -55) celsius = -55; 646 | 647 | ScratchPad scratchPad; 648 | if (isConnected(deviceAddress, scratchPad)){ 649 | scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius; 650 | writeScratchPad(deviceAddress, scratchPad); 651 | } 652 | 653 | } 654 | 655 | // returns a char with the current high alarm temperature or 656 | // DEVICE_DISCONNECTED for an address 657 | char DS18B20_DS2482::getHighAlarmTemp(const uint8_t* deviceAddress){ 658 | 659 | ScratchPad scratchPad; 660 | if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[HIGH_ALARM_TEMP]; 661 | return DEVICE_DISCONNECTED_C; 662 | 663 | } 664 | 665 | // returns a char with the current low alarm temperature or 666 | // DEVICE_DISCONNECTED for an address 667 | char DS18B20_DS2482::getLowAlarmTemp(const uint8_t* deviceAddress){ 668 | 669 | ScratchPad scratchPad; 670 | if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[LOW_ALARM_TEMP]; 671 | return DEVICE_DISCONNECTED_C; 672 | 673 | } 674 | 675 | // resets internal variables used for the alarm search 676 | void DS18B20_DS2482::resetAlarmSearch(){ 677 | 678 | alarmSearchJunction = -1; 679 | alarmSearchExhausted = 0; 680 | for(uint8_t i = 0; i < 7; i++){ 681 | alarmSearchAddress[i] = 0; 682 | } 683 | 684 | } 685 | 686 | // This is a modified version of the OneWire::search method. 687 | // 688 | // Also added the OneWire search fix documented here: 689 | // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 690 | // 691 | // Perform an alarm search. If this function returns a '1' then it has 692 | // enumerated the next device and you may retrieve the ROM from the 693 | // OneWire::address variable. If there are no devices, no further 694 | // devices, or something horrible happens in the middle of the 695 | // enumeration then a 0 is returned. If a new device is found then 696 | // its address is copied to newAddr. Use 697 | // DS18B20_DS2482::resetAlarmSearch() to start over. 698 | bool DS18B20_DS2482::alarmSearch(uint8_t* newAddr){ 699 | 700 | uint8_t i; 701 | char lastJunction = -1; 702 | uint8_t done = 1; 703 | 704 | if (alarmSearchExhausted) return false; 705 | if (!_wire->reset()) return false; 706 | 707 | // send the alarm search command 708 | //_wire->wireWriteByte(0xEC, 0); 709 | _wire->wireWriteByte(0xEC); 710 | 711 | for(i = 0; i < 64; i++){ 712 | 713 | uint8_t a = _wire->wireReadBit( ); 714 | uint8_t nota = _wire->wireReadBit( ); 715 | uint8_t ibyte = i / 8; 716 | uint8_t ibit = 1 << (i & 7); 717 | 718 | // I don't think this should happen, this means nothing responded, but maybe if 719 | // something vanishes during the search it will come up. 720 | if (a && nota) return false; 721 | 722 | if (!a && !nota){ 723 | if (i == alarmSearchJunction){ 724 | // this is our time to decide differently, we went zero last time, go one. 725 | a = 1; 726 | alarmSearchJunction = lastJunction; 727 | }else if (i < alarmSearchJunction){ 728 | 729 | // take whatever we took last time, look in address 730 | if (alarmSearchAddress[ibyte] & ibit){ 731 | a = 1; 732 | }else{ 733 | // Only 0s count as pending junctions, we've already exhausted the 0 side of 1s 734 | a = 0; 735 | done = 0; 736 | lastJunction = i; 737 | } 738 | }else{ 739 | // we are blazing new tree, take the 0 740 | a = 0; 741 | alarmSearchJunction = i; 742 | done = 0; 743 | } 744 | // OneWire search fix 745 | // See: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295 746 | } 747 | 748 | if (a) alarmSearchAddress[ibyte] |= ibit; 749 | else alarmSearchAddress[ibyte] &= ~ibit; 750 | 751 | _wire->wireWriteBit(a); 752 | } 753 | 754 | if (done) alarmSearchExhausted = 1; 755 | for (i = 0; i < 8; i++) newAddr[i] = alarmSearchAddress[i]; 756 | return true; 757 | 758 | } 759 | 760 | // returns true if device address might have an alarm condition 761 | // (only an alarm search can verify this) 762 | bool DS18B20_DS2482::hasAlarm(uint8_t* deviceAddress){ 763 | 764 | ScratchPad scratchPad; 765 | if (isConnected(deviceAddress, scratchPad)){ 766 | 767 | char temp = calculateTemperature(deviceAddress, scratchPad) >> 7; 768 | 769 | // check low alarm 770 | if (temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true; 771 | 772 | // check high alarm 773 | if (temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true; 774 | } 775 | 776 | // no alarm 777 | return false; 778 | 779 | } 780 | 781 | // returns true if any device is reporting an alarm condition on the bus 782 | bool DS18B20_DS2482::hasAlarm(void){ 783 | 784 | DeviceAddress deviceAddress; 785 | resetAlarmSearch(); 786 | return alarmSearch(deviceAddress); 787 | 788 | } 789 | 790 | // runs the alarm handler for all devices returned by alarmSearch() 791 | void DS18B20_DS2482::processAlarms(void){ 792 | 793 | resetAlarmSearch(); 794 | DeviceAddress alarmAddr; 795 | 796 | while (alarmSearch(alarmAddr)){ 797 | 798 | if (validAddress(alarmAddr)){ 799 | _AlarmHandler(alarmAddr); 800 | } 801 | 802 | } 803 | } 804 | 805 | // sets the alarm handler 806 | void DS18B20_DS2482::setAlarmHandler(AlarmHandler *handler){ 807 | _AlarmHandler = handler; 808 | } 809 | 810 | // The default alarm handler 811 | void DS18B20_DS2482::defaultAlarmHandler(const uint8_t* deviceAddress){} 812 | 813 | #endif 814 | 815 | #if REQUIRESNEW 816 | 817 | // MnetCS - Allocates memory for DS18B20_DS2482. Allows us to instance a new object 818 | void* DS18B20_DS2482::operator new(unsigned int size){ // Implicit NSS obj size 819 | 820 | void * p; // void pointer 821 | p = malloc(size); // Allocate memory 822 | memset((DS18B20_DS2482*)p,0,size); // Initialise memory 823 | 824 | //!!! CANT EXPLICITLY CALL CONSTRUCTOR - workaround by using an init() methodR - workaround by using an init() method 825 | return (DS18B20_DS2482*) p; // Cast blank region to NSS pointer 826 | } 827 | 828 | // MnetCS 2009 - Free the memory used by this instance 829 | void DS18B20_DS2482::operator delete(void* p){ 830 | 831 | DS18B20_DS2482* pNss = (DS18B20_DS2482*) p; // Cast to NSS pointer 832 | pNss->~DS18B20_DS2482(); // Destruct the object 833 | 834 | free(p); // Free the memory 835 | } 836 | 837 | #endif 838 | -------------------------------------------------------------------------------- /DS18B20_DS2482.h: -------------------------------------------------------------------------------- 1 | #ifndef DS18B20_DS2482_h 2 | #define DS18B20_DS2482_h 3 | 4 | #define DALLASTEMPLIBVERSION "3.7.7" // To be deprecated 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 false 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 | #define DS28EA00MODEL 0x42 30 | 31 | // OneWire commands 32 | #define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad 33 | #define COPYSCRATCH 0x48 // Copy EEPROM 34 | #define READSCRATCH 0xBE // Read EEPROM 35 | #define WRITESCRATCH 0x4E // Write to EEPROM 36 | #define RECALLSCRATCH 0xB8 // Reload from last known 37 | #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power 38 | #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition 39 | 40 | // Scratchpad locations 41 | #define TEMP_LSB 0 42 | #define TEMP_MSB 1 43 | #define HIGH_ALARM_TEMP 2 44 | #define LOW_ALARM_TEMP 3 45 | #define CONFIGURATION 4 46 | #define INTERNAL_BYTE 5 47 | #define COUNT_REMAIN 6 48 | #define COUNT_PER_C 7 49 | #define SCRATCHPAD_CRC 8 50 | 51 | // Device resolution 52 | #define TEMP_9_BIT 0x1F // 9 bit 53 | #define TEMP_10_BIT 0x3F // 10 bit 54 | #define TEMP_11_BIT 0x5F // 11 bit 55 | #define TEMP_12_BIT 0x7F // 12 bit 56 | 57 | // Error Codes 58 | #define DEVICE_DISCONNECTED_C -127 59 | #define DEVICE_DISCONNECTED_F -196.6 60 | #define DEVICE_DISCONNECTED_RAW -7040 61 | 62 | typedef uint8_t DeviceAddress[8]; 63 | 64 | class DS18B20_DS2482 65 | { 66 | public: 67 | 68 | DS18B20_DS2482(); 69 | DS18B20_DS2482(DS2482*); 70 | 71 | void setOneWire(DS2482*); 72 | 73 | // initialise bus 74 | void begin(void); 75 | 76 | // returns the number of devices found on the bus 77 | uint8_t getDeviceCount(void); 78 | 79 | // returns true if address is valid 80 | bool validAddress(const uint8_t*); 81 | 82 | // returns true if address is of the family of sensors the lib supports. 83 | bool validFamily(const uint8_t* deviceAddress); 84 | 85 | // finds an address at a given index on the bus 86 | bool getAddress(uint8_t*, uint8_t); 87 | 88 | // attempt to determine if the device at the given address is connected to the bus 89 | bool isConnected(const uint8_t*); 90 | 91 | // attempt to determine if the device at the given address is connected to the bus 92 | // also allows for updating the read scratchpad 93 | bool isConnected(const uint8_t*, uint8_t*); 94 | 95 | // read device's scratchpad 96 | bool readScratchPad(const uint8_t*, uint8_t*); 97 | 98 | // write device's scratchpad 99 | void writeScratchPad(const uint8_t*, const uint8_t*); 100 | 101 | // read device's power requirements 102 | bool readPowerSupply(const uint8_t*); 103 | 104 | // get global resolution 105 | uint8_t getResolution(); 106 | 107 | // set global resolution to 9, 10, 11, or 12 bits 108 | void setResolution(uint8_t); 109 | 110 | // returns the device resolution: 9, 10, 11, or 12 bits 111 | uint8_t getResolution(const uint8_t*); 112 | 113 | // set resolution of a device to 9, 10, 11, or 12 bits 114 | bool setResolution(const uint8_t*, uint8_t, bool skipGlobalBitResolutionCalculation = false); 115 | 116 | // sets/gets the waitForConversion flag 117 | void setWaitForConversion(bool); 118 | bool getWaitForConversion(void); 119 | 120 | // sets/gets the checkForConversion flag 121 | void setCheckForConversion(bool); 122 | bool getCheckForConversion(void); 123 | 124 | // sends command for all devices on the bus to perform a temperature conversion 125 | void requestTemperatures(void); 126 | 127 | // sends command for one device to perform a temperature conversion by address 128 | bool requestTemperaturesByAddress(const uint8_t*); 129 | 130 | // sends command for one device to perform a temperature conversion by index 131 | bool requestTemperaturesByIndex(uint8_t); 132 | 133 | // returns temperature raw value (12 bit integer of 1/128 degrees C) 134 | int16_t getTemp(const uint8_t*); 135 | 136 | // returns temperature in degrees C 137 | float getTempC(const uint8_t*); 138 | 139 | // returns temperature in degrees F 140 | float getTempF(const uint8_t*); 141 | 142 | // Get temperature for device index (slow) 143 | float getTempCByIndex(uint8_t); 144 | 145 | // Get temperature for device index (slow) 146 | float getTempFByIndex(uint8_t); 147 | 148 | // returns true if the bus requires parasite power 149 | bool isParasitePowerMode(void); 150 | 151 | // Is a conversion complete on the wire? 152 | bool isConversionComplete(void); 153 | 154 | int16_t millisToWaitForConversion(uint8_t); 155 | 156 | #if REQUIRESALARMS 157 | 158 | typedef void AlarmHandler(const uint8_t*); 159 | 160 | // sets the high alarm temperature for a device 161 | // accepts a char. valid range is -55C - 125C 162 | void setHighAlarmTemp(const uint8_t*, char); 163 | 164 | // sets the low alarm temperature for a device 165 | // accepts a char. valid range is -55C - 125C 166 | void setLowAlarmTemp(const uint8_t*, char); 167 | 168 | // returns a signed char with the current high alarm temperature for a device 169 | // in the range -55C - 125C 170 | char getHighAlarmTemp(const uint8_t*); 171 | 172 | // returns a signed char with the current low alarm temperature for a device 173 | // in the range -55C - 125C 174 | char getLowAlarmTemp(const uint8_t*); 175 | 176 | // resets internal variables used for the alarm search 177 | void resetAlarmSearch(void); 178 | 179 | // search the wire for devices with active alarms 180 | bool alarmSearch(uint8_t*); 181 | 182 | // returns true if ia specific device has an alarm 183 | bool hasAlarm(const uint8_t*); 184 | 185 | // returns true if any device is reporting an alarm on the bus 186 | bool hasAlarm(void); 187 | 188 | // runs the alarm handler for all devices returned by alarmSearch() 189 | void processAlarms(void); 190 | 191 | // sets the alarm handler 192 | void setAlarmHandler(const AlarmHandler *); 193 | 194 | // The default alarm handler 195 | static void defaultAlarmHandler(const uint8_t*); 196 | 197 | #endif 198 | 199 | // if no alarm handler is used the two bytes can be used as user data 200 | // example of such usage is an ID. 201 | // note if device is not connected it will fail writing the data. 202 | // note if address cannot be found no error will be reported. 203 | // in short use carefully 204 | void setUserData(const uint8_t*, int16_t ); 205 | void setUserDataByIndex(uint8_t, int16_t ); 206 | int16_t getUserData(const uint8_t* ); 207 | int16_t getUserDataByIndex(uint8_t ); 208 | 209 | // convert from Celsius to Fahrenheit 210 | static float toFahrenheit(float); 211 | 212 | // convert from Fahrenheit to Celsius 213 | static float toCelsius(float); 214 | 215 | // convert from raw to Celsius 216 | static float rawToCelsius(int16_t); 217 | 218 | // convert from raw to Fahrenheit 219 | static float rawToFahrenheit(int16_t); 220 | 221 | #if REQUIRESNEW 222 | 223 | // initialize memory area 224 | void* operator new (unsigned int); 225 | 226 | // delete memory reference 227 | void operator delete(void*); 228 | 229 | #endif 230 | 231 | private: 232 | typedef uint8_t ScratchPad[9]; 233 | 234 | // parasite power on or off 235 | bool parasite; 236 | 237 | // used to determine the delay amount needed to allow for the 238 | // temperature conversion to take place 239 | uint8_t bitResolution; 240 | 241 | // used to requestTemperature with or without delay 242 | bool waitForConversion; 243 | 244 | // used to requestTemperature to dynamically check if a conversion is complete 245 | bool checkForConversion; 246 | 247 | // count of devices on the bus 248 | uint8_t devices; 249 | 250 | // Take a pointer to one wire instance 251 | DS2482* _wire; 252 | 253 | // reads scratchpad and returns the raw temperature 254 | int16_t calculateTemperature(const uint8_t*, uint8_t*); 255 | 256 | void blockTillConversionComplete(uint8_t); 257 | 258 | #if REQUIRESALARMS 259 | 260 | // required for alarmSearch 261 | uint8_t alarmSearchAddress[8]; 262 | char alarmSearchJunction; 263 | uint8_t alarmSearchExhausted; 264 | 265 | // the alarm handler function pointer 266 | AlarmHandler *_AlarmHandler; 267 | 268 | #endif 269 | 270 | }; 271 | #endif -------------------------------------------------------------------------------- /DS2482.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DS2482 library for Arduino 3 | Copyright (C) 2009-2010 Paeae Technologies 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have readd a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | 18 | crc code is from OneWire library 19 | 20 | -Updates: 21 | * fixed wireReadByte busyWait (thanks Mike Jackson) 22 | * Modified search function (thanks Gary Fariss) 23 | 24 | */ 25 | #include "Arduino.h" // according http://blog.makezine.com/2011/12/01/arduino-1-0-is-out-heres-what-you-need-to-know/ 26 | 27 | #include "DS2482.h" 28 | #include "Wire.h" 29 | 30 | 31 | #define PTR_STATUS 0xf0 32 | #define PTR_READ 0xe1 33 | #define PTR_CONFIG 0xc3 34 | 35 | enum { 36 | DS18S20 = (byte)0x10 37 | , DS18B20 = (byte)0x28 38 | , DS1822 = (byte)0x22 39 | , DS1825 = (byte)0x3B 40 | } TemperatureSensors; 41 | 42 | enum { 43 | DS2406 = (byte)0x12 44 | } SwitchSensors; 45 | 46 | DS2482::DS2482(uint8_t addr) 47 | { 48 | mAddress = 0x18 | addr; 49 | 50 | } 51 | 52 | //-------helpers 53 | void DS2482::begin() 54 | { 55 | Wire.beginTransmission(mAddress); 56 | } 57 | 58 | void DS2482::end() 59 | { 60 | Wire.endTransmission(); 61 | } 62 | 63 | void DS2482::setReadPtr(uint8_t readPtr) 64 | { 65 | begin(); 66 | Wire.write(0xe1); // changed from 'send' to 'write' according http://blog.makezine.com/2011/12/01/arduino-1-0-is-out-heres-what-you-need-to-know/' 67 | Wire.write(readPtr); 68 | end(); 69 | } 70 | 71 | uint8_t DS2482::readByte() 72 | { 73 | Wire.requestFrom(mAddress,(uint8_t)1); 74 | return Wire.read(); 75 | } 76 | 77 | uint8_t DS2482::wireReadStatus(bool setPtr) 78 | { 79 | if (setPtr) 80 | setReadPtr(PTR_STATUS); 81 | 82 | return readByte(); 83 | } 84 | 85 | uint8_t DS2482::busyWait(bool setReadPtr) 86 | { 87 | uint8_t status; 88 | int loopCount = 1000; 89 | while((status = wireReadStatus(setReadPtr)) & DS2482_STATUS_BUSY) 90 | { 91 | if (--loopCount <= 0) 92 | { 93 | mTimeout = 1; 94 | break; 95 | } 96 | delayMicroseconds(20); 97 | } 98 | return status; 99 | } 100 | 101 | //----------interface 102 | uint8_t DS2482::reset() 103 | { 104 | return wireReset(); 105 | } 106 | 107 | bool DS2482::configure(uint8_t config) 108 | { 109 | busyWait(true); 110 | begin(); 111 | Wire.write(0xd2); 112 | Wire.write(config | (~config)<<4); 113 | 114 | return readByte() == config; 115 | } 116 | 117 | bool DS2482::selectChannel(uint8_t channel) 118 | { 119 | uint8_t ch, ch_read; 120 | 121 | switch (channel) 122 | { 123 | case 0: 124 | default: 125 | ch = 0xf0; 126 | ch_read = 0xb8; 127 | break; 128 | case 1: 129 | ch = 0xe1; 130 | ch_read = 0xb1; 131 | break; 132 | case 2: 133 | ch = 0xd2; 134 | ch_read = 0xaa; 135 | break; 136 | case 3: 137 | ch = 0xc3; 138 | ch_read = 0xa3; 139 | break; 140 | case 4: 141 | ch = 0xb4; 142 | ch_read = 0x9c; 143 | break; 144 | case 5: 145 | ch = 0xa5; 146 | ch_read = 0x95; 147 | break; 148 | case 6: 149 | ch = 0x96; 150 | ch_read = 0x8e; 151 | break; 152 | case 7: 153 | ch = 0x87; 154 | ch_read = 0x87; 155 | break; 156 | }; 157 | 158 | busyWait(true); 159 | begin(); 160 | Wire.write(0xc3); 161 | Wire.write(ch); 162 | end(); 163 | busyWait(); 164 | 165 | uint8_t check = readByte(); 166 | 167 | return check == ch_read; 168 | } 169 | 170 | 171 | 172 | bool DS2482::wireReset() 173 | { 174 | busyWait(true); 175 | begin(); 176 | Wire.write(0xb4); 177 | end(); 178 | 179 | uint8_t status = busyWait(); 180 | 181 | return status & DS2482_STATUS_PPD ? true : false; 182 | } 183 | 184 | 185 | void DS2482::wireWriteByte(uint8_t b) 186 | { 187 | busyWait(true); 188 | begin(); 189 | Wire.write(0xa5); 190 | Wire.write(b); 191 | end(); 192 | } 193 | 194 | uint8_t DS2482::wireReadByte() 195 | { 196 | busyWait(true); 197 | begin(); 198 | Wire.write(0x96); 199 | end(); 200 | busyWait(); 201 | setReadPtr(PTR_READ); 202 | return readByte(); 203 | } 204 | 205 | void DS2482::wireWriteBit(uint8_t bit) 206 | { 207 | busyWait(true); 208 | begin(); 209 | Wire.write(0x87); 210 | Wire.write(bit ? 0x80 : 0); 211 | end(); 212 | } 213 | 214 | uint8_t DS2482::wireReadBit() 215 | { 216 | wireWriteBit(1); 217 | uint8_t status = busyWait(true); 218 | return status & DS2482_STATUS_SBR ? 1 : 0; 219 | } 220 | 221 | void DS2482::wireSkip() 222 | { 223 | wireWriteByte(0xcc); 224 | } 225 | 226 | void DS2482::wireSelect(uint8_t rom[8]) 227 | { 228 | wireWriteByte(0x55); 229 | for (int i=0;i<8;i++) 230 | wireWriteByte(rom[i]); 231 | } 232 | 233 | 234 | #if ONEWIRE_SEARCH 235 | void DS2482::wireResetSearch() 236 | { 237 | searchExhausted = 0; 238 | searchLastDisrepancy = 0; 239 | 240 | for(uint8_t i = 0; i<8; i++) 241 | searchAddress[i] = 0; 242 | } 243 | 244 | uint8_t DS2482::wireSearch(uint8_t *newAddr) 245 | { 246 | uint8_t i; 247 | uint8_t direction; 248 | uint8_t last_zero=0; 249 | 250 | if (searchExhausted) 251 | return 0; 252 | 253 | if (!wireReset()) 254 | return 0; 255 | 256 | busyWait(true); 257 | wireWriteByte(0xf0); 258 | 259 | for(i=1;i<65;i++) 260 | { 261 | int romByte = (i-1)>>3; 262 | int romBit = 1<<((i-1)&7); 263 | 264 | if (i < searchLastDisrepancy) 265 | direction = searchAddress[romByte] & romBit; 266 | else 267 | direction = i == searchLastDisrepancy; 268 | 269 | busyWait(); 270 | begin(); 271 | Wire.write(0x78); 272 | Wire.write(direction ? 0x80 : 0); 273 | end(); 274 | uint8_t status = busyWait(); 275 | 276 | uint8_t id = status & DS2482_STATUS_SBR; 277 | uint8_t comp_id = status & DS2482_STATUS_TSB; 278 | direction = status & DS2482_STATUS_DIR; 279 | 280 | if (id && comp_id) 281 | return 0; 282 | else 283 | { 284 | if (!id && !comp_id && !direction) 285 | last_zero = i; 286 | } 287 | 288 | if (direction) 289 | searchAddress[romByte] |= romBit; 290 | else 291 | searchAddress[romByte] &= (uint8_t)~romBit; 292 | } 293 | 294 | searchLastDisrepancy = last_zero; 295 | 296 | if (last_zero == 0) 297 | searchExhausted = 1; 298 | 299 | for (i=0;i<8;i++) 300 | newAddr[i] = searchAddress[i]; 301 | 302 | return 1; 303 | } 304 | #endif 305 | 306 | uint8_t DS2482::devicesCount(bool printAddress){ 307 | uint8_t address[8]; 308 | uint8_t count = 0; 309 | String SerialNumber = ""; 310 | 311 | wireResetSearch(); 312 | while (wireSearch(address)){ 313 | count++; 314 | SerialNumber = ""; 315 | for (uint8_t i = 0; i < 8; i++){ 316 | if (address[i] < 0x10) SerialNumber += "0"; 317 | SerialNumber += String(address[i], HEX); 318 | if (i < 7) SerialNumber += "-"; 319 | } 320 | if (printAddress){ 321 | Serial.print(SerialNumber); 322 | deviceName(address[0]); 323 | Serial.println(); 324 | } 325 | } 326 | return count; 327 | } 328 | 329 | #if ONEWIRE_CRC 330 | // The 1-Wire CRC scheme is described in Maxim Application Note 27: 331 | // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" 332 | // 333 | 334 | uint8_t DS2482::crc8( uint8_t *addr, uint8_t len) 335 | { 336 | uint8_t crc=0; 337 | 338 | for (uint8_t i=0; i>= 1; 345 | if (mix) 346 | crc ^= 0x8C; 347 | 348 | inbyte >>= 1; 349 | } 350 | } 351 | return crc; 352 | } 353 | 354 | // tools 355 | #define getString(type) (String)#type 356 | 357 | void DS2482::deviceName(uint8_t device) { 358 | String result = ""; 359 | 360 | switch(device) { 361 | case DS18S20: 362 | result = getString(DS18S20); 363 | break; 364 | case DS18B20: 365 | result = getString(DS18B20); 366 | break; 367 | case DS1822: 368 | result = getString(DS1822); 369 | break; 370 | case DS1825: 371 | result = getString(DS1825); 372 | break; 373 | case DS2406: 374 | result = getString(DS2406); 375 | break; 376 | } 377 | 378 | if (result != "") 379 | Serial.print(" - " + result); 380 | } 381 | 382 | #endif 383 | -------------------------------------------------------------------------------- /DS2482.h: -------------------------------------------------------------------------------- 1 | /* 2 | DS2482 library for Arduino 3 | Copyright (C) 2009-2010 Paeae Technologies 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef __DS2482_H__ 20 | #define __DS2482_H__ 21 | 22 | #include 23 | 24 | // you can exclude onewire_search by defining that to 0 25 | #ifndef ONEWIRE_SEARCH 26 | #define ONEWIRE_SEARCH 1 27 | #endif 28 | 29 | // You can exclude CRC checks altogether by defining this to 0 30 | #ifndef ONEWIRE_CRC 31 | #define ONEWIRE_CRC 1 32 | #endif 33 | 34 | 35 | #define DS2482_CONFIG_APU (1<<0) 36 | #define DS2482_CONFIG_PPM (1<<1) 37 | #define DS2482_CONFIG_SPU (1<<2) 38 | #define DS2484_CONFIG_WS (1<<3) 39 | 40 | #define DS2482_STATUS_BUSY (1<<0) 41 | #define DS2482_STATUS_PPD (1<<1) 42 | #define DS2482_STATUS_SD (1<<2) 43 | #define DS2482_STATUS_LL (1<<3) 44 | #define DS2482_STATUS_RST (1<<4) 45 | #define DS2482_STATUS_SBR (1<<5) 46 | #define DS2482_STATUS_TSB (1<<6) 47 | #define DS2482_STATUS_DIR (1<<7) 48 | 49 | class DS2482 50 | { 51 | public: 52 | //Address is 0-3 53 | DS2482(uint8_t address); 54 | 55 | bool configure(uint8_t config); 56 | uint8_t reset(); 57 | 58 | //DS2482-800 only 59 | bool selectChannel(uint8_t channel); 60 | 61 | bool wireReset(); // return true if presence pulse is detected 62 | uint8_t wireReadStatus(bool setPtr=false); 63 | 64 | void wireWriteByte(uint8_t b); 65 | uint8_t wireReadByte(); 66 | 67 | void wireWriteBit(uint8_t bit); 68 | uint8_t wireReadBit(); 69 | // Issue a 1-Wire rom select command, you do the reset first. 70 | void wireSelect( uint8_t rom[8]); 71 | // Issue skip rom 72 | void wireSkip(); 73 | 74 | uint8_t hasTimeout() { return mTimeout; } 75 | #if ONEWIRE_SEARCH 76 | // Clear the search state so that if will start from the beginning again. 77 | void wireResetSearch(); 78 | 79 | // Look for the next device. Returns 1 if a new address has been 80 | // returned. A zero might mean that the bus is shorted, there are 81 | // no devices, or you have already retrieved all of them. It 82 | // might be a good idea to check the CRC to make sure you didn't 83 | // get garbage. The order is deterministic. You will always get 84 | // the same devices in the same order. 85 | uint8_t wireSearch(uint8_t *newAddr); 86 | #endif 87 | uint8_t devicesCount(bool printAddress); 88 | #if ONEWIRE_CRC 89 | // Compute a Dallas Semiconductor 8 bit CRC, these are used in the 90 | // ROM and scratchpad registers. 91 | static uint8_t crc8( uint8_t *addr, uint8_t len); 92 | #endif 93 | 94 | private: 95 | 96 | uint8_t mAddress; 97 | uint8_t mTimeout; 98 | uint8_t readByte(); 99 | void setReadPtr(uint8_t readPtr); 100 | 101 | uint8_t busyWait(bool setReadPtr=false); //blocks until 102 | void begin(); 103 | void end(); 104 | void deviceName(uint8_t device); 105 | 106 | #if ONEWIRE_SEARCH 107 | uint8_t searchAddress[8]; 108 | uint8_t searchLastDisrepancy; 109 | uint8_t searchExhausted; 110 | #endif 111 | 112 | }; 113 | 114 | 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DS18B20_DS2482 2 | **DS2482 - I2C to 1-Wire bridge used with ESP8266 WIFI on ARDUINO** 3 | 4 | ``` 5 | 6 | //ESP8266 7 | #include 8 | //Tools 9 | #include //I²C 10 | 11 | //DS2482 12 | #include 13 | #include 14 | DS2482 DS2482(0); // 0 = 0x18 15 | DS18B20_DS2482 DS18B20_devices(&DS2482); 16 | DeviceAddress DS18B20_Address; 17 | int DevicesCount = 0; 18 | 19 | void setup() { 20 | 21 | Serial.begin(115200); 22 | Wire.begin(13, 12); //Start I²C pin 12=SCL 13=SDA 23 | DS2482.reset(); 24 | Serial.println(""); 25 | Serial.println(""); 26 | 27 | //search for devices and print address = true 28 | DevicesCount = DS2482.devicesCount(true); 29 | 30 | DS18B20_devices.begin(); 31 | Serial.println(""); 32 | } 33 | 34 | void loop() { 35 | 36 | for (uint8_t i = 0; i < DevicesCount; i++){ 37 | DS18B20_devices.requestTemperaturesByIndex(i); 38 | Serial.print("device #"); 39 | Serial.print(i); 40 | Serial.print(": "); 41 | Serial.println(DS18B20_devices.getTempCByIndex(i)); 42 | } 43 | Serial.println(""); 44 | delay(5000); 45 | 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /examples/DS2482_DEMO/DS2482_DEMO.ino: -------------------------------------------------------------------------------- 1 | 2 | //ESP8266 3 | #include 4 | //Tools 5 | #include //I²C 6 | 7 | //DS2482 8 | #include 9 | #include 10 | DS2482 DS2482(0); // 0 = 0x18 11 | DS18B20_DS2482 DS18B20_devices(&DS2482); 12 | DeviceAddress DS18B20_Address; 13 | int DevicesCount = 0; 14 | int TemperatueCount = 0; 15 | 16 | unsigned long lastTemp = 0, tempScanInterval = 60 * 1000 * 1000; 17 | 18 | void setup() { 19 | 20 | Serial.begin(115200); 21 | delay(1000); 22 | Serial.println("\n\nDS2482-100 Test\n\n"); 23 | delay(1000); 24 | 25 | Serial.print("starting I2C: "); 26 | Wire.begin(SDA, SCL); //Start I²C 27 | Serial.println("ok"); 28 | scanI2C(); 29 | 30 | Serial.print("DS2482-100 reset: "); 31 | DS2482.reset(); 32 | Serial.println("ok"); 33 | 34 | //search for devices and print address = true 35 | Serial.print("DS2482-100 scan: \n"); 36 | DevicesCount = DS2482.devicesCount(true); 37 | Serial.println("devices: #" + (String)DevicesCount); 38 | 39 | delay(10000); 40 | Serial.print("DS18B20 begin: "); 41 | DS18B20_devices.begin(); 42 | Serial.println("ok"); 43 | TemperatueCount = DS18B20_devices.getDeviceCount(); 44 | Serial.println("devices: #" + (String)TemperatueCount); 45 | } 46 | 47 | void loop() { 48 | unsigned long currMicros = micros(); 49 | unsigned long nextTemp; 50 | 51 | nextTemp = lastTemp + tempScanInterval; 52 | delay(100); 53 | 54 | // temperature 55 | if (nextTemp < currMicros) { 56 | for (uint8_t i = 0; i < TemperatueCount; i++){ 57 | DS18B20_devices.requestTemperaturesByIndex(i); 58 | Serial.print("temp #"); 59 | Serial.print(i); 60 | Serial.print(": "); 61 | Serial.println(DS18B20_devices.getTempCByIndex(i)); 62 | } 63 | 64 | lastTemp = currMicros; 65 | } 66 | } 67 | 68 | void scanI2C() { 69 | for(byte address = 1; address < 127; address++ ) 70 | { 71 | // The i2c_scanner uses the return value of 72 | // the Write.endTransmisstion to see if 73 | // a device did acknowledge to the address. 74 | Wire.beginTransmission(address); 75 | byte error = Wire.endTransmission(); 76 | 77 | if (error == 0) 78 | { 79 | Serial.print("I2C device found at address 0x"); 80 | if (address<16) 81 | Serial.print("0"); 82 | Serial.print(address, HEX); 83 | Serial.println(" !"); 84 | } 85 | } 86 | } 87 | --------------------------------------------------------------------------------