The TSL2561 is a sensor that measures the light-intensity and transforms it to a 16-bit resolution digital value. There are two photodiodes on the sensor, one to sense the light intensity plus infrared light and a second one to measure only infrared light. These two photodiodes convert the measured light-intensity simultaneously. There are two channels available on the sensor to transfer the values into the data register (channel 0 and channel 1). The idea is to subtract the infrared part of the light, so that the resulting light spectrum is the human seeable light.
The measured data can be received via I2C or SMBus. In this article the I2C bus will be for the communicatation between the STM32F4 and the with the TSL2561.
Connect the device
The TSL2561 works with 3.8V, don’t use the 5V pin, you may destroy the sensor. Futher there are two pins (SDA and SCL) for the I2C bus communication. The SDA is the data line, while SCL is the clock. The address pin is to set a unique I2C bus address. The default address can be used, unless there is another device with the same address on the bus. The default address is 0x39, but it can also be set to 0x29 or 0x49. The sensor can generate an interrupt, so that it is not necessary to poll the device. In this example the interrupt signal is not used.
The software part
The STM32F4 controller has several I2C interfaces. The example implementation uses the I2C1, which is connected to GPIO6 (SCL) and GPIO7 (SDA). The configuration is encapsulated to an configuration header, so it is easy to change the bus. The software can be downloaded from the repository (the project is called TSL2561_example). The maximum clock frequency for the device is 400kHz, so this frequency is set in the configuration file. The init_lightsensor(void) method is the configures the necessary IOs and the I2C communication via initLightSensorI2C(void).
To read the measured values, there are four register (two for every channel), that can be read. First there is a 8 bit register that contains the values low byte an then there is a second register for the high byte.
|0x8C||low byte (channel0)|
|0x8D||high byte (channel0)|
|0x8E||low byte (channel1)|
|0x8F||high byte (channel1)|
To read bytes from the device registers, the requested register addresses should be send bytewise to the control register (0x00). There is a command bit that must be set so that the device reacts on the request.
The received data can be calculated to the SI unit LUX. This calculation is already implemented in the example code. The read_lightness_value() method receives the data bytes via I2C and processes the calculation to LUX.