Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Thu Jul 14 2022 20:23:26 by
1.7.2