En muchas casas el pasillo queda completamente a oscuras de noche y la única opción es prender la luz del techo, que encandila. Una luz nocturna que se regula sola. brillante cuando está todo oscuro, apagada cuando ya entra luz suficiente. resuelve ese problema con menos de $25.000 en componentes y unas cuarenta líneas de código.
Al terminar este tutorial vas a tener un indicador de luz ambiental funcionando sobre Arduino: un sensor que informa la luminosidad en lux por el bus I2C, un LED cuyo brillo se calcula a partir de esa lectura, y un botón para forzar el apagado. Más importante que el montaje: vas a entender por qué un sensor digital de lux le gana a una fotorresistencia cuando necesitas medidas que signifiquen algo.
Qué mide realmente un sensor de luz ambiental
Acá conviene detenerse antes de conectar nada, porque este es el punto que la mayoría de los tutoriales salta.
Una fotorresistencia (LDR) es una resistencia que cambia de valor con la luz. Es barata y sirve, pero lo que lees en el pin analógico es un voltaje que depende de la LDR y de la resistencia que le pusiste en serie, de la temperatura, y de qué tan rápido responde el material. Dos LDR del mismo paquete pueden darte lecturas distintas bajo la misma luz. Sirve para "hay luz / no hay luz", no para "hay 320 lux".
Un sensor digital de luz ambiental como el BH1750 o el VEML7700 trae adentro un fotodiodo, un amplificador y un conversor analógico digital ya calibrados de fábrica. Lo que te entrega por I2C es directamente el valor en lux, la unidad fotométrica que pondera la luz según la sensibilidad del ojo humano. Un LED infrarrojo que satura una LDR casi no mueve la lectura de estos sensores, porque su respuesta espectral está filtrada para parecerse a la del ojo.
Esa diferencia importa en la práctica: si mañana quieres que la luz se encienda "cuando la pieza esté como al atardecer", con lux tienes un número reproducible (unos 10 a 50 lx). Con una LDR tienes un valor de ADC que solo vale para tu circuito.

Hardware: cuatro cables y un bus compartido
El montaje completo se resuelve con el bus I2C, que necesita solo dos líneas de datos sin importar cuántos dispositivos cuelgues de él.
Conecta el sensor al Arduino Uno así:
- VCC del sensor al pin 5V (o 3.3V, según el módulo que tengas).
- GND del sensor al GND del Arduino.
- SDA del sensor al pin A4.
- SCL del sensor al pin A5.
En el Uno, A4 y A5 son los pines I2C por hardware: no son analógicos comunes cuando usas la librería Wire. En un Mega serían 20 y 21, y en un ESP32 los defines tú.
El LED va al pin 9 con una resistencia de 220Ω en serie hacia GND. Ese detalle no es decorativo: el pin 9 es uno de los pines PWM del Uno, y necesitas PWM para atenuar el LED en lugar de solo prenderlo y apagarlo. Si lo conectas al pin 7, por ejemplo, analogWrite() no va a atenuar nada.
El botón va entre el pin 2 y GND, usando la resistencia pull up interna del microcontrolador (INPUT_PULLUP). Así te ahorras un componente y el pin queda en alto cuando el botón está suelto.
Un detalle que ahorra media hora de frustración: la mayoría de los módulos BH1750 y VEML7700 ya traen las resistencias pull up del bus I2C soldadas en la placa. Si conectas tres o cuatro módulos al mismo bus, esas resistencias quedan en paralelo, el bus se pone "duro" y las comunicaciones empiezan a fallar de forma intermitente. Con un solo sensor no vas a tener ese problema.
El sketch: leer lux y mapearlo a brillo
Instala las librerías desde el gestor del IDE de Arduino (Sketch > Incluir librería > Administrar bibliotecas) y carga el código. Este es el sketch tal como lo publica SparkFun para su combinación de sensor y botón Qwiic; el listado completo está en el tutorial original enlazado al final.
#include <Wire.h>
#include <SparkFun_Qwiic_Button.h>
#include <SparkFun_VEML7700_Arduino_Library.h>
QwiicButton button;
VEML7700 lightSensor;
void setup() {
Serial.begin(115200);
Wire.begin();
// Initialize the button
if (!button.begin()) {
Serial.println("Button not found!");
while (1);
}
Serial.println("Button found.");
// Initialize the ambient light sensor
if (!lightSensor.begin()) {
Serial.println("Light sensor not found!");
while (1);
}
Serial.println("Light sensor found.");
button.LEDon(0); // Start with LED on, but low brightness
}
void loop() {
// Check if button is pressed
if (button.isPressed()) {
// If pressed, turn off LED regardless of light
button.LEDoff();
Serial.println("Button pressed, LED off.");
// Wait until released
while (button.isPressed()) {
delay(10);
}
Serial.println("Button released.");
} else {
// Read light level
float lux = lightSensor.getLux();
// Clamp lux to a usable range (0 to 400 for mapping)
if (lux > 400) lux = 400;
if (lux < 0) lux = 0;
// Invert lux to brightness: lower light → higher brightness (0–255)
uint8_t brightness = map(lux, 0, 400, 255, 0);
// Apply brightness to LED
button.LEDon(brightness);
Serial.print("Lux: ");
Serial.print(lux);
Si estás usando un BH1750 en vez del VEML7700, la estructura es idéntica: cambia el #include por el de la librería del BH1750 y la llamada de lectura, y todo el resto del razonamiento se mantiene.
Por qué el mapeo va al revés (y cómo evitar el parpadeo)
Fíjate en esta línea del sketch:
uint8_t brightness = map(lux, 0, 400, 255, 0);
Los rangos están invertidos a propósito. map() toma el valor de lux entre 0 y 400 y lo traduce a un brillo entre 255 y 0: más luz ambiente, menos brillo en el LED. Es la lógica de una luz nocturna, no la de un indicador de nivel. Si algún día quieres el comportamiento contrario (un LED que brille más cuando hay más luz, tipo medidor), das vuelta esos dos últimos parámetros y listo.
El número 400 es el umbral, y es lo primero que vas a querer ajustar. Bájalo a 100 y el LED solo va a encenderse en oscuridad casi total; súbelo a 1000 y va a estar encendido buena parte del día.
Ahora, el problema que aparece en cuanto lo dejas funcionando de verdad: el parpadeo en el borde. Cuando la luz de la pieza queda justo en el umbral, cualquier variación mínima. una nube, una sombra al pasar. hace que el LED oscile. La solución clásica es agregar histéresis: usar dos umbrales en vez de uno. Por ejemplo, encender bajo 80 lx pero apagar recién sobre 120 lx. Entre esos dos valores el sistema simplemente mantiene el estado que ya tenía, y el parpadeo desaparece.
Una segunda mejora barata: promediar. En lugar de actuar sobre cada lectura, guarda las últimas cinco o diez mediciones y usa el promedio. Suaviza los picos de una linterna de celular que pasa por delante y no te cuesta ni memoria ni tiempo perceptible.
Variantes y mejoras
- Sensor de presencia en vez de botón. Reemplaza el pulsador por un sensor PIR: la luz se enciende solo si está oscuro y además detecta movimiento en el pasillo. Es la lógica AND que usan las luces de escalera comerciales, y baja el consumo a casi cero cuando no hay nadie.
- Tira LED en vez de un LED de 5mm. El pin del Arduino entrega 20 mA como máximo, suficiente para un LED indicador pero no para iluminar. Con un transistor MOSFET de canal N controlado por el mismo pin PWM puedes manejar una tira LED de 12V y convertir el proyecto en una luz funcional de verdad.
- Registro de datos de luminosidad. Agrega un módulo de tarjeta microSD por SPI y guarda una lectura por minuto. En una semana tienes el perfil real de luz de tu pieza y puedes elegir el umbral con datos en vez de a ojo. Es también la base de un medidor de luz para plantas de interior.
Personalización para Chile
El tutorial original está armado sobre el sistema Qwiic de SparkFun, que no se distribuye en Chile. La buena noticia es que ninguna de esas piezas es imprescindible: Qwiic es un conector, no una tecnología aparte. Debajo hay un bus I2C común y corriente, así que todo el proyecto se replica con componentes que están en stock en MechatronicStore.

- Módulo sensor de luz BH1750 GY-302 (SKU GN1-6). $3.990 CLP. Es el reemplazo directo del VEML7700: también entrega lux por I2C. Su rango llega a unos 65.000 lx en vez de 120.000, diferencia que solo notarías apuntando el sensor al sol de mediodía.
- Arduino Uno R3 (SKU X4-8). $9.990 CLP. Equivalente funcional de la RedBoard Qwiic del original: mismo microcontrolador ATmega328P, mismo bus I2C en A4/A5. Lo único que pierdes es el conector Qwiic, que acá reemplazas con cuatro cables.

- Botón pulsador switch de 4 pines 12x12x8mm (SKU GA6-16). $290 CLP, más LED 5mm verde (SKU GA5-5). $100 CLP y Resistencia 220Ω 1/4W (SKU GK1-18). $100 CLP. Entre los tres cumplen la función del Qwiic Button con LED integrado del original, a una fracción del precio.
- Protoboard 830 puntos MB102 (SKU C-302). $3.790 CLP y Cables macho hembra 30cm (SKU C-418). $1.990 CLP, para el cableado sin soldar.
- Cable Arduino USB tipo B (SKU X9-3). $790 CLP, para programar y alimentar la placa.

El total ronda los $21.000 CLP, y con lo que sobra del pack de cables y del protoboard te quedan materiales para el siguiente proyecto.
Recursos
- Tutorial original: Qwiic & Easy DIY Ambient Light Indicator (SparkFun Learn, licencia CC BY SA 4.0)
- Librerías:
SparkFun VEML7700 Arduino LibraryySparkFun Qwiic Button, ambas instalables desde el gestor de bibliotecas del IDE de Arduino - Documentación adicional: hoja de datos del BH1750 (Rohm) para el detalle de modos de medición y tiempos de integración
Versión chilena con componentes en stock local, inspirada en el tutorial de SparkFun Learn.












