OneWire Temperature library for interfacing DS18B20
Dependents: DallasTemperature project1
Diff: OneWireThermometer.cpp
- 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