Loading...

TSL2561 leer datos y configurar

Pablo Durán
Comparte el post:

Datos técnicos

El sensor TSL2561 es un sensor digital con comunicación I2C que mide la la luz visible e infrarroja. Utiliza una alimentación de 3.3V.
  • Luz total: La luz total es el conjunto de la luz visible e infrarroja que puede medir el sensor. Su rango va desde 0 a 65535 Lux
  • Ruta I2C: La ruta predeterminada es la 0x39 pero tambien puede operar en las rutas 0x29 y 0x49. Esta última la usaremos para uno de los ADC por lo que no se debe usar ahora mismo.

Funcionamiento

En este caso el código es algo diferente a los anteriores ya que no he podido encontrar una librería con la que ahorrarme código y se ha tenido que hacer la obtención de los datos de forma manual.

Para poder hacer la lectura manual y el registro de errores necesitamos importar las librerías smbus, time y logging.

Aunque la conexión haya sido manual sigue el mismo fundamento que los dos sensores anteriores por lo que el diagrama de flujo es el mismo.

Para realizar la conexión manual se tiene que llamar al canal 1 del smbus que es el que lleva las comunicaciones I2C principales. Usamos el método write_byte_data que nos proporciona el smbus para escribir 0x03 en el registro de la ruta 0x39 canal 0x00 y 0x02 en el canal 0x01 de la misma ruta.

Después de haber realizado esta escritura esperamos 0.5 segundos para que se integren los datos y ya podemos leer los canales de salida del sensor con 2 bits de precisión en los canales 0x0C y 0x0E de la ruta 0x39 con el método read_i2c_block_data. Este método nos devuelve un array de dos posiciones en el que el rango de lectura es entre 0 y 255. Para obtener la cantidad de lux con estos datos tenemos que multiplicar el segundo valor del array por 256 y sumarle el primer valor del array dándonos como máximo 65535 Lux de máximo como luz total.

Los parámetros que obtiene este sensor son: Luz total, luz visible y luz infrarrojatodos estos en Luz, sin decimales y en formato String para evitar problemas en el programa principal.

Diagrama del flujo del sensor TSL2561

Cableado

El sensor a utilizar es el TSL2561 tiene 4 pines y se conectan de la siguiente forma.

  • Pin VIN: se conecta a un pin 3.3V de la Raspberry Pi.
  • pin GND: se conecta a cualquier pin GND de la Raspberry Pi.
  • Pin SCL: se conecta al pin SCL (GPIO 8) de la Raspberry Pi.
  • Pin SDA: se conecta al pin SDA (GPIO 9) de la Raspberry Pi.

Quedando de el cableado de la siguiente forma:

Cableado del sensor tsl2561

Si prefieres verlo en su esquema te la dejo justo aquí.

Esquema del sensor tsl2561

Código

Test

En este apartado puedes obtener el código básico para poder leer el sensor TSL2561. Si has visto como leen los anteriores sensores te darás cuenta de que este es algo más complejo. Esto se debe a que no estamos usando una librería que nos automatiza el proceso por lo que toca hacerlo manualmente. El siguiente código lo pueden encontrar en el github de ryker1990.


# Distributed with a free-will license.
# Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
# TSL2561
# This code is designed to work with the TSL2561_I2CS I2C Mini Module available from ControlEverything.com.
# https://www.controleverything.com/content/Light?sku=TSL2561_I2CS#tabs-0-product_tabset-2

import smbus  # Nos conectará con el sensor
import time  # lo usamos para crear tiempos de espera

# Recibimos el bus I2C
bus = smbus.SMBus(1)

# TSL2561 address, 0x39(57)
# Selecciona el registro de control, 0x00(00) con el comando register, 0x80(128)
#		0x03(03)	modo Power ON
bus.write_byte_data(0x39, 0x00 | 0x80, 0x03)
# TSL2561 address, 0x39(57)
# Selecciona el registro de tiempo, 0x01(01) con el comando register, 0x80(128)
#		0x02(02)	Tiempo de integración nominal = 402ms
bus.write_byte_data(0x39, 0x01 | 0x80, 0x02)

time.sleep(0.5)

# Leer datos de 0x0C(12) con el comando register, 0x80(128), 2 bytes
# ch0 LSB, ch0 MSB
data = bus.read_i2c_block_data(0x39, 0x0C | 0x80, 2)

# Leer datos de 0x0E(14) con el comando register, 0x80(128), 2 bytes
# ch1 LSB, ch1 MSB
data1 = bus.read_i2c_block_data(0x39, 0x0E | 0x80, 2)

# Convertir los datos
ch0 = data[1] * 256 + data[0]
ch1 = data1[1] * 256 + data1[0]

# Salida de datos por pantalla
print("Full Spectrum(IR + Visible) :%d lux" % ch0)
print("Infrared Value :%d lux" % ch1)
print("Visible Value :%d lux" % (ch0 - ch1))
    

Clase

Ahora lo que se va a ahacer es automatizar el proceso de lectura de datos. A la hora de hacerlo vamos a tener varias cosas en cuenta:

  • Se creará una clase para que sea más fácil trabar con el sensor.
  • Se leereán los datos cada vez que se cree un objeto de esta clase.
  • Se calculará el factor de corrección a aplicar al resultado para tener en cuenta el filtro el filtro aplicado. Ver siguiente apartado para comprender mejor.
  • Se pasarán los datos al programa principal mediante metodos GET.
  • Se hará captura de excepciones para no bloquear el programa en el caso de que el sensor dejede funcionar.

Teniendo todo lo anterior en cuenta esta parte del programa nos queda de la siguiente forma:


import smbus
import time
import logging


class Tsl2561:
    '''Lee todos los datos del sensor Tsl2561'''

    def __init__(self):

        try:
            # Recibimos el bus I2C
            bus = smbus.SMBus(1)

            # TSL2561 address, 0x39(57)
            # Selecciona el registro de control, 0x00(00) con el comando register, 0x80(128)
            #		0x03(03)	modo Power ON
            bus.write_byte_data(0x39, 0x00 | 0x80, 0x03)
            # TSL2561 address, 0x39(57)
            # Selecciona el registro de tiempo, 0x01(01) con el comando register, 0x80(128)
            #		0x02(02)	Tiempo de integración nominal = 402ms
            bus.write_byte_data(0x39, 0x01 | 0x80, 0x02)

            time.sleep(0.5)

            # Leer datos de 0x0C(12) con el comando register, 0x80(128), 2 bytes
            # ch0 LSB, ch0 MSB
            data = bus.read_i2c_block_data(0x39, 0x0C | 0x80, 2)

            # Leer datos de 0x0E(14) con el comando register, 0x80(128), 2 bytes
            # ch1 LSB, ch1 MSB
            data1 = bus.read_i2c_block_data(0x39, 0x0E | 0x80, 2)

            # Convertir los datos
            self.luz_total = data[1] * 256 + data[0]
            self.luz_infrarroja = data1[1] * 256 + data1[0]

        # Recoge el error de lectura del canal SDA
        except OSError:
            logging.error('El sensor TSL2561 ha dejado de funcionar.')
            self.luz_total = 0
            self.luz_infrarroja = 0

    def get_luz_total(self):
        '''Devuelve la luz total en Lux sin decimales. Es necesario crear un constructor
         Tsl2561() para actualizar los datos'''

        return str(round(self.luz_total))

    def get_luz_infrarroja(self):
        '''Devuelve la luz infrarroja en Lux sin decimales. Es necesario crear un constructor
         Tsl2561() para actualizar los datos'''

        return str(round(self.luz_infrarroja))

    def get_luz_visible(self):
        '''Devuelve la luz visible en Lux sin decimales. Es necesario crear un constructor
         Tsl2561() para actualizar los datos'''

        return str(round(self.luz_total - self.luz_infrarroja))
    

Calibración

En este caso se ha tenido que hacer una calibración importante al sensor debido a que los sensores de luz no están diseñados para medir luz solar como sí que los están los Piranómetros. El problema estos últimos es que cuestan varios centenares de euros a diferencia de un sensor de luz de 2 euros.

El sensor de luz solo puede leer 65535 Lux entre visible e infrarroja mientras que el sol emite más de 100mil lux de luz visible por lo que es necesario ponerle al sensor un filtro neutro que genere opacidad y reduzca la intensidad de luz recibida por el sensor para que no llegue a cegarse.

Para conseguir este filtro neutro simplemente se ha tenido que pintar un tarro de cristal con barniz color negro específico para cristal. Dejando un acabado mate muy resistente.

Para sabe cuanta luz retiene el cristal se han tenido que hacer varias pruebas apuntando con una linterna al sensor con diferentes intensidades de luz tanto con un tarro de cristal sin pintar como el pintado de negro. Los resultados obtenidos son los siguientes:

Intensidad Luz total luz total trans. Luz infra. luz infra. trans. Luz visible luz visible trans.
alta 59675 100,00% 4745 100,00% 54930 100.00%
alta filtro 16666 27,93% 1572 33,13% 15094 27,48%
media 45187 100,00% 3274 100,00% 41913 100.00%
media filtro 12587 27,86% 1158 35,37% 11429 27,27%
baja 23706 100,00% 1682 100,00% 22024 100.00%
baja filtro 6629 27,96% 603 35,85% 6026 27,36%

De esta forma sabemos cuanta luz le llega al sensor y cuanto es retenida por el filtro. Una vez que sacamos las medias y obtenemos su factor de conversión tenemos que multiplicar los datos leídos por el sensor por el factor de conversión.

Luz total trans. Luz infra. trans. Luz visible trans.
Media 27,93% 35,37% 27,36%
Factor corrección 3,58 2,87 3,65

Ahora simplemente tenemos que multiplicar la luz total recibida por el sensor por su factor de corrección el cual es 3.58. Lo mismo se hace con la luz infrarroja y su factor de corrección que es 2.87.