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.
Dependents: MusicBoxForFathersDay FTHR_SensorHub Affich_Lum_Moist Projetv0 ... more
TSL2561.cpp
00001 /*! 00002 * @file Adafruit_TSL2561_U.cpp 00003 * 00004 * @mainpage Adafruit TSL2561 Light/Lux sensor driver 00005 * 00006 * @section intro_sec Introduction 00007 * 00008 * This is the documentation for Adafruit's TSL2561 driver for the 00009 * Arduino platform. It is designed specifically to work with the 00010 * Adafruit TSL2561 breakout: http://www.adafruit.com/products/439 00011 * 00012 * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required 00013 * to interface with the breakout. 00014 * 00015 * Adafruit invests time and resources providing this open source code, 00016 * please support Adafruit and open-source hardware by purchasing 00017 * products from Adafruit! 00018 * 00019 * @section dependencies Dependencies 00020 * 00021 * This library depends on 00022 * <a href="https://github.com/adafruit/Adafruit_Sensor"> 00023 * Adafruit_Sensor</a> being present on your system. Please make sure you have 00024 * installed the latest version before using this library. 00025 * 00026 * @section author Author 00027 * 00028 * Written by Kevin "KTOWN" Townsend for Adafruit Industries. 00029 * 00030 * @section license License 00031 * 00032 * BSD license, all text here must be included in any redistribution. 00033 * 00034 * @section HISTORY 00035 * 00036 * v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and 00037 * added lux clipping check (returns 0 lux on sensor saturation) 00038 * v1.0 - First release (previously TSL2561) 00039 */ 00040 /**************************************************************************/ 00041 00042 //------- Modified by ---------------------------------------------------------- 00043 // Kenji Arai / JH1PJL 00044 // http://www.page.sannet.ne.jp/kenjia/index.html 00045 // http://mbed.org/users/kenjiArai/ 00046 // Created: Feburary 21st, 2015 00047 // Revised: August 23rd, 2017 00048 // Revised: Feburary 20th, 2018 bug fix -> read_ID() & who_am_i() 00049 // Thanks PARK JAICHANG 00050 // Revised: March 31st, 2018 Added "Auto Range mode" 00051 // Use Adafruit library 00052 // 00053 // Original information https://www.adafruit.com/product/439 00054 // Original source files https://github.com/adafruit/TSL2561-Arduino-Library 00055 // https://github.com/adafruit/Adafruit_TSL2561 00056 // Change for Mbed platform 00057 // modified -> all related files 00058 //------------------------------------------------------------------------------ 00059 00060 #include "TSL2561.h" 00061 00062 // T, FN and CL package values 00063 #define TSL2561_LUX_K1T (0x0040) ///< 0.125 * 2^RATIO_SCALE 00064 #define TSL2561_LUX_B1T (0x01f2) ///< 0.0304 * 2^LUX_SCALE 00065 #define TSL2561_LUX_M1T (0x01be) ///< 0.0272 * 2^LUX_SCALE 00066 #define TSL2561_LUX_K2T (0x0080) ///< 0.250 * 2^RATIO_SCALE 00067 #define TSL2561_LUX_B2T (0x0214) ///< 0.0325 * 2^LUX_SCALE 00068 #define TSL2561_LUX_M2T (0x02d1) ///< 0.0440 * 2^LUX_SCALE 00069 #define TSL2561_LUX_K3T (0x00c0) ///< 0.375 * 2^RATIO_SCALE 00070 #define TSL2561_LUX_B3T (0x023f) ///< 0.0351 * 2^LUX_SCALE 00071 #define TSL2561_LUX_M3T (0x037b) ///< 0.0544 * 2^LUX_SCALE 00072 #define TSL2561_LUX_K4T (0x0100) ///< 0.50 * 2^RATIO_SCALE 00073 #define TSL2561_LUX_B4T (0x0270) ///< 0.0381 * 2^LUX_SCALE 00074 #define TSL2561_LUX_M4T (0x03fe) ///< 0.0624 * 2^LUX_SCALE 00075 #define TSL2561_LUX_K5T (0x0138) ///< 0.61 * 2^RATIO_SCALE 00076 #define TSL2561_LUX_B5T (0x016f) ///< 0.0224 * 2^LUX_SCALE 00077 #define TSL2561_LUX_M5T (0x01fc) ///< 0.0310 * 2^LUX_SCALE 00078 #define TSL2561_LUX_K6T (0x019a) ///< 0.80 * 2^RATIO_SCALE 00079 #define TSL2561_LUX_B6T (0x00d2) ///< 0.0128 * 2^LUX_SCALE 00080 #define TSL2561_LUX_M6T (0x00fb) ///< 0.0153 * 2^LUX_SCALE 00081 #define TSL2561_LUX_K7T (0x029a) ///< 1.3 * 2^RATIO_SCALE 00082 #define TSL2561_LUX_B7T (0x0018) ///< 0.00146 * 2^LUX_SCALE 00083 #define TSL2561_LUX_M7T (0x0012) ///< 0.00112 * 2^LUX_SCALE 00084 #define TSL2561_LUX_K8T (0x029a) ///< 1.3 * 2^RATIO_SCALE 00085 #define TSL2561_LUX_B8T (0x0000) ///< 0.000 * 2^LUX_SCALE 00086 #define TSL2561_LUX_M8T (0x0000) ///< 0.000 * 2^LUX_SCALE 00087 00088 // CS package values 00089 #define TSL2561_LUX_K1C (0x0043) ///< 0.130 * 2^RATIO_SCALE 00090 #define TSL2561_LUX_B1C (0x0204) ///< 0.0315 * 2^LUX_SCALE 00091 #define TSL2561_LUX_M1C (0x01ad) ///< 0.0262 * 2^LUX_SCALE 00092 #define TSL2561_LUX_K2C (0x0085) ///< 0.260 * 2^RATIO_SCALE 00093 #define TSL2561_LUX_B2C (0x0228) ///< 0.0337 * 2^LUX_SCALE 00094 #define TSL2561_LUX_M2C (0x02c1) ///< 0.0430 * 2^LUX_SCALE 00095 #define TSL2561_LUX_K3C (0x00c8) ///< 0.390 * 2^RATIO_SCALE 00096 #define TSL2561_LUX_B3C (0x0253) ///< 0.0363 * 2^LUX_SCALE 00097 #define TSL2561_LUX_M3C (0x0363) ///< 0.0529 * 2^LUX_SCALE 00098 #define TSL2561_LUX_K4C (0x010a) ///< 0.520 * 2^RATIO_SCALE 00099 #define TSL2561_LUX_B4C (0x0282) ///< 0.0392 * 2^LUX_SCALE 00100 #define TSL2561_LUX_M4C (0x03df) ///< 0.0605 * 2^LUX_SCALE 00101 #define TSL2561_LUX_K5C (0x014d) ///< 0.65 * 2^RATIO_SCALE 00102 #define TSL2561_LUX_B5C (0x0177) ///< 0.0229 * 2^LUX_SCALE 00103 #define TSL2561_LUX_M5C (0x01dd) ///< 0.0291 * 2^LUX_SCALE 00104 #define TSL2561_LUX_K6C (0x019a) ///< 0.80 * 2^RATIO_SCALE 00105 #define TSL2561_LUX_B6C (0x0101) ///< 0.0157 * 2^LUX_SCALE 00106 #define TSL2561_LUX_M6C (0x0127) ///< 0.0180 * 2^LUX_SCALE 00107 #define TSL2561_LUX_K7C (0x029a) ///< 1.3 * 2^RATIO_SCALE 00108 #define TSL2561_LUX_B7C (0x0037) ///< 0.00338 * 2^LUX_SCALE 00109 #define TSL2561_LUX_M7C (0x002b) ///< 0.00260 * 2^LUX_SCALE 00110 #define TSL2561_LUX_K8C (0x029a) ///< 1.3 * 2^RATIO_SCALE 00111 #define TSL2561_LUX_B8C (0x0000) ///< 0.000 * 2^LUX_SCALE 00112 #define TSL2561_LUX_M8C (0x0000) ///< 0.000 * 2^LUX_SCALE 00113 00114 // Auto-gain thresholds 00115 #define TSL2561_AGC_THI_13MS (4850) ///< Max value at Ti 13ms = 5047 00116 #define TSL2561_AGC_TLO_13MS (100) ///< Min value at Ti 13ms = 100 00117 #define TSL2561_AGC_THI_101MS (36000) ///< Max value at Ti 101ms = 37177 00118 #define TSL2561_AGC_TLO_101MS (200) ///< Min value at Ti 101ms = 200 00119 #define TSL2561_AGC_THI_402MS (63000) ///< Max value at Ti 402ms = 65535 00120 #define TSL2561_AGC_TLO_402MS (500) ///< Min value at Ti 402ms = 500 00121 00122 // Clipping thresholds ///< # Counts that trigger a change in gain/integration 00123 #define TSL2561_CLIPPING_13MS (4900) 00124 #define TSL2561_CLIPPING_101MS (37000) 00125 #define TSL2561_CLIPPING_402MS (65000) 00126 00127 // Delay for integration times 00128 #define TSL2561_DELAY_INTTIME_13MS (15) ///< Wait 15ms for 13ms integration 00129 #define TSL2561_DELAY_INTTIME_101MS (120) ///< Wait 120ms for 101ms integration 00130 #define TSL2561_DELAY_INTTIME_402MS (450) ///< Wait 450ms for 402ms integration 00131 00132 /*========================================================================*/ 00133 /* CONSTRUCTORS */ 00134 /*========================================================================*/ 00135 00136 TSL2561::TSL2561 (PinName p_sda, PinName p_scl) 00137 : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00138 { 00139 _addr = TSL2561_ADDR_LOW; 00140 init(); 00141 } 00142 00143 TSL2561::TSL2561 (PinName p_sda, PinName p_scl, uint8_t addr) 00144 : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) 00145 { 00146 _addr = addr; 00147 init(); 00148 } 00149 00150 TSL2561::TSL2561 (I2C& p_i2c) 00151 : _i2c(p_i2c) 00152 { 00153 _addr = TSL2561_ADDR_LOW; 00154 init(); 00155 } 00156 00157 TSL2561::TSL2561 (I2C& p_i2c, uint8_t addr) 00158 : _i2c(p_i2c) 00159 { 00160 _addr = addr; 00161 init(); 00162 } 00163 00164 /*========================================================================*/ 00165 /* PUBLIC FUNCTIONS */ 00166 /*========================================================================*/ 00167 /////////////// Read Lux from sensor ////////////////////// 00168 /* 00169 For 0 < CH1/CH0 < 0.50 Lux = 0.0304 x CH0-0.062 x CH0 x ((CH1/CH0)1.4) 00170 For 0.50 < CH1/CH0 < 0.61 Lux = 0.0224 x CH0-0.031 x CH1 00171 For 0.61 < CH1/CH0 < 0.80 Lux = 0.0128 x CH0-0.0153 x CH1 00172 For 0.80 < CH1/CH0 < 1.30 Lux = 0.00146 x CH0-0.00112x CH1 00173 For CH1/CH0 > 1.30 Lux = 0 00174 */ 00175 float TSL2561::lux() 00176 { 00177 double lux0, lux1; 00178 double ratio; 00179 double dlux; 00180 00181 _TSL2561AutoGain = false; 00182 _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; 00183 _TSL2561Gain = TSL2561_GAIN_1X; 00184 /* Set default integration time and gain */ 00185 setIntegrationTime(_TSL2561IntegrationTime); 00186 setGain(_TSL2561Gain); 00187 uint16_t x0, x1; 00188 getLuminosity(&x0, &x1); 00189 ch0 = x0; 00190 ch1 = x1; 00191 //printf("ch0 = %d, ch1 = %d\r\n", ch0, ch1); 00192 //printf("Integ. Time = %d, Gain %d\r\n", 00193 // _TSL2561IntegrationTime, _TSL2561Gain); 00194 lux0 = (double)ch0; 00195 lux1 = (double)ch1; 00196 ratio = lux1 / lux0; 00197 read_timing_reg(); 00198 lux0 *= (402.0/(double)integ_time); 00199 lux1 *= (402.0/(double)integ_time); 00200 lux0 /= gain; 00201 lux1 /= gain; 00202 //printf("Integ. Time = %f, Gain %d\r\n", integ_time, gain); 00203 if (ratio <= 0.5) { 00204 dlux = 0.03040 * lux0 - 0.06200 * lux0 * pow(ratio,1.4); 00205 } else if (ratio <= 0.61) { 00206 dlux = 0.02240 * lux0 - 0.03100 * lux1; 00207 } else if (ratio <= 0.80) { 00208 dlux = 0.01280 * lux0 - 0.01530 * lux1; 00209 } else if (ratio <= 1.30) { 00210 dlux = 0.00146 * lux0 - 0.00112 * lux1; 00211 } else { 00212 dlux = 0; 00213 } 00214 disable(); 00215 return (float)dlux; 00216 } 00217 00218 float TSL2561::lux_auto(void) 00219 { 00220 uint32_t data; 00221 00222 enableAutoRange(true); 00223 getEvent(&data); 00224 //printf("line:%d\r\n", __LINE__); 00225 return (float)data; 00226 } 00227 00228 /**************************************************************************/ 00229 /*! 00230 @brief Initializes I2C connection and settings. 00231 Attempts to determine if the sensor is contactable, then sets up a default 00232 integration time and gain. Then powers down the chip. 00233 @returns True if sensor is found and initialized, false otherwise. 00234 */ 00235 /**************************************************************************/ 00236 bool TSL2561::init() 00237 { 00238 _TSL2561Initialised = false; 00239 _TSL2561AutoGain = false; 00240 _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; 00241 _TSL2561Gain = TSL2561_GAIN_1X; 00242 00243 /* Make sure we're actually connected */ 00244 uint8_t x = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID); 00245 if (x & 0xF0 != 0x50) { // ID code for TSL2561 00246 //printf("initialize error!\r\n"); 00247 return false; 00248 } 00249 //printf("ID=0x%02x\r\n", x); 00250 _TSL2561Initialised = true; 00251 00252 /* Set default integration time and gain */ 00253 setIntegrationTime(_TSL2561IntegrationTime); 00254 setGain(_TSL2561Gain); 00255 read_timing_reg(); 00256 00257 /* Note: by default, the device is in power down mode on bootup */ 00258 disable(); 00259 00260 t.reset(); 00261 t.start(); 00262 //printf("Integ. Time = %d, Gain %d\r\n", 00263 // _TSL2561IntegrationTime, _TSL2561Gain); 00264 //printf("initialize finished!\r\n"); 00265 x = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING); 00266 //printf("TIMING REG=0x%02x\r\n", x); 00267 return true; 00268 } 00269 00270 /**************************************************************************/ 00271 /*! 00272 @brief Enables or disables the auto-gain settings when reading 00273 data from the sensor 00274 @param enable Set to true to enable, False to disable 00275 */ 00276 /**************************************************************************/ 00277 void TSL2561::enableAutoRange(bool enable) 00278 { 00279 _TSL2561AutoGain = enable ? true : false; 00280 } 00281 00282 /**************************************************************************/ 00283 /*! 00284 @brief Sets the integration time for the TSL2561. Higher time means 00285 more light captured (better for low light conditions) but will 00286 take longer to run readings. 00287 @param time The amount of time we'd like to add up values 00288 */ 00289 /**************************************************************************/ 00290 void TSL2561::setIntegrationTime(TSL2561IntegrationTime_t time) 00291 { 00292 /* Enable the device by setting the control bit to 0x03 */ 00293 enable(); 00294 /* Update the timing register */ 00295 write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | _TSL2561Gain); 00296 /* Update value placeholders */ 00297 _TSL2561IntegrationTime = time; 00298 /* Turn the device off to save power */ 00299 disable(); 00300 } 00301 00302 /**************************************************************************/ 00303 /*! 00304 @brief Adjusts the gain on the TSL2561 (adjusts the sensitivity to light) 00305 @param gain The value we'd like to set the gain to 00306 */ 00307 /**************************************************************************/ 00308 void TSL2561::setGain(TSL2561Gain_t gain) 00309 { 00310 /* Enable the device by setting the control bit to 0x03 */ 00311 enable(); 00312 /* Update the timing register */ 00313 write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _TSL2561IntegrationTime | gain); 00314 /* Update value placeholders */ 00315 _TSL2561Gain = gain; 00316 /* Turn the device off to save power */ 00317 disable(); 00318 } 00319 00320 /**************************************************************************/ 00321 /*! 00322 @brief Gets the broadband (mixed lighting) and IR only values from 00323 the TSL2561, adjusting gain if auto-gain is enabled 00324 @param broadband Pointer to a uint16_t we will fill with a sensor 00325 reading from the IR+visible light diode. 00326 @param ir Pointer to a uint16_t we will fill with a sensor the 00327 IR-only light diode. 00328 */ 00329 /**************************************************************************/ 00330 void TSL2561::getLuminosity (uint16_t *broadband, uint16_t *ir) 00331 { 00332 bool valid = false; 00333 00334 /* If Auto gain disabled get a single reading and continue */ 00335 if(!_TSL2561AutoGain) { 00336 //printf("Get data without Auto gain\r\n"); 00337 getData (broadband, ir); 00338 return; 00339 } 00340 //printf("Get data with Auto gain\r\n"); 00341 /* Read data until we find a valid range */ 00342 bool _agcCheck = false; 00343 do { 00344 uint16_t _b, _ir; 00345 uint16_t _hi, _lo; 00346 TSL2561IntegrationTime_t _it = _TSL2561IntegrationTime; 00347 00348 /* Get the hi/low threshold for the current integration time */ 00349 switch(_it) { 00350 case TSL2561_INTEGRATIONTIME_13MS: 00351 _hi = TSL2561_AGC_THI_13MS; 00352 _lo = TSL2561_AGC_TLO_13MS; 00353 break; 00354 case TSL2561_INTEGRATIONTIME_101MS: 00355 _hi = TSL2561_AGC_THI_101MS; 00356 _lo = TSL2561_AGC_TLO_101MS; 00357 break; 00358 default: 00359 _hi = TSL2561_AGC_THI_402MS; 00360 _lo = TSL2561_AGC_TLO_402MS; 00361 break; 00362 } 00363 00364 getData(&_b, &_ir); 00365 00366 /* Run an auto-gain check if we haven't already done so ... */ 00367 if (!_agcCheck) { 00368 if ((_b < _lo) && (_TSL2561Gain == TSL2561_GAIN_1X)) { 00369 /* Increase the gain and try again */ 00370 setGain(TSL2561_GAIN_16X); 00371 /* Drop the previous conversion results */ 00372 getData(&_b, &_ir); 00373 /* Set a flag to indicate we've adjusted the gain */ 00374 _agcCheck = true; 00375 } else if ((_b > _hi) && (_TSL2561Gain == TSL2561_GAIN_16X)) { 00376 /* Drop gain to 1x and try again */ 00377 setGain(TSL2561_GAIN_1X); 00378 /* Drop the previous conversion results */ 00379 getData(&_b, &_ir); 00380 /* Set a flag to indicate we've adjusted the gain */ 00381 _agcCheck = true; 00382 } else { 00383 /* Nothing to look at here, keep moving .... 00384 Reading is either valid, or we're already at the chips limits */ 00385 *broadband = _b; 00386 *ir = _ir; 00387 valid = true; 00388 } 00389 } else { 00390 /* If we've already adjusted the gain once, just return the new results. 00391 This avoids endless loops where a value is at one extreme pre-gain, 00392 and the the other extreme post-gain */ 00393 *broadband = _b; 00394 *ir = _ir; 00395 valid = true; 00396 } 00397 } while (!valid); 00398 } 00399 00400 /**************************************************************************/ 00401 /*! 00402 Enables the device 00403 */ 00404 /**************************************************************************/ 00405 void TSL2561::enable(void) 00406 { 00407 /* Enable the device by setting the control bit to 0x03 */ 00408 write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON); 00409 } 00410 00411 /**************************************************************************/ 00412 /*! 00413 Disables the device (putting it in lower power sleep mode) 00414 */ 00415 /**************************************************************************/ 00416 void TSL2561::disable(void) 00417 { 00418 /* Turn the device off to save power */ 00419 write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF); 00420 } 00421 00422 /**************************************************************************/ 00423 /*! 00424 Private function to read luminosity on both channels 00425 */ 00426 /**************************************************************************/ 00427 void TSL2561::getData (uint16_t *broadband, uint16_t *ir) 00428 { 00429 /* Enable the device by setting the control bit to 0x03 */ 00430 enable(); 00431 00432 /* Wait x ms for ADC to complete */ 00433 switch (_TSL2561IntegrationTime) { 00434 case TSL2561_INTEGRATIONTIME_13MS: 00435 wait_ms(TSL2561_DELAY_INTTIME_13MS); 00436 break; 00437 case TSL2561_INTEGRATIONTIME_101MS: 00438 wait_ms(TSL2561_DELAY_INTTIME_101MS); 00439 break; 00440 default: 00441 wait_ms(TSL2561_DELAY_INTTIME_402MS); 00442 break; 00443 } 00444 00445 /* Reads a two byte value from channel 0 (visible + infrared) */ 00446 *broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW); 00447 00448 /* Reads a two byte value from channel 1 (infrared) */ 00449 *ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW); 00450 00451 /* Turn the device off to save power */ 00452 disable(); 00453 } 00454 00455 /**************************************************************************/ 00456 /*! 00457 @brief Converts the raw sensor values to the standard SI lux equivalent. 00458 @param broadband The 16-bit sensor reading from the IR+visible light diode. 00459 @param ir The 16-bit sensor reading from the IR-only light diode. 00460 @returns The integer Lux value we calcuated. 00461 Returns 0 if the sensor is saturated and the values are 00462 unreliable, or 65536 if the sensor is saturated. 00463 */ 00464 /**************************************************************************/ 00465 /**************************************************************************/ 00466 /*! 00467 00468 Returns 00469 */ 00470 /**************************************************************************/ 00471 uint32_t TSL2561::calculateLux(uint16_t broadband, uint16_t ir) 00472 { 00473 unsigned long chScale; 00474 unsigned long channel1; 00475 unsigned long channel0; 00476 00477 //printf("line:%d\r\n", __LINE__); 00478 /* Make sure the sensor isn't saturated! */ 00479 uint16_t clipThreshold; 00480 //printf("_TSL2561IntegrationTime=%d\r\n", _TSL2561IntegrationTime); 00481 switch (_TSL2561IntegrationTime) { 00482 case TSL2561_INTEGRATIONTIME_13MS: 00483 clipThreshold = TSL2561_CLIPPING_13MS; 00484 chScale = TSL2561_LUX_CHSCALE_TINT0; 00485 //printf("line:%d\r\n", __LINE__); 00486 break; 00487 case TSL2561_INTEGRATIONTIME_101MS: 00488 clipThreshold = TSL2561_CLIPPING_101MS; 00489 chScale = TSL2561_LUX_CHSCALE_TINT1; 00490 break; 00491 default: 00492 clipThreshold = TSL2561_CLIPPING_402MS; 00493 chScale = (1 << TSL2561_LUX_CHSCALE); 00494 break; 00495 } 00496 //printf("clipThreshold=%d\r\n", clipThreshold); 00497 /* Return 65536 lux if the sensor is saturated */ 00498 if ((broadband > clipThreshold) || (ir > clipThreshold)) { 00499 //printf("line:%d\r\n", __LINE__); 00500 return 65536; 00501 } 00502 00503 //printf("line:%d\r\n", __LINE__); 00504 //printf("chScale=%d\r\n", chScale); 00505 /* Scale for gain (1x or 16x) */ 00506 if (!_TSL2561Gain) { 00507 chScale = chScale << 4; 00508 } 00509 //printf("chScale=%d\r\n", chScale); 00510 /* Scale the channel values */ 00511 channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE; 00512 channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE; 00513 //printf("channel0=%d, channel1=%d\r\n", channel0, channel1); 00514 00515 /* Find the ratio of the channel values (Channel1/Channel0) */ 00516 unsigned long ratio1 = 0; 00517 if (channel0 != 0) { 00518 ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0; 00519 } 00520 00521 /* round the ratio value */ 00522 long ratio = (ratio1 + 1) >> 1; 00523 //printf("ratio1=%d, ratio=%d\r\n", ratio1, ratio); 00524 unsigned int b, m; 00525 00526 #ifdef TSL2561_PACKAGE_CS 00527 //printf("line:%d\r\n", __LINE__); 00528 if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C)) { 00529 b=TSL2561_LUX_B1C; 00530 m=TSL2561_LUX_M1C; 00531 } else if (ratio <= TSL2561_LUX_K2C) { 00532 b=TSL2561_LUX_B2C; 00533 m=TSL2561_LUX_M2C; 00534 } else if (ratio <= TSL2561_LUX_K3C) { 00535 b=TSL2561_LUX_B3C; 00536 m=TSL2561_LUX_M3C; 00537 } else if (ratio <= TSL2561_LUX_K4C) { 00538 b=TSL2561_LUX_B4C; 00539 m=TSL2561_LUX_M4C; 00540 } else if (ratio <= TSL2561_LUX_K5C) { 00541 b=TSL2561_LUX_B5C; 00542 m=TSL2561_LUX_M5C; 00543 } else if (ratio <= TSL2561_LUX_K6C) { 00544 b=TSL2561_LUX_B6C; 00545 m=TSL2561_LUX_M6C; 00546 } else if (ratio <= TSL2561_LUX_K7C) { 00547 b=TSL2561_LUX_B7C; 00548 m=TSL2561_LUX_M7C; 00549 } else if (ratio > TSL2561_LUX_K8C) { 00550 b=TSL2561_LUX_B8C; 00551 m=TSL2561_LUX_M8C; 00552 } 00553 #else 00554 //printf("line:%d\r\n", __LINE__); 00555 if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T)) { 00556 b=TSL2561_LUX_B1T; 00557 m=TSL2561_LUX_M1T; 00558 } else if (ratio <= TSL2561_LUX_K2T) { 00559 b=TSL2561_LUX_B2T; 00560 m=TSL2561_LUX_M2T; 00561 } else if (ratio <= TSL2561_LUX_K3T) { 00562 b=TSL2561_LUX_B3T; 00563 m=TSL2561_LUX_M3T; 00564 } else if (ratio <= TSL2561_LUX_K4T) { 00565 b=TSL2561_LUX_B4T; 00566 m=TSL2561_LUX_M4T; 00567 } else if (ratio <= TSL2561_LUX_K5T) { 00568 b=TSL2561_LUX_B5T; 00569 m=TSL2561_LUX_M5T; 00570 } else if (ratio <= TSL2561_LUX_K6T) { 00571 b=TSL2561_LUX_B6T; 00572 m=TSL2561_LUX_M6T; 00573 } else if (ratio <= TSL2561_LUX_K7T) { 00574 b=TSL2561_LUX_B7T; 00575 m=TSL2561_LUX_M7T; 00576 } else if (ratio > TSL2561_LUX_K8T) { 00577 b=TSL2561_LUX_B8T; 00578 m=TSL2561_LUX_M8T; 00579 } 00580 #endif 00581 00582 long temp; 00583 temp = ((channel0 * b) - (channel1 * m)); 00584 00585 /* Do not allow negative lux value */ 00586 if (temp < 0L) { 00587 temp = 0; 00588 } 00589 //printf("line:%d\r\n", __LINE__); 00590 /* Round lsb (2^(LUX_SCALE-1)) */ 00591 temp += (1 << (TSL2561_LUX_LUXSCALE-1)); 00592 00593 /* Strip off fractional portion */ 00594 uint32_t lux = temp >> TSL2561_LUX_LUXSCALE; 00595 00596 /* Signal I2C had no errors */ 00597 //printf("Lux=%d\r\n", lux); 00598 return lux; 00599 } 00600 00601 /**************************************************************************/ 00602 /*! 00603 @brief Gets the most recent sensor event 00604 @param event Pointer to a sensor_event_t type that will be filled 00605 with the lux value, timestamp, data type and sensor ID. 00606 @returns True if sensor reading is between 0 and 65535 lux, 00607 false if sensor is saturated 00608 */ 00609 /**************************************************************************/ 00610 bool TSL2561::getEvent(uint32_t *event) 00611 { 00612 uint16_t broadband, ir; 00613 00614 /* Calculate the actual lux value */ 00615 getLuminosity(&broadband, &ir); 00616 //printf("broadband=%d, ir=%d\r\n", broadband, ir); 00617 *event = calculateLux(broadband, ir); 00618 //printf("LUX=%f\r\n", event->light); 00619 //printf("LUX=%d\r\n", *event); 00620 //printf("line:%d\r\n", __LINE__); 00621 if (*event == 65536) { 00622 //printf("line:%d\r\n", __LINE__); 00623 return false; 00624 } 00625 //printf("line:%d\r\n", __LINE__); 00626 return true; 00627 } 00628 00629 /**************************************************************************/ 00630 /*! 00631 @brief Gets the sensor_t data 00632 @param sensor A pointer to a sensor_t structure that we will fill with 00633 details about the TSL2561 and its capabilities 00634 */ 00635 /**************************************************************************/ 00636 void TSL2561::getSensor(sensor_t *sensor) 00637 { 00638 /* Insert the sensor name in the fixed length char array */ 00639 //sensor->version = 1; 00640 sensor->min_delay = 0; 00641 sensor->max_value = 17000.0; /* Based on trial and error ... confirm! */ 00642 sensor->min_value = 1.0; 00643 sensor->resolution = 1.0; 00644 } 00645 00646 /*========================================================================*/ 00647 /* PRIVATE FUNCTIONS */ 00648 /*========================================================================*/ 00649 00650 /**************************************************************************/ 00651 /*! 00652 @brief Writes a register and an 8 bit value over I2C 00653 @param reg I2C register to write the value to 00654 @param value The 8-bit value we're writing to the register 00655 */ 00656 /**************************************************************************/ 00657 void TSL2561::write8 (uint8_t reg, uint8_t value) 00658 { 00659 dt[0] = reg; 00660 dt[1] = value; 00661 _i2c.write((int)_addr, (char *)dt, 2, false); 00662 } 00663 00664 /**************************************************************************/ 00665 /*! 00666 @brief Reads an 8 bit value over I2C 00667 @param reg I2C register to read from 00668 @returns 8-bit value containing single byte data read 00669 */ 00670 /**************************************************************************/ 00671 uint8_t TSL2561::read8(uint8_t reg) 00672 { 00673 dt[0] = reg; 00674 _i2c.write((int)_addr, (char *)dt, 1, true); 00675 _i2c.read(_addr, (char *)dt, 1, false); 00676 return dt[0]; 00677 } 00678 00679 /**************************************************************************/ 00680 /*! 00681 @brief Reads a 16 bit values over I2C 00682 @param reg I2C register to read from 00683 @returns 16-bit value containing 2-byte data read 00684 */ 00685 /**************************************************************************/ 00686 uint16_t TSL2561::read16(uint8_t reg) 00687 { 00688 dt[0] = reg; 00689 _i2c.write((int)_addr, (char *)dt, 1, true); 00690 _i2c.read(_addr, (char *)dt, 2, false); 00691 uint16_t data = ((uint16_t)dt[1] << 8) + dt[0]; 00692 return data; 00693 } 00694 00695 /*========================================================================*/ 00696 /* JH1PJL Original Functions -> Keep compacibility for older revision */ 00697 /*========================================================================*/ 00698 00699 /////////////// Timing Register /////////////////////////// 00700 uint8_t TSL2561::set_timing_reg(uint8_t parameter) 00701 { 00702 enable(); 00703 write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, parameter); 00704 return read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING); 00705 } 00706 00707 uint8_t TSL2561::read_timing_reg(void) 00708 { 00709 uint8_t i, data; 00710 00711 data = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING); 00712 if (data & TSL2561_GAIN_16X) { 00713 gain = 16; 00714 _TSL2561Gain = TSL2561_GAIN_16X; 00715 } else { 00716 gain = 1; 00717 _TSL2561Gain = TSL2561_GAIN_1X; 00718 } 00719 i = data & 0x3; 00720 switch (i) { 00721 case 0: 00722 integ_time = 13.7; 00723 _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; 00724 break; 00725 case 1: 00726 integ_time = 101.0; 00727 _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_101MS; 00728 break; 00729 case 2: 00730 integ_time = 402.0; 00731 _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_402MS; 00732 break; 00733 default: 00734 integ_time = 0; 00735 _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; 00736 break; 00737 } 00738 return dt[0]; 00739 } 00740 00741 /////////////// ID //////////////////////////////////////// 00742 uint8_t TSL2561::read_ID() 00743 { 00744 id_number = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID); 00745 return id_number; 00746 } 00747 00748 uint8_t TSL2561::who_am_i() 00749 { 00750 read_ID(); 00751 if ((id_number >> 4) == I_AM_TSL2561CS) { 00752 return 1; 00753 } else if ((id_number >> 4) == I_AM_TSL2561T_FN_CL) { 00754 return 1; 00755 } else { 00756 return 0; 00757 } 00758 } 00759 00760 /////////////// Power ON/OFF ////////////////////////////// 00761 void TSL2561::power_up() 00762 { 00763 enable(); 00764 } 00765 00766 void TSL2561::power_down() 00767 { 00768 disable(); 00769 } 00770 00771 /////////////// I2C Freq. ///////////////////////////////// 00772 void TSL2561::frequency(int hz) 00773 { 00774 _i2c.frequency(hz); 00775 }
Generated on Wed Jul 13 2022 17:46:41 by
