Lucian Corduneanu / DS1820

Dependencies:   OneWire

Fork of DS1820 by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DS1820.cpp Source File

DS1820.cpp

00001 /*
00002  * Dallas' DS1820 family temperature sensor.
00003  * This library depends on the OneWire library (Dallas' 1-Wire bus protocol implementation)
00004  * available at <http://developer.mbed.org/users/hudakz/code/OneWire/>
00005  *
00006  * Example of use:
00007 
00008 #include "mbed.h"
00009 #include "DS1820.h"
00010 
00011 Serial serial(USBTX, USBRX);
00012 
00013 int main() {
00014     serial.baud(115200);
00015     DS1820  ds1820(PB_2);  // substitute PB_2 with actual mbed pin name connected to the DS1820 data pin.
00016 
00017     if(ds1820.begin()) {
00018         ds1820.startConversion();   // start temperature conversion
00019         wait(2.0);                  // let DS1820 complete the temperature conversion
00020         while(1) {
00021             float temp = 0.0;
00022             ds1820.read(temp);
00023             serial.printf("temp = %3.1f\r\n", temp);     // read temperature
00024             ds1820.startConversion();     // start temperature conversion
00025             wait(1.0);                    // let DS1820 complete the temperature conversion
00026         }
00027     } else
00028         serial.printf("No DS1820 sensor found!\r\n");
00029 }
00030 
00031  */
00032 
00033 #include "DS1820.h"
00034 
00035 /**
00036  * @brief   Constructs a generic DS1820 sensor
00037  * @note    begin() must be called to detect and initialize the actual model
00038  * @param   pin: Name of data pin
00039  * @retval
00040  */
00041 DS1820::DS1820(PinName pin) : oneWire(pin) {
00042     present = false;
00043     model_s = false;
00044 }
00045 
00046 /**
00047  * @brief   Constructs a specific model
00048  * @note    No need to call begin() to detect and initialize the model
00049  * @param   model:  One character model name: 'S', 's', 'B' or 'b'
00050  *          pin:    Name of data pin
00051  * @retval
00052  */
00053 DS1820::DS1820(char model, PinName pin) :
00054         oneWire(pin) {
00055     if ((model == 'S') or (model == 's')) {
00056         present = true;
00057         model_s = true;
00058     } else if ((model == 'B') or (model == 'b')) {
00059         present = true;
00060         model_s = false;
00061     } else
00062         present = false;
00063 }
00064 
00065 /**
00066  * @brief   Detects and initializes the actual DS1820 model
00067  * @note
00068  * @param
00069  * @retval  true:   if a DS1820 family sensor was detected and initialized
00070             false:  otherwise
00071  */
00072 bool DS1820::begin(void) {
00073     oneWire.reset_search();
00074     wait_ms(250);
00075     if (!oneWire.search(addr)) {
00076         debug_if(DEBUG, "No addresses.\r\n");
00077         oneWire.reset_search();
00078         wait_ms(250);
00079         return false;
00080     }
00081 
00082     debug_if(DEBUG, "ROM =");
00083     for (uint8_t i = 0; i < 8; i++) {
00084         debug_if(DEBUG, " %x", addr[i]);
00085     }
00086     debug_if(DEBUG, "\r\n");
00087 
00088     if (OneWire::crc8(addr, 7) == addr[7]) {
00089         present = true;
00090 
00091         // the first ROM byte indicates which chip
00092         switch (addr[0]) {
00093             case 0x10:
00094                 model_s = true;
00095                 debug_if(DEBUG, "DS18S20 or old DS1820\r\n");
00096                 break;
00097 
00098             case 0x28:
00099                 model_s = false;
00100                 debug_if(DEBUG, "DS18B20\r\n");
00101                 break;
00102 
00103             case 0x22:
00104                 model_s = false;
00105                 debug_if(DEBUG, "DS1822\r\n");
00106                 break;
00107 
00108             default:
00109                 present = false;
00110                 debug_if(DEBUG, "Device doesn't belong to the DS1820 family\r\n");
00111                 return false;
00112         }
00113         return true;
00114     } else {
00115         return false;
00116     }
00117 }
00118 
00119 /**
00120  * @brief   Informs about presence of a DS1820 sensor.
00121  * @note    begin() shall be called before using this function
00122  *          if a generic DS1820 instance was created by the user.
00123  *          No need to call begin() for a specific DS1820 instance.
00124  * @param
00125  * @retval  true:   when a DS1820 sensor is present
00126  *          false:  otherwise
00127  */
00128 bool DS1820::isPresent(void) {
00129     return present;
00130 }
00131 
00132 /**
00133  * @brief   Sets temperature-to-digital conversion resolution.
00134  * @note    The configuration register allows the user to set the resolution
00135  *          of the temperature-to-digital conversion to 9, 10, 11, or 12 bits.
00136  *          Defaults to 12-bit resolution for DS18B20.
00137  *          DS18S20 allows only 9-bit resolution.
00138  * @param   res:    Resolution of the temperature-to-digital conversion in bits.
00139  * @retval
00140  */
00141 void DS1820::setResolution(uint8_t res) {
00142     // keep resolution within limits
00143     if (res > 12)
00144         res = 12;
00145     if (res < 9)
00146         res = 9;
00147     if (model_s)
00148         res = 9;
00149 
00150     oneWire.reset();
00151     oneWire.skip();
00152     oneWire.write(0xBE);            // to read Scratchpad
00153     for (uint8_t i = 0; i < 9; i++)  // read Scratchpad bytes
00154         data[i] = oneWire.read();
00155 
00156     data[4] |= (res - 9) << 5;      // update configuration byte (set resolution)
00157     oneWire.reset();
00158     oneWire.skip();
00159     oneWire.write(0x4E);            // to write into Scratchpad
00160     for (uint8_t i = 2; i < 5; i++)  // write three bytes (2nd, 3rd, 4th) into Scratchpad
00161         oneWire.write(data[i]);
00162 }
00163 
00164 /**
00165  * @brief   Starts temperature conversion
00166  * @note    The time to complete the converion depends on the selected resolution:
00167  *           9-bit resolution -> max conversion time = 93.75ms
00168  *          10-bit resolution -> max conversion time = 187.5ms
00169  *          11-bit resolution -> max conversion time = 375ms
00170  *          12-bit resolution -> max conversion time = 750ms
00171  * @param
00172  * @retval
00173  */
00174 void DS1820::startConversion(void) {
00175     if (present) {
00176         oneWire.reset();
00177         oneWire.skip();
00178         oneWire.write(0x44);    //start temperature conversion
00179     }
00180 }
00181 
00182 /**
00183  * @brief   Reads temperature from chip's scratchpad.
00184  * @note    Verifies data integrity by calculating cyclic redundancy check (CRC).
00185  *          If the calculated CRC dosn't match the one stored in chip's scratchpad register
00186  *          the temperature variable is not updated and CRC error code is returned.
00187  * @param   temp: The temperature variable to be updated by this routine.
00188  *                (It's passed as reference to floating point.)
00189  * @retval  error code:
00190  *              0 - no errors ('temp' contains the temperature measured)
00191  *              1 - sensor not present ('temp' is not updated)
00192  *              2 - CRC error ('temp' is not updated)
00193  */
00194 uint8_t DS1820::read(float &temp) {
00195     uint16_t temp_uint16 = 0;
00196     uint8_t result = readRaw(temp_uint16);
00197     bool temp_available = 0 == result;
00198 
00199     if (temp_available) {
00200         debug_if(DEBUG, "raw uint16 = 0x%02X \r\n", temp_uint16);
00201         // Convert to floating point value
00202         temp = toFloat(temp_uint16);
00203     }
00204 }
00205 
00206 /**
00207  * @brief   Reads temperature from chip's scratchpad.
00208  * @note    Verifies data integrity by calculating cyclic redundancy check (CRC).
00209  *          If the calculated CRC dosn't match the one stored in chip's scratchpad register
00210  *          the temperature variable is not updated and CRC error code is returned.
00211  * @param   temp: The temperature variable to be updated by this routine.
00212  *                (It's passed as reference to uint16_t)
00213  * @retval  error code:
00214  *              0 - no errors ('temp' contains the temperature measured)
00215  *              1 - sensor not present ('temp' is not updated)
00216  *              2 - CRC error ('temp' is not updated)
00217  */
00218 uint8_t DS1820::readRaw(uint16_t &temp) {
00219     if (present) {
00220         oneWire.reset();
00221         oneWire.skip();
00222         oneWire.write(0xBE);            // to read Scratchpad
00223         for (uint8_t i = 0; i < 9; i++)  // reading scratchpad registers
00224             data[i] = oneWire.read();
00225 
00226         if (oneWire.crc8(data, 8) != data[8])    // if calculated CRC does not match the stored one
00227             return 2;                           // return with CRC error
00228 
00229         // Convert the raw bytes to a 16bit unsigned value
00230         uint16_t *p_word = reinterpret_cast < uint16_t * > (&data[0]);
00231 
00232         debug_if(DEBUG, "raw = %#x\r\n", *p_word);
00233 
00234         if (model_s) {
00235             *p_word = *p_word << 3;         // 9 bit resolution,  max conversion time = 750ms
00236             if (data[7] == 0x10) {
00237 
00238                 // "count remain" gives full 12 bit resolution
00239                 *p_word = (*p_word & 0xFFF0) + 12 - data[6];
00240             }
00241 
00242             // Convert the raw bytes to a 16bit signed fixed point value :
00243             // 1 sign bit, 7 integer bits, 8 fractional bits (two's compliment
00244             // and the LSB of the 16bit binary number represents 1/256th of a unit).
00245             *p_word = *p_word << 4;
00246             // Convert to floating point value
00247             temp = toFloat(*p_word);
00248             return 0;   // return with no errors
00249         } else {
00250             uint8_t cfg = (data[4] & 0x60); // default 12bit resolution, max conversion time = 750ms
00251 
00252             // at lower resolution, the low bits are undefined, so let's clear them
00253             if (cfg == 0x00)
00254                 *p_word = *p_word & ~7;      //  9bit resolution, max conversion time = 93.75ms
00255             else if (cfg == 0x20)
00256                 *p_word = *p_word & ~3;      // 10bit resolution, max conversion time = 187.5ms
00257             else if (cfg == 0x40)
00258                 *p_word = *p_word & ~1;      // 11bit resolution, max conversion time = 375ms
00259 
00260             // Convert the raw bytes to a 16bit signed fixed point value :
00261             // 1 sign bit, 7 integer bits, 8 fractional bits (two's compliment
00262             // and the LSB of the 16bit binary number represents 1/256th of a unit).
00263             *p_word = *p_word << 4;
00264             // Convert to floating point value
00265             temp = *p_word;
00266             return 0;   // return with no errors
00267         }
00268     } else
00269         return 1;   // error, sensor is not present
00270 }
00271 
00272 /**
00273  * @brief   Converts a 16-bit signed fixed point value to floating point value
00274  * @note    The 16-bit unsigned integer represnts actually
00275  *          a 16-bit signed fixed point value:
00276  *          1 sign bit, 7 integer bits, 8 fractional bits (two’s compliment
00277  *          and the LSB of the 16-bit binary number represents 1/256th of a unit).
00278  * @param   16-bit unsigned integer
00279  * @retval  Floating point value
00280  */
00281 float DS1820::toFloat(uint16_t word) {
00282     if (word & 0x8000)
00283         return (-float(uint16_t(~word + 1)) / 256.0f);
00284     else
00285         return (float(word) / 256.0f);
00286 }
00287 
00288