OneWire Temperature library for interfacing DS18B20

Dependents:   DallasTemperature project1

Revision:
0:ad90c2e86a63
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OneWireThermometer.cpp	Sun Apr 17 17:27:20 2011 +0000
@@ -0,0 +1,207 @@
+/*
+* OneWireThermometer. Base class for Maxim One-Wire Thermometers.
+* Uses the OneWireCRC library.
+*
+* Copyright (C) <2010> Petras Saduikis <petras@petras.co.uk>
+*
+* This file is part of OneWireThermometer.
+*
+* OneWireThermometer is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* OneWireThermometer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with OneWireThermometer.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "OneWireThermometer.h"
+#include "OneWireDefs.h"
+#include "DebugTrace.h"
+
+DebugTrace pc(ON, TO_SERIAL);
+
+// constructor specifies standard speed for the 1-Wire comms
+OneWireThermometer::OneWireThermometer(PinName pin, bool crcOn, bool useAddr, bool parasitic, int device_id, unsigned char *ROMaddress)
+        :oneWire(pin, STANDARD) {
+    _useCRC=crcOn;
+    _useAddress=useAddr;
+    _useParasiticPower=parasitic;
+    _deviceId= device_id;
+    _resolution=twelveBit;
+
+    if (_useAddress) {
+        for (int i = 0; i < ADDRESS_SIZE; i++)
+            _ROMCode[i]=ROMaddress[i];
+    } else {
+        for (int i = 0; i < ADDRESS_SIZE; i++)
+            _ROMCode[i]=0;
+    }
+
+    // NOTE: the power-up resolution of a DS18B20 is 12 bits. The DS18S20's resolution is always
+    // 9 bits + enhancement, but we treat the DS18S20 as fixed to 12 bits for calculating the
+    // conversion time Tconv.
+
+}
+
+bool OneWireThermometer::initialize() {
+
+    int OneWireFound;
+    int OneWireSameAddress;
+    int i;
+    BYTE _dummyaddress[8];
+
+
+    if (_useAddress) {
+        pc.traceOut("Scan for device with address ");
+        for (i = 0; i < ADDRESS_SIZE; i++) {
+            pc.traceOut("%x ", (int)_ROMCode[i]);
+        }
+        pc.traceOut("\r\n");
+    }
+    OneWireSameAddress=0;
+
+    oneWire.resetSearch();
+    do {
+        OneWireFound=(oneWire.search(_dummyaddress));
+        if (OneWireFound) {
+
+            if (!_useAddress) {
+                pc.traceOut("Device found with Address = ");
+                for (i = 0; i < ADDRESS_SIZE; i++) {
+                    pc.traceOut("%x ", (int)_dummyaddress[i]);
+                }
+            }
+            OneWireSameAddress=1;
+
+            if (_useAddress) {
+                for (i = 0; i < ADDRESS_SIZE; i++) {
+                    if (!((OneWireSameAddress) && (_ROMCode[i] ==_dummyaddress[i])))
+                        OneWireSameAddress=0;
+                }
+            } else {
+                for (i = 0; i < ADDRESS_SIZE; i++) {
+                    _ROMCode[i] =_dummyaddress[i];
+                }
+            }
+
+            /*           if (OneWireSameAddress) {
+                           pc.traceOut("-> Address valid!\r\n");
+
+                       } else {
+                           pc.traceOut("-> Address NOT valid.\r\n");
+                       }*/
+
+        } else {
+
+            pc.traceOut("No more addresses.\r\n");
+            oneWire.resetSearch();
+            wait_ms(250);  //500
+        }
+    } while (OneWireFound && !OneWireSameAddress);
+
+    if (!OneWireSameAddress) {
+        pc.traceOut("-> No Valid ROM Code found.\r\n");
+        return false;
+    }
+
+    if (OneWireCRC::crc8(_ROMCode, ADDRESS_CRC_BYTE) != _ROMCode[ADDRESS_CRC_BYTE]) { // check address CRC is valid
+        pc.traceOut("CRC is not valid!\r\n");
+        // wait_ms(500);
+        return false;
+    }
+
+    if (_ROMCode[0] != _deviceId) {
+        // Make sure it is a one-wire thermometer device
+        if (DS18B20_ID == _deviceId)
+            pc.traceOut("You need to use a DS1820 or DS18S20 for correct results.\r\n");
+        else if (DS18S20_ID == _deviceId)
+            pc.traceOut("You need to use a DS18B20 for correct results.\r\n");
+        else
+            pc.traceOut("Device is not a DS18B20/DS1820/DS18S20 device.\r\n");
+
+        //  wait_ms(500);
+        return false;
+    } else {
+        if (DS18B20_ID == _deviceId) pc.traceOut("DS18B20 present and correct.\r\n");
+        if (DS18S20_ID == _deviceId) pc.traceOut("DS1820/DS18S20 present and correct.\r\n");
+    }
+
+
+    return true;
+}
+
+// NOTE ON USING SKIP ROM: ok to use before a Convert command to get all
+// devices on the bus to do simultaneous temperature conversions. BUT can
+// only use before a Read Scratchpad command if there is only one device on the
+// bus. For purpose of this library it is assumed there is only one device
+// on the bus.
+
+void OneWireThermometer::resetAndAddress() {
+    oneWire.reset();                // reset device
+    if (_useAddress) {
+        oneWire.matchROM(_ROMCode);  // select which device to talk to
+    } else {
+        oneWire.skipROM();          // broadcast
+    }
+}
+
+bool OneWireThermometer::readAndValidateData(BYTE* data) {
+    bool dataOk = true;
+
+    resetAndAddress();
+    oneWire.writeByte(DS18X20_READSCRATCH);    // read Scratchpad
+
+    // pc.traceOut("read = ");
+    for (int i = 0; i < THERMOM_SCRATCHPAD_SIZE; i++) {
+        // we need all bytes which includes CRC check byte
+        data[i] = oneWire.readByte();
+        //   pc.traceOut("%x ", (int)data[i]);
+    }
+    //pc.traceOut("\r\n");
+
+    // Check CRC is valid if you want to
+    if (_useCRC && !(OneWireCRC::crc8(data, THERMOM_CRC_BYTE) == data[THERMOM_CRC_BYTE])) {
+        // CRC failed
+        pc.traceOut("CRC FAILED... \r\n");
+        dataOk = false;
+    }
+
+    return dataOk;
+}
+
+float OneWireThermometer::readTemperature() {
+    BYTE data[THERMOM_SCRATCHPAD_SIZE];
+    float realTemp = -999;
+    int i = 0;
+
+    do {
+
+        resetAndAddress();
+        oneWire.writeByte(CONVERT);     // issue Convert command
+
+        if (_useParasiticPower) {
+            // wait while converting - Tconv (according to resolution of reading)
+            wait_ms(CONVERSION_TIME[_resolution]);
+        } else {
+            // TODO
+            // after the Convert command, the device should respond by transmitting 0
+            // while the temperature conversion is in progress and 1 when the conversion is done
+            // - as were are not checking this (TODO), we use Tconv, as we would do for
+            // parasitic power
+            wait_ms(CONVERSION_TIME[_resolution]);
+        }
+
+        if (readAndValidateData(data)) {  // issue Read Scratchpad commmand and get data
+            realTemp = calculateTemperature(data);
+            i++;
+        }
+    } while ((realTemp==-999) && (i<5));
+
+    return realTemp;
+}
\ No newline at end of file