En esta entrada aprenderemos a medir el nivel de luz, tanto en interiores o exteriores, con la ayuda de Arduino y una fotoresistencia LDR (familia GL55 o similar), usando las entradas analógicas de Arduino.
¿Qué es un fotoresistor LDR?
Un fotoresistor, o LDR (light-dependent resistor) es un dispositivo cuya resistencia varia en función de la luz recibida. Podemos usar esta variación para medir, a través de las entradas analógicas, una estimación del nivel del luz.
Un fotoresistor está formado por un semiconductor, típicamente sulfuro de cadmio CdS. Al incidir la luz sobre él algunos de los fotones son absorbidos, provocando que electrones pasen a la banda de conducción y, por tanto, disminuyendo la resistencia del componente.
Por tanto, un fotoresistor disminuye su resistencia a medida que aumenta la luz sobre él. Los valores típicos son de 1 MOhm en total oscuridad, a 50-100 Ohm bajo luz brillante.
Por otro lado, la variación de la resistencia es relativamente lenta, de 20 a 100 ms en función del modelo. Esta lentitud hace que no sea posible registrar variaciones rápidas, como las producidas en fuentes de luz artificiales alimentadas por corriente alterna. Este comportamiento puede ser beneficioso, ya que dota al sensor de una gran estabilidad.
Finalmente, los fotoresistores no resultan adecuados para proporcionar una medición de la iluminancia, es decir, para servir como luxómetro Esto es debido a su baja precisión, su fuerte dependencia con la temperatura y, especialmente, a que su distribución espectral no resulta adecuada para la medición de iluminancia.
Por tanto, un LDR es una sensor que resulta adecuado para proporcionar medidas cuantitativas sobre el nivel de luz, tanto en interiores como en exteriores, y reaccionar, por ejemplo, encendiendo una luz, subiendo una persiana, u orientando un robot.
Para medir la cantidad de luxes con Arduino necesitaréis un luxómetro como el BH1750 como vemos en la entrada Medir cantidad de luxes con Arduino y el luxómetro BH1750
Precio
Las fotoresistencias son dispositivos realmente baratos. Podemos encontrar 20 sensores LDR por 1€ en vendedores internacionales en Ebay, gastos de envío incluidos.
¿Cómo funciona un fotoresistor LDR?
Matemáticamente, la relación entre la iluminancia y la resistencia de una LDR sigue una función potencial.
Siendo R0 la resistencia a una intensidad I0, ambas conocidas.
La constante gamma es la pendiente de la gráfica logarítmica, o la pérdida de resistencia por década. Su valor típicamente 0.5 a 0.8.
Por este motivo, frecuentemente las gráficas que relacionan ambos valores se representan en escalas logarítmicas para ambos ejes. Bajo esta representación, la relación se muestra como una gráfica lineal.
Estos valores pueden ser obtenidos del datasheet del componente. Por ejemplo, para la familia GL55 de fotoresistores son los siguientes:
Modelo | Pico espectral (nm) | Resistencia luz brillante (KΩ) | Resistencia oscuridad (KΩ) | gamma | Tiempo respuesta (ms) |
---|---|---|---|---|---|
GL5516 | 540 | 5-10 | 500 | 0.5 | 30 |
GL5528 | 540 | 10-20 | 1000 | 0.6 | 25 |
GL5537-1 | 540 | 20-30 | 2000 | 0.6 | 25 |
GL5537-2 | 540 | 30-50 | 3000 | 0.7 | 25 |
GL5539 | 540 | 50-100 | 5000 | 0.8 | 25 |
GL5549 | 540 | 100-200 | 10000 | 0.9 | 25 |
Sin embargo, siempre existirán pequeñas variaciones entre dispositivos, incluso dentro de la misma familia, debidos a la fabricación del componente.
El comportamiento potencial hace que estas pequeñas diferencias supongan grandes variaciones en la medición, por lo que no es posible, en general, emplear estos valores de forma absoluta sin un proceso de calibración.
Esquema eléctrico
El esquema eléctrico sería el siguiente.
Montaje
Por su parte, el montaje eléctrico en una protoboard quedaría de la siguiente manera.
Ejemplos de código
A continuación tenéis algunos ejemplos de código. En el siguiente, usamos las entradas digitales para hacer parpadear el LED integrado en la placa mientras el LDR recibe luz suficiente.
const int LEDPin = 13;
const int LDRPin = 2;
void setup()
{
pinMode(LEDPin, OUTPUT);
pinMode(LDRPin, INPUT);
}
void loop()
{
int value = digitalRead(LDRPin);
if (value == HIGH)
{
digitalWrite(LEDPin, HIGH);
delay(50);
digitalWrite(LEDPin, LOW);
delay(50);
}
}
El siguiente ejemplo emplea una entrada analógica para activar el LED integrado en la placa si supera un cierto umbral (threshold).
const int LEDPin = 13;
const int LDRPin = A0;
const int threshold = 100;
void setup() {
pinMode(LEDPin, OUTPUT);
pinMode(LDRPin, INPUT);
}
void loop() {
int input = analogRead(LDRPin);
if (input > threshold) {
digitalWrite(LEDPin, HIGH);
}
else {
digitalWrite(LEDPin, LOW);
}
}
El siguiente código proporciona una lectura del nivel de iluminación recibido. Observar que los cálculos se realizan con aritmética de enteros, evitando emplear números de coma flotante, dado que ralentizan mucho la ejecución del código.
const long A = 1000; //Resistencia en oscuridad en KΩ
const int B = 15; //Resistencia a la luz (10 Lux) en KΩ
const int Rc = 10; //Resistencia calibracion en KΩ
const int LDRPin = A0; //Pin del LDR
int V;
int ilum;
void setup()
{
Serial.begin(115200);
}
void loop()
{
V = analogRead(LDRPin);
//ilum = ((long)(1024-V)*A*10)/((long)B*Rc*V); //usar si LDR entre GND y A0
ilum = ((long)V*A*10)/((long)B*Rc*(1024-V)); //usar si LDR entre A0 y Vcc (como en el esquema anterior)
Serial.println(ilum);
delay(1000);
}
Descarga el código
Todo el código de esta entrada está disponible para su descarga en Github.