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.

/media/uploads/richardlane/ds18b20_terminal.png

Files at this revision

API Documentation at this revision

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