Kenji Arai / TSL2561

Dependents:   MusicBoxForFathersDay FTHR_SensorHub Affich_Lum_Moist Projetv0 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TSL2561.cpp Source File

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 }