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.

Dependencies:   mbed

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(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 }