A lux sensor library
Diff: TSL2561.cpp
- Revision:
- 2:c45d34e9c3f0
- Parent:
- 1:52b855c13204
- Child:
- 3:5b5911bfc644
--- a/TSL2561.cpp Tue Aug 04 17:15:01 2015 +0000 +++ b/TSL2561.cpp Wed Aug 12 19:57:46 2015 +0000 @@ -26,260 +26,245 @@ #include "TSL2561.h" TSL2561::TSL2561(PinName sda, PinName scl, char slave_address) -: - i2c_p(new I2C(sda, scl)), + : + i2c_p(new I2C(sda, scl)), i2c(*i2c_p), address(slave_address), - t_fine(0), - _integration(TSL2561_INTEGRATIONTIME_13MS), - _gain(TSL2561_GAIN_16X), - _initialized(false) + _integration(TSL2561_INTEGRATIONTIME_402MS), + _gain(TSL2561_GAIN_0X) { - //enable(); + initialize(); } TSL2561::TSL2561(I2C &i2c_obj, char slave_address) -: - i2c_p(NULL), + : + i2c_p(NULL), i2c(i2c_obj), address(slave_address), - t_fine(0), - _integration(TSL2561_INTEGRATIONTIME_13MS), - _gain(TSL2561_GAIN_16X), - _initialized(false) + _integration(TSL2561_INTEGRATIONTIME_402MS), + _gain(TSL2561_GAIN_0X) { - //enable(); + initialize(); } -//TSL2561::~TSL2561() -//{ -// if (NULL != i2c_p) -// delete i2c_p; -//} +TSL2561::~TSL2561() +{ + if (NULL != i2c_p) { + delete i2c_p; + } +} //The register addresses are all passed to i2c write via the bottum 4 bits of the command register //check and see if it is reading the correct id register (should read (0x10) for register value -bool TSL2561::begin(void) +bool TSL2561::initialize(void) { - //float idf; + float idf; //debug uint16_t idu; char ID_REGISTER[1] = {TSL2561_REGISTER_ID}; i2c.write(address, ID_REGISTER, 1, true); char DATA[1] = {0}; i2c.read(address, DATA, 1, false); idu = DATA[0]; - //idf = (float)idu; - - if (idu & 0x0A) - { - //pc.printf("FOUND TSL2561\r\n"); - } - else - { - //pc.printf("NOT FOUND TSL2561\r\n"); - //pc.printf("%4.0f ID\n",idf); + idf = (float)idu; //debug + + if (idu & 0x0A) { + pc.printf("FOUND TSL2561\r\n"); //debug + } else { + pc.printf("NOT FOUND TSL2561\r\n"); //debug + pc.printf("%4.0f ID\n",idf); //debug return false; } - _initialized = true; - + //set default integration time and gain - setTiming(_integration); - setGain(_gain); - + setTimingGain(_integration, _gain); + disable(); - + return true; } - - + + void TSL2561::enable(void) { - if (!_initialized) - { - begin(); - } - //power on device by writing 0x03 to the control register char CONTROL_ON[2] = {TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON}; i2c.write(address, CONTROL_ON, 2); - + //***//Comment this wait out and the disable function to reduce read time, at the cost of power consumption. + //wait_ms(400); //It takes a sec for the TSL to start up. + //***// //This sets everything to default values. (402ms integration time, interupts disabled etc.) } - + void TSL2561::disable(void) { - if (!_initialized) - { - begin(); - } - - //power off device by writing 0x00 in control register - char CONTROL_OFF[2] = {TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF}; - i2c.write(address, CONTROL_OFF, 2); -} + //power off device by writing 0x00 in control register + //***// + //char CONTROL_OFF[2] = {TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF}; + //i2c.write(address, CONTROL_OFF, 2); + //***// +} -//function that sets gain to x16 -void TSL2561::setGain(tsl2561Gain_t gain) +void TSL2561::setTimingGain(tsl2561IntegrationTime_t integration, tsl2561Gain_t gain) { - if(!_initialized) - { - begin(); - } - enable(); - _gain = gain; - - char GAIN_SETTING[2] = {TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _integration | _gain}; - i2c.write(address, GAIN_SETTING, 2); - - disable(); -} - -void TSL2561::setTiming(tsl2561IntegrationTime_t integration) -{ - if(!_initialized) - { - begin(); - } enable(); _integration = integration; - + _gain = gain; + char TIME_SETTING[2] = {TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _integration | _gain}; i2c.write(address, TIME_SETTING, 2); - + disable(); } + + + + + + + + + uint32_t TSL2561::calculateLux(uint16_t ch0, uint16_t ch1) { unsigned long chScale; unsigned long channel1; unsigned long channel0; - + //scale the measurment if the integration time is not 402 ms - switch (_integration) - { + switch (_integration) { case TSL2561_INTEGRATIONTIME_13MS: - chScale = CHSCALE_TINT0; - break; - + chScale = CHSCALE_TINT0; + break; + case TSL2561_INTEGRATIONTIME_101MS: - chScale = CHSCALE_TINT1; - break; - + chScale = CHSCALE_TINT1; + break; + default: //No scaling when integration time is set to 402 ms - chScale = (1 << CH_SCALE); - break; + chScale = (1 << CH_SCALE); + break; } - + //scale the measurment if gain is NOT x16 - if(!_gain) - { + if(!_gain) { chScale = chScale << 4; } - - //scale the channel values + + //scale the channel values channel0 = (ch0 * chScale) >> CH_SCALE; channel1 = (ch1 * chScale) >> CH_SCALE; - + //Find the ratio of the channel values (Channel 11/Channel 10) to set coeficients unsigned long ratio1 = 0; - if (channel0 != 0) - { + if (channel0 != 0) { ratio1 = (channel1 << (RATIO_SCALE+1))/channel0; } - + //round the ratio value unsigned long ratio = (ratio1 + 1) >> 1; - + unsigned int b=0, m=0; - + //check which coefficients the ratio dictates - + #ifdef TSL2561_PACKAGE_CS //Adafruit sells the T package but these coefficients are for the CS package - if ((ratio >= 0) && (ratio <= K1C)) - {b = B1C; m = M1C;} - else if (ratio <= K2C) - {b = B2C; m = M2C;} - else if (ratio <= K3C) - {b = B3C; m = M3C;} - else if (ratio <= K4C) - {b = B4C; m = M4C;} - else if (ratio <= K5C) - {b = B5C; m = M5C;} - else if (ratio <= K6C) - {b = B6C; m = M6C;} - else if (ratio <= K7C) - {b = B7C; m = M7C;} - else if (ratio <= K8C) - {b = B8C; m = M8C;} + if ((ratio >= 0) && (ratio <= K1C)) { + b = B1C; + m = M1C; + } else if (ratio <= K2C) { + b = B2C; + m = M2C; + } else if (ratio <= K3C) { + b = B3C; + m = M3C; + } else if (ratio <= K4C) { + b = B4C; + m = M4C; + } else if (ratio <= K5C) { + b = B5C; + m = M5C; + } else if (ratio <= K6C) { + b = B6C; + m = M6C; + } else if (ratio <= K7C) { + b = B7C; + m = M7C; + } else if (ratio <= K8C) { + b = B8C; + m = M8C; + } #else - if ((ratio >= 0) && (ratio <= K1T)) //Coefficients for all other packages, will probably use these - {b = B1T; m = M1T;} - else if (ratio <= K2T) - {b = B2T; m = M2T;} - else if (ratio <= K3T) - {b = B3T; m = M3T;} - else if (ratio <= K4T) - {b = B4T; m = M4T;} - else if (ratio <= K5T) - {b = B5T; m = M5T;} - else if (ratio <= K6T) - {b = B6T; m = M6T;} - else if (ratio <= K7T) - {b = B7T; m = M7T;} - else if (ratio <= K8T) - {b = B8T; m = M8T;} -#endif + if ((ratio >= 0) && (ratio <= K1T)) { //Coefficients for all other packages, will probably use these + b = B1T; + m = M1T; + } else if (ratio <= K2T) { + b = B2T; + m = M2T; + } else if (ratio <= K3T) { + b = B3T; + m = M3T; + } else if (ratio <= K4T) { + b = B4T; + m = M4T; + } else if (ratio <= K5T) { + b = B5T; + m = M5T; + } else if (ratio <= K6T) { + b = B6T; + m = M6T; + } else if (ratio <= K7T) { + b = B7T; + m = M7T; + } else if (ratio <= K8T) { + b = B8T; + m = M8T; + } +#endif unsigned long temp_val; temp_val = ((channel0*b) - (channel1*m)); - + //do not allow negative lux value - if (temp_val < 0) - { + if (temp_val < 0) { temp_val = 0; } - + //round lsb (2^(LUX_SCALE-1)) temp_val += (1 << (LUX_SCALE-1)); - + //strip off fractional portion uint32_t lux = temp_val >> LUX_SCALE; - + //signal I2C had no errors return lux; } uint32_t TSL2561::getFullLuminosity (void) { - if (_initialized) - { - begin(); - } // Enable the device by setting the control bit to 0x03 enable(); - + // Wait x ms for ADC to complete - switch (_integration) - { + switch (_integration) { case TSL2561_INTEGRATIONTIME_13MS: - wait(14/1000); - break; + wait(14/1000); + break; case TSL2561_INTEGRATIONTIME_101MS: - wait(102/1000); - break; + wait(102/1000); + break; default: - wait(403/1000); - break; + wait(403/1000); + break; } - + uint32_t x; //will store data for luminosity //uint16_t x1; //will store data from channel 1 (optional to store data in steps) //uint16_t x0; //will store data from channel 0 (I just modified x) - - + + //Address the Ch1 lower data register and configure for Read Word char ch1_reg[1] = {TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW}; //Create array to store data @@ -289,7 +274,7 @@ // Merge bytes x = ch1_data[0] | (ch1_data[1] << 8); // int x <<= 16; - + //Address the Ch1 lower data register and configure for Read Word char ch0_reg[1] = {TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW}; //Create array to store data @@ -298,50 +283,56 @@ i2c.read(address, ch0_data, 2); // Merge bytes of channel 0 and channel 1 x |= ch0_data[0] | (ch0_data[1] << 8); // int - + disable(); - + return x; } - + uint16_t TSL2561::getLuminosity (uint8_t channel) { uint32_t x = getFullLuminosity(); - - if (channel == 0) - { - // Reads two byte value from channel 0 (visible + infrared) - return (x & 0xFFFF); - } - else if (channel == 1) - { - // Reads two byte value from channel 1 (infrared) - return (x >> 16); - } - else if (channel == 2) - { - // Reads all and subtracts out just the visible - return ( (x & 0xFFFF) - (x >> 16)); + + if (channel == 0) { + // Reads two byte value from channel 0 (visible + infrared) + return (x & 0xFFFF); + } else if (channel == 1) { + // Reads two byte value from channel 1 (infrared) + return (x >> 16); + } else if (channel == 2) { + // Reads all and subtracts out just the visible + return ( (x & 0xFFFF) - (x >> 16)); } // unknown channel return 0; } - - - - - - - - - - - - +void TSL2561::read_lux(void) +{ + uint32_t full_lums; + //set to default gain (Note: going high gain to low is slower but more reliable, low gain to high gain is faster but less reliable) + setTimingGain(TSL2561_INTEGRATIONTIME_101MS, TSL2561_GAIN_16X); // start at high gain and long readings + //decreas gain/time if reading is to high (diable this block and change that^ line for fixed gain) + //take reading +read_again: + full_lums = getFullLuminosity(); + channal0 = (full_lums & 0xFFFF); + channal1 = (full_lums >> 16); + //If ir, or vis and ir, are within 5% of max then decreas the gain/time and repeat + //Pick the corect time to match ^ + //if(((channal0 > 4794) | (channal1 > 4792)) & (_gain != TSL2561_GAIN_0X)){ //13ms + if(((channal0 > 35318) | (channal1 > 35318)) & (_gain != TSL2561_GAIN_0X)){ //101ms + //if(((channal0 > 62258) | (channal1 > 62258)) & (_gain != TSL2561_GAIN_0X)){ //402ms + setTimingGain(_integration, TSL2561_GAIN_0X); + goto read_again; + } - + //calculate lux from reading + lux = calculateLux(channal0, channal1); + pc.printf("gain: %d time: %d, lux:%d\r\n", _gain, _integration, lux); - \ No newline at end of file +} + +