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 * wait(1.0); // 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 * wait(1.0); // 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) { 00112 oneWire = new OneWire(pin); 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 wait_ms(250); 00150 return false; 00151 } 00152 00153 for (int i = 0; i < 8; i++) 00154 addr[i] = lastAddr[i]; 00155 00156 #if DEBUG 00157 printf("ROM ="); 00158 for(uint8_t i = 0; i < 8; i++) { 00159 printf(" %x", addr[i]); 00160 } 00161 printf("\r\n"); 00162 #endif 00163 00164 if(OneWire::crc8(addr, 7) == addr[7]) { 00165 present = true; 00166 00167 // the first ROM byte indicates which chip 00168 switch(addr[0]) { 00169 case 0x10: 00170 model_s = true; 00171 #if DEBUG 00172 printf("DS18S20 or old DS1820\r\n"); 00173 #endif 00174 break; 00175 00176 case 0x28: 00177 model_s = false; 00178 #if DEBUG 00179 printf("DS18B20\r\n"); 00180 #endif 00181 break; 00182 00183 case 0x22: 00184 model_s = false; 00185 #if DEBUG 00186 printf("DS1822\r\n"); 00187 #endif 00188 break; 00189 00190 default: 00191 present = false; 00192 #if DEBUG 00193 printf("Device doesn't belong to the DS1820 family\r\n"); 00194 #endif 00195 return false; 00196 } 00197 return true; 00198 } 00199 else { 00200 #if DEBUG 00201 printf("Invalid CRC!\r\n"); 00202 #endif 00203 return false; 00204 } 00205 } 00206 00207 /** 00208 * @brief Informs about presence of a DS1820 sensor. 00209 * @note begin() shall be called before using this function 00210 * if a generic DS1820 instance was created by the user. 00211 * No need to call begin() for a specific DS1820 instance. 00212 * @param 00213 * @retval true: when a DS1820 sensor is present 00214 * false: otherwise 00215 */ 00216 bool DS1820::isPresent(void) { 00217 return present; 00218 } 00219 00220 /** 00221 * @brief Sets temperature-to-digital conversion resolution. 00222 * @note The configuration register allows the user to set the resolution 00223 * of the temperature-to-digital conversion to 9, 10, 11, or 12 bits. 00224 * Defaults to 12-bit resolution for DS18B20. 00225 * DS18S20 allows only 9-bit resolution. 00226 * @param res: Resolution of the temperature-to-digital conversion in bits. 00227 * @retval 00228 */ 00229 void DS1820::setResolution(uint8_t res) { 00230 // keep resolution within limits 00231 if(res > 12) 00232 res = 12; 00233 if(res < 9) 00234 res = 9; 00235 if(model_s) 00236 res = 9; 00237 00238 oneWire->reset(); 00239 oneWire->select(addr); 00240 oneWire->write_byte(0xBE); // to read Scratchpad 00241 for(uint8_t i = 0; i < 9; i++) // read Scratchpad bytes 00242 data[i] = oneWire->read_byte(); 00243 00244 data[4] |= (res - 9) << 5; // update configuration byte (set resolution) 00245 oneWire->reset(); 00246 oneWire->select(addr); 00247 oneWire->write_byte(0x4E); // to write into Scratchpad 00248 for(uint8_t i = 2; i < 5; i++) // write three bytes (2nd, 3rd, 4th) into Scratchpad 00249 oneWire->write_byte(data[i]); 00250 } 00251 00252 /** 00253 * @brief Starts temperature conversion 00254 * @note The time to complete the converion depends on the selected resolution: 00255 * 9-bit resolution -> max conversion time = 93.75ms 00256 * 10-bit resolution -> max conversion time = 187.5ms 00257 * 11-bit resolution -> max conversion time = 375ms 00258 * 12-bit resolution -> max conversion time = 750ms 00259 * @param 00260 * @retval 00261 */ 00262 void DS1820::startConversion(void) { 00263 if(present) { 00264 oneWire->reset(); 00265 oneWire->select(addr); 00266 oneWire->write_byte(0x44); //start temperature conversion 00267 } 00268 } 00269 00270 /** 00271 * @brief Reads temperature from the chip's Scratchpad 00272 * @note 00273 * @param 00274 * @retval Floating point temperature value 00275 */ 00276 float DS1820::read(void) { 00277 if(present) { 00278 oneWire->reset(); 00279 oneWire->select(addr); 00280 oneWire->write_byte(0xBE); // to read Scratchpad 00281 for(uint8_t i = 0; i < 9; i++) // reading scratchpad registers 00282 data[i] = oneWire->read_byte(); 00283 00284 // Convert the raw bytes to a 16-bit unsigned value 00285 uint16_t* p_word = reinterpret_cast < uint16_t * > (&data[0]); 00286 00287 #if DEBUG 00288 printf("raw = %#x\r\n", *p_word); 00289 #endif 00290 00291 if(model_s) { 00292 *p_word = *p_word << 3; // 9-bit resolution 00293 if(data[7] == 0x10) { 00294 00295 // "count remain" gives full 12-bit resolution 00296 *p_word = (*p_word & 0xFFF0) + 12 - data[6]; 00297 } 00298 } 00299 else { 00300 uint8_t cfg = (data[4] & 0x60); // default 12-bit resolution 00301 00302 // at lower resolution, the low bits are undefined, so let's clear them 00303 if(cfg == 0x00) 00304 *p_word = *p_word &~7; // 9-bit resolution 00305 else 00306 if(cfg == 0x20) 00307 *p_word = *p_word &~3; // 10-bit resolution 00308 else 00309 if(cfg == 0x40) 00310 *p_word = *p_word &~1; // 11-bit resolution 00311 00312 } 00313 00314 // Convert the raw bytes to a 16-bit signed fixed point value : 00315 // 1 sign bit, 7 integer bits, 8 fractional bits (two’s compliment 00316 // and the LSB of the 16-bit binary number represents 1/256th of a unit). 00317 *p_word = *p_word << 4; 00318 00319 // Convert to floating point value 00320 return(toFloat(*p_word)); 00321 } 00322 else 00323 return 0; 00324 } 00325 00326 /** 00327 * @brief Reads temperature from chip's scratchpad. 00328 * @note Verifies data integrity by calculating cyclic redundancy check (CRC). 00329 * If the calculated CRC dosn't match the one stored in chip's scratchpad register 00330 * the temperature variable is not updated and CRC error code is returned. 00331 * @param temp: The temperature variable to be updated by this routine. 00332 * (It's passed as reference to floating point.) 00333 * @retval error code: 00334 * 0 - no errors ('temp' contains the temperature measured) 00335 * 1 - sensor not present ('temp' is not updated) 00336 * 2 - CRC error ('temp' is not updated) 00337 */ 00338 uint8_t DS1820::read(float& temp) { 00339 if(present) { 00340 oneWire->reset(); 00341 oneWire->select(addr); 00342 oneWire->write_byte(0xBE); // to read Scratchpad 00343 for(uint8_t i = 0; i < 9; i++) // reading scratchpad registers 00344 data[i] = oneWire->read_byte(); 00345 00346 if(oneWire->crc8(data, 8) != data[8]) // if calculated CRC does not match the stored one 00347 { 00348 #if DEBUG 00349 for(uint8_t i = 0; i < 9; i++) 00350 printf("data[%d]=0x%.2x\r\n", i, data[i]); 00351 #endif 00352 return 2; // return with CRC error 00353 } 00354 00355 // Convert the raw bytes to a 16bit unsigned value 00356 uint16_t* p_word = reinterpret_cast < uint16_t * > (&data[0]); 00357 00358 #if DEBUG 00359 printf("raw = %#x\r\n", *p_word); 00360 #endif 00361 00362 if(model_s) { 00363 *p_word = *p_word << 3; // 9 bit resolution, max conversion time = 750ms 00364 if(data[7] == 0x10) { 00365 00366 // "count remain" gives full 12 bit resolution 00367 *p_word = (*p_word & 0xFFF0) + 12 - data[6]; 00368 } 00369 00370 // Convert the raw bytes to a 16bit signed fixed point value : 00371 // 1 sign bit, 7 integer bits, 8 fractional bits (two's compliment 00372 // and the LSB of the 16bit binary number represents 1/256th of a unit). 00373 *p_word = *p_word << 4; 00374 // Convert to floating point value 00375 temp = toFloat(*p_word); 00376 return 0; // return with no errors 00377 } 00378 else { 00379 uint8_t cfg = (data[4] & 0x60); // default 12bit resolution, max conversion time = 750ms 00380 00381 // at lower resolution, the low bits are undefined, so let's clear them 00382 if(cfg == 0x00) 00383 *p_word = *p_word &~7; // 9bit resolution, max conversion time = 93.75ms 00384 else 00385 if(cfg == 0x20) 00386 *p_word = *p_word &~3; // 10bit resolution, max conversion time = 187.5ms 00387 else 00388 if(cfg == 0x40) 00389 *p_word = *p_word &~1; // 11bit resolution, max conversion time = 375ms 00390 00391 // Convert the raw bytes to a 16bit signed fixed point value : 00392 // 1 sign bit, 7 integer bits, 8 fractional bits (two's complement 00393 // and the LSB of the 16bit binary number represents 1/256th of a unit). 00394 *p_word = *p_word << 4; 00395 // Convert to floating point value 00396 temp = toFloat(*p_word); 00397 return 0; // return with no errors 00398 } 00399 } 00400 else 00401 return 1; // error, sensor is not present 00402 } 00403 00404 /** 00405 * @brief Converts a 16-bit signed fixed point value to floating point value 00406 * @note The 16-bit unsigned integer represnts actually 00407 * a 16-bit signed fixed point value: 00408 * 1 sign bit, 7 integer bits, 8 fractional bits (two’s complement 00409 * and the LSB of the 16-bit binary number represents 1/256th of a unit). 00410 * @param 16-bit unsigned integer 00411 * @retval Floating point value 00412 */ 00413 float DS1820::toFloat(uint16_t word) { 00414 if(word & 0x8000) 00415 return (-float(uint16_t(~word + 1)) / 256.0f); 00416 else 00417 return (float(word) / 256.0f); 00418 } 00419
Generated on Fri Jul 22 2022 18:19:23 by
1.7.2