OneWire Temperature library for interfacing DS18B20
Dependents: DallasTemperature project1
Revision 0:ad90c2e86a63, committed 2011-04-17
- Comitter:
- Wimpie
- Date:
- Sun Apr 17 17:27:20 2011 +0000
- Commit message:
- improved 1W search function
Changed in this revision
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