Wim De Roeve / DS18B20

Dependents:   DallasTemperature project1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OneWireThermometer.cpp Source File

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(PinName pin, bool crcOn, bool useAddr, bool parasitic, int device_id, unsigned char *ROMaddress)
00031         :oneWire(pin, STANDARD) {
00032     _useCRC=crcOn;
00033     _useAddress=useAddr;
00034     _useParasiticPower=parasitic;
00035     _deviceId= device_id;
00036     _resolution=twelveBit;
00037 
00038     if (_useAddress) {
00039         for (int i = 0; i < ADDRESS_SIZE; i++)
00040             _ROMCode[i]=ROMaddress[i];
00041     } else {
00042         for (int i = 0; i < ADDRESS_SIZE; i++)
00043             _ROMCode[i]=0;
00044     }
00045 
00046     // NOTE: the power-up resolution of a DS18B20 is 12 bits. The DS18S20's resolution is always
00047     // 9 bits + enhancement, but we treat the DS18S20 as fixed to 12 bits for calculating the
00048     // conversion time Tconv.
00049 
00050 }
00051 
00052 bool OneWireThermometer::initialize() {
00053 
00054     int OneWireFound;
00055     int OneWireSameAddress;
00056     int i;
00057     BYTE _dummyaddress[8];
00058 
00059 
00060     if (_useAddress) {
00061         pc.traceOut("Scan for device with address ");
00062         for (i = 0; i < ADDRESS_SIZE; i++) {
00063             pc.traceOut("%x ", (int)_ROMCode[i]);
00064         }
00065         pc.traceOut("\r\n");
00066     }
00067     OneWireSameAddress=0;
00068 
00069     oneWire.resetSearch();
00070     do {
00071         OneWireFound=(oneWire.search(_dummyaddress));
00072         if (OneWireFound) {
00073 
00074             if (!_useAddress) {
00075                 pc.traceOut("Device found with Address = ");
00076                 for (i = 0; i < ADDRESS_SIZE; i++) {
00077                     pc.traceOut("%x ", (int)_dummyaddress[i]);
00078                 }
00079             }
00080             OneWireSameAddress=1;
00081 
00082             if (_useAddress) {
00083                 for (i = 0; i < ADDRESS_SIZE; i++) {
00084                     if (!((OneWireSameAddress) && (_ROMCode[i] ==_dummyaddress[i])))
00085                         OneWireSameAddress=0;
00086                 }
00087             } else {
00088                 for (i = 0; i < ADDRESS_SIZE; i++) {
00089                     _ROMCode[i] =_dummyaddress[i];
00090                 }
00091             }
00092 
00093             /*           if (OneWireSameAddress) {
00094                            pc.traceOut("-> Address valid!\r\n");
00095 
00096                        } else {
00097                            pc.traceOut("-> Address NOT valid.\r\n");
00098                        }*/
00099 
00100         } else {
00101 
00102             pc.traceOut("No more addresses.\r\n");
00103             oneWire.resetSearch();
00104             wait_ms(250);  //500
00105         }
00106     } while (OneWireFound && !OneWireSameAddress);
00107 
00108     if (!OneWireSameAddress) {
00109         pc.traceOut("-> No Valid ROM Code found.\r\n");
00110         return false;
00111     }
00112 
00113     if (OneWireCRC::crc8(_ROMCode, ADDRESS_CRC_BYTE) != _ROMCode[ADDRESS_CRC_BYTE]) { // check address CRC is valid
00114         pc.traceOut("CRC is not valid!\r\n");
00115         // wait_ms(500);
00116         return false;
00117     }
00118 
00119     if (_ROMCode[0] != _deviceId) {
00120         // Make sure it is a one-wire thermometer device
00121         if (DS18B20_ID == _deviceId)
00122             pc.traceOut("You need to use a DS1820 or DS18S20 for correct results.\r\n");
00123         else if (DS18S20_ID == _deviceId)
00124             pc.traceOut("You need to use a DS18B20 for correct results.\r\n");
00125         else
00126             pc.traceOut("Device is not a DS18B20/DS1820/DS18S20 device.\r\n");
00127 
00128         //  wait_ms(500);
00129         return false;
00130     } else {
00131         if (DS18B20_ID == _deviceId) pc.traceOut("DS18B20 present and correct.\r\n");
00132         if (DS18S20_ID == _deviceId) pc.traceOut("DS1820/DS18S20 present and correct.\r\n");
00133     }
00134 
00135 
00136     return true;
00137 }
00138 
00139 // NOTE ON USING SKIP ROM: ok to use before a Convert command to get all
00140 // devices on the bus to do simultaneous temperature conversions. BUT can
00141 // only use before a Read Scratchpad command if there is only one device on the
00142 // bus. For purpose of this library it is assumed there is only one device
00143 // on the bus.
00144 
00145 void OneWireThermometer::resetAndAddress() {
00146     oneWire.reset();                // reset device
00147     if (_useAddress) {
00148         oneWire.matchROM(_ROMCode);  // select which device to talk to
00149     } else {
00150         oneWire.skipROM();          // broadcast
00151     }
00152 }
00153 
00154 bool OneWireThermometer::readAndValidateData(BYTE* data) {
00155     bool dataOk = true;
00156 
00157     resetAndAddress();
00158     oneWire.writeByte(DS18X20_READSCRATCH);    // read Scratchpad
00159 
00160     // pc.traceOut("read = ");
00161     for (int i = 0; i < THERMOM_SCRATCHPAD_SIZE; i++) {
00162         // we need all bytes which includes CRC check byte
00163         data[i] = oneWire.readByte();
00164         //   pc.traceOut("%x ", (int)data[i]);
00165     }
00166     //pc.traceOut("\r\n");
00167 
00168     // Check CRC is valid if you want to
00169     if (_useCRC && !(OneWireCRC::crc8(data, THERMOM_CRC_BYTE) == data[THERMOM_CRC_BYTE])) {
00170         // CRC failed
00171         pc.traceOut("CRC FAILED... \r\n");
00172         dataOk = false;
00173     }
00174 
00175     return dataOk;
00176 }
00177 
00178 float OneWireThermometer::readTemperature() {
00179     BYTE data[THERMOM_SCRATCHPAD_SIZE];
00180     float realTemp = -999;
00181     int i = 0;
00182 
00183     do {
00184 
00185         resetAndAddress();
00186         oneWire.writeByte(CONVERT);     // issue Convert command
00187 
00188         if (_useParasiticPower) {
00189             // wait while converting - Tconv (according to resolution of reading)
00190             wait_ms(CONVERSION_TIME[_resolution]);
00191         } else {
00192             // TODO
00193             // after the Convert command, the device should respond by transmitting 0
00194             // while the temperature conversion is in progress and 1 when the conversion is done
00195             // - as were are not checking this (TODO), we use Tconv, as we would do for
00196             // parasitic power
00197             wait_ms(CONVERSION_TIME[_resolution]);
00198         }
00199 
00200         if (readAndValidateData(data)) {  // issue Read Scratchpad commmand and get data
00201             realTemp = calculateTemperature(data);
00202             i++;
00203         }
00204     } while ((realTemp==-999) && (i<5));
00205 
00206     return realTemp;
00207 }