OneWire Temperature library for interfacing DS18B20
Dependents: DallasTemperature project1
OneWireThermometer.cpp
- Committer:
- Wimpie
- Date:
- 2011-04-17
- Revision:
- 0:ad90c2e86a63
File content as of revision 0:ad90c2e86a63:
/* * 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; }