Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MusicBoxForFathersDay FTHR_SensorHub Affich_Lum_Moist Projetv0 ... more
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
--- /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
--- /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;
+}
--- /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
--- /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);
+}
--- 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);
}
-
--- 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