MAX31850, DS18B20, DS2450, thermocouple
Embed:
(wiki syntax)
Show/hide line numbers
DS18X20.cpp
00001 /** 00002 * @file DS18x20.c 00003 * @brief library of DS18X20 1-Wire digital thermometer (http://www.maxim-ic.com/datasheet/index.mvp/id/2812) 00004 * @author Maciej Rajtar (Published 10 May 2010 www.mbed.org) 00005 * @author Frederic BLANC (Published 01/03/2012 www.mbed.org) 00006 */ 00007 #include "mbed.h" 00008 #include "onewire.h" 00009 #include "DS18X20.h" 00010 #include "crc8.h" 00011 #include "utils.h" 00012 //********************************************************************************************************** 00013 //* DS18X20_show_temp 00014 //********************************************************************************************************** 00015 00016 /** 00017 * @brief DS18X20_show_temp 00018 * @param [in] id[] = rom_code 00019 * @param [in] n number of id[n] 00020 * @param [out] text temp in degre celsius 00021 00022 * @date 20/06/2011 00023 */ 00024 void DS18X20_show_temp(uint8_t subzero, uint8_t cel, uint8_t cel_frac_bits,char *text) { 00025 uint16_t decicelsius; 00026 char s[10]; 00027 float temperature; 00028 sprintf(text,""); 00029 sprintf(s,"%s", (subzero)?"-":""); 00030 strcat(text,s); 00031 decicelsius = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits); 00032 temperature = decicelsius; 00033 temperature = temperature/10; 00034 sprintf(s,"%4.1f", temperature); 00035 strcat(text,s); 00036 00037 } 00038 /** 00039 * @brief DS18X20_show_temp 00040 * @param [in] id[] = rom_code 00041 * @param [in] n number of id[n] 00042 * @return temp in degre celsius 00043 00044 * @date 21/10/2011 00045 */ 00046 float DS18X20_temp(uint8_t subzero, uint8_t cel, uint8_t cel_frac_bits) { 00047 return ((subzero)?-1:1)*DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits)/10; 00048 } 00049 //********************************************************************************************************** 00050 //* DS18X20_get_power_status 00051 //********************************************************************************************************** 00052 00053 /** 00054 * @brief get power status of DS18x20 00055 * @param [in] id[] = rom_code 00056 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE 00057 * @date 20/06/2011 00058 */ 00059 uint8_t DS18X20_get_power_status(uint8_t id[]) { 00060 uint8_t pstat; 00061 ow_reset(); 00062 ow_command(DS18X20_READ_POWER_SUPPLY, id); 00063 pstat=ow_bit_io(1); // pstat 0=is parasite/ !=0 ext. powered 00064 ow_reset(); 00065 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE; 00066 } 00067 00068 /** 00069 * @brief get power status of DS18x20 00070 * @param [in] n num bus onewire 00071 * @param [in] id[] = rom_code 00072 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE 00073 * @date 6/09/2011 00074 */ 00075 uint8_t DS18X20_get_power_status(uint8_t n,uint8_t id[]) { 00076 uint8_t pstat; 00077 ow_reset(n); 00078 ow_command(n,DS18X20_READ_POWER_SUPPLY, id); 00079 pstat=ow_bit_io(n,1); // pstat 0=is parasite/ !=0 ext. powered 00080 ow_reset(n); 00081 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE; 00082 } 00083 //********************************************************************************************************** 00084 //* DS18X20_start_meas 00085 //********************************************************************************************************** 00086 /** 00087 * @brief reads temperature (scratchpad) of sensor with rom-code id 00088 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00089 in millicelsius*0.1 00090 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00091 * @param [in] n num bus onewire 00092 * @param [in] id[] = rom_code 00093 * @param [out] temperature 00094 * @return DS18X20_OK or DS18X20_ERROR_CRC 00095 * @date 07/12/2012 00096 */ 00097 uint8_t DS18X20_read_meas(uint8_t n,uint8_t id[], float* temperature) { 00098 uint8_t i; 00099 uint8_t sp[DS18X20_SP_SIZE]; 00100 uint8_t subzero; 00101 uint8_t cel; 00102 uint8_t cel_frac_bits; 00103 00104 ow_reset(n); 00105 ow_command(n,DS18X20_READ, id); 00106 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00107 sp[i]=ow_byte_rd(n); 00108 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00109 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00110 return OW_ERROR; // bus error 00111 return DS18X20_ERROR_CRC; // data error 00112 } 00113 00114 DS18X20_meas_to_cel(id[0], sp, &subzero, &cel, &cel_frac_bits); 00115 *temperature = cel_frac_bits*.0625; 00116 *temperature += cel; 00117 if (subzero) 00118 *temperature *= -1; 00119 return DS18X20_OK; 00120 } 00121 /** 00122 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL 00123 or for single sensor. then id is the rom-code 00124 * @param [in] with_power_extern 00125 * @param [in] rom_code 00126 * @return DS18X20_OK or DS18X20_START_FAIL 00127 * @date 20/06/2011 00128 */ 00129 uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[]) { 00130 ow_reset(); //** 00131 if ( ow_test_pin() ) { // only send if bus is "idle" = high 00132 ow_command( DS18X20_CONVERT_T, id ); 00133 if (with_power_extern != DS18X20_POWER_EXTERN) 00134 ow_parasite_enable(); 00135 return DS18X20_OK; 00136 } 00137 return DS18X20_START_FAIL; 00138 00139 } 00140 /** 00141 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL 00142 or for single sensor. then id is the rom-code 00143 * @param [in] n num bus onewire 00144 * @param [in] with_power_extern 00145 * @param [in] rom_code 00146 * @return DS18X20_OK or DS18X20_START_FAIL 00147 * @date 06/09/2011 00148 */ 00149 uint8_t DS18X20_start_meas(uint8_t n, uint8_t with_power_extern, uint8_t id[]) { 00150 ow_reset(n); //** 00151 if ( ow_test_pin(n) ) { // only send if bus is "idle" = high 00152 ow_command(n, DS18X20_CONVERT_T, id ); 00153 if (with_power_extern != DS18X20_POWER_EXTERN) 00154 ow_parasite_enable(n); 00155 return DS18X20_OK; 00156 } 00157 return DS18X20_START_FAIL; 00158 00159 } 00160 //********************************************************************************************************** 00161 //* DS18X20_read_meas 00162 //********************************************************************************************************** 00163 00164 /** 00165 * @brief reads temperature (scratchpad) of sensor with rom-code id 00166 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00167 in millicelsius*0.1 00168 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00169 * @param [in] id[] = rom_code 00170 * @param [out] subzero 00171 * @param [out] cel 00172 * @param [out] cel_frac_bits 00173 * @return DS18X20_OK or DS18X20_ERROR_CRC 00174 * @date 20/06/2011 00175 */ 00176 uint8_t DS18X20_read_meas(uint8_t id[], uint8_t *subzero, 00177 uint8_t *cel, uint8_t *cel_frac_bits) { 00178 uint8_t i; 00179 uint8_t sp[DS18X20_SP_SIZE]; 00180 00181 ow_reset(); 00182 ow_command(DS18X20_READ, id); 00183 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00184 sp[i]=ow_byte_rd(); 00185 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00186 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00187 return OW_ERROR; // bus error 00188 return DS18X20_ERROR_CRC; // data error 00189 } 00190 00191 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits); 00192 return DS18X20_OK; 00193 } 00194 /** 00195 * @brief reads temperature (scratchpad) of sensor with rom-code id 00196 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00197 in millicelsius*0.1 00198 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00199 * @param [in] n num bus onewire 00200 * @param [in] id[] = rom_code 00201 * @param [out] subzero 00202 * @param [out] cel 00203 * @param [out] cel_frac_bits 00204 * @return DS18X20_OK or DS18X20_ERROR_CRC 00205 * @date 06/09/2011 00206 */ 00207 uint8_t DS18X20_read_meas(uint8_t n,uint8_t id[], uint8_t *subzero, 00208 uint8_t *cel, uint8_t *cel_frac_bits) { 00209 uint8_t i; 00210 uint8_t sp[DS18X20_SP_SIZE]; 00211 00212 ow_reset(n); 00213 ow_command(n,DS18X20_READ, id); 00214 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00215 sp[i]=ow_byte_rd(n); 00216 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00217 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00218 return OW_ERROR; // bus error 00219 return DS18X20_ERROR_CRC; // data error 00220 } 00221 00222 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits); 00223 return DS18X20_OK; 00224 } 00225 /** 00226 * @brief convert raw value from DS18x20 to Celsius 00227 input is: 00228 - familycode fc (0x10/0x28 see header) 00229 - scratchpad-buffer 00230 output is: 00231 - cel full celsius 00232 - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits) 00233 - subzero =0 positiv / 1 negativ 00234 always returns DS18X20_OK 00235 TODO invalid-values detection (but should be covered by CRC) 00236 * @param [in] fc 00237 * @param [in] sp 00238 * @param [out] subzero 00239 * @param [out] cel 00240 * @param [out] cel_frac_bits 00241 * @return DS18X20_OK 00242 * @date 20/06/2011 00243 */ 00244 uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp, 00245 uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits) { 00246 uint16_t meas; 00247 uint8_t i; 00248 00249 meas = sp[0]; // LSB 00250 meas |= ((uint16_t)sp[1])<<8; // MSB 00251 //meas = 0xff5e; meas = 0xfe6f; 00252 00253 // only work on 12bit-base 00254 if ( fc == DS18S20_ID ) { // 9 -> 12 bit if 18S20 00255 /* Extended measurements for DS18S20 contributed by Carsten Foss */ 00256 meas &= (uint16_t) 0xfffe; // Discard LSB , needed for later extended precicion calc 00257 meas <<= 3; // Convert to 12-bit , now degrees are in 1/16 degrees units 00258 meas += (16 - sp[6]) - 4; // Add the compensation , and remember to subtract 0.25 degree (4/16) 00259 } 00260 00261 // check for negative 00262 if ( meas & 0x8000 ) { 00263 *subzero=1; // mark negative 00264 meas ^= 0xffff; // convert to positive => (twos complement)++ 00265 meas++; 00266 } else *subzero=0; 00267 00268 // clear undefined bits for B != 12bit 00269 if ( fc == DS18B20_ID ) { // check resolution 18B20 00270 i = sp[DS18B20_CONF_REG]; 00271 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) ; 00272 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) 00273 meas &= ~(DS18B20_11_BIT_UNDF); 00274 else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) 00275 meas &= ~(DS18B20_10_BIT_UNDF); 00276 else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) { 00277 meas &= ~(DS18B20_9_BIT_UNDF); 00278 } 00279 } 00280 00281 *cel = (uint8_t)(meas >> 4); 00282 *cel_frac_bits = (uint8_t)(meas & 0x000F); 00283 00284 return DS18X20_OK; 00285 } 00286 00287 /** 00288 * @brief converts to decicelsius 00289 input is ouput from meas_to_cel 00290 i.e.: sz=0, c=28, frac=15 returns 289 (=28.9�C) 00291 0 0 0 00292 1 625 625 1 00293 2 1250 250 00294 3 1875 875 3 00295 4 2500 500 4 00296 5 3125 125 00297 6 3750 750 6 00298 7 4375 375 00299 8 5000 0 00300 9 5625 625 9 00301 10 6250 250 00302 11 6875 875 11 00303 12 7500 500 12 00304 13 8125 125 00305 14 8750 750 14 00306 15 9375 375 00307 * @param [in] subzero 00308 * @param [in] cel 00309 * @param [in] cel_frac_bits 00310 * @return absolute value of temperatur in decicelsius 00311 * @date 20/06/2011 00312 */ 00313 uint16_t DS18X20_temp_to_decicel(uint8_t subzero, uint8_t cel, 00314 uint8_t cel_frac_bits) { 00315 uint16_t h; 00316 uint8_t i; 00317 uint8_t need_rounding[] = { 1, 3, 4, 6, 9, 11, 12, 14 }; 00318 00319 h = cel_frac_bits*DS18X20_FRACCONV/1000; 00320 h += cel*10; 00321 if (!subzero) { 00322 for (i=0; i<sizeof(need_rounding); i++) { 00323 if ( cel_frac_bits == need_rounding[i] ) { 00324 h++; 00325 break; 00326 } 00327 } 00328 } 00329 return h; 00330 } 00331 /** 00332 * @brief compare temperature values (full celsius only) 00333 * @param [in] subzero1 00334 * @param [in] cel1 00335 * @param [in] subzero2 00336 * @param [in] cel2 00337 * @return -1 if param-pair1 < param-pair2 00338 0 if == 00339 1 if > 00340 * @date 20/06/2011 00341 */ 00342 int8_t DS18X20_temp_cmp(uint8_t subzero1, uint16_t cel1, 00343 uint8_t subzero2, uint16_t cel2) { 00344 int16_t t1 = (subzero1) ? (cel1*(-1)) : (cel1); 00345 int16_t t2 = (subzero2) ? (cel2*(-1)) : (cel2); 00346 00347 if (t1<t2) return -1; 00348 if (t1>t2) return 1; 00349 return 0; 00350 }
Generated on Mon Jul 18 2022 20:45:44 by
1.7.2
frederic blanc