Luminosity sensor by Texas Advanced Optoelectronic Solutions Inc.. Device combines one broadband photodiode (visible plus infrared) and one infrared-responding photodiode. Sets Gain x1 and 402mS as default.
Dependents: MusicBoxForFathersDay FTHR_SensorHub Affich_Lum_Moist Projetv0 ... more
TSL2561.cpp
- Committer:
- kenjiArai
- Date:
- 2018-09-21
- Revision:
- 5:5b1b625fda6f
- Parent:
- 4:05d322353720
File content as of revision 5:5b1b625fda6f:
/*! * @file Adafruit_TSL2561_U.cpp * * @mainpage Adafruit TSL2561 Light/Lux sensor driver * * @section intro_sec Introduction * * This is the documentation for Adafruit's TSL2561 driver for the * Arduino platform. It is designed specifically to work with the * Adafruit TSL2561 breakout: http://www.adafruit.com/products/439 * * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required * to interface with the breakout. * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * * @section dependencies Dependencies * * This library depends on * <a href="https://github.com/adafruit/Adafruit_Sensor"> * Adafruit_Sensor</a> being present on your system. Please make sure you have * installed the latest version before using this library. * * @section author Author * * Written by Kevin "KTOWN" Townsend for Adafruit Industries. * * @section license License * * BSD license, all text here must be included in any redistribution. * * @section HISTORY * * v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and * added lux clipping check (returns 0 lux on sensor saturation) * v1.0 - First release (previously TSL2561) */ /**************************************************************************/ //------- Modified by ---------------------------------------------------------- // Kenji Arai / JH1PJL // http://www.page.sannet.ne.jp/kenjia/index.html // http://mbed.org/users/kenjiArai/ // Created: Feburary 21st, 2015 // Revised: August 23rd, 2017 // Revised: Feburary 20th, 2018 bug fix -> read_ID() & who_am_i() // Thanks PARK JAICHANG // Revised: March 31st, 2018 Added "Auto Range mode" // Use Adafruit library // // Original information https://www.adafruit.com/product/439 // Original source files https://github.com/adafruit/TSL2561-Arduino-Library // https://github.com/adafruit/Adafruit_TSL2561 // Change for Mbed platform // modified -> all related files //------------------------------------------------------------------------------ #include "TSL2561.h" // T, FN and CL package values #define TSL2561_LUX_K1T (0x0040) ///< 0.125 * 2^RATIO_SCALE #define TSL2561_LUX_B1T (0x01f2) ///< 0.0304 * 2^LUX_SCALE #define TSL2561_LUX_M1T (0x01be) ///< 0.0272 * 2^LUX_SCALE #define TSL2561_LUX_K2T (0x0080) ///< 0.250 * 2^RATIO_SCALE #define TSL2561_LUX_B2T (0x0214) ///< 0.0325 * 2^LUX_SCALE #define TSL2561_LUX_M2T (0x02d1) ///< 0.0440 * 2^LUX_SCALE #define TSL2561_LUX_K3T (0x00c0) ///< 0.375 * 2^RATIO_SCALE #define TSL2561_LUX_B3T (0x023f) ///< 0.0351 * 2^LUX_SCALE #define TSL2561_LUX_M3T (0x037b) ///< 0.0544 * 2^LUX_SCALE #define TSL2561_LUX_K4T (0x0100) ///< 0.50 * 2^RATIO_SCALE #define TSL2561_LUX_B4T (0x0270) ///< 0.0381 * 2^LUX_SCALE #define TSL2561_LUX_M4T (0x03fe) ///< 0.0624 * 2^LUX_SCALE #define TSL2561_LUX_K5T (0x0138) ///< 0.61 * 2^RATIO_SCALE #define TSL2561_LUX_B5T (0x016f) ///< 0.0224 * 2^LUX_SCALE #define TSL2561_LUX_M5T (0x01fc) ///< 0.0310 * 2^LUX_SCALE #define TSL2561_LUX_K6T (0x019a) ///< 0.80 * 2^RATIO_SCALE #define TSL2561_LUX_B6T (0x00d2) ///< 0.0128 * 2^LUX_SCALE #define TSL2561_LUX_M6T (0x00fb) ///< 0.0153 * 2^LUX_SCALE #define TSL2561_LUX_K7T (0x029a) ///< 1.3 * 2^RATIO_SCALE #define TSL2561_LUX_B7T (0x0018) ///< 0.00146 * 2^LUX_SCALE #define TSL2561_LUX_M7T (0x0012) ///< 0.00112 * 2^LUX_SCALE #define TSL2561_LUX_K8T (0x029a) ///< 1.3 * 2^RATIO_SCALE #define TSL2561_LUX_B8T (0x0000) ///< 0.000 * 2^LUX_SCALE #define TSL2561_LUX_M8T (0x0000) ///< 0.000 * 2^LUX_SCALE // CS package values #define TSL2561_LUX_K1C (0x0043) ///< 0.130 * 2^RATIO_SCALE #define TSL2561_LUX_B1C (0x0204) ///< 0.0315 * 2^LUX_SCALE #define TSL2561_LUX_M1C (0x01ad) ///< 0.0262 * 2^LUX_SCALE #define TSL2561_LUX_K2C (0x0085) ///< 0.260 * 2^RATIO_SCALE #define TSL2561_LUX_B2C (0x0228) ///< 0.0337 * 2^LUX_SCALE #define TSL2561_LUX_M2C (0x02c1) ///< 0.0430 * 2^LUX_SCALE #define TSL2561_LUX_K3C (0x00c8) ///< 0.390 * 2^RATIO_SCALE #define TSL2561_LUX_B3C (0x0253) ///< 0.0363 * 2^LUX_SCALE #define TSL2561_LUX_M3C (0x0363) ///< 0.0529 * 2^LUX_SCALE #define TSL2561_LUX_K4C (0x010a) ///< 0.520 * 2^RATIO_SCALE #define TSL2561_LUX_B4C (0x0282) ///< 0.0392 * 2^LUX_SCALE #define TSL2561_LUX_M4C (0x03df) ///< 0.0605 * 2^LUX_SCALE #define TSL2561_LUX_K5C (0x014d) ///< 0.65 * 2^RATIO_SCALE #define TSL2561_LUX_B5C (0x0177) ///< 0.0229 * 2^LUX_SCALE #define TSL2561_LUX_M5C (0x01dd) ///< 0.0291 * 2^LUX_SCALE #define TSL2561_LUX_K6C (0x019a) ///< 0.80 * 2^RATIO_SCALE #define TSL2561_LUX_B6C (0x0101) ///< 0.0157 * 2^LUX_SCALE #define TSL2561_LUX_M6C (0x0127) ///< 0.0180 * 2^LUX_SCALE #define TSL2561_LUX_K7C (0x029a) ///< 1.3 * 2^RATIO_SCALE #define TSL2561_LUX_B7C (0x0037) ///< 0.00338 * 2^LUX_SCALE #define TSL2561_LUX_M7C (0x002b) ///< 0.00260 * 2^LUX_SCALE #define TSL2561_LUX_K8C (0x029a) ///< 1.3 * 2^RATIO_SCALE #define TSL2561_LUX_B8C (0x0000) ///< 0.000 * 2^LUX_SCALE #define TSL2561_LUX_M8C (0x0000) ///< 0.000 * 2^LUX_SCALE // Auto-gain thresholds #define TSL2561_AGC_THI_13MS (4850) ///< Max value at Ti 13ms = 5047 #define TSL2561_AGC_TLO_13MS (100) ///< Min value at Ti 13ms = 100 #define TSL2561_AGC_THI_101MS (36000) ///< Max value at Ti 101ms = 37177 #define TSL2561_AGC_TLO_101MS (200) ///< Min value at Ti 101ms = 200 #define TSL2561_AGC_THI_402MS (63000) ///< Max value at Ti 402ms = 65535 #define TSL2561_AGC_TLO_402MS (500) ///< Min value at Ti 402ms = 500 // Clipping thresholds ///< # Counts that trigger a change in gain/integration #define TSL2561_CLIPPING_13MS (4900) #define TSL2561_CLIPPING_101MS (37000) #define TSL2561_CLIPPING_402MS (65000) // Delay for integration times #define TSL2561_DELAY_INTTIME_13MS (15) ///< Wait 15ms for 13ms integration #define TSL2561_DELAY_INTTIME_101MS (120) ///< Wait 120ms for 101ms integration #define TSL2561_DELAY_INTTIME_402MS (450) ///< Wait 450ms for 402ms integration /*========================================================================*/ /* CONSTRUCTORS */ /*========================================================================*/ TSL2561::TSL2561 (PinName p_sda, PinName p_scl) : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) { _addr = TSL2561_ADDR_LOW; init(); } TSL2561::TSL2561 (PinName p_sda, PinName p_scl, uint8_t addr) : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) { _addr = addr; init(); } TSL2561::TSL2561 (I2C& p_i2c) : _i2c(p_i2c) { _addr = TSL2561_ADDR_LOW; init(); } TSL2561::TSL2561 (I2C& p_i2c, uint8_t addr) : _i2c(p_i2c) { _addr = addr; init(); } /*========================================================================*/ /* PUBLIC FUNCTIONS */ /*========================================================================*/ /////////////// Read Lux from sensor ////////////////////// /* For 0 < CH1/CH0 < 0.50 Lux = 0.0304 x CH0-0.062 x CH0 x ((CH1/CH0)1.4) For 0.50 < CH1/CH0 < 0.61 Lux = 0.0224 x CH0-0.031 x CH1 For 0.61 < CH1/CH0 < 0.80 Lux = 0.0128 x CH0-0.0153 x CH1 For 0.80 < CH1/CH0 < 1.30 Lux = 0.00146 x CH0-0.00112x CH1 For CH1/CH0 > 1.30 Lux = 0 */ float TSL2561::lux() { double lux0, lux1; double ratio; double dlux; _TSL2561AutoGain = false; _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; _TSL2561Gain = TSL2561_GAIN_1X; /* Set default integration time and gain */ setIntegrationTime(_TSL2561IntegrationTime); setGain(_TSL2561Gain); uint16_t x0, x1; getLuminosity(&x0, &x1); ch0 = x0; ch1 = x1; //printf("ch0 = %d, ch1 = %d\r\n", ch0, ch1); //printf("Integ. Time = %d, Gain %d\r\n", // _TSL2561IntegrationTime, _TSL2561Gain); lux0 = (double)ch0; lux1 = (double)ch1; ratio = lux1 / lux0; read_timing_reg(); lux0 *= (402.0/(double)integ_time); lux1 *= (402.0/(double)integ_time); lux0 /= gain; lux1 /= gain; //printf("Integ. Time = %f, Gain %d\r\n", integ_time, gain); if (ratio <= 0.5) { dlux = 0.03040 * lux0 - 0.06200 * lux0 * pow(ratio,1.4); } else if (ratio <= 0.61) { dlux = 0.02240 * lux0 - 0.03100 * lux1; } else if (ratio <= 0.80) { dlux = 0.01280 * lux0 - 0.01530 * lux1; } else if (ratio <= 1.30) { dlux = 0.00146 * lux0 - 0.00112 * lux1; } else { dlux = 0; } disable(); return (float)dlux; } float TSL2561::lux_auto(void) { uint32_t data; enableAutoRange(true); getEvent(&data); //printf("line:%d\r\n", __LINE__); return (float)data; } /**************************************************************************/ /*! @brief Initializes I2C connection and settings. Attempts to determine if the sensor is contactable, then sets up a default integration time and gain. Then powers down the chip. @returns True if sensor is found and initialized, false otherwise. */ /**************************************************************************/ bool TSL2561::init() { _TSL2561Initialised = false; _TSL2561AutoGain = false; _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; _TSL2561Gain = TSL2561_GAIN_1X; /* Make sure we're actually connected */ uint8_t x = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID); if (x & 0xF0 != 0x50) { // ID code for TSL2561 //printf("initialize error!\r\n"); return false; } //printf("ID=0x%02x\r\n", x); _TSL2561Initialised = true; /* Set default integration time and gain */ setIntegrationTime(_TSL2561IntegrationTime); setGain(_TSL2561Gain); read_timing_reg(); /* Note: by default, the device is in power down mode on bootup */ disable(); t.reset(); t.start(); //printf("Integ. Time = %d, Gain %d\r\n", // _TSL2561IntegrationTime, _TSL2561Gain); //printf("initialize finished!\r\n"); x = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING); //printf("TIMING REG=0x%02x\r\n", x); return true; } /**************************************************************************/ /*! @brief Enables or disables the auto-gain settings when reading data from the sensor @param enable Set to true to enable, False to disable */ /**************************************************************************/ void TSL2561::enableAutoRange(bool enable) { _TSL2561AutoGain = enable ? true : false; } /**************************************************************************/ /*! @brief Sets the integration time for the TSL2561. Higher time means more light captured (better for low light conditions) but will take longer to run readings. @param time The amount of time we'd like to add up values */ /**************************************************************************/ void TSL2561::setIntegrationTime(TSL2561IntegrationTime_t time) { /* Enable the device by setting the control bit to 0x03 */ enable(); /* Update the timing register */ write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | _TSL2561Gain); /* Update value placeholders */ _TSL2561IntegrationTime = time; /* Turn the device off to save power */ disable(); } /**************************************************************************/ /*! @brief Adjusts the gain on the TSL2561 (adjusts the sensitivity to light) @param gain The value we'd like to set the gain to */ /**************************************************************************/ void TSL2561::setGain(TSL2561Gain_t gain) { /* Enable the device by setting the control bit to 0x03 */ enable(); /* Update the timing register */ write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _TSL2561IntegrationTime | gain); /* Update value placeholders */ _TSL2561Gain = gain; /* Turn the device off to save power */ disable(); } /**************************************************************************/ /*! @brief Gets the broadband (mixed lighting) and IR only values from the TSL2561, adjusting gain if auto-gain is enabled @param broadband Pointer to a uint16_t we will fill with a sensor reading from the IR+visible light diode. @param ir Pointer to a uint16_t we will fill with a sensor the IR-only light diode. */ /**************************************************************************/ void TSL2561::getLuminosity (uint16_t *broadband, uint16_t *ir) { bool valid = false; /* If Auto gain disabled get a single reading and continue */ if(!_TSL2561AutoGain) { //printf("Get data without Auto gain\r\n"); getData (broadband, ir); return; } //printf("Get data with Auto gain\r\n"); /* Read data until we find a valid range */ bool _agcCheck = false; do { uint16_t _b, _ir; uint16_t _hi, _lo; TSL2561IntegrationTime_t _it = _TSL2561IntegrationTime; /* Get the hi/low threshold for the current integration time */ switch(_it) { case TSL2561_INTEGRATIONTIME_13MS: _hi = TSL2561_AGC_THI_13MS; _lo = TSL2561_AGC_TLO_13MS; break; case TSL2561_INTEGRATIONTIME_101MS: _hi = TSL2561_AGC_THI_101MS; _lo = TSL2561_AGC_TLO_101MS; break; default: _hi = TSL2561_AGC_THI_402MS; _lo = TSL2561_AGC_TLO_402MS; break; } getData(&_b, &_ir); /* Run an auto-gain check if we haven't already done so ... */ if (!_agcCheck) { if ((_b < _lo) && (_TSL2561Gain == TSL2561_GAIN_1X)) { /* Increase the gain and try again */ setGain(TSL2561_GAIN_16X); /* Drop the previous conversion results */ getData(&_b, &_ir); /* Set a flag to indicate we've adjusted the gain */ _agcCheck = true; } else if ((_b > _hi) && (_TSL2561Gain == TSL2561_GAIN_16X)) { /* Drop gain to 1x and try again */ setGain(TSL2561_GAIN_1X); /* Drop the previous conversion results */ getData(&_b, &_ir); /* Set a flag to indicate we've adjusted the gain */ _agcCheck = true; } else { /* Nothing to look at here, keep moving .... Reading is either valid, or we're already at the chips limits */ *broadband = _b; *ir = _ir; valid = true; } } else { /* If we've already adjusted the gain once, just return the new results. This avoids endless loops where a value is at one extreme pre-gain, and the the other extreme post-gain */ *broadband = _b; *ir = _ir; valid = true; } } while (!valid); } /**************************************************************************/ /*! Enables the device */ /**************************************************************************/ void TSL2561::enable(void) { /* Enable the device by setting the control bit to 0x03 */ write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON); } /**************************************************************************/ /*! Disables the device (putting it in lower power sleep mode) */ /**************************************************************************/ void TSL2561::disable(void) { /* Turn the device off to save power */ write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF); } /**************************************************************************/ /*! Private function to read luminosity on both channels */ /**************************************************************************/ void TSL2561::getData (uint16_t *broadband, uint16_t *ir) { /* Enable the device by setting the control bit to 0x03 */ enable(); /* Wait x ms for ADC to complete */ switch (_TSL2561IntegrationTime) { case TSL2561_INTEGRATIONTIME_13MS: wait_ms(TSL2561_DELAY_INTTIME_13MS); break; case TSL2561_INTEGRATIONTIME_101MS: wait_ms(TSL2561_DELAY_INTTIME_101MS); break; default: wait_ms(TSL2561_DELAY_INTTIME_402MS); break; } /* Reads a two byte value from channel 0 (visible + infrared) */ *broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW); /* Reads a two byte value from channel 1 (infrared) */ *ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW); /* Turn the device off to save power */ disable(); } /**************************************************************************/ /*! @brief Converts the raw sensor values to the standard SI lux equivalent. @param broadband The 16-bit sensor reading from the IR+visible light diode. @param ir The 16-bit sensor reading from the IR-only light diode. @returns The integer Lux value we calcuated. Returns 0 if the sensor is saturated and the values are unreliable, or 65536 if the sensor is saturated. */ /**************************************************************************/ /**************************************************************************/ /*! Returns */ /**************************************************************************/ uint32_t TSL2561::calculateLux(uint16_t broadband, uint16_t ir) { unsigned long chScale; unsigned long channel1; unsigned long channel0; //printf("line:%d\r\n", __LINE__); /* Make sure the sensor isn't saturated! */ uint16_t clipThreshold; //printf("_TSL2561IntegrationTime=%d\r\n", _TSL2561IntegrationTime); switch (_TSL2561IntegrationTime) { case TSL2561_INTEGRATIONTIME_13MS: clipThreshold = TSL2561_CLIPPING_13MS; chScale = TSL2561_LUX_CHSCALE_TINT0; //printf("line:%d\r\n", __LINE__); break; case TSL2561_INTEGRATIONTIME_101MS: clipThreshold = TSL2561_CLIPPING_101MS; chScale = TSL2561_LUX_CHSCALE_TINT1; break; default: clipThreshold = TSL2561_CLIPPING_402MS; chScale = (1 << TSL2561_LUX_CHSCALE); break; } //printf("clipThreshold=%d\r\n", clipThreshold); /* Return 65536 lux if the sensor is saturated */ if ((broadband > clipThreshold) || (ir > clipThreshold)) { //printf("line:%d\r\n", __LINE__); return 65536; } //printf("line:%d\r\n", __LINE__); //printf("chScale=%d\r\n", chScale); /* Scale for gain (1x or 16x) */ if (!_TSL2561Gain) { chScale = chScale << 4; } //printf("chScale=%d\r\n", chScale); /* Scale the channel values */ channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE; channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE; //printf("channel0=%d, channel1=%d\r\n", channel0, channel1); /* Find the ratio of the channel values (Channel1/Channel0) */ unsigned long ratio1 = 0; if (channel0 != 0) { ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0; } /* round the ratio value */ long ratio = (ratio1 + 1) >> 1; //printf("ratio1=%d, ratio=%d\r\n", ratio1, ratio); unsigned int b, m; #ifdef TSL2561_PACKAGE_CS //printf("line:%d\r\n", __LINE__); if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C)) { b=TSL2561_LUX_B1C; m=TSL2561_LUX_M1C; } else if (ratio <= TSL2561_LUX_K2C) { b=TSL2561_LUX_B2C; m=TSL2561_LUX_M2C; } else if (ratio <= TSL2561_LUX_K3C) { b=TSL2561_LUX_B3C; m=TSL2561_LUX_M3C; } else if (ratio <= TSL2561_LUX_K4C) { b=TSL2561_LUX_B4C; m=TSL2561_LUX_M4C; } else if (ratio <= TSL2561_LUX_K5C) { b=TSL2561_LUX_B5C; m=TSL2561_LUX_M5C; } else if (ratio <= TSL2561_LUX_K6C) { b=TSL2561_LUX_B6C; m=TSL2561_LUX_M6C; } else if (ratio <= TSL2561_LUX_K7C) { b=TSL2561_LUX_B7C; m=TSL2561_LUX_M7C; } else if (ratio > TSL2561_LUX_K8C) { b=TSL2561_LUX_B8C; m=TSL2561_LUX_M8C; } #else //printf("line:%d\r\n", __LINE__); if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T)) { b=TSL2561_LUX_B1T; m=TSL2561_LUX_M1T; } else if (ratio <= TSL2561_LUX_K2T) { b=TSL2561_LUX_B2T; m=TSL2561_LUX_M2T; } else if (ratio <= TSL2561_LUX_K3T) { b=TSL2561_LUX_B3T; m=TSL2561_LUX_M3T; } else if (ratio <= TSL2561_LUX_K4T) { b=TSL2561_LUX_B4T; m=TSL2561_LUX_M4T; } else if (ratio <= TSL2561_LUX_K5T) { b=TSL2561_LUX_B5T; m=TSL2561_LUX_M5T; } else if (ratio <= TSL2561_LUX_K6T) { b=TSL2561_LUX_B6T; m=TSL2561_LUX_M6T; } else if (ratio <= TSL2561_LUX_K7T) { b=TSL2561_LUX_B7T; m=TSL2561_LUX_M7T; } else if (ratio > TSL2561_LUX_K8T) { b=TSL2561_LUX_B8T; m=TSL2561_LUX_M8T; } #endif long temp; temp = ((channel0 * b) - (channel1 * m)); /* Do not allow negative lux value */ if (temp < 0L) { temp = 0; } //printf("line:%d\r\n", __LINE__); /* Round lsb (2^(LUX_SCALE-1)) */ temp += (1 << (TSL2561_LUX_LUXSCALE-1)); /* Strip off fractional portion */ uint32_t lux = temp >> TSL2561_LUX_LUXSCALE; /* Signal I2C had no errors */ //printf("Lux=%d\r\n", lux); return lux; } /**************************************************************************/ /*! @brief Gets the most recent sensor event @param event Pointer to a sensor_event_t type that will be filled with the lux value, timestamp, data type and sensor ID. @returns True if sensor reading is between 0 and 65535 lux, false if sensor is saturated */ /**************************************************************************/ bool TSL2561::getEvent(uint32_t *event) { uint16_t broadband, ir; /* Calculate the actual lux value */ getLuminosity(&broadband, &ir); //printf("broadband=%d, ir=%d\r\n", broadband, ir); *event = calculateLux(broadband, ir); //printf("LUX=%f\r\n", event->light); //printf("LUX=%d\r\n", *event); //printf("line:%d\r\n", __LINE__); if (*event == 65536) { //printf("line:%d\r\n", __LINE__); return false; } //printf("line:%d\r\n", __LINE__); return true; } /**************************************************************************/ /*! @brief Gets the sensor_t data @param sensor A pointer to a sensor_t structure that we will fill with details about the TSL2561 and its capabilities */ /**************************************************************************/ void TSL2561::getSensor(sensor_t *sensor) { /* Insert the sensor name in the fixed length char array */ //sensor->version = 1; sensor->min_delay = 0; sensor->max_value = 17000.0; /* Based on trial and error ... confirm! */ sensor->min_value = 1.0; sensor->resolution = 1.0; } /*========================================================================*/ /* PRIVATE FUNCTIONS */ /*========================================================================*/ /**************************************************************************/ /*! @brief Writes a register and an 8 bit value over I2C @param reg I2C register to write the value to @param value The 8-bit value we're writing to the register */ /**************************************************************************/ void TSL2561::write8 (uint8_t reg, uint8_t value) { dt[0] = reg; dt[1] = value; _i2c.write((int)_addr, (char *)dt, 2, false); } /**************************************************************************/ /*! @brief Reads an 8 bit value over I2C @param reg I2C register to read from @returns 8-bit value containing single byte data read */ /**************************************************************************/ uint8_t TSL2561::read8(uint8_t reg) { dt[0] = reg; _i2c.write((int)_addr, (char *)dt, 1, true); _i2c.read(_addr, (char *)dt, 1, false); return dt[0]; } /**************************************************************************/ /*! @brief Reads a 16 bit values over I2C @param reg I2C register to read from @returns 16-bit value containing 2-byte data read */ /**************************************************************************/ uint16_t TSL2561::read16(uint8_t reg) { dt[0] = reg; _i2c.write((int)_addr, (char *)dt, 1, true); _i2c.read(_addr, (char *)dt, 2, false); uint16_t data = ((uint16_t)dt[1] << 8) + dt[0]; return data; } /*========================================================================*/ /* JH1PJL Original Functions -> Keep compacibility for older revision */ /*========================================================================*/ /////////////// Timing Register /////////////////////////// uint8_t TSL2561::set_timing_reg(uint8_t parameter) { enable(); write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, parameter); return read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING); } uint8_t TSL2561::read_timing_reg(void) { uint8_t i, data; data = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING); if (data & TSL2561_GAIN_16X) { gain = 16; _TSL2561Gain = TSL2561_GAIN_16X; } else { gain = 1; _TSL2561Gain = TSL2561_GAIN_1X; } i = data & 0x3; switch (i) { case 0: integ_time = 13.7; _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; break; case 1: integ_time = 101.0; _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_101MS; break; case 2: integ_time = 402.0; _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_402MS; break; default: integ_time = 0; _TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; break; } return dt[0]; } /////////////// ID //////////////////////////////////////// uint8_t TSL2561::read_ID() { id_number = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID); return id_number; } uint8_t TSL2561::who_am_i() { read_ID(); if ((id_number >> 4) == I_AM_TSL2561CS) { return 1; } else if ((id_number >> 4) == I_AM_TSL2561T_FN_CL) { return 1; } else { return 0; } } /////////////// Power ON/OFF ////////////////////////////// void TSL2561::power_up() { enable(); } void TSL2561::power_down() { disable(); } /////////////// I2C Freq. ///////////////////////////////// void TSL2561::frequency(int hz) { _i2c.frequency(hz); }