Now supports DS18B20 and DS18S20 Maxim/Dallas one-wire thermometer devices. Also supports DS18S20 in 9, 10, 11, and 12 bit resolution modes. 'Use Address' mode now checks if the correct device type is present, and informs the user which device to use. Correct temperature conversion times now used in non-parasitic mode. The device should be placed at least 6 inches (15 cm) from the mbed board in order to accurately read ambient temperature.
OneWireThermometer.cpp
00001 /* 00002 * OneWireThermometer. Base class for Maxim One-Wire Thermometers. 00003 * Uses the OneWireCRC library. 00004 * 00005 * Copyright (C) <2010> Petras Saduikis <petras@petras.co.uk> 00006 * 00007 * This file is part of OneWireThermometer. 00008 * 00009 * OneWireThermometer is free software: you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation, either version 3 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * OneWireThermometer is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with OneWireThermometer. If not, see <http://www.gnu.org/licenses/>. 00021 */ 00022 00023 #include "OneWireThermometer.h" 00024 #include "OneWireDefs.h" 00025 #include "DebugTrace.h" 00026 00027 DebugTrace pc(ON, TO_SERIAL); 00028 00029 // constructor specifies standard speed for the 1-Wire comms 00030 OneWireThermometer::OneWireThermometer(bool crcOn, bool useAddr, bool parasitic, PinName pin, int device_id) : 00031 useCRC(crcOn), useAddress(useAddr), useParasiticPower(parasitic), 00032 oneWire(pin, STANDARD), deviceId(device_id), resolution(twelveBit) 00033 { 00034 // NOTE: the power-up resolution of a DS18B20 is 12 bits. The DS18S20's resolution is always 00035 // 9 bits + enhancement, but we treat the DS18S20 as fixed to 12 bits for calculating the 00036 // conversion time Tconv. 00037 } 00038 00039 bool OneWireThermometer::initialize() 00040 { 00041 // get the device address for use in selectROM() when reading the temperature 00042 // - not really needed except for device validation if using skipROM() 00043 if (useAddress) 00044 { 00045 pc.traceOut("\r\n"); 00046 pc.traceOut("New Scan\r\n"); 00047 00048 oneWire.resetSearch(); 00049 if (!oneWire.search(address)) // search for 1-wire device address 00050 { 00051 pc.traceOut("No more addresses.\r\n"); 00052 wait(2); 00053 return false; 00054 } 00055 00056 pc.traceOut("Address = "); 00057 for (int i = 0; i < ADDRESS_SIZE; i++) 00058 { 00059 pc.traceOut("%x ", (int)address[i]); 00060 } 00061 pc.traceOut("\r\n"); 00062 00063 if (OneWireCRC::crc8(address, ADDRESS_CRC_BYTE) != address[ADDRESS_CRC_BYTE]) // check address CRC is valid 00064 { 00065 pc.traceOut("CRC is not valid!\r\n"); 00066 wait(2); 00067 return false; 00068 } 00069 00070 if (address[0] != deviceId) 00071 { 00072 // Make sure it is a one-wire thermometer device 00073 if (DS18B20_ID == deviceId) 00074 pc.traceOut("You need to use a DS1820 or DS18S20 for correct results.\r\n"); 00075 else if (DS18S20_ID == deviceId) 00076 pc.traceOut("You need to use a DS18B20 for correct results.\r\n"); 00077 else 00078 pc.traceOut("Device is not a DS18B20/DS1820/DS18S20 device.\r\n"); 00079 00080 wait(2); 00081 return false; 00082 } 00083 else 00084 { 00085 if (DS18B20_ID == deviceId) pc.traceOut("DS18B20 present and correct.\r\n"); 00086 if (DS18S20_ID == deviceId) pc.traceOut("DS1820/DS18S20 present and correct.\r\n"); 00087 } 00088 } 00089 00090 return true; 00091 } 00092 00093 // NOTE ON USING SKIP ROM: ok to use before a Convert command to get all 00094 // devices on the bus to do simultaneous temperature conversions. BUT can 00095 // only use before a Read Scratchpad command if there is only one device on the 00096 // bus. For purpose of this library it is assumed there is only one device 00097 // on the bus. 00098 void OneWireThermometer::resetAndAddress() 00099 { 00100 oneWire.reset(); // reset device 00101 if (useAddress) 00102 { 00103 oneWire.matchROM(address); // select which device to talk to 00104 } 00105 else 00106 { 00107 oneWire.skipROM(); // broadcast 00108 } 00109 } 00110 00111 bool OneWireThermometer::readAndValidateData(BYTE* data) 00112 { 00113 bool dataOk = true; 00114 00115 resetAndAddress(); 00116 oneWire.writeByte(READSCRATCH); // read Scratchpad 00117 00118 pc.traceOut("read = "); 00119 for (int i = 0; i < THERMOM_SCRATCHPAD_SIZE; i++) 00120 { 00121 // we need all bytes which includes CRC check byte 00122 data[i] = oneWire.readByte(); 00123 pc.traceOut("%x ", (int)data[i]); 00124 } 00125 pc.traceOut("\r\n"); 00126 00127 // Check CRC is valid if you want to 00128 if (useCRC && !(OneWireCRC::crc8(data, THERMOM_CRC_BYTE) == data[THERMOM_CRC_BYTE])) 00129 { 00130 // CRC failed 00131 pc.traceOut("CRC FAILED... \r\n"); 00132 dataOk = false; 00133 } 00134 00135 return dataOk; 00136 } 00137 00138 float OneWireThermometer::readTemperature() 00139 { 00140 BYTE data[THERMOM_SCRATCHPAD_SIZE]; 00141 float realTemp = -999; 00142 00143 resetAndAddress(); 00144 oneWire.writeByte(CONVERT); // issue Convert command 00145 00146 if (useParasiticPower) 00147 { 00148 // wait while converting - Tconv (according to resolution of reading) 00149 wait_ms(CONVERSION_TIME[resolution]); 00150 } 00151 else 00152 { 00153 // TODO 00154 // after the Convert command, the device should respond by transmitting 0 00155 // while the temperature conversion is in progress and 1 when the conversion is done 00156 // - as were are not checking this (TODO), we use Tconv, as we would do for 00157 // parasitic power 00158 wait_ms(CONVERSION_TIME[resolution]); 00159 } 00160 00161 if (readAndValidateData(data)) // issue Read Scratchpad commmand and get data 00162 { 00163 realTemp = calculateTemperature(data); 00164 } 00165 00166 return realTemp; 00167 }
Generated on Sat Jul 16 2022 06:12:12 by 1.7.2