|
00001 /*!@addtogroup lego 00002 * @{ 00003 * @defgroup legotmp Temperature Sensor 00004 * Temperature Sensor 00005 * @{ 00006 */ 00007 00008 /* 00009 * $Id: lego-temp.h 133 2013-03-10 15:15:38Z xander $ 00010 */ 00011 00012 #ifndef __LEGOTMP_DRIVER_H__ 00013 #define __LEGOTMP_DRIVER_H__ 00014 00015 /** \file lego-temp.h 00016 * \brief RobotC New Temperature Sensor Driver 00017 * 00018 * lego-temp.h provides an API for the Lego Temperature Sensor. 00019 * 00020 * Changelog: 00021 * - 0.1: Initial release 00022 * - 0.2: Partial rewrite by Xander Soldaat to simplify API 00023 * 00024 * Credits : 00025 * - Based on http://focus.ti.com/lit/ds/symlink/tmp275.pdf (Thank to Xander Soldaat who found the internal design) 00026 * - Based on Xander Soldaat's RobotC driver template 00027 * 00028 * License: You may use this code as you wish, provided you give credit where its due. 00029 * 00030 * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 3.59 AND HIGHER. 00031 00032 * \author Sylvain CACHEUX (sylcalego@cacheux.info) 00033 * \author Xander Soldaat (mightor@gmail.com), version 0.2 00034 * \date 15 february 2010 00035 * \version 0.2 00036 * \example lego-temp-test1.c 00037 * \example lego-temp-test2.c 00038 */ 00039 00040 #pragma systemFile 00041 00042 #ifndef __COMMON_H__ 00043 #include "common.h" 00044 #endif 00045 00046 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00047 /* 00048 <Address definitions> 00049 */ 00050 #define LEGOTMP_I2C_ADDR 0x98 /*!< New LEGO Temperature Sensor I2C device address */ 00051 #define LEGOTMP_TEMP 0x00 /*!< Temperature value (return on 2 bytes, 1rst : most significant byte, 2nd byte only half used) */ 00052 #define LEGOTMP_CONFIG 0x01 /*!< Configuration registry (see http://focus.ti.com/lit/ds/symlink/tmp275.pdf) */ 00053 00054 00055 00056 // ---------------------------- Definitions -------------------------------------- 00057 /*!< Command modes definition */ 00058 typedef enum { 00059 A_MIN = 8, // 0.5, * 16 (typedef needs integer...) 00060 A_MEAN1 = 4, // 0.25 * 16 (so *16 here...) 00061 A_MEAN2 = 2, // 0.125 * 16 (... and /16 in functions) 00062 A_MAX = 1 // 0.0625 * 16 (I'll have to improve that later...) 00063 } tLEGOTMPAccuracy; // The 4 available accuracy of the sensor 00064 00065 00066 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00067 // Function prototypes 00068 bool LEGOTMPreadTemp(tSensors link, float &temp); 00069 bool LEGOTMPreadAccuracy(tSensors link, tLEGOTMPAccuracy &accuracy); 00070 bool LEGOTMPsetAccuracy(tSensors link, tLEGOTMPAccuracy accuracy); 00071 bool LEGOTMPsetSingleShot(tSensors link); 00072 bool LEGOTMPsetContinuous(tSensors link); 00073 bool _LEGOTMPreadConfig(tSensors link, ubyte &config); 00074 tLEGOTMPAccuracy _LEGOTMPconvertAccuracy(ubyte config); 00075 00076 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00077 // global variables 00078 tByteArray LEGOTMP_I2CRequest; /*!< Array to hold I2C command data */ 00079 tByteArray LEGOTMP_I2CReply; /*!< Array to hold I2C reply data */ 00080 00081 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00082 00083 00084 /** 00085 * Read the current configuration register 00086 * 00087 * Note: this is an internal function and should not be called directly. 00088 * @param link the LEGO Temp Sensor port number 00089 * @param config the contents of the register 00090 * @return true if no error occured, false if it did 00091 */ 00092 bool _LEGOTMPreadConfig(tSensors link, ubyte &config) { 00093 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00094 00095 LEGOTMP_I2CRequest[0] = 2; // Message size 00096 LEGOTMP_I2CRequest[1] = LEGOTMP_I2C_ADDR; // I2C Address 00097 LEGOTMP_I2CRequest[2] = LEGOTMP_CONFIG; // Value address 00098 00099 if (!writeI2C(link, LEGOTMP_I2CRequest, LEGOTMP_I2CReply, 1)) 00100 return false; 00101 00102 config = LEGOTMP_I2CReply[0]; 00103 00104 return true; 00105 } 00106 00107 00108 /** 00109 * Set the configuration register 00110 * 00111 * Note: this is an internal function and should not be called directly. 00112 * @param link the LEGO Temp Sensor port number 00113 * @param config the contents of the register 00114 * @return true if no error occured, false if it did 00115 */ 00116 bool _LEGOTMPsetConfig(tSensors link, ubyte &config) { 00117 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00118 00119 LEGOTMP_I2CRequest[0] = 3; // Message size 00120 LEGOTMP_I2CRequest[1] = LEGOTMP_I2C_ADDR; // I2C Address 00121 LEGOTMP_I2CRequest[2] = LEGOTMP_CONFIG; // Value address 00122 LEGOTMP_I2CRequest[3] = config; // Value to be set 00123 00124 return writeI2C(link, LEGOTMP_I2CRequest); 00125 } 00126 00127 00128 /** 00129 * Retrieve the accuracy level from the config bytes 00130 * 00131 * Note: this is an internal function and should not be called directly. 00132 * @param config the contents of the register 00133 * @return true if no error occured, false if it did 00134 */ 00135 tLEGOTMPAccuracy _LEGOTMPconvertAccuracy(ubyte config) { 00136 /* the accuracy is in bits 6 & 5<br> 00137 * Config registry :<br> 00138 * BYTE D7 <D6 D5> D4 D3 D2 D1 D0<br> 00139 * 1 OS <R1 R0> F1 F0 POL TM SD<br> 00140 * so shifting bits to have the bits 6 and 5 at the right of the byte<br> 00141 * then doing a AND with 11 (3) to know the value of the accuracy.<br> 00142 */ 00143 00144 config = (config >> 5) & 3; 00145 switch (config) { 00146 case 0: 00147 // bits are 0 0, so the minimum accuracy 00148 return A_MIN; 00149 break; 00150 case 1: 00151 // bits are 0 1, so the mean1 accuracy 00152 return A_MEAN1; 00153 break; 00154 case 2: 00155 // bits are 1 0, so the mean2 accuracy 00156 return A_MEAN2; 00157 break; 00158 case 3: 00159 // bits are 1 1, so the maximum accuracy 00160 return A_MAX; 00161 break; 00162 } 00163 return A_MIN; 00164 } 00165 00166 00167 /** 00168 * Read the temperature. 00169 * @param link the LEGO Temp Sensor port number 00170 * @param temp the temperature value, 00171 * @return true if no error occured, false if it did 00172 */ 00173 bool LEGOTMPreadTemp(tSensors link, float &temp) { 00174 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00175 int b1; 00176 float b2; 00177 ubyte config; 00178 00179 //reading current accuracy 00180 if (!_LEGOTMPreadConfig(link, config)) 00181 return false; 00182 00183 // Check if we're in shutdown mode, if so, we're doing 00184 // one-shotted readings. 00185 if (config & 1 == 1) { 00186 config |= (1<<7); // set bit 7 for one-shot mode 00187 00188 if (!_LEGOTMPsetConfig(link, config)) 00189 return false; 00190 00191 // Now we need to wait a specific amount of time, depending on the 00192 // accuracy level. 00193 00194 switch (_LEGOTMPconvertAccuracy(config)) { 00195 case A_MIN: 00196 // conversion takes 27.5ms 00197 wait1Msec(28); 00198 break; 00199 case A_MEAN1: 00200 // conversion takes 55ms 00201 wait1Msec(55); 00202 break; 00203 case A_MEAN2: 00204 // conversion takes 110ms 00205 wait1Msec(110); 00206 break; 00207 case A_MAX: 00208 // conversion takes 220ms 00209 wait1Msec(220); 00210 break; 00211 } 00212 } 00213 00214 // clear the array again 00215 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00216 LEGOTMP_I2CRequest[0] = 2; // Message size 00217 LEGOTMP_I2CRequest[1] = LEGOTMP_I2C_ADDR; // I2C Address 00218 LEGOTMP_I2CRequest[2] = LEGOTMP_TEMP; // Value address 00219 00220 if (!writeI2C(link, LEGOTMP_I2CRequest, LEGOTMP_I2CReply, 2)) 00221 return false; 00222 00223 b1 = (int)LEGOTMP_I2CReply[0]; 00224 00225 switch (_LEGOTMPconvertAccuracy(config)) { 00226 case A_MIN: 00227 ///128 to have only the most significant bit (9 bits accuracy - 8 (b1) = 1 bit to keep) 00228 b2 = ((int)LEGOTMP_I2CReply[1] >> 7) * 0.5; 00229 break; 00230 case A_MEAN1: 00231 ///64 to have only the 2 most significant bits 00232 b2 = ((int)LEGOTMP_I2CReply[1] >> 6) * 0.25; 00233 break; 00234 case A_MEAN2: 00235 ///32 to have only the 3 most significant bits 00236 b2 = ((int)LEGOTMP_I2CReply[1] >> 5) * 0.125; 00237 break; 00238 case A_MAX: 00239 ///16 to have only the 4 most significant bits 00240 b2 = ((int)LEGOTMP_I2CReply[1] >> 4) * 0.0625; 00241 break; 00242 } 00243 00244 if (b1 < 128) temp = b1 + b2; // positive temp 00245 if (b1 > 127) temp = (b1 - 256) + b2; // negative temp 00246 00247 return true; 00248 } 00249 00250 00251 /** 00252 * Read the temperature sensor's accuracy 00253 * @param link the LEGO Temp Sensor port number, 00254 * @param accuracy the accuracy value to be read 00255 * @return true if no error occured, false if it did 00256 */ 00257 bool LEGOTMPreadAccuracy(tSensors link, tLEGOTMPAccuracy &accuracy) { 00258 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00259 ubyte config; 00260 00261 if (!_LEGOTMPreadConfig(link, config)) 00262 return false; 00263 00264 accuracy = _LEGOTMPconvertAccuracy(config); 00265 00266 return true; 00267 } 00268 00269 00270 /** 00271 * Set the temperature sensor's accuracy 00272 * @param link the LEGO Temp Sensor port number 00273 * @param accuracy the accuracy value to be set 00274 * @return true if no error occured, false if it did 00275 */ 00276 bool LEGOTMPsetAccuracy(tSensors link, tLEGOTMPAccuracy accuracy) { 00277 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00278 ubyte config; 00279 00280 // reading the configuration registry to know the other bits values 00281 if (!_LEGOTMPreadConfig(link, config)) 00282 return false; 00283 00284 // setting the value to be writed in the configuration registry depending on the others bits values 00285 /* the accuracy is in bits 6 & 5<br> 00286 * Config registry :<br> 00287 * BYTE D7 <D6 D5> D4 D3 D2 D1 D0<br> 00288 * 1 OS <R1 R0> F1 F0 POL TM SD<br> 00289 * 128 <64 32> 16 8 4 2 1<br> 00290 */ 00291 00292 // Clear bits 5 and 6 00293 config &= 0x9F; 00294 00295 switch (accuracy) { 00296 case A_MIN: 00297 // Minimum accuracy, so bits 6 5 must be 0 0, so doing an OR with 0000 0000; 00298 config |= 0x00; // 00299 break; 00300 case A_MEAN1: 00301 // Mean accuracy 1, so bits 6 5 must be 0 1, so doing an OR with 0010 0000 (0x20) 00302 config |= 0x20; 00303 break; 00304 case A_MEAN2: 00305 // Mean accuracy 2, so bits 6 5 must be 1 0, so doing an OR with 0100 0000 (0x40 00306 config |= 0x40; 00307 break; 00308 case A_MAX: 00309 // Maximum accuracy, so bits 6 5 must be 1 1, so doing a OR with 0110 0000 (0x60 00310 config |= 0x60; 00311 break; 00312 } 00313 00314 // Send new configuration to the sensor 00315 return _LEGOTMPsetConfig(link, config); 00316 } 00317 00318 00319 /** 00320 * Configure the sensor for Single Shot mode 00321 * @param link the New LEGO Sensor port number 00322 * @return true if no error occured, false if it did 00323 */ 00324 bool LEGOTMPsetSingleShot(tSensors link) { 00325 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00326 ubyte config; 00327 00328 // reading the configuration registry to know the other bits values 00329 if (!_LEGOTMPreadConfig(link, config)) 00330 return false; 00331 00332 // setting the value to be written in the configuration registry depending on the others bits values 00333 /* the shutdown mode bit it bit 0<br> 00334 * Config registry :<br> 00335 * BYTE D7 <D6 D5> D4 D3 D2 D1 D0<br> 00336 * 1 OS <R1 R0> F1 F0 POL TM SD<br> 00337 * 128 <64 32> 16 8 4 2 1<br> 00338 */ 00339 00340 // Set bit 0 to 1 00341 config |= 1; 00342 00343 // Send new configuration to the sensor 00344 return _LEGOTMPsetConfig(link, config); 00345 } 00346 00347 00348 /** 00349 * Configure the sensor for Continuous mode 00350 * @param link the New LEGO Sensor port number 00351 * @return true if no error occured, false if it did 00352 */ 00353 bool LEGOTMPsetContinuous(tSensors link) { 00354 memset(LEGOTMP_I2CRequest, 0, sizeof(tByteArray)); 00355 ubyte config; 00356 00357 // reading the configuration registry to know the other bits values 00358 if (!_LEGOTMPreadConfig(link, config)) 00359 return false; 00360 00361 // setting the value to be written in the configuration registry depending on the others bits values 00362 /* the shutdown mode bit it bit 0<br> 00363 * Config registry :<br> 00364 * BYTE D7 <D6 D5> D4 D3 D2 D1 D0<br> 00365 * 1 OS <R1 R0> F1 F0 POL TM SD<br> 00366 * 128 <64 32> 16 8 4 2 1<br> 00367 */ 00368 00369 // Set bit 0 to 0 00370 config &= 0xFE; 00371 00372 // Send new configuration to the sensor 00373 return _LEGOTMPsetConfig(link, config); 00374 } 00375 00376 #endif // __LEGOTMP_DRIVER_H__ 00377 00378 /* 00379 * $Id: lego-temp.h 133 2013-03-10 15:15:38Z xander $ 00380 */ 00381 /* @} */ 00382 /* @} */