Руслан Бредун / Mbed 2 deprecated stm32-sensor-base2

Dependencies:   mbed Watchdog

Dependents:   STM32-MC_node

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  * Single sensor.
00009  *
00010  * #include "mbed.h"
00011  * #include "DS1820.h"
00012  * 
00013  * Serial      pc(USBTX, USBRX);
00014  * DigitalOut  led(LED1);
00015  * OneWire     oneWire(D8);    // substitute D8 with actual mbed pin name connected 1-wire bus
00016  * float       temp = 0;
00017  * int         result = 0;
00018  * 
00019  * int main()
00020  * {
00021  *     pc.printf("\r\n--Starting--\r\n");
00022  *     if (ds1820.begin()) {
00023  *         while (1) {
00024  *             ds1820.startConversion();   // start temperature conversion from analog to digital
00025  *             ThisThread::sleep_for(1000);// let DS1820 complete the temperature conversion
00026  *             result = ds1820.read(temp); // read temperature from DS1820 and perform cyclic redundancy check (CRC)
00027  *             switch (result) {
00028  *                 case 0:                 // no errors -> 'temp' contains the value of measured temperature
00029  *                     pc.printf("temp = %3.1f%cC\r\n", temp, 176);
00030  *                     break;
00031  * 
00032  *                 case 1:                 // no sensor present -> 'temp' is not updated
00033  *                     pc.printf("no sensor present\n\r");
00034  *                     break;
00035  * 
00036  *                 case 2:                 // CRC error -> 'temp' is not updated
00037  *                     pc.printf("CRC error\r\n");
00038  *             }
00039  * 
00040  *             led = !led;
00041  *         }
00042  *     }
00043  *     else
00044  *         pc.printf("No DS1820 sensor found!\r\n");
00045  * }
00046  * 
00047  * 
00048  * More sensors connected to the same 1-wire bus.
00049  * 
00050  * #include "mbed.h"
00051  * #include "DS1820.h"
00052  * 
00053  * #define     SENSORS_COUNT   64      // number of DS1820 sensors to be connected to the 1-wire bus (max 256)
00054  * 
00055  * Serial      pc(USBTX, USBRX);
00056  * DigitalOut  led(LED1);
00057  * OneWire     oneWire(D8);            // substitute D8 with actual mbed pin name connected to the DS1820 data pin
00058  * DS1820*     ds1820[SENSORS_COUNT];
00059  * int         sensors_found = 0;      // counts the actually found DS1820 sensors
00060  * float       temp = 0;
00061  * int         result = 0;
00062  * 
00063  * int main() {
00064  *     int i = 0;
00065  *     
00066  *     pc.printf("\r\n Starting \r\n");
00067  *     //Enumerate (i.e. detect) DS1820 sensors on the 1-wire bus
00068  *     for(i = 0; i < SENSORS_COUNT; i++) {
00069  *         ds1820[i] = new DS1820(&oneWire);
00070  *         if(!ds1820[i]->begin()) {
00071  *             delete ds1820[i];
00072  *             break;
00073  *         }
00074  *     }
00075  *     
00076  *     sensors_found = i;
00077  *     
00078  *     if (sensors_found == 0) {
00079  *         pc.printf("No DS1820 sensor found!\r\n");
00080  *         return -1;
00081  *     }
00082  *     else
00083  *         pc.printf("Found %d sensors.\r\n", sensors_found);
00084  *     
00085  *     while(1) {
00086  *         pc.printf("-------------------\r\n");
00087  *         for(i = 0; i < sensors_found; i++)
00088  *             ds1820[i]->startConversion();   // start temperature conversion from analog to digital       
00089  *         ThisThread::sleep_for(1000);        // let DS1820s complete the temperature conversion
00090  *         for(int i = 0; i < sensors_found; i++) {
00091  *             if(ds1820[i]->isPresent())
00092  *                 pc.printf("temp[%d] = %3.1f%cC\r\n", i, ds1820[i]->read(), 176);     // read temperature
00093  *         }
00094  *     }
00095  * }
00096  * 
00097  */
00098  
00099 #include "DS1820.h"
00100 
00101 #define DEBUG 0
00102 
00103 //* Initializing static members
00104 uint8_t DS1820::lastAddr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00105 /**
00106  * @brief   Constructs a generic DS1820 sensor
00107  * @note    begin() must be called to detect and initialize the actual model
00108  * @param   pin: Name of data pin
00109  * @retval
00110  */
00111 DS1820::DS1820(PinName pin, int sample_point_us /* = 13 */) {
00112     oneWire = new OneWire(pin, sample_point_us);
00113     present = false;
00114     model_s = false;
00115 }
00116 
00117 /**
00118  * @brief   Constructs a generic DS1820 sensor
00119  * @note    begin() must be called to detect and initialize the actual model
00120  * @param   pin: Name of data pin
00121  * @retval
00122  */
00123 DS1820::DS1820(OneWire* wire) :
00124     oneWire(wire) {
00125     present = false;
00126     model_s = false;
00127 }
00128 
00129 /**
00130  * @brief   Detects and initializes the actual DS1820 model
00131  * @note
00132  * @param
00133  * @retval  true:   if a DS1820 family sensor was detected and initialized
00134             false:  otherwise
00135  */
00136 bool DS1820::begin(void) {
00137 #if DEBUG
00138     printf("lastAddr =");
00139     for(uint8_t i = 0; i < 8; i++) {
00140         printf(" %x", lastAddr[i]);
00141     }
00142     printf("\r\n");
00143 #endif
00144     if(!oneWire->search(lastAddr)) {
00145 #if DEBUG
00146         printf("No addresses.\r\n");
00147 #endif
00148         oneWire->reset_search();
00149         //ThisThread::sleep_for(250);
00150         wait_ms (250);
00151         return false;
00152     }
00153     
00154     for (int i = 0; i < 8; i++)
00155         addr[i] = lastAddr[i];
00156 
00157 #if DEBUG
00158     printf("ROM =");
00159     for(uint8_t i = 0; i < 8; i++) {
00160         printf(" %x", addr[i]);
00161     }
00162     printf("\r\n");
00163 #endif
00164 
00165     if(OneWire::crc8(addr, 7) == addr[7]) {
00166         present = true;
00167 
00168         // the first ROM byte indicates which chip
00169         switch(addr[0]) {
00170         case 0x10:
00171             model_s = true;
00172 #if DEBUG
00173             printf("DS18S20 or old DS1820\r\n");
00174 #endif            
00175             break;
00176 
00177         case 0x28:
00178             model_s = false;
00179 #if DEBUG
00180             printf("DS18B20\r\n");
00181 #endif            
00182             break;
00183 
00184         case 0x22:
00185             model_s = false;
00186 #if DEBUG
00187             printf("DS1822\r\n");
00188 #endif            
00189             break;
00190 
00191         default:
00192             present = false;
00193 #if DEBUG
00194             printf("Device doesn't belong to the DS1820 family\r\n");
00195 #endif            
00196             return false;
00197         }
00198         return true;
00199     }
00200     else {
00201 #if DEBUG    
00202         printf("Invalid CRC!\r\n");
00203 #endif    
00204         return false;
00205     }
00206 }
00207 
00208 /**
00209  * @brief   Informs about presence of a DS1820 sensor.
00210  * @note    begin() shall be called before using this function
00211  *          if a generic DS1820 instance was created by the user. 
00212  *          No need to call begin() for a specific DS1820 instance.
00213  * @param
00214  * @retval  true:   when a DS1820 sensor is present
00215  *          false:  otherwise
00216  */
00217 bool DS1820::isPresent(void) {
00218     return present;
00219 }
00220 
00221 /**
00222  * @brief   Sets temperature-to-digital conversion resolution.
00223  * @note    The configuration register allows the user to set the resolution
00224  *          of the temperature-to-digital conversion to 9, 10, 11, or 12 bits.
00225  *          Defaults to 12-bit resolution for DS18B20.
00226  *          DS18S20 allows only 9-bit resolution.
00227  * @param   res:    Resolution of the temperature-to-digital conversion in bits.
00228  * @retval
00229  */
00230 void DS1820::setResolution(uint8_t res) {
00231     // keep resolution within limits
00232     if(res > 12)
00233         res = 12;
00234     if(res < 9)
00235         res = 9;      
00236     if(model_s)
00237         res = 9;
00238        
00239     oneWire->reset();
00240     oneWire->select(addr);
00241     oneWire->write_byte(0xBE);            // to read Scratchpad
00242     for(uint8_t i = 0; i < 9; i++)  // read Scratchpad bytes
00243         data[i] = oneWire->read_byte();   
00244 
00245     data[4] |= (res - 9) << 5;      // update configuration byte (set resolution)  
00246     oneWire->reset();
00247     oneWire->select(addr);
00248     oneWire->write_byte(0x4E);            // to write into Scratchpad
00249     for(uint8_t i = 2; i < 5; i++)  // write three bytes (2nd, 3rd, 4th) into Scratchpad
00250         oneWire->write_byte(data[i]);
00251 }
00252 
00253 /**
00254  * @brief   Starts temperature conversion
00255  * @note    The time to complete the converion depends on the selected resolution:
00256  *           9-bit resolution -> max conversion time = 93.75ms
00257  *          10-bit resolution -> max conversion time = 187.5ms
00258  *          11-bit resolution -> max conversion time = 375ms
00259  *          12-bit resolution -> max conversion time = 750ms
00260  * @param
00261  * @retval
00262  */
00263 void DS1820::startConversion(void) {
00264     if(present) {
00265         oneWire->reset();
00266         oneWire->select(addr);
00267         oneWire->write_byte(0x44);    //start temperature conversion
00268     }
00269 }
00270 
00271 /**
00272  * @brief   Reads temperature from the chip's Scratchpad
00273  * @note
00274  * @param
00275  * @retval  Floating point temperature value
00276  */
00277 float DS1820::read(void) {
00278     if(present) {
00279         oneWire->reset();
00280         oneWire->select(addr);
00281         oneWire->write_byte(0xBE);           // to read Scratchpad
00282         for(uint8_t i = 0; i < 9; i++)      // reading scratchpad registers
00283             data[i] = oneWire->read_byte();
00284 
00285         // Convert the raw bytes to a 16-bit unsigned value
00286         uint16_t*   p_word = reinterpret_cast < uint16_t * > (&data[0]);
00287 
00288 #if DEBUG
00289         printf("raw = %#x\r\n", *p_word);
00290 #endif            
00291 
00292         if(model_s) {
00293             *p_word = *p_word << 3;         // 9-bit resolution
00294             if(data[7] == 0x10) {
00295 
00296                 // "count remain" gives full 12-bit resolution
00297                 *p_word = (*p_word & 0xFFF0) + 12 - data[6];
00298             }
00299         }
00300         else {
00301             uint8_t cfg = (data[4] & 0x60); // default 12-bit resolution
00302             
00303             // at lower resolution, the low bits are undefined, so let's clear them
00304             if(cfg == 0x00)
00305                 *p_word = *p_word &~7;      //  9-bit resolution
00306             else
00307             if(cfg == 0x20)
00308                 *p_word = *p_word &~3;      // 10-bit resolution
00309             else
00310             if(cfg == 0x40)
00311                 *p_word = *p_word &~1;      // 11-bit resolution
00312                                                
00313         }
00314 
00315         // Convert the raw bytes to a 16-bit signed fixed point value :
00316         // 1 sign bit, 7 integer bits, 8 fractional bits (two’s compliment
00317         // and the LSB of the 16-bit binary number represents 1/256th of a unit).
00318         *p_word = *p_word << 4;
00319         
00320         // Convert to floating point value
00321         return(toFloat(*p_word));
00322     }
00323     else
00324         return 0;
00325 }
00326 
00327 /**
00328  * @brief   Reads temperature from chip's scratchpad.
00329  * @note    Verifies data integrity by calculating cyclic redundancy check (CRC).
00330  *          If the calculated CRC dosn't match the one stored in chip's scratchpad register
00331  *          the temperature variable is not updated and CRC error code is returned.
00332  * @param   temp: The temperature variable to be updated by this routine.
00333  *                (It's passed as reference to floating point.)
00334  * @retval  error code:
00335  *              0 - no errors ('temp' contains the temperature measured)
00336  *              1 - sensor not present ('temp' is not updated)
00337  *              2 - CRC error ('temp' is not updated)
00338  */
00339 uint8_t DS1820::read(float& temp) {
00340     if(present) {
00341         oneWire->reset();
00342         oneWire->select(addr);
00343         oneWire->write_byte(0xBE);               // to read Scratchpad
00344         for(uint8_t i = 0; i < 9; i++)          // reading scratchpad registers
00345             data[i] = oneWire->read_byte();
00346 
00347         if(oneWire->crc8(data, 8) != data[8])    // if calculated CRC does not match the stored one
00348         {
00349 #if DEBUG
00350             for(uint8_t i = 0; i < 9; i++)
00351                 printf("data[%d]=0x%.2x\r\n", i, data[i]);
00352 #endif            
00353             return 2;                           // return with CRC error
00354         }
00355 
00356         // Convert the raw bytes to a 16bit unsigned value
00357         uint16_t*   p_word = reinterpret_cast < uint16_t * > (&data[0]);
00358 
00359 #if DEBUG
00360         printf("raw = %#x\r\n", *p_word);
00361 #endif
00362 
00363         if(model_s) {
00364             *p_word = *p_word << 3;         // 9 bit resolution,  max conversion time = 750ms
00365             if(data[7] == 0x10) {
00366 
00367                 // "count remain" gives full 12 bit resolution
00368                 *p_word = (*p_word & 0xFFF0) + 12 - data[6];
00369             }
00370 
00371             // Convert the raw bytes to a 16bit signed fixed point value :
00372             // 1 sign bit, 7 integer bits, 8 fractional bits (two's compliment
00373             // and the LSB of the 16bit binary number represents 1/256th of a unit).
00374             *p_word = *p_word << 4;
00375             // Convert to floating point value
00376             temp = toFloat(*p_word);
00377             return 0;   // return with no errors
00378         }
00379         else {
00380             uint8_t cfg = (data[4] & 0x60); // default 12bit resolution, max conversion time = 750ms
00381 
00382             // at lower resolution, the low bits are undefined, so let's clear them
00383             if(cfg == 0x00)
00384                 *p_word = *p_word &~7;      //  9bit resolution, max conversion time = 93.75ms
00385             else
00386             if(cfg == 0x20)
00387                 *p_word = *p_word &~3;      // 10bit resolution, max conversion time = 187.5ms
00388             else
00389             if(cfg == 0x40)
00390                 *p_word = *p_word &~1;      // 11bit resolution, max conversion time = 375ms
00391 
00392             // Convert the raw bytes to a 16bit signed fixed point value :
00393             // 1 sign bit, 7 integer bits, 8 fractional bits (two's complement
00394             // and the LSB of the 16bit binary number represents 1/256th of a unit).
00395             *p_word = *p_word << 4;
00396             // Convert to floating point value
00397             temp = toFloat(*p_word);
00398             return 0;   // return with no errors
00399         }
00400     }
00401     else
00402         return 1;   // error, sensor is not present
00403 }
00404 
00405 /**
00406  * @brief   Converts a 16-bit signed fixed point value to floating point value
00407  * @note    The 16-bit unsigned integer represnts actually
00408  *          a 16-bit signed fixed point value:
00409  *          1 sign bit, 7 integer bits, 8 fractional bits (two’s complement
00410  *          and the LSB of the 16-bit binary number represents 1/256th of a unit).       
00411  * @param   16-bit unsigned integer
00412  * @retval  Floating point value
00413  */
00414 float DS1820::toFloat(uint16_t word) {
00415     if(word & 0x8000)
00416         return (-float(uint16_t(~word + 1)) / 256.0f);
00417     else
00418         return (float(word) / 256.0f);
00419 }
00420