Light Sensor

From Waveshare Wiki
Revision as of 04:09, 27 March 2017 by Wiki Editorial Team (talk | contribs) (Created page with "{{Infobox item|colorscheme=blue |brief=Ambient Light Detecting |img=300px|link=http://www.waveshare.com/light-sensor.htm |caption=Light Sensor,...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Light Sensor
Ambient Light Detecting
Light-sensor-intro.jpg

Light Sensor, detects the ambient light intensity, I2C interface
{{{name2}}}

{{{name3}}}

{{{name4}}}

{{{name5}}}

Introduction

Light Sensor, detects the ambient light intensity, I2C interface

More

Getting Started

Schematic

Timing analysis

TSL2581 has a data line and a clock signal line, and adopts I2C communication mode. There are three types of signals will be used on the course of the I2C bus data transmission. They are Start signal, Stop signal, and Ack signal.

SPI timing
  • Start signal: When SCL is HIGH and SDA jumps from HIGH to LOW, the data transmission starts.
  • Stop signal: When SCL is HIGH and SDA jumps from LOW to HIGH, the data transmission stops.
  • Ack signal: When the receiver IC have received 8 bit of data, it will send out a special LOW level pulse to the transmitter IC to indicate that the data have been received.

I2C writing

I2C writing

At the beginning, the Host (here is STM32, and we will call it the Host hereafter) sends out a start signal, and combines the 7 bit of I2C address with the Write bit, then, sends this 8 bit of data to the Slave (here is TSL2581 sensor, and we will refer it to the Slave hereafter). Then, the Slave sends back an ACK signal when it has received the data. The Host transmits the address of the command register to the Slave as soon as it received the ACK signal. And the Slave responds an ACK signal when it has received the address. By following, the Host sends the value of the command register to the Slave. And the Slave responds an ACK signal once again. The I2C writing operation will be continued till the Host sends out a stop signal.

I2C reading

I2C reading

At the beginning, the Host sends out a start signal, and combines the 7 bit of I2C address with the Write bit, then, sends this 8 bit of data to the Slave. Then, the Slave sends back an ACK signal when it has received the data. The Host transmits the address of the command register to the Slave as soon as it received the ACK signal. And the Slave responds an ACK signal when it has received the address. At this moment, the Host sends out a start signal once again, and combines its 7 bit of address with Read bit, then, sends this 8 bit of data to the Slave. And then, the Slave responds an ACK signal to the Host when it has received the data, and sends out the value stored in the Slave register to the Host. The Host sends back an ACK signal as soon as it received the value. The I2C communication will be continued, till the Host sends out a stop signal.

Command Code

7 6 5 4 3 2 1 0
CMD TRANSACTION ADDRESS
  • CMD: select the command register. This bit should be set to 1 for addressing the COMMAND register.
  • TRANSACTION: These bits can select the R/W mode and the special function register. For 10, select the I2C reading mode which supports the read block protocol. For 00, select the I2C writing mode. For 11, select the special function register. Under this mode, the ADDRESS can be set as following:
0 0001: clear the interrupt; since the interrupt output would remain at 0 after the sensor triggered the interrupt, you should set this bit to 1 by hand to clear the interrupt;
0 0010: stop the manual integration;
0 0011: start the manual integration.
  • ADDRESS: As the description above, you can know that when the bit 5 and bit 6 are set to 10, the I2C reading mode is selected; when 00, the I2C writing mode is selected. Under the I2C R/W mode, the lower 5 bits are the addresses of the registers. In the following section, we will illustrate the address settings and configuration codes.

I2C address

This module has a digital (i2c) interface. And there are three kinds of addresses applicable, as the table lists below. You can select one of them. The sensor internal address is a 7 bit address.

ADDR state Address
VCC 0X49
FLOAT 0X39
GND 0X29

Notes: The ADDR pin on the development board here is set to FLOAT by default.

Device ID

The device ID can be obtained by writing the register address 0x12 as below:

ReadBuffer =  I2C_DEV_Read(COMMAND_CMD |TRANSACTION |ID);

As the relative datasheet describes, the device ID is stored in the 8 bits register, of which the higher 4 bits store the part number of the device, while the lower 4 bits store the silicon version number of the device. However, the datasheet has not presented the silicon version number. So, we need to deal with the data read out as following:

ID = ReadBuffer & 0XF0;

Now, we can get the device ID. TakingTSL2581 as an example, its device ID is 0x90.

Demo description (take STM32 for example)

According to the description of the datasheet, you should power up the device to make it run before performing write operation and reading the value from two channels of ADC. So here is the configuration code to power up the device.

I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD| CONTROL,ADC_EN|CONTROL_POWERON);

In which,

ADDR_FLOAT_Write: the address of I2C, its lowest bit is a write data bit;
COMMAND_CMD: On I2C command writing, its highest bit should be set to 1, so as to make sure the written data is valid;
CONTROL: control register address: 00h, it is able to configure ADC enable and device enable;
ADC_EN: enable the ADC channel to start integrating operation;
CONTROL_POWERON: enable the device.

After powering up the device, you should configure the integration time to 400ms and the Gain of the channel to 16 times. Since TSL2581 can perform an integration every 2.7ms, there will be 148 integration periods with the integration time of 400ms.

I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD | TIMING, INTEGRATIONTIME_400MS);
I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD | ANALOG, GAIN_16X);

Now, you can read the value of the channels. According to the definition of the datasheet, the lower bit of the data would be read out first. (Here we only present the configuration code of the channel 0. The channel 1 can be configured at the same way.)

DataLow = I2C_DEV_Read(COMMAND_CMD | TRANSACTION | DATA0LOW);
DataHigh = I2C_DEV_Read(COMMAND_CMD | TRANSACTION | DATA0HIGH);
Channel_0 = 256 * DataHigh + DataLow ;

The lower bit of the data is read out first, and then the higher bit is followed. There will be two sets of 8 bit data. Combine them into a 16 bit data after reading out. What you can get from the channel 0 is the value of visible light and infrared light, and from the channel 1 is the value of infrared light, ch1 << ch2.

The values of the channels should be converted to the luminous intensity when you get them. In the configuration described above, we have set the integration time to 400ms, and the Gain to 16 times. To accurately get the current luminous intensity, we should scale the value. For the integration time is 400ms, the Maximum value of the channel is 65536.

chScale0 = 65536;

With the Gain of 16 times, this value would be reduced to 4096:

chScale0 = chScale0 >> 4;
chScale1 = chScale0;

Here are the formulas for scaling:

channel0 = (Channel_0 * chScale0) >>  16;
channel1 = (Channel_1 * chScale1) >>  16;

After scaling, calculate the ratio between channel 0 and channel 1 with the formula:

ratio1 = (channel1 << (RATIO_SCALE + 1)) / channel0;

in which,

RATIO_SCALE = 9;
ratio = (ratio1 + 1) >> 1;

Now, you can get the relationships listed below, according to the experience formulas:

if ((ratio >= 0X00) && (ratio <= K1C)) 
{
  b = B1C; 
  m = M1C;
}
else if (ratio <= K2C)
{
  b = B2C;
  m = M2C;
}
else if (ratio <= K3C)
{
  b = B3C;
  m = M3C;
}
else if (ratio <= K4C)
{
  b = B4C;
  m = M4C;
}
else if (ratio > K5C)
{
  b = B5C;
  m = M5C;
}

In which:

When ratio <= 0.3, b = 0.130, m = 0.240
When ratio <= 0.38, b = 0.1649, m = 0.3562
When ratio <= 0.45, b = 0.0974, m = 0.1786
When ratio <= 0.54, b = 0.062, m = 0.100
When ratio > 0.54, b = m = 0

After calculated the multiple of the relative channel, you can export the current luminous intensity:

temp = ((channel0 * b) - (channel1 * m));
temp += (1 << (16 - 1));
lux = temp >> 16;

Here, the Lux is the current luminous intensity.

Interrupt configuration

According to the datasheet, the threshold of the register is 03h-06h, in which 03h is the lower 8 bits of the lower threshold, 04h is the higher 8 bits of the lower threshold, 05h is the lower 8 bits of the higher threshold, and 06h is the higher 8bits of the higher threshold.

DataLLow = min % 256;
DataLHigh = min / 256;
I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD | THLLOW, DataLLow);
I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD | THLHIGH, DataLHigh);

The interrupt threshold register is only valid for channel 0, therefore the minimum threshold should not exceed 2^16.

When the value of the channel 0 is lower than the given lower threshold or higher than the given higher threshold in certain integration time, the interrupt output bit will be set to 1 and remain at this state till the special function register clear it by setting the TRANSACTION bit to 11. Also, the ADC will be disabled. To enable the ADC, you should configure the register CONTROL to power up the device.

I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD | TRANSACTION_SPECIAL | SPECIAL_FUN_INTCLEAR, INTR_INTER_MODE);
I2C_DEV_Write(ADDR_FLOAT_Write,COMMAND_CMD | CONTROL, ADC_EN | CONTROL_POWERON); 

In which:

TRANSACTION_SPECIAL = 0x60, it means TRANSACTION is set to 11;
SPECIAL_FUN_INTCLEAR is ADDRESS, its value is 0 0001;
INTR_INTER_MODE this parameter specifies the interrupt generated every 8 integration time. It allows channel 0 remain at certain value for a while before the interrupt is triggered.

How to use

In the following section, we will present how to use the module with the XNUCLEO-F103RB (STM32F103R) and Arduino UNO development boards.

  1. Download the corresponding program to the development board;
  2. Connect the module to the development board via a serial cable. Then, power up the development board, and start up the serial debugging software.

Here are the connections between the module and the development board.

Table 1. STM32 interface:

Port XNUCLEO-F103RB
VCC 3.3V or 5V
GND GND
SDA PB8
SCL PB9
INT PA7

Table 2. Arduino UNO PLUS interface:

Port Arduino
VCC 3.3V or 5V
GND GND
SDA SDA
SCL SCL
INT 13

Table 3. Serial port configuration:

Baud rate 115200
Data bits 8
Stop bit 1
Parity bit NONE

Expected result: When the sensor get close to different light sources, you can find that the serial data output changes as well. The data outputted on the screen is in the unit of LUX. For more detailed information of the testing, please refer to Appendix.

Appendix

Light-sensor-manual-04.png
Light-sensor-manual-05.png

The figure on the left shows the results of luminous intensity measured by the sensor;

The figure on the right shows the testing result of the same light source measured by the TA8133 portable digital illuminometer.

Resources

Support

Support

If you require technical support, please go to the Support page and open a ticket.