OneWire Temperature library for interfacing DS18B20

Dependents:   DallasTemperature project1

Files at this revision

API Documentation at this revision

Comitter:
Wimpie
Date:
Sun Apr 17 17:27:20 2011 +0000
Commit message:
improved 1W search function

Changed in this revision

DS18B20.cpp Show annotated file Show diff for this revision Revisions of this file
DS18B20.h Show annotated file Show diff for this revision Revisions of this file
OneWireDefs.h Show annotated file Show diff for this revision Revisions of this file
OneWireThermometer.cpp Show annotated file Show diff for this revision Revisions of this file
OneWireThermometer.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r ad90c2e86a63 DS18B20.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DS18B20.cpp	Sun Apr 17 17:27:20 2011 +0000
@@ -0,0 +1,95 @@
+/*
+* DS18B20. Maxim DS18B20 One-Wire Thermometer.
+* 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 "DS18B20.h"
+#include "DebugTrace.h"
+
+DebugTrace pc_ds18B20(OFF, TO_SERIAL);
+
+DS18B20::DS18B20(PinName pin,bool crcOn, bool useAddr, bool parasitic, unsigned char *Address) :
+        OneWireThermometer(pin, crcOn, useAddr, parasitic, DS18B20_ID, Address) {
+}
+
+void DS18B20::setResolution(eResolution resln) {
+    // as the write to the configuration register involves a write to the
+    // high and low alarm bytes, need to read these registers first
+    // and copy them back on the write
+
+    BYTE read_data[THERMOM_SCRATCHPAD_SIZE];
+    BYTE write_data[ALARM_CONFIG_SIZE];
+
+    if (readAndValidateData(read_data)) {
+        // copy alarm and config data to write data
+        for (int k = 2; k < 5; k++) {
+            write_data[k - 2] = read_data[k];
+        }
+        int config = write_data[2];
+        config &= 0x9F;
+        config ^= (resln << 5);
+        write_data[2] = config;
+
+        resetAndAddress();
+        oneWire.writeByte(DS18X20_WRITESCRATCH);
+        for (int k = 0; k < 3; k++) {
+            oneWire.writeByte(write_data[k]);
+        }
+
+        // remember it so we can use the correct delay in reading the temperature
+        // for parasitic power
+        _resolution = resln;
+    }
+}
+
+float DS18B20::calculateTemperature(BYTE* data) {
+    bool signBit = false;
+    if (data[TEMPERATURE_MSB] & 0x80) signBit = true;
+
+    int read_temp = (data[TEMPERATURE_MSB] << 8) + data[TEMPERATURE_LSB];
+    if (signBit) {
+        read_temp = (read_temp ^ 0xFFFF) + 1;    // two's complement
+        read_temp *= -1;
+    }
+
+    int resolution = (data[CONFIG_REG_BYTE] & 0x60) >> 5; // mask off bits 6,5 and move to 1,0
+    switch (resolution) {
+        case nineBit:    // 0.5 deg C increments
+            read_temp &= 0xFFF8;                // bits 2,1,0 are undefined
+            pc_ds18B20.traceOut("9 bit resolution ...\r\n");
+            break;
+        case tenBit:     // 0.25 deg C increments
+            read_temp &= 0xFFFC;                // bits 1,0 are undefined
+            pc_ds18B20.traceOut("10 bit resolution ...\r\n");
+            break;
+        case elevenBit:  // 0.125 deg C increments
+            read_temp &= 0xFFFE;                // bit 0 is undefined
+            pc_ds18B20.traceOut("11 bit resolution ...\r\n");
+            break;
+        case twelveBit:  // 0.0625 deg C increments
+            pc_ds18B20.traceOut("12 bit resolution ...\r\n");
+            break;
+    }
+    float realTemp = (float)read_temp/16 ;
+
+    pc_ds18B20.traceOut("TEMP_READ/REAL TEMP: %f \r\n", realTemp);
+
+    return realTemp;
+}
\ No newline at end of file
diff -r 000000000000 -r ad90c2e86a63 DS18B20.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DS18B20.h	Sun Apr 17 17:27:20 2011 +0000
@@ -0,0 +1,41 @@
+/*
+* DS18B20. Maxim DS18B20 One-Wire Thermometer. 
+* 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/>.
+*/
+
+#ifndef SNATCH59_DS18B20_H
+#define SNATCH59_DS18B20_H
+
+#include "OneWireThermometer.h"
+#include "OneWireDefs.h"
+
+class DS18B20 : public OneWireThermometer
+{
+public:
+    DS18B20(PinName pin,bool crcOn, bool useAddr, bool parasitic,unsigned char *Address);
+    
+    virtual void setResolution(eResolution resln);
+    
+protected:
+    virtual float calculateTemperature(BYTE* data);
+};
+
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r ad90c2e86a63 OneWireDefs.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OneWireDefs.h	Sun Apr 17 17:27:20 2011 +0000
@@ -0,0 +1,68 @@
+/*
+* OneWireCRC. This is a port to mbed of Jim Studt's Adruino One Wire
+* library.
+*
+* Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk>
+* Added Wim
+ * This file is part of OneWireCRC.
+*
+* OneWireCRC 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.
+* 
+* OneWireCRC 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 OneWireCRC.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _ONEWIREDEFS_H
+#define _ONEWIREDEFS_H
+
+// device ids
+#define DS18B20_ID        0x28
+#define DS18S20_ID        0x10
+
+#define ALARM_CONFIG_SIZE 3
+#define THERMOM_SCRATCHPAD_SIZE    9
+#define THERMOM_CRC_BYTE  8
+#define ADDRESS_SIZE      8
+#define ADDRESS_CRC_BYTE  7
+
+// One Wire command codes
+#define OVERDRIVE_SKIP    0x3C
+// ROM commands
+#define SEARCH_ROM         0xF0
+#define READ_ROM           0x33
+#define MATCH_ROM          0x55
+#define SKIP_ROM           0xCC
+#define OVERDRIVESKIP_ROM  0x3C
+#define OVERDRIVEMATCH_ROM 0x69
+#define ALARM_SEARCH       0xEC
+// Functions Commnds
+#define CONVERT            0x44
+#define RECALLE2           0xB8
+#define READPOWERSUPPLY    0xB4
+
+// temperature read resolutions
+enum eResolution {nineBit = 0, tenBit, elevenBit, twelveBit};
+const int CONVERSION_TIME[] = {94, 188, 375, 750};    // milli-seconds
+
+// DS18B20/DS18S20 related
+#define DS18X20_WRITESCRATCH      0x4E
+#define DS18X20_READSCRATCH       0xBE
+#define DS18X20_COPYSCRATCH       0x48
+#define TEMPERATURE_LSB    0
+#define TEMPERATURE_MSB    1
+#define HIGH_ALARM_BYTE    2
+#define LOW_ALARM_BYTE     3
+#define CONFIG_REG_BYTE    4
+#define CONFIG_READ_END    5
+#define COUNT_REMAIN_BYTE  6
+#define COUNT_PER_DEG_BYTE 7
+
+#endif
diff -r 000000000000 -r ad90c2e86a63 OneWireThermometer.cpp
--- /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
diff -r 000000000000 -r ad90c2e86a63 OneWireThermometer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OneWireThermometer.h	Sun Apr 17 17:27:20 2011 +0000
@@ -0,0 +1,57 @@
+/*
+* 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/>.
+*/
+
+#ifndef SNATCH59_ONEWIRETHERMOMETER_H
+#define SNATCH59_ONEWIRETHERMOMETER_H
+
+#include "mbed.h"
+#include "OneWireCRC.h"
+#include "OneWireDefs.h"
+
+typedef unsigned char BYTE;    // something a byte wide
+
+class OneWireThermometer {
+public:
+    OneWireThermometer(PinName pin, bool crcOn, bool useAddr, bool parasitic,  int device_id, unsigned char *Address );
+
+    bool initialize();
+    float readTemperature();
+    virtual void setResolution(eResolution resln) = 0;
+
+protected:
+    bool _useParasiticPower;
+    bool _useCRC;
+    bool _useAddress;
+    int _deviceId;
+
+    eResolution _resolution;
+    BYTE _ROMCode[8];
+     
+
+    OneWireCRC oneWire;
+
+    void resetAndAddress();
+    bool readAndValidateData(BYTE* data);
+    virtual float calculateTemperature(BYTE* data) = 0;    // device specific
+};
+
+#endif
\ No newline at end of file