Para que negarlo, estamos rodeados de sensores que nos hacen la vida un poco más fácil, a veces por necesidad, otras por vaguería. Vamos a repasar el uso del sensor ALS y proximidad TMD2771 y lo controlaremos con Arduino, aunque puedes usar otra placa con micro o con FPGA.
En otras ocasiones hemos tratado el uno de sensores de luz basados en LDR, esta ocasión lo hacemos con un sensor basado en fotodiodos y comunicación I2C.
El integrado TMD2771
Este integrado es fabricado por AMS y es un sensor al que denominaremos mixto ya que en su interior encontramos tres posibilidades de medida.
El TMD2771 consta de un LED infrarrojo y dos fotodiodos, el primero de luz visible y el segundo infrarrojo. Además monta 3 ADCs, la lógica para controlarlos y realizar los cálculos, una memoria de 8 bits y una interfaz I2C.
La combinación de ambos fotodiodos con sus ADC y la lógica de control crean el sensor ALS. Por su parte la combinación de uno o dos fotodiodos y una segunda lógica de control crean el sensor de proximidad.
Sensor ALS
ALS no es otra cosa que la siglas en inglés de Ambient Ligh Sensor es decir, sensor de luz ambiente. Y es uno de los sensores más usados a día de hoy junto con el de temperatura ya que todos los smartphone montan al manos uno de estos sensores.
Dentro de un smartphone, el sensor ALS se suele usar para controlar el brillo de pantalla cuando varia la luz ambiente.
En este caso, la salida que proporciona el sensor es en lux.
Senor de proximidad
El sensor de proximidad también se monta en smartphons debido a su uso en otros para bloquear la pantalla cuando acercas el telefono a la cara al recibir una llamada o al escuchar una nota de audio en WhatsApp.
Quizá el uso más original que he conocido de un sensor de proximidad en un smartphone es el uso que Casey Neistat y su equipo le dieron en su App original «Beme» la cual ya se encuentra extinta.
Acceso a los datos del sensor ALS y proximidad TMD2771
Para acceder al sensor usamos su interfaz I2C y en resumen lo que haremos será leer registros de su memoria. Más adelante encontraras como usar el sensor ALS y proximidad TMD2771 usando Arduino.
Los datos de salida de los ADC que convierten la señal analógica de los fotodiodos en una señal digital es almacenada en los registros comprendidos entre 0x14 y 0x19. En la tabla que nos proporciona el fabricante en el Datasheet los encontramos en las últimas posiciones del mapa.
La manera en que que accedamos a leer los registros depende de la placa, micro o FPGA que usemos , para este ejemplo voy a usar Arduino debido a la existencia de una librería muy extendida y reconocida que recibe el nombre de wire.
Si analizas la columna de «Register Function» de las direcciones 0x14 y 0x15, observaras que ambas hablan sobre el ADC del canal 0. Sin embargo, la 0x14 habla del registro bajo y la 0x15 habla del registro alto.
Esta distinción es debida a que la salida de los ADC que usa el sensor ALS y proximidad TMD2771 es de 16 bits, pero los registros de memoria son de 8 bits.
Como la salida de los ADC ocupa el doble de «espacio» que un registro, cada palabra del ADC se divide por la mitad. El registro bajo hace referencia a los 8 bits menos significativos mientras que el registro alto hace referencia a los 8 bits más significativos.
Cuando queramos realizar una lectura, deberemos leer ambos registros de 8 bits y concatenarlos para generar la palabra de 16 bits que representa la lectura del sensor.
Como dato curioso decir que este problema se plantea debido a que a través de I2C solo se pueden enviar Bytes, nunca palabras de más de 8 bits, es por esto que los registro son de 8 bits. De esta manera se simplifica el uso de la información.
Configuración de registros
El TMD2771 es un sensor mixto que debe ser configurado tras cada corte de alimentación, es decir, cada vez que alimentamos el sensor, debemos confirar algunos registros para indicarle como queremos que se comporte.
El primer registro que vamos a configurar es el que en el mapa de memoria se denomina con ENABLE y se encuentra en la dirección de memoria 0x00.
Si analizamos la tabla del datasheet donde vemos el significado de ese registro, nuestro registro debe tomar el valor 0000 1111, este valor en binario se convierte a hexadecimal y queda como 0x0F. Es decir que en el registro 0x00 debemos configurar 0x0F.
También debemos configurar otos registros tal y como se aprecia en la siguiente tabla para pder usar ambos sensores sin interrupciones. Si tienes cualquier duda sobre alguno de los registros, preguntalo en los comentarios y la responderemos.
Dirección – Dato
0x00 – 0x0F
0x01 – 0xDB
0x02 – 0xFF
0x03 – 0xFF
0x0E – 0x04
0x0F – 0x20
Conversor de niveles
Debido a que el sensor trabaja a tensiones comprendidas entre 1.25 y 3.3v no lo podemos conectar directamente a Arduino o cualquier otra placa que no use estas tensiones. La solución es usar un conversor de niveles, en el caso del vídeo uso un módulo que implementa dos canales de conversión de niveles. Si no dispones de este tipo de módulos, siempre puedes montar el circuito con componentes discretos. Por ejemplo usando el transistor MOSFET de canal N BSS138 implementado el siguiente circuito.
Implementación con Arduino
De nuevo y para no faltar a la tradición, vamos a leer los datos del sensor ALS y proximidad TMD2771 usando Arduino ya que estoy seguro que tienes uno en casa 😉
El resumen rápido es que tras indicar la librería a usar y crear una constante con la dirección del sensor TMD2771, inicializamos comunicaciones y enviamos todos los registros de configuración a la memoria usando la función set, la cual he creado solo para este caso.
En el loop conectamos con el sensor, se cambia su puntero a la dirección de memoria 0x14 y se piden 6 registros a partir de el. Los dos primeros de el primer fotodiodo, los dos segundos del segundo fotodiodo y los dos últimos del sensor de proximidad.
#include "Wire.h" //Dirección del integrado (siempre 0x39) #define addr 0x39 void setup() { Wire.begin(); //Inicializar I2C Serial.begin(9600); //Inicializar puerto serie //Configurar los registros para: set(0x00, 0x0F); //Activar ALS, proximidad, temporizador y sensor set(0x01, 0xDB); //Tiempo de integración del ALS 101ms set(0x02, 0xFF); //Tiempo de integración de proximidad (0xFF - 2.72ms, recomendado) set(0x03, 0xFF); //Tiempo de espera set(0x0E, 0x04); //Número de pulsos emiidos por el LED (4) set(0x0F, 0x20); //Registro de control (LED 100%, CH1 para proximidad, again x1 conversor //Los registros están descritos en el datasheet del TMD2771 delay(800); } void loop() { byte registro[6]; //Registros para almacenar los datos //Petición de los registros a partir del 0x14 Wire.beginTransmission(addr); Wire.write(0x14 | 0xA0); Wire.endTransmission(); //Pedir 6 registros 0x14 al 0x19 Wire.requestFrom(addr, 6); //Recuperar los registros desde I2C if(Wire.available() == 6) { registro[0] = Wire.read(); registro[1] = Wire.read(); registro[2] = Wire.read(); registro[3] = Wire.read(); registro[4] = Wire.read(); registro[5] = Wire.read(); } //Calcular proximidad int proximidad = registro[5]<<8|registro[4]; //Calcular luminancia int ch0 = registro[1]<<8|registro[0]; int ch1 = registro[3]<<8|registro[2]; float CPL = (101.0) / 24.0; float fotodiodo1 = (ch0 - 2 * ch1) / CPL; float fotodiodo2 = (0.6 * ch0 - ch1) / CPL; float luminancia = 0.0; if(fotodiodo1 > fotodiodo2) { luminancia = fotodiodo1; } else if(fotodiodo2 > fotodiodo1) { luminancia = fotodiodo2; } //Mostrar datos Serial.print("Proximidad: "); Serial.print(proximidad); Serial.print("\t | ALS: "); Serial.print(luminancia); Serial.println(" lux"); delay(1000); } void set(byte dir, byte value){ Wire.beginTransmission(addr); //Iniciar comunicación Wire.write(dir); //Seleccionar registro Wire.write(value); //Enviar valor Wire.endTransmission(); //Finalizar comunicación }