OneWire Temperature library for interfacing DS18B20
Dependents: DallasTemperature project1
OneWireThermometer.cpp@0:ad90c2e86a63, 2011-04-17 (annotated)
- Committer:
- Wimpie
- Date:
- Sun Apr 17 17:27:20 2011 +0000
- Revision:
- 0:ad90c2e86a63
improved 1W search function
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wimpie | 0:ad90c2e86a63 | 1 | /* |
Wimpie | 0:ad90c2e86a63 | 2 | * OneWireThermometer. Base class for Maxim One-Wire Thermometers. |
Wimpie | 0:ad90c2e86a63 | 3 | * Uses the OneWireCRC library. |
Wimpie | 0:ad90c2e86a63 | 4 | * |
Wimpie | 0:ad90c2e86a63 | 5 | * Copyright (C) <2010> Petras Saduikis <petras@petras.co.uk> |
Wimpie | 0:ad90c2e86a63 | 6 | * |
Wimpie | 0:ad90c2e86a63 | 7 | * This file is part of OneWireThermometer. |
Wimpie | 0:ad90c2e86a63 | 8 | * |
Wimpie | 0:ad90c2e86a63 | 9 | * OneWireThermometer is free software: you can redistribute it and/or modify |
Wimpie | 0:ad90c2e86a63 | 10 | * it under the terms of the GNU General Public License as published by |
Wimpie | 0:ad90c2e86a63 | 11 | * the Free Software Foundation, either version 3 of the License, or |
Wimpie | 0:ad90c2e86a63 | 12 | * (at your option) any later version. |
Wimpie | 0:ad90c2e86a63 | 13 | * |
Wimpie | 0:ad90c2e86a63 | 14 | * OneWireThermometer is distributed in the hope that it will be useful, |
Wimpie | 0:ad90c2e86a63 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
Wimpie | 0:ad90c2e86a63 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
Wimpie | 0:ad90c2e86a63 | 17 | * GNU General Public License for more details. |
Wimpie | 0:ad90c2e86a63 | 18 | * |
Wimpie | 0:ad90c2e86a63 | 19 | * You should have received a copy of the GNU General Public License |
Wimpie | 0:ad90c2e86a63 | 20 | * along with OneWireThermometer. If not, see <http://www.gnu.org/licenses/>. |
Wimpie | 0:ad90c2e86a63 | 21 | */ |
Wimpie | 0:ad90c2e86a63 | 22 | |
Wimpie | 0:ad90c2e86a63 | 23 | #include "OneWireThermometer.h" |
Wimpie | 0:ad90c2e86a63 | 24 | #include "OneWireDefs.h" |
Wimpie | 0:ad90c2e86a63 | 25 | #include "DebugTrace.h" |
Wimpie | 0:ad90c2e86a63 | 26 | |
Wimpie | 0:ad90c2e86a63 | 27 | DebugTrace pc(ON, TO_SERIAL); |
Wimpie | 0:ad90c2e86a63 | 28 | |
Wimpie | 0:ad90c2e86a63 | 29 | // constructor specifies standard speed for the 1-Wire comms |
Wimpie | 0:ad90c2e86a63 | 30 | OneWireThermometer::OneWireThermometer(PinName pin, bool crcOn, bool useAddr, bool parasitic, int device_id, unsigned char *ROMaddress) |
Wimpie | 0:ad90c2e86a63 | 31 | :oneWire(pin, STANDARD) { |
Wimpie | 0:ad90c2e86a63 | 32 | _useCRC=crcOn; |
Wimpie | 0:ad90c2e86a63 | 33 | _useAddress=useAddr; |
Wimpie | 0:ad90c2e86a63 | 34 | _useParasiticPower=parasitic; |
Wimpie | 0:ad90c2e86a63 | 35 | _deviceId= device_id; |
Wimpie | 0:ad90c2e86a63 | 36 | _resolution=twelveBit; |
Wimpie | 0:ad90c2e86a63 | 37 | |
Wimpie | 0:ad90c2e86a63 | 38 | if (_useAddress) { |
Wimpie | 0:ad90c2e86a63 | 39 | for (int i = 0; i < ADDRESS_SIZE; i++) |
Wimpie | 0:ad90c2e86a63 | 40 | _ROMCode[i]=ROMaddress[i]; |
Wimpie | 0:ad90c2e86a63 | 41 | } else { |
Wimpie | 0:ad90c2e86a63 | 42 | for (int i = 0; i < ADDRESS_SIZE; i++) |
Wimpie | 0:ad90c2e86a63 | 43 | _ROMCode[i]=0; |
Wimpie | 0:ad90c2e86a63 | 44 | } |
Wimpie | 0:ad90c2e86a63 | 45 | |
Wimpie | 0:ad90c2e86a63 | 46 | // NOTE: the power-up resolution of a DS18B20 is 12 bits. The DS18S20's resolution is always |
Wimpie | 0:ad90c2e86a63 | 47 | // 9 bits + enhancement, but we treat the DS18S20 as fixed to 12 bits for calculating the |
Wimpie | 0:ad90c2e86a63 | 48 | // conversion time Tconv. |
Wimpie | 0:ad90c2e86a63 | 49 | |
Wimpie | 0:ad90c2e86a63 | 50 | } |
Wimpie | 0:ad90c2e86a63 | 51 | |
Wimpie | 0:ad90c2e86a63 | 52 | bool OneWireThermometer::initialize() { |
Wimpie | 0:ad90c2e86a63 | 53 | |
Wimpie | 0:ad90c2e86a63 | 54 | int OneWireFound; |
Wimpie | 0:ad90c2e86a63 | 55 | int OneWireSameAddress; |
Wimpie | 0:ad90c2e86a63 | 56 | int i; |
Wimpie | 0:ad90c2e86a63 | 57 | BYTE _dummyaddress[8]; |
Wimpie | 0:ad90c2e86a63 | 58 | |
Wimpie | 0:ad90c2e86a63 | 59 | |
Wimpie | 0:ad90c2e86a63 | 60 | if (_useAddress) { |
Wimpie | 0:ad90c2e86a63 | 61 | pc.traceOut("Scan for device with address "); |
Wimpie | 0:ad90c2e86a63 | 62 | for (i = 0; i < ADDRESS_SIZE; i++) { |
Wimpie | 0:ad90c2e86a63 | 63 | pc.traceOut("%x ", (int)_ROMCode[i]); |
Wimpie | 0:ad90c2e86a63 | 64 | } |
Wimpie | 0:ad90c2e86a63 | 65 | pc.traceOut("\r\n"); |
Wimpie | 0:ad90c2e86a63 | 66 | } |
Wimpie | 0:ad90c2e86a63 | 67 | OneWireSameAddress=0; |
Wimpie | 0:ad90c2e86a63 | 68 | |
Wimpie | 0:ad90c2e86a63 | 69 | oneWire.resetSearch(); |
Wimpie | 0:ad90c2e86a63 | 70 | do { |
Wimpie | 0:ad90c2e86a63 | 71 | OneWireFound=(oneWire.search(_dummyaddress)); |
Wimpie | 0:ad90c2e86a63 | 72 | if (OneWireFound) { |
Wimpie | 0:ad90c2e86a63 | 73 | |
Wimpie | 0:ad90c2e86a63 | 74 | if (!_useAddress) { |
Wimpie | 0:ad90c2e86a63 | 75 | pc.traceOut("Device found with Address = "); |
Wimpie | 0:ad90c2e86a63 | 76 | for (i = 0; i < ADDRESS_SIZE; i++) { |
Wimpie | 0:ad90c2e86a63 | 77 | pc.traceOut("%x ", (int)_dummyaddress[i]); |
Wimpie | 0:ad90c2e86a63 | 78 | } |
Wimpie | 0:ad90c2e86a63 | 79 | } |
Wimpie | 0:ad90c2e86a63 | 80 | OneWireSameAddress=1; |
Wimpie | 0:ad90c2e86a63 | 81 | |
Wimpie | 0:ad90c2e86a63 | 82 | if (_useAddress) { |
Wimpie | 0:ad90c2e86a63 | 83 | for (i = 0; i < ADDRESS_SIZE; i++) { |
Wimpie | 0:ad90c2e86a63 | 84 | if (!((OneWireSameAddress) && (_ROMCode[i] ==_dummyaddress[i]))) |
Wimpie | 0:ad90c2e86a63 | 85 | OneWireSameAddress=0; |
Wimpie | 0:ad90c2e86a63 | 86 | } |
Wimpie | 0:ad90c2e86a63 | 87 | } else { |
Wimpie | 0:ad90c2e86a63 | 88 | for (i = 0; i < ADDRESS_SIZE; i++) { |
Wimpie | 0:ad90c2e86a63 | 89 | _ROMCode[i] =_dummyaddress[i]; |
Wimpie | 0:ad90c2e86a63 | 90 | } |
Wimpie | 0:ad90c2e86a63 | 91 | } |
Wimpie | 0:ad90c2e86a63 | 92 | |
Wimpie | 0:ad90c2e86a63 | 93 | /* if (OneWireSameAddress) { |
Wimpie | 0:ad90c2e86a63 | 94 | pc.traceOut("-> Address valid!\r\n"); |
Wimpie | 0:ad90c2e86a63 | 95 | |
Wimpie | 0:ad90c2e86a63 | 96 | } else { |
Wimpie | 0:ad90c2e86a63 | 97 | pc.traceOut("-> Address NOT valid.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 98 | }*/ |
Wimpie | 0:ad90c2e86a63 | 99 | |
Wimpie | 0:ad90c2e86a63 | 100 | } else { |
Wimpie | 0:ad90c2e86a63 | 101 | |
Wimpie | 0:ad90c2e86a63 | 102 | pc.traceOut("No more addresses.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 103 | oneWire.resetSearch(); |
Wimpie | 0:ad90c2e86a63 | 104 | wait_ms(250); //500 |
Wimpie | 0:ad90c2e86a63 | 105 | } |
Wimpie | 0:ad90c2e86a63 | 106 | } while (OneWireFound && !OneWireSameAddress); |
Wimpie | 0:ad90c2e86a63 | 107 | |
Wimpie | 0:ad90c2e86a63 | 108 | if (!OneWireSameAddress) { |
Wimpie | 0:ad90c2e86a63 | 109 | pc.traceOut("-> No Valid ROM Code found.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 110 | return false; |
Wimpie | 0:ad90c2e86a63 | 111 | } |
Wimpie | 0:ad90c2e86a63 | 112 | |
Wimpie | 0:ad90c2e86a63 | 113 | if (OneWireCRC::crc8(_ROMCode, ADDRESS_CRC_BYTE) != _ROMCode[ADDRESS_CRC_BYTE]) { // check address CRC is valid |
Wimpie | 0:ad90c2e86a63 | 114 | pc.traceOut("CRC is not valid!\r\n"); |
Wimpie | 0:ad90c2e86a63 | 115 | // wait_ms(500); |
Wimpie | 0:ad90c2e86a63 | 116 | return false; |
Wimpie | 0:ad90c2e86a63 | 117 | } |
Wimpie | 0:ad90c2e86a63 | 118 | |
Wimpie | 0:ad90c2e86a63 | 119 | if (_ROMCode[0] != _deviceId) { |
Wimpie | 0:ad90c2e86a63 | 120 | // Make sure it is a one-wire thermometer device |
Wimpie | 0:ad90c2e86a63 | 121 | if (DS18B20_ID == _deviceId) |
Wimpie | 0:ad90c2e86a63 | 122 | pc.traceOut("You need to use a DS1820 or DS18S20 for correct results.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 123 | else if (DS18S20_ID == _deviceId) |
Wimpie | 0:ad90c2e86a63 | 124 | pc.traceOut("You need to use a DS18B20 for correct results.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 125 | else |
Wimpie | 0:ad90c2e86a63 | 126 | pc.traceOut("Device is not a DS18B20/DS1820/DS18S20 device.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 127 | |
Wimpie | 0:ad90c2e86a63 | 128 | // wait_ms(500); |
Wimpie | 0:ad90c2e86a63 | 129 | return false; |
Wimpie | 0:ad90c2e86a63 | 130 | } else { |
Wimpie | 0:ad90c2e86a63 | 131 | if (DS18B20_ID == _deviceId) pc.traceOut("DS18B20 present and correct.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 132 | if (DS18S20_ID == _deviceId) pc.traceOut("DS1820/DS18S20 present and correct.\r\n"); |
Wimpie | 0:ad90c2e86a63 | 133 | } |
Wimpie | 0:ad90c2e86a63 | 134 | |
Wimpie | 0:ad90c2e86a63 | 135 | |
Wimpie | 0:ad90c2e86a63 | 136 | return true; |
Wimpie | 0:ad90c2e86a63 | 137 | } |
Wimpie | 0:ad90c2e86a63 | 138 | |
Wimpie | 0:ad90c2e86a63 | 139 | // NOTE ON USING SKIP ROM: ok to use before a Convert command to get all |
Wimpie | 0:ad90c2e86a63 | 140 | // devices on the bus to do simultaneous temperature conversions. BUT can |
Wimpie | 0:ad90c2e86a63 | 141 | // only use before a Read Scratchpad command if there is only one device on the |
Wimpie | 0:ad90c2e86a63 | 142 | // bus. For purpose of this library it is assumed there is only one device |
Wimpie | 0:ad90c2e86a63 | 143 | // on the bus. |
Wimpie | 0:ad90c2e86a63 | 144 | |
Wimpie | 0:ad90c2e86a63 | 145 | void OneWireThermometer::resetAndAddress() { |
Wimpie | 0:ad90c2e86a63 | 146 | oneWire.reset(); // reset device |
Wimpie | 0:ad90c2e86a63 | 147 | if (_useAddress) { |
Wimpie | 0:ad90c2e86a63 | 148 | oneWire.matchROM(_ROMCode); // select which device to talk to |
Wimpie | 0:ad90c2e86a63 | 149 | } else { |
Wimpie | 0:ad90c2e86a63 | 150 | oneWire.skipROM(); // broadcast |
Wimpie | 0:ad90c2e86a63 | 151 | } |
Wimpie | 0:ad90c2e86a63 | 152 | } |
Wimpie | 0:ad90c2e86a63 | 153 | |
Wimpie | 0:ad90c2e86a63 | 154 | bool OneWireThermometer::readAndValidateData(BYTE* data) { |
Wimpie | 0:ad90c2e86a63 | 155 | bool dataOk = true; |
Wimpie | 0:ad90c2e86a63 | 156 | |
Wimpie | 0:ad90c2e86a63 | 157 | resetAndAddress(); |
Wimpie | 0:ad90c2e86a63 | 158 | oneWire.writeByte(DS18X20_READSCRATCH); // read Scratchpad |
Wimpie | 0:ad90c2e86a63 | 159 | |
Wimpie | 0:ad90c2e86a63 | 160 | // pc.traceOut("read = "); |
Wimpie | 0:ad90c2e86a63 | 161 | for (int i = 0; i < THERMOM_SCRATCHPAD_SIZE; i++) { |
Wimpie | 0:ad90c2e86a63 | 162 | // we need all bytes which includes CRC check byte |
Wimpie | 0:ad90c2e86a63 | 163 | data[i] = oneWire.readByte(); |
Wimpie | 0:ad90c2e86a63 | 164 | // pc.traceOut("%x ", (int)data[i]); |
Wimpie | 0:ad90c2e86a63 | 165 | } |
Wimpie | 0:ad90c2e86a63 | 166 | //pc.traceOut("\r\n"); |
Wimpie | 0:ad90c2e86a63 | 167 | |
Wimpie | 0:ad90c2e86a63 | 168 | // Check CRC is valid if you want to |
Wimpie | 0:ad90c2e86a63 | 169 | if (_useCRC && !(OneWireCRC::crc8(data, THERMOM_CRC_BYTE) == data[THERMOM_CRC_BYTE])) { |
Wimpie | 0:ad90c2e86a63 | 170 | // CRC failed |
Wimpie | 0:ad90c2e86a63 | 171 | pc.traceOut("CRC FAILED... \r\n"); |
Wimpie | 0:ad90c2e86a63 | 172 | dataOk = false; |
Wimpie | 0:ad90c2e86a63 | 173 | } |
Wimpie | 0:ad90c2e86a63 | 174 | |
Wimpie | 0:ad90c2e86a63 | 175 | return dataOk; |
Wimpie | 0:ad90c2e86a63 | 176 | } |
Wimpie | 0:ad90c2e86a63 | 177 | |
Wimpie | 0:ad90c2e86a63 | 178 | float OneWireThermometer::readTemperature() { |
Wimpie | 0:ad90c2e86a63 | 179 | BYTE data[THERMOM_SCRATCHPAD_SIZE]; |
Wimpie | 0:ad90c2e86a63 | 180 | float realTemp = -999; |
Wimpie | 0:ad90c2e86a63 | 181 | int i = 0; |
Wimpie | 0:ad90c2e86a63 | 182 | |
Wimpie | 0:ad90c2e86a63 | 183 | do { |
Wimpie | 0:ad90c2e86a63 | 184 | |
Wimpie | 0:ad90c2e86a63 | 185 | resetAndAddress(); |
Wimpie | 0:ad90c2e86a63 | 186 | oneWire.writeByte(CONVERT); // issue Convert command |
Wimpie | 0:ad90c2e86a63 | 187 | |
Wimpie | 0:ad90c2e86a63 | 188 | if (_useParasiticPower) { |
Wimpie | 0:ad90c2e86a63 | 189 | // wait while converting - Tconv (according to resolution of reading) |
Wimpie | 0:ad90c2e86a63 | 190 | wait_ms(CONVERSION_TIME[_resolution]); |
Wimpie | 0:ad90c2e86a63 | 191 | } else { |
Wimpie | 0:ad90c2e86a63 | 192 | // TODO |
Wimpie | 0:ad90c2e86a63 | 193 | // after the Convert command, the device should respond by transmitting 0 |
Wimpie | 0:ad90c2e86a63 | 194 | // while the temperature conversion is in progress and 1 when the conversion is done |
Wimpie | 0:ad90c2e86a63 | 195 | // - as were are not checking this (TODO), we use Tconv, as we would do for |
Wimpie | 0:ad90c2e86a63 | 196 | // parasitic power |
Wimpie | 0:ad90c2e86a63 | 197 | wait_ms(CONVERSION_TIME[_resolution]); |
Wimpie | 0:ad90c2e86a63 | 198 | } |
Wimpie | 0:ad90c2e86a63 | 199 | |
Wimpie | 0:ad90c2e86a63 | 200 | if (readAndValidateData(data)) { // issue Read Scratchpad commmand and get data |
Wimpie | 0:ad90c2e86a63 | 201 | realTemp = calculateTemperature(data); |
Wimpie | 0:ad90c2e86a63 | 202 | i++; |
Wimpie | 0:ad90c2e86a63 | 203 | } |
Wimpie | 0:ad90c2e86a63 | 204 | } while ((realTemp==-999) && (i<5)); |
Wimpie | 0:ad90c2e86a63 | 205 | |
Wimpie | 0:ad90c2e86a63 | 206 | return realTemp; |
Wimpie | 0:ad90c2e86a63 | 207 | } |