Interface for Dallas DS18B20 digital thermometer device.
Dependents: WIZ550io_Xively_Demo ESP8266-WEB-Mbed-Controller BrewCtrl Brew_Keg ... more
The output from the example program should look like this.
Revision 0:769f9b2b30d5, committed 2013-07-05
- Comitter:
- richardlane
- Date:
- Fri Jul 05 22:14:08 2013 +0000
- Child:
- 1:00972ed59ba3
- Commit message:
- Initial commit.
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 |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DS18B20.cpp Fri Jul 05 22:14:08 2013 +0000 @@ -0,0 +1,133 @@ +#include "DS18B20.h" + +DS18B20::DS18B20(PinName pin, unsigned resolution) : + _pin(pin) { + SetResolution(resolution); +} + +DS18B20::~DS18B20() { +} + +// Reset 1-wire interface. +unsigned DS18B20::Reset() { + _pin.output(); + _pin = 0; // drive bus low + wait_us(H); + _pin.input(); // release bus + wait_us(I); + unsigned result = _pin; // read bus value + wait_us(J); + return result; +} + +// Write bit to 1-wire. +void DS18B20::WriteBit(unsigned bit) { + _pin.output(); + if (bit) { + _pin = 0; // drive bus low + wait_us(A); // delay A + _pin.input(); // release bus + wait_us(B); // delay B + } else { + _pin = 0; // drive bus low + wait_us(C); // delay C + _pin.input(); // release bus + wait_us(D); // delay D + } +} + +// Read bit from 1-wire. +unsigned DS18B20::ReadBit() { + unsigned bit_value; + _pin.output(); + _pin = 0; // drive bus low + wait_us(A); // delay A + _pin.input(); // release bus + wait_us(E); // delay E + bit_value = _pin; // master sample bus + wait_us(F); + return bit_value; +} + +// Write byte to 1-wire. +void DS18B20::WriteByte(unsigned byte) { + for (unsigned bit = 0; bit < 8; ++bit) { + WriteBit(byte & 0x01); // lsb to msb + byte >>= 1; // right shift by 1-bit + } +} + +// Read byte from 1-wire. +unsigned DS18B20::ReadByte() { + unsigned byte = 0; + for (unsigned bit = 0; bit < 8; ++bit) { + byte |= (ReadBit() << bit); // Reads lsb to msb + } + return byte; +} + +// Set number of bits in the conversion. +unsigned DS18B20::SetResolution(unsigned resolution) { + if (Reset() != 0) + return 1; + else { + WriteByte(SKIP_ROM); // Skip ROM + WriteByte(WRITE_SCRATCHPAD); // WRITE_SCRATCHPAD + WriteByte(0x7f); // Alarm TH + WriteByte(0x80); // Alarm TL + WriteByte(resolution); // 0xx11111 xx=resolution (9-12 bits) + } + return 0; +} + +// Trigger a temperature conversion but don't read the temperature. +unsigned DS18B20::DoConversion() { + if (Reset() != 0) + return 1; + else { + WriteByte(SKIP_ROM); // Skip ROM + WriteByte(CONVERT); // Convert + while (ReadBit() == 0) + ; // wait for conversion to complete + } + return 0; +} + +// Do Conversion and get temperature as s8.4 sign-extended to 16-bits. +int DS18B20::RawTemperature() { + // Perform the temperature conversion. + if (DoConversion() != 0) + return INVALID_TEMPERATURE; + // Read the temperature back. + if (Reset() != 0) + return INVALID_TEMPERATURE; + else { + WriteByte(SKIP_ROM); // Skip ROM + WriteByte(READ_SCRATCHPAD); // Read Scrachpad + unsigned LSB = ReadByte(); + unsigned MSB = ReadByte(); + // Terminate read as we only want temperature + Reset(); + // Ensure correct sign-extension. + return (int)((int16_t)((MSB << 8) | LSB)); + } +} + +// Read temperature in floating point format. +float DS18B20::GetTemperature() { + int temperature = RawTemperature(); + return ((float)temperature) / 16.0; +} + +// Read back DS18B20 ROM. +int DS18B20::ReadROM(DS18B20::ROM_Code_t *ROM_Code) { + if (Reset() != 0) + return 1; + else { + WriteByte(READ_ROM); // Read ROM + for (unsigned i = 0; i < 8; ++i) { + ROM_Code->rom[i] = ReadByte(); + } + } + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DS18B20.h Fri Jul 05 22:14:08 2013 +0000 @@ -0,0 +1,129 @@ +#ifndef DS18B20_H +#define DS18B20_H + +#include "mbed.h" +#include <stdint.h> + +/** A DS18B20 Dallas 1-wire digital thermometer interface. + * + * Currently supports 9, 10, 11 or 12-bit conversions. Fewer bits + * require less conversion time from 93.75ms to 750ms. Also supports + * reading back the 8-byte internal ROM. Orignal code copied from + * DS18B20 C program by Niall Cooling (thanks!) and wrapped in C++ + * class by this library. + * + * @code + * #include "mbed.h" + * #include <stdint.h> + * #include "DS18B20.h" + * + * Serial pc(USBTX, USBRX); // serial comms over usb back to console + * DS18B20 thermom(p16, DS18B20::RES_12_BIT); // Dallas 1-wire + * + * int main() { + * pc.printf("DS18B20 Configuration\n\r"); + * + * DS18B20::ROM_Code_t ROM_Code; + * thermom.ReadROM(&ROM_Code); + * pc.printf("Family code: 0x%X\n\r", ROM_Code.BYTES.familyCode); + * pc.printf("Serial Number: "); + * for (unsigned i = 6; i != 0; --i) { + * pc.printf("%02X%s", ROM_Code.BYTES.serialNo[i-1], (i != 1)?":":"\r\n"); + * } + * pc.printf("CRC: 0x%X\r\n", ROM_Code.BYTES.CRC); + * + * pc.printf("\n\rRunning temperature conversion...\n\r"); + * while (1) { + * pc.printf("Temperature is: %.4fC\n\r", thermom.GetTemperature()); + * wait(10); + * } + * } + * @endcode + */ + +class DS18B20 +{ +public: + /** Value to return when Reset() fails */ + enum {INVALID_TEMPERATURE = -10000}; + + /** Temperature conversion dit width resolutions */ + enum RESOLUTION { RES_9_BIT=0x1f, /**< 93.75ms */ + RES_10_BIT=0x3f, /**< 187.5ms */ + RES_11_BIT=0x5f, /**< 375ms */ + RES_12_BIT=0x7f }; /**< 750ms */ + + /** Holds 8-byte internal ROM */ + typedef union { + uint8_t rom[8]; + struct { + uint8_t familyCode; /**< Family Code */ + uint8_t serialNo[6]; /**< Serial Number */ + uint8_t CRC; /**< CRC check byte */ + } BYTES; + } ROM_Code_t; + + /** Device onboard register layout (for reference only, not currently used) */ + typedef struct { + uint8_t LSB; /**< LSB of converted temperature */ + uint8_t MSB; /**< MSB of converted temperature */ + uint8_t Th; /**< Threshold for high alarm */ + uint8_t Tl; /**< Threshold for low alarm */ + uint8_t config; /**< Conversion resultion */ + uint8_t reserved0xFF; + uint8_t reserved0xCH; + uint8_t reserved0x10; + uint8_t CRC; /**< CRC check byte */ + } ScratchPad_t; + + /** Create a Dallas DS18B20 1-wire interface + * + * @param pin Pin to use for 1-wire interface (bidirectional I/O) + * @param resolution Sets the conversion bit width (using RESOLUTION enum) + */ + DS18B20(PinName pin, unsigned resolution); + + /** Destructor */ + ~DS18B20(); + + /** Performs conversion in DS18B20 and then reads and converts returned temperature + * to floating point. For many applications this is the only required method that + * needs to be used. + */ + float GetTemperature(); + + /** Performs conversion but does not read back temperature. Not needed if + * GetTemperature() is used as this calls DoConversion() itself. */ + unsigned DoConversion(); + + /** The method that GetTemperature() calls to do all the conversion and reading + * but this method returns a 32-bit signed integer. The integer contains 4 + * fractional LSBs. Sometimes referred to as s28.4 format. */ + int RawTemperature(); + + /** Reads and returns the 8-byte internal ROM */ + int ReadROM(ROM_Code_t *ROM_Code); + + /** Sets the conversion resolution with RESOLUTION enum (9-12 bits signed) */ + unsigned SetResolution(unsigned resolution); + +protected: + + // Timing delay for 1-wire serial standard option + enum DELAY { A = 6, B = 64, C = 60, D = 10, E = 9, F = 55, G = 0, H = 480, I = 70, J = 410 }; + + // Device byte commands over 1-wire serial + enum COMMANDS { READ_ROM = 0x33, CONVERT = 0x44, READ_SCRATCHPAD = 0xBE, WRITE_SCRATCHPAD = 0x4E, SKIP_ROM = 0xCC }; + + // Methods from DS1Wire.h + unsigned Reset(); + void WriteBit(unsigned bit); + unsigned ReadBit(); + void WriteByte(unsigned byte); + unsigned ReadByte(); + + // The pin used for the Dallas 1-wire interface + DigitalInOut _pin; +}; + +#endif