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
Revision 5:5b1b625fda6f, committed 2018-09-21
- Comitter:
- kenjiArai
- Date:
- Fri Sep 21 22:57:07 2018 +0000
- Parent:
- 4:05d322353720
- Commit message:
- based on Adafruit program and keep interface functions
Changed in this revision
diff -r 05d322353720 -r 5b1b625fda6f Original/Adafruit_Sensor_h.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Original/Adafruit_Sensor_h.txt Fri Sep 21 22:57:07 2018 +0000 @@ -0,0 +1,154 @@ +/* +* Copyright (C) 2008 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software< /span> +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and + * extended sensor support to include color, voltage and current */ + +#ifndef _ADAFRUIT_SENSOR_H +#define _ADAFRUIT_SENSOR_H + +#if ARDUINO >= 100 + #include "Arduino.h" + #include "Print.h" +#else + #include "WProgram.h" +#endif + +/* Intentionally modeled after sensors.h in the Android API: + * https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */ + +/* Constants */ +#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */ +#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */ +#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */ +#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH) +#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */ +#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */ +#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */ +#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */ +#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */ + +/** Sensor types */ +typedef enum +{ + SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */ + SENSOR_TYPE_MAGNETIC_FIELD = (2), + SENSOR_TYPE_ORIENTATION = (3), + SENSOR_TYPE_GYROSCOPE = (4), + SENSOR_TYPE_LIGHT = (5), + SENSOR_TYPE_PRESSURE = (6), + SENSOR_TYPE_PROXIMITY = (8), + SENSOR_TYPE_GRAVITY = (9), + SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */ + SENSOR_TYPE_ROTATION_VECTOR = (11), + SENSOR_TYPE_RELATIVE_HUMIDITY = (12), + SENSOR_TYPE_AMBIENT_TEMPERATURE = (13), + SENSOR_TYPE_VOLTAGE = (15), + SENSOR_TYPE_CURRENT = (16), + SENSOR_TYPE_COLOR = (17) +} sensors_type_t; + +/** struct sensors_vec_s is used to return a vector in a common format. */ +typedef struct { + union { + float v[3]; + struct { + float x; + float y; + float z; + }; + /* Orientation sensors */ + struct { + float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90�<=roll<=90� */ + float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180�<=pitch<=180�) */ + float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359� */ + }; + }; + int8_t status; + uint8_t reserved[3]; +} sensors_vec_t; + +/** struct sensors_color_s is used to return color data in a common format. */ +typedef struct { + union { + float c[3]; + /* RGB color space */ + struct { + float r; /**< Red component */ + float g; /**< Green component */ + float b; /**< Blue component */ + }; + }; + uint32_t rgba; /**< 24-bit RGBA value */ +} sensors_color_t; + +/* Sensor event (36 bytes) */ +/** struct sensor_event_s is used to provide a single sensor event in a common format. */ +typedef struct +{ + int32_t version; /**< must be sizeof(struct sensors_event_t) */ + int32_t sensor_id; /**< unique sensor identifier */ + int32_t type; /**< sensor type */ + int32_t reserved0; /**< reserved */ + int32_t timestamp; /**< time is in milliseconds */ + union + { + float data[4]; + sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */ + sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */ + sensors_vec_t orientation; /**< orientation values are in degrees */ + sensors_vec_t gyro; /**< gyroscope values are in rad/s */ + float temperature; /**< temperature is in degrees centigrade (Celsius) */ + float distance; /**< distance in centimeters */ + float light; /**< light in SI lux units */ + float pressure; /**< pressure in hectopascal (hPa) */ + float relative_humidity; /**< relative humidity in percent */ + float current; /**< current in milliamps (mA) */ + float voltage; /**< voltage in volts (V) */ + sensors_color_t color; /**< color in RGB component values */ + }; +} sensors_event_t; + +/* Sensor details (40 bytes) */ +/** struct sensor_s is used to describe basic information about a specific sensor. */ +typedef struct +{ + char name[12]; /**< sensor name */ + int32_t version; /**< version of the hardware + driver */ + int32_t sensor_id; /**< unique sensor identifier */ + int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */ + float max_value; /**< maximum value of this sensor's value in SI units */ + float min_value; /**< minimum value of this sensor's value in SI units */ + float resolution; /**< smallest difference between two values reported by this sensor */ + int32_t min_delay; /**< min delay in microseconds between events. zero = not a constant rate */ +} sensor_t; + +class Adafruit_Sensor { + public: + // Constructor(s) + Adafruit_Sensor() {} + virtual ~Adafruit_Sensor() {} + + // These must be defined by the subclass + virtual void enableAutoRange(bool enabled) {}; + virtual bool getEvent(sensors_event_t*) = 0; + virtual void getSensor(sensor_t*) = 0; + + private: + bool _autoRange; +}; + +#endif \ No newline at end of file
diff -r 05d322353720 -r 5b1b625fda6f Original/Adafruit_TSL2561_U_cpp.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Original/Adafruit_TSL2561_U_cpp.txt Fri Sep 21 22:57:07 2018 +0000 @@ -0,0 +1,575 @@ +/*! + * @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) +*/ +/**************************************************************************/ + +#include "Adafruit_TSL2561_U.h" + +/*========================================================================*/ +/* CONSTRUCTORS */ +/*========================================================================*/ + +/**************************************************************************/ +/*! + @brief Constructor + @param addr The I2C address this chip can be found on, 0x29, 0x39 or 0x49 + @param sensorID An optional ID that will be placed in sensor events to help + keep track if you have many sensors in use +*/ +/**************************************************************************/ +Adafruit_TSL2561_Unified::Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID) +{ + _addr = addr; + _tsl2561Initialised = false; + _tsl2561AutoGain = false; + _tsl2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS; + _tsl2561Gain = TSL2561_GAIN_1X; + _tsl2561SensorID = sensorID; +} + +/*========================================================================*/ +/* PUBLIC FUNCTIONS */ +/*========================================================================*/ + +/**************************************************************************/ +/*! + @brief Initializes I2C and configures the sensor with default Wire I2C + (call this function before doing anything else) + @returns True if sensor is found and initialized, false otherwise. +*/ +/**************************************************************************/ +boolean Adafruit_TSL2561_Unified::begin() +{ + _i2c = &Wire; + _i2c->begin(); + return init(); +} + +/**************************************************************************/ +/*! + @brief Initializes I2C and configures the sensor with provided I2C device + (call this function before doing anything else) + @param theWire A pointer to any I2C interface (e.g. &Wire1) + @returns True if sensor is found and initialized, false otherwise. +*/ +/**************************************************************************/ +boolean Adafruit_TSL2561_Unified::begin(TwoWire *theWire) +{ + _i2c = theWire; + _i2c-> begin(); + return init(); +} + +/**************************************************************************/ +/*! + @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. +*/ +/**************************************************************************/ +boolean Adafruit_TSL2561_Unified::init() +{ + /* Make sure we're actually connected */ + uint8_t x = read8(TSL2561_REGISTER_ID); + if (x & 0xF0 != 0x10) { // ID code for TSL2561 + return false; + } + _tsl2561Initialised = true; + + /* Set default integration time and gain */ + setIntegrationTime(_tsl2561IntegrationTime); + setGain(_tsl2561Gain); + + /* Note: by default, the device is in power down mode on bootup */ + disable(); + + 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 Adafruit_TSL2561_Unified::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 Adafruit_TSL2561_Unified::setIntegrationTime(tsl2561IntegrationTime_t time) +{ + if (!_tsl2561Initialised) begin(); + + /* 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 Adafruit_TSL2561_Unified::setGain(tsl2561Gain_t gain) +{ + if (!_tsl2561Initialised) begin(); + + /* 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 Adafruit_TSL2561_Unified::getLuminosity (uint16_t *broadband, uint16_t *ir) +{ + bool valid = false; + + if (!_tsl2561Initialised) begin(); + + /* If Auto gain disabled get a single reading and continue */ + if(!_tsl2561AutoGain) + { + getData (broadband, ir); + return; + } + + /* 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 Adafruit_TSL2561_Unified::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 Adafruit_TSL2561_Unified::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 Adafruit_TSL2561_Unified::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: + delay(TSL2561_DELAY_INTTIME_13MS); // KTOWN: Was 14ms + break; + case TSL2561_INTEGRATIONTIME_101MS: + delay(TSL2561_DELAY_INTTIME_101MS); // KTOWN: Was 102ms + break; + default: + delay(TSL2561_DELAY_INTTIME_402MS); // KTOWN: Was 403ms + 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 Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband, uint16_t ir) +{ + unsigned long chScale; + unsigned long channel1; + unsigned long channel0; + + /* Make sure the sensor isn't saturated! */ + uint16_t clipThreshold; + switch (_tsl2561IntegrationTime) + { + case TSL2561_INTEGRATIONTIME_13MS: + clipThreshold = TSL2561_CLIPPING_13MS; + break; + case TSL2561_INTEGRATIONTIME_101MS: + clipThreshold = TSL2561_CLIPPING_101MS; + break; + default: + clipThreshold = TSL2561_CLIPPING_402MS; + break; + } + + /* Return 65536 lux if the sensor is saturated */ + if ((broadband > clipThreshold) || (ir > clipThreshold)) + { + return 65536; + } + + /* Get the correct scale depending on the intergration time */ + switch (_tsl2561IntegrationTime) + { + case TSL2561_INTEGRATIONTIME_13MS: + chScale = TSL2561_LUX_CHSCALE_TINT0; + break; + case TSL2561_INTEGRATIONTIME_101MS: + chScale = TSL2561_LUX_CHSCALE_TINT1; + break; + default: /* No scaling ... integration time = 402ms */ + chScale = (1 << TSL2561_LUX_CHSCALE); + break; + } + + /* Scale for gain (1x or 16x) */ + if (!_tsl2561Gain) chScale = chScale << 4; + + /* Scale the channel values */ + channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE; + channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE; + + /* 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 */ + unsigned long ratio = (ratio1 + 1) >> 1; + + unsigned int b, m; + +#ifdef TSL2561_PACKAGE_CS + 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 + 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 + + unsigned long temp; + temp = ((channel0 * b) - (channel1 * m)); + + /* Do not allow negative lux value */ + if (temp < 0) temp = 0; + + /* 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 */ + 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 Adafruit_TSL2561_Unified::getEvent(sensors_event_t *event) +{ + uint16_t broadband, ir; + + /* Clear the event */ + memset(event, 0, sizeof(sensors_event_t)); + + event->version = sizeof(sensors_event_t); + event->sensor_id = _tsl2561SensorID; + event->type = SENSOR_TYPE_LIGHT; + event->timestamp = millis(); + + /* Calculate the actual lux value */ + getLuminosity(&broadband, &ir); + event->light = calculateLux(broadband, ir); + + if (event->light == 65536) { + return false; + } + 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 Adafruit_TSL2561_Unified::getSensor(sensor_t *sensor) +{ + /* Clear the sensor_t object */ + memset(sensor, 0, sizeof(sensor_t)); + + /* Insert the sensor name in the fixed length char array */ + strncpy (sensor->name, "TSL2561", sizeof(sensor->name) - 1); + sensor->name[sizeof(sensor->name)- 1] = 0; + sensor->version = 1; + sensor->sensor_id = _tsl2561SensorID; + sensor->type = SENSOR_TYPE_LIGHT; + 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 Adafruit_TSL2561_Unified::write8 (uint8_t reg, uint8_t value) +{ + _i2c->beginTransmission(_addr); + _i2c->write(reg); + _i2c->write(value); + _i2c->endTransmission(); +} + +/**************************************************************************/ +/*! + @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 Adafruit_TSL2561_Unified::read8(uint8_t reg) +{ + _i2c->beginTransmission(_addr); + _i2c->write(reg); + _i2c->endTransmission(); + + _i2c->requestFrom(_addr, 1); + return _i2c-> read(); +} + +/**************************************************************************/ +/*! + @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 Adafruit_TSL2561_Unified::read16(uint8_t reg) +{ + uint16_t x, t; + + _i2c->beginTransmission(_addr); + _i2c->write(reg); + _i2c->endTransmission(); + + _i2c->requestFrom(_addr, 2); + t = _i2c->read(); + x = _i2c->read(); + x <<= 8; + x |= t; + return x; +}
diff -r 05d322353720 -r 5b1b625fda6f Original/Adafruit_TSL2561_U_h.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Original/Adafruit_TSL2561_U_h.txt Fri Sep 21 22:57:07 2018 +0000 @@ -0,0 +1,203 @@ +/*! + * @file Adafruit_TSL2561_U.h + * + * This is part of Adafruit's FXOS8700 driver for the Arduino platform. It is + * designed specifically to work with the Adafruit FXOS8700 breakout: + * https://www.adafruit.com/products/3463 + * + * 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! + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ + +#ifndef ADAFRUIT_TSL2561_H_ +#define ADAFRUIT_TSL2561_H_ + +#include <Arduino.h> +#include <Adafruit_Sensor.h> +#include <Wire.h> + +#define TSL2561_VISIBLE 2 ///< channel 0 - channel 1 +#define TSL2561_INFRARED 1 ///< channel 1 +#define TSL2561_FULLSPECTRUM 0 ///< channel 0 + +// I2C address options +#define TSL2561_ADDR_LOW (0x29) ///< Default address (pin pulled low) +#define TSL2561_ADDR_FLOAT (0x39) ///< Default address (pin left floating) +#define TSL2561_ADDR_HIGH (0x49) ///< Default address (pin pulled high) + +// Lux calculations differ slightly for CS package +//#define TSL2561_PACKAGE_CS ///< Chip scale package +#define TSL2561_PACKAGE_T_FN_CL ///< Dual Flat No-Lead package + +#define TSL2561_COMMAND_BIT (0x80) ///< Must be 1 +#define TSL2561_CLEAR_BIT (0x40) ///< Clears any pending interrupt (write 1 to clear) +#define TSL2561_WORD_BIT (0x20) ///< 1 = read/write word (rather than byte) +#define TSL2561_BLOCK_BIT (0x10) ///< 1 = using block read/write + +#define TSL2561_CONTROL_POWERON (0x03) ///< Control register setting to turn on +#define TSL2561_CONTROL_POWEROFF (0x00) ///< Control register setting to turn off + +#define TSL2561_LUX_LUXSCALE (14) ///< Scale by 2^14 +#define TSL2561_LUX_RATIOSCALE (9) ///< Scale ratio by 2^9 +#define TSL2561_LUX_CHSCALE (10) ///< Scale channel values by 2^10 +#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) ///< 322/11 * 2^TSL2561_LUX_CHSCALE +#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) ///< 322/81 * 2^TSL2561_LUX_CHSCALE + +// 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 +#define TSL2561_CLIPPING_13MS (4900) ///< # Counts that trigger a change in gain/integration +#define TSL2561_CLIPPING_101MS (37000) ///< # Counts that trigger a change in gain/integration +#define TSL2561_CLIPPING_402MS (65000) ///< # Counts that trigger a change in gain/integration + +// 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 + +/** TSL2561 I2C Registers */ +enum +{ + TSL2561_REGISTER_CONTROL = 0x00, // Control/power register + TSL2561_REGISTER_TIMING = 0x01, // Set integration time register + TSL2561_REGISTER_THRESHHOLDL_LOW = 0x02, // Interrupt low threshold low-byte + TSL2561_REGISTER_THRESHHOLDL_HIGH = 0x03, // Interrupt low threshold high-byte + TSL2561_REGISTER_THRESHHOLDH_LOW = 0x04, // Interrupt high threshold low-byte + TSL2561_REGISTER_THRESHHOLDH_HIGH = 0x05, // Interrupt high threshold high-byte + TSL2561_REGISTER_INTERRUPT = 0x06, // Interrupt settings + TSL2561_REGISTER_CRC = 0x08, // Factory use only + TSL2561_REGISTER_ID = 0x0A, // TSL2561 identification setting + TSL2561_REGISTER_CHAN0_LOW = 0x0C, // Light data channel 0, low byte + TSL2561_REGISTER_CHAN0_HIGH = 0x0D, // Light data channel 0, high byte + TSL2561_REGISTER_CHAN1_LOW = 0x0E, // Light data channel 1, low byte + TSL2561_REGISTER_CHAN1_HIGH = 0x0F // Light data channel 1, high byte +}; + +/** Three options for how long to integrate readings for */ +typedef enum +{ + TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms + TSL2561_INTEGRATIONTIME_101MS = 0x01, // 101ms + TSL2561_INTEGRATIONTIME_402MS = 0x02 // 402ms +} +tsl2561IntegrationTime_t; + +/** TSL2561 offers 2 gain settings */ +typedef enum +{ + TSL2561_GAIN_1X = 0x00, // No gain + TSL2561_GAIN_16X = 0x10, // 16x gain +} +tsl2561Gain_t; + + + +/**************************************************************************/ +/*! + @brief Class that stores state and functions for interacting with TSL2561 Light Sensor +*/ +/**************************************************************************/ +class Adafruit_TSL2561_Unified : public Adafruit_Sensor { + public: + Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID = -1); + boolean begin(void); + boolean begin(TwoWire *theWire); + boolean init(); + + /* TSL2561 Functions */ + void enableAutoRange(bool enable); + void setIntegrationTime(tsl2561IntegrationTime_t time); + void setGain(tsl2561Gain_t gain); + void getLuminosity (uint16_t *broadband, uint16_t *ir); + uint32_t calculateLux(uint16_t broadband, uint16_t ir); + + /* Unified Sensor API Functions */ + bool getEvent(sensors_event_t*); + void getSensor(sensor_t*); + + private: + TwoWire *_i2c; + + int8_t _addr; + boolean _tsl2561Initialised; + boolean _tsl2561AutoGain; + tsl2561IntegrationTime_t _tsl2561IntegrationTime; + tsl2561Gain_t _tsl2561Gain; + int32_t _tsl2561SensorID; + + void enable (void); + void disable (void); + void write8 (uint8_t reg, uint8_t value); + uint8_t read8 (uint8_t reg); + uint16_t read16 (uint8_t reg); + void getData (uint16_t *broadband, uint16_t *ir); +}; + +#endif // ADAFRUIT_TSL2561_H
diff -r 05d322353720 -r 5b1b625fda6f Original/sensorapi_ino.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Original/sensorapi_ino.txt Fri Sep 21 22:57:07 2018 +0000 @@ -0,0 +1,140 @@ +#include <Wire.h> +#include <Adafruit_Sensor.h> +#include <Adafruit_TSL2561_U.h> + +/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor), + which provides a common 'type' for sensor data and some helper functions. + + To use this driver you will also need to download the Adafruit_Sensor + library and include it in your libraries folder. + + You should also assign a unique ID to this sensor for use with + the Adafruit Sensor API so that you can identify this particular + sensor in any data logs, etc. To assign a unique ID, simply + provide an appropriate value in the constructor below (12345 + is used by default in this example). + + Connections + =========== + Connect SCL to I2C SCL Clock + Connect SDA to I2C SDA Data + Connect VDD to 3.3V or 5V (whatever your logic level is) + Connect GROUND to common ground + + I2C Address + =========== + The address will be different depending on whether you leave + the ADDR pin floating (addr 0x39), or tie it to ground or vcc. + The default addess is 0x39, which assumes the ADDR pin is floating + (not connected to anything). If you set the ADDR pin high + or low, use TSL2561_ADDR_HIGH (0x49) or TSL2561_ADDR_LOW + (0x29) respectively. + + History + ======= + 2013/JAN/31 - First version (KTOWN) +*/ + +Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345); + +/**************************************************************************/ +/* + Displays some basic information on this sensor from the unified + sensor API sensor_t type (see Adafruit_Sensor for more information) +*/ +/**************************************************************************/ +void displaySensorDetails(void) +{ + sensor_t sensor; + tsl.getSensor(&sensor); + Serial.println("------------------------------------"); + Serial.print ("Sensor: "); Serial.println(sensor.name); + Serial.print ("Driver Ver: "); Serial.println(sensor.version); + Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); + Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux"); + Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux"); + Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux"); + Serial.println("------------------------------------"); + Serial.println(""); + delay(500); +} + +/**************************************************************************/ +/* + Configures the gain and integration time for the TSL2561 +*/ +/**************************************************************************/ +void configureSensor(void) +{ + /* You can also manually set the gain or enable auto-gain support */ + // tsl.setGain(TSL2561_GAIN_1X); /* No gain ... use in bright light to avoid sensor saturation */ + // tsl.setGain(TSL2561_GAIN_16X); /* 16x gain ... use in low light to boost sensitivity */ + tsl.enableAutoRange(true); /* Auto-gain ... switches automatically between 1x and 16x */ + + /* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */ + tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); /* fast but low resolution */ + // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS); /* medium resolution and speed */ + // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); /* 16-bit data but slowest conversions */ + + /* Update these values depending on what you've set above! */ + Serial.println("------------------------------------"); + Serial.print ("Gain: "); Serial.println("Auto"); + Serial.print ("Timing: "); Serial.println("13 ms"); + Serial.println("------------------------------------"); +} + +/**************************************************************************/ +/* + Arduino setup function (automatically called at startup) +*/ +/**************************************************************************/ +void setup(void) +{ + Serial.begin(9600); + Serial.println("Light Sensor Test"); Serial.println(""); + + /* Initialise the sensor */ + //use tsl.begin() to default to Wire, + //tsl.begin(&Wire2) directs api to use Wire2, etc. + if(!tsl.begin()) + { + /* There was a problem detecting the TSL2561 ... check your connections */ + Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!"); + while(1); + } + + /* Display some basic information on this sensor */ + displaySensorDetails(); + + /* Setup the sensor gain and integration time */ + configureSensor(); + + /* We're ready to go! */ + Serial.println(""); +} + +/**************************************************************************/ +/* + Arduino loop function, called once 'setup' is complete (your own code + should go here) +*/ +/**************************************************************************/ +void loop(void) +{ + /* Get a new sensor event */ + sensors_event_t event; + tsl.getEvent(&event); + + /* Display the results (light is measured in lux) */ + if (event.light) + { + Serial.print(event.light); Serial.println(" lux"); + } + else + { + /* If event.light = 0 lux the sensor is probably saturated + and no reliable data could be generated! */ + Serial.println("Sensor overload"); + } + delay(250); +}
diff -r 05d322353720 -r 5b1b625fda6f TSL2561.cpp --- a/TSL2561.cpp Tue Feb 20 10:52:41 2018 +0000 +++ b/TSL2561.cpp Fri Sep 21 22:57:07 2018 +0000 @@ -1,47 +1,169 @@ -/* - * mbed library program - * Luminosity sensor -- LIGHT-TO-DIGITAL CONVERTER (light intensity to a digital signal output) - * TSL2561 by Texas Advanced Optoelectronic Solutions Inc. +/*! + * @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. * - * Copyright (c) 2015,'17,'18 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 - */ + * @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) + : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) { - TSL2561_addr = TSL2561_ADDRESS_GND; + _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) + : _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p) { - TSL2561_addr = addr; + _addr = addr; init(); } TSL2561::TSL2561 (I2C& p_i2c) - : _i2c(p_i2c) + : _i2c(p_i2c) { - TSL2561_addr = TSL2561_ADDRESS_GND; + _addr = TSL2561_ADDR_LOW; init(); } TSL2561::TSL2561 (I2C& p_i2c, uint8_t addr) - : _i2c(p_i2c) + : _i2c(p_i2c) { - TSL2561_addr = addr; + _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) @@ -56,25 +178,28 @@ double ratio; double dlux; - dt[0] = CMD_MULTI + TSL2561_DATA0LOW; - _i2c.write((int)TSL2561_addr, (char *)dt, 1, true); - _i2c.read(TSL2561_addr, (char *)dt, 2, false); - ch0 = dt[1] << 8 | dt[0]; - dt[0] = CMD_MULTI + TSL2561_DATA1LOW; - _i2c.write((int)TSL2561_addr, (char *)dt, 1, true); - _i2c.read(TSL2561_addr, (char *)dt, 2, false); - ch1 = dt[1] << 8 | dt[0]; - if (ch0 == 0xFFFF) { - return 2500.0; - } + _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/integ_time); - lux1 *= (402.0/integ_time); + 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) { @@ -86,54 +211,528 @@ } else { dlux = 0; } + disable(); return (float)dlux; } -/////////////// Initialize //////////////////////////////// -void TSL2561::init() +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) { - _i2c.frequency(100000); - power_up(); - set_timing_reg(TIMING_DEFAULT); + /* 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) { - dt[0] = CMD_SINGLE + TSL2561_TIMING; - dt[1] = parameter; - _i2c.write((int)TSL2561_addr, (char *)dt, 2, false); - dt[0] = CMD_SINGLE + TSL2561_TIMING; - _i2c.write((int)TSL2561_addr, (char *)dt, 1, true); - _i2c.read(TSL2561_addr, (char *)dt, 1, false); - return dt[0]; + 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; + uint8_t i, data; - dt[0] = CMD_SINGLE + TSL2561_TIMING; - _i2c.write((int)TSL2561_addr, (char *)dt, 1, true); - _i2c.read(TSL2561_addr, (char *)dt, 1, false); - if (dt[0] & TIMING_GAIN_16){ + 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 = dt[0] & 0x3; + 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]; @@ -142,10 +741,7 @@ /////////////// ID //////////////////////////////////////// uint8_t TSL2561::read_ID() { - dt[0] = CMD_SINGLE + TSL2561_ID; - _i2c.write((int)TSL2561_addr, (char *)dt, 1, true); - _i2c.read(TSL2561_addr, (char *)dt, 2, false); - id_number = dt[0]; + id_number = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID); return id_number; } @@ -164,16 +760,12 @@ /////////////// Power ON/OFF ////////////////////////////// void TSL2561::power_up() { - dt[0] = CMD_SINGLE + TSL2561_CONTROL; - dt[1] = 3; - _i2c.write((int)TSL2561_addr, (char *)dt, 2, false); + enable(); } void TSL2561::power_down() { - dt[0] = CMD_SINGLE + TSL2561_CONTROL; - dt[1] = 0; - _i2c.write((int)TSL2561_addr, (char *)dt, 2, false); + disable(); } /////////////// I2C Freq. ///////////////////////////////// @@ -181,4 +773,3 @@ { _i2c.frequency(hz); } -
diff -r 05d322353720 -r 5b1b625fda6f TSL2561.h --- a/TSL2561.h Tue Feb 20 10:52:41 2018 +0000 +++ b/TSL2561.h Fri Sep 21 22:57:07 2018 +0000 @@ -1,164 +1,273 @@ -/* - * mbed library program - * Luminosity sensor -- LIGHT-TO-DIGITAL CONVERTER (light intensity to a digital signal output) - * TSL2561 by Texas Advanced Optoelectronic Solutions Inc. - * - * Copyright (c) 2015,'17,'18 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 - */ -/* - *---------------- REFERENCE ---------------------------------------------------------------------- - * https://docs.google.com/viewer?url=http%3A%2F%2Fwww.adafruit.com%2Fdatasheets%2FTSL256x.pdf - * https://learn.adafruit.com/tsl2561?view=all - * http://www.adafruit.com/products/439 - * http://akizukidenshi.com/catalog/g/gM-08219/ - */ - -#ifndef TSL2561_H -#define TSL2561_H - -#include "mbed.h" - -// Luminosity sensor, TSL2561 -// Address b7=0,b6=1,b5=1,b4=1,b3=0,b2=0,b1=1, b0=R/W -#define TSL2561_ADDRESS_GND (0x29 << 1) -#define TSL2561_ADDRESS_FLOAT (0x39 << 1) -#define TSL2561_ADDRESS_VDD (0x49 << 1) - -////////////// Registers ////////////////////////////////// -// Register definition -#define TSL2561_CONTROL 0x00 -#define TSL2561_TIMING 0x01 -#define TSL2561_THRESHLOWLOW 0x02 -#define TSL2561_THRESHHIGHLOW 0x04 -#define TSL2561_INTERRUPT 0x06 -#define TSL2561_CRC 0x08 -#define TSL2561_ID 0x0A -#define TSL2561_DATA0LOW 0x0C -#define TSL2561_DATA0HIGH 0x0D -#define TSL2561_DATA1LOW 0x0E -#define TSL2561_DATA1HIGH 0x0F - -////////////// TIMING PARAMETER /////////////////////////// -#define TIMING_GAIN_1 (0UL << 4) -#define TIMING_GAIN_16 (1UL << 4) -#define TIMING_TIME_13R7 (0x0) -#define TIMING_TIME_101 (0x1) -#define TIMING_TIME_402 (0x2) -#define TIMING_TIME_MANU (0x3) -#define TIMING_DEFAULT (TIMING_GAIN_1 + TIMING_TIME_402) - -////////////// ID ///////////////////////////////////////// -#define I_AM_TSL2561CS 0x01 -#define I_AM_TSL2561T_FN_CL 0x05 - -////////////// COMMAND //////////////////////////////////// -#define CMD_CMDMODE (1UL << 7) -#define CMD_CLEAR (1UL << 6) -#define CMD_WORD (1UL << 5) -#define CMD_BLOCK (1UL << 4) -#define CMD_SINGLE (CMD_CMDMODE) -#define CMD_MULTI (CMD_CMDMODE + CMD_WORD) - -/** Interface for Luminosity sensor, TSL2561 - * @code - * #include "mbed.h" - * #include "TSL2561.h" - * - * // I2C Communication - * TSL2561 lum(dp5,dp27); // TSL2561 SDA, SCL - * // If you connected I2C line not only this device but also other devices, - * // you need to declare following method. - * I2C i2c(dp5,dp27); // SDA, SCL - * TSL2561 lum(i2c); // TSL2561 SDA, SCL (Data available every 400mSec) - * - * int main() {; - * while(true){ - * printf("Illuminance: %+7.2f [Lux]\r\n", lum.lux()); - * wait(1.0); - * } - * } - * @endcode - */ - -class TSL2561 -{ -public: - /** Configure data pin - * @param data SDA and SCL pins - */ - TSL2561(PinName p_sda, PinName p_scl); - TSL2561(PinName p_sda, PinName p_scl, uint8_t addr); - - /** Configure data pin (with other devices on I2C line) - * @param I2C previous definition - */ - TSL2561(I2C& p_i2c); - TSL2561(I2C& p_i2c, uint8_t addr); - - /** Get approximates the human eye response - * in the commonly used Illuminance unit of Lux - * @param none - * @return Lux - */ - float lux(void); - - /** Set timing register - * @param timing parameter - * @return timing read data - */ - uint8_t set_timing_reg(uint8_t parameter); - - /** Read timing register - * @param timing parameter - * @return timing read data - */ - uint8_t read_timing_reg(void); - - /** Set I2C clock frequency - * @param freq. - * @return none - */ - void frequency(int hz); - - /** check Device ID number - * @param none - * @return TSL2561 = 1, others 0 - */ - uint8_t who_am_i(void); - - /** Read ID and Revision Number - * @param none - * @return ID + REVNO - */ - uint8_t read_ID(void); - - /** Power Up/Down - * @param none - * @return none - */ - void power_up(void); - void power_down(void); - -protected: - I2C *_i2c_p; - I2C &_i2c; - - void init(void); - -private: - uint8_t TSL2561_addr; - uint8_t dt[4]; - uint32_t ch0; - uint32_t ch1; - int8_t gain; - uint8_t id_number; - double integ_time; -}; - -#endif // TSL2561_H +/*! + * @file Adafruit_TSL2561_U.h + * + * This is part of Adafruit's FXOS8700 driver for the Arduino platform. It is + * designed specifically to work with the Adafruit FXOS8700 breakout: + * https://www.adafruit.com/products/3463 + * + * 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! + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ + +//------- 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 +//------------------------------------------------------------------------------ + +#ifndef TSL2561_H_ +#define TSL2561_H_ + +#include "mbed.h" + +// Luminosity sensor, TSL2561 +// Address b7=0,b6=1,b5=1,b4=1,b3=0,b2=0,b1=1, b0=R/W +#define TSL2561_ADDRESS_GND (0x29 << 1) +#define TSL2561_ADDR_LOW (0x29 << 1) +#define TSL2561_ADDRESS_FLOAT (0x39 << 1) +#define TSL2561_ADDR_FLOAT (0x39 << 1) +#define TSL2561_ADDRESS_VDD (0x49 << 1) +#define TSL2561_ADDR_HIGH (0x49 << 1) + +// Lux calculations differ slightly for CS package +//#define TSL2561_PACKAGE_CS ///< Chip scale package +#define TSL2561_PACKAGE_T_FN_CL ///< Dual Flat No-Lead package + +// ID +#define I_AM_TSL2561CS 0x01 +#define I_AM_TSL2561T_FN_CL 0x05 + +// COMMAND register bit definition +#define TSL2561_COMMAND_BIT (0x80) ///< Must be 1 +///< Clears any pending interrupt (write 1 to clear) +#define TSL2561_CLEAR_BIT (0x40) +///< 1 = read/write word (rather than byte) +#define TSL2561_WORD_BIT (0x20) +///< 1 = using block read/write +#define TSL2561_BLOCK_BIT (0x10) + +// Control register setting to turn on/off +#define TSL2561_CONTROL_POWERON (0x03) +#define TSL2561_CONTROL_POWEROFF (0x00) + +#define TSL2561_LUX_LUXSCALE (14) ///< Scale by 2^14 +#define TSL2561_LUX_RATIOSCALE (9) ///< Scale ratio by 2^9 +#define TSL2561_LUX_CHSCALE (10) ///< Scale channel values by 2^10 +#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) ///< 322/11 * 2^TSL2561_LUX_CHSCALE +#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) ///< 322/81 * 2^TSL2561_LUX_CHSCALE + +/** TSL2561 I2C Registers */ +enum { + TSL2561_REGISTER_CONTROL = 0x00, // Control/power register + TSL2561_REGISTER_TIMING = 0x01, // Set integration time register + TSL2561_REGISTER_THRESHHOLDL_LOW = 0x02, // Interrupt low threshold low-byte + TSL2561_REGISTER_THRESHHOLDL_HIGH = 0x03, // Interrupt low threshold high-byte + TSL2561_REGISTER_THRESHHOLDH_LOW = 0x04, // Interrupt high threshold low-byte + TSL2561_REGISTER_THRESHHOLDH_HIGH = 0x05, // Interrupt high threshold high-byte + TSL2561_REGISTER_INTERRUPT = 0x06, // Interrupt settings + TSL2561_REGISTER_CRC = 0x08, // Factory use only + TSL2561_REGISTER_ID = 0x0A, // TSL2561 identification setting + TSL2561_REGISTER_CHAN0_LOW = 0x0C, // Light data channel 0, low byte + TSL2561_REGISTER_CHAN0_HIGH = 0x0D, // Light data channel 0, high byte + TSL2561_REGISTER_CHAN1_LOW = 0x0E, // Light data channel 1, low byte + TSL2561_REGISTER_CHAN1_HIGH = 0x0F // Light data channel 1, high byte +}; + +/** Three options for how long to integrate readings for */ +typedef enum { + TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms + TSL2561_INTEGRATIONTIME_101MS = 0x01, // 101ms + TSL2561_INTEGRATIONTIME_402MS = 0x02 // 402ms +} +TSL2561IntegrationTime_t; + +/** TSL2561 offers 2 gain settings */ +typedef enum { + TSL2561_GAIN_1X = 0x00, // No gain + TSL2561_GAIN_16X = 0x10, // 16x gain +} +TSL2561Gain_t; + +/** struct sensors_color_s is used to return color data in a common format. */ +typedef struct { + union { + float c[3]; + /* RGB color space */ + struct { + float r; /**< Red component */ + float g; /**< Green component */ + float b; /**< Blue component */ + }; + }; + uint32_t rgba; /**< 24-bit RGBA value */ +} sensors_color_t; + +#define SENSOR_TYPE_LIGHT 5 + +/* Sensor details */ +/** struct sensor_s is used to describe basic information + about a specific sensor. */ +typedef struct { + float max_value; /**< maximum value of this sensor's value in SI units */ + float min_value; /**< minimum value of this sensor's value in SI units */ + /**< smallest difference between two values reported by this sensor */ + float resolution; + /**< min delay in microseconds between events. zero = not a constant rate */ + int32_t min_delay; +} sensor_t; + +/** Interface for Luminosity sensor, TSL2561 + * @code + * #include "mbed.h" + * #include "TSL2561.h" + * + * // I2C Communication + * TSL2561 lum(dp5,dp27); // TSL2561 SDA, SCL + * // If you connected I2C line not only this device but also other devices, + * // you need to declare following method. + * I2C i2c(dp5,dp27); // SDA, SCL + * TSL2561 lum(i2c); // TSL2561 SDA, SCL (Data available every 400mSec) + * + * int main() {; + * while(true){ + * printf("Illuminance: %+7.2f [Lux]\r\n", lum.lux()); + * wait(1.0); + * } + * } + * @endcode + */ + +/**************************************************************************/ +/*! + @brief Class that stores state and functions + for interacting with TSL2561 Light Sensor +*/ +/**************************************************************************/ +class TSL2561 +{ +public: + /** Configure data pin + * @param data SDA and SCL pins + */ + TSL2561(PinName p_sda, PinName p_scl); + TSL2561(PinName p_sda, PinName p_scl, uint8_t addr); + + /** Configure data pin (with other devices on I2C line) + * @param I2C previous definition + */ + TSL2561(I2C& p_i2c); + TSL2561(I2C& p_i2c, uint8_t addr); + + /** Get approximates the human eye response + * in the commonly used Illuminance unit of Lux + * @param none + * @return Lux + */ + float lux(void); + + /** Get approximates the human eye response with "Auto Range" + * in the commonly used Illuminance unit of Lux + * @param none + * @return Lux + */ + float lux_auto(void); + + /** Set timing register + * @param timing parameter + * @return timing read data + */ + uint8_t set_timing_reg(uint8_t parameter); + + /** Read timing register + * @param timing parameter + * @return timing read data + */ + uint8_t read_timing_reg(void); + + /** Set I2C clock frequency + * @param freq. + * @return none + */ + void frequency(int hz); + + /** check Device ID number + * @param none + * @return TSL2561 = 1, others 0 + */ + uint8_t who_am_i(void); + + /** Read ID and Revision Number + * @param none + * @return ID + REVNO + */ + uint8_t read_ID(void); + + /** Power Up/Down + * @param none + * @return none + */ + void power_up(void); + void power_down(void); + + //---------- Adafruit_TSL2561_U.h Original functions part ------------------ + bool init(); + + /* TSL2561 Functions */ + void enableAutoRange(bool enable); + void setIntegrationTime(TSL2561IntegrationTime_t time); + void setGain(TSL2561Gain_t gain); + void getLuminosity (uint16_t *broadband, uint16_t *ir); + uint32_t calculateLux(uint16_t broadband, uint16_t ir); + + /* Unified Sensor API Functions */ + bool getEvent(uint32_t*); + void getSensor(sensor_t*); + +private: + I2C *_i2c_p; + I2C &_i2c; + Timer t; + + int8_t _addr; + bool _TSL2561Initialised; + bool _TSL2561AutoGain; + TSL2561IntegrationTime_t _TSL2561IntegrationTime; + TSL2561Gain_t _TSL2561Gain; + uint32_t ch0; + uint32_t ch1; + int8_t gain; + uint8_t id_number; + float integ_time; + + uint8_t dt[4]; + + void enable (void); + void disable (void); + void write8 (uint8_t reg, uint8_t value); + uint8_t read8 (uint8_t reg); + uint16_t read16 (uint8_t reg); + void getData (uint16_t *broadband, uint16_t *ir); +}; + +#endif // TSL2561_H