sábado, 10 de enero de 2015

Interruptor crepuscular con LDR y Arduino

Hola a todos. Espero que hayáis tenido una buena entrada de año. Una vez pasadas las fiestas retomamos el hilo de este blog.

Esta vez nuestra propuesta es construir un interruptor que active nuestro led en función de la luz ambiental. Un proyecto sencillo pero que nos sirve para empezar a trabajar con sensores.
Hasta ahora hemos dado siempre a nuestro Arduino las órdenes de forma manual, ya sea a través de pulsadores, interruptores o potenciómetros.

Ahora nuestro circuito será capaz de decidir "solito" en función de una variable ambiental. Así que paso a describir del componente que nos hará posible realizar el proyecto.

Fotorresistor o LDR ("ligth-dependent resistor")


El fotorresistor es un componente electrónico, del tipo semiconductor, cuya resistencia varía en función de la luz que recibe.
Los valores resistivos que alcanza van de los 100Ω a los 10kΩ bajo una luz brillante, hasta valores en la oscuridad que típicamente están entre los 500kΩ y los 10MΩ .
Para nuestro ejemplo usaremos el  VT90N2. Aquí lo tenéis junto a una tarjeta SD para comparar el tamaño.



Este modelo en concreto se encuentra en muchos kits de Arduino, tiene una resistencia en la oscuridad de 0,5MΩ y unos 100Ω, bajo luz intensa.
Para usarla en este montaje necesita una resistencia convencional para montar un divisor de tensión a modo de resistencia pull-down. El esquema del circuito que utilizaremos es el siguiente:



Mi propuesta para el montaje en la protoboard es esta:



Es totalmente necesario el uso de la resistencia pull para poder tener variación de tensión en la entrada analógica del Arduino, pues si conectaremos la resistencia directamente a la entrada analógica, entre VCC y masa, tendríamos variación en la intensidad que fluye a través de la resistencia, pero no variaciones de tensión que es lo que podemos analizar con el conversor AD.

El algoritmo del sketch sería muy sencillo, pues tan solo queremos que lea el valor de la resistencia, lo compare con un valor de consigna, y decida si debe apagar o encender el led.

Os invito a intentar encontrar la solución antes de continuar leyendo... tic tac tic tac.

De acuerdo pues aquí os dejo el sketch. Y podéis descargarlo desde aquí.

/* Ejemplo !_), recreamos un interruptor
crepuscular que actua en funcion del valor leido
por una LDR. Ver el video para ver como ajustar
en http://arduinopractico.blogspot.com.es */

int LDR_Pin = 0;  //pin conectado al fotoresistor LDR
int ledPin=9;     //pin conectado al led
int luminosidad;  // variable para registrar la lectura del LDR
int umbral=330;   // valor umbral de luminosidad
void setup()
{
    Serial.begin(9600);  //Begin serial communcation
    pinMode( ledPin, OUTPUT );//  Lo usaremos para ver la lectura real
    digitalWrite(ledPin,LOW);// y ajustar si necesario
}

void loop()
{
   
    luminosidad= analogRead(LDR_Pin); 
    Serial.println(analogRead(luminosidad)); //Escribimos el valor en monitor serie
    //monitorizando este valor podemos  ajustar el umbral para encender el led
    //en funci´n de la luminosidad
    if (luminosidad > umbral)// valor experimental
    {
      digitalWrite(ledPin,LOW);// si la luminosidad es mayor apagamos el led
    }    
    else
    {
      digitalWrite(ledPin,HIGH);// en caso contrario encendemos el led
    }
      
   delay(10); // A mayor valor mas lenta sera la respuesta a los cambios de luminosidad
}





Si os fijais, he incluido una línea para poder monitorizar el valor que obtenemos, ( entre 0 y 1023) de la resistencia LDR en el pin A0 del micro. Para activarlo debereis ir al monitor serial desde el IDE de Arduino.

Serial.println(analogRead(luminosidad));


La explicación del funcionamiento es muy sencilla, primero declaramos las cuatro variables que intervienen en el ejemplo:

int LDR_Pin = 0;  //pin conectado al fotoresistor LDR
int ledPin=9;     //pin conectado al led
int luminosidad;  // variable para registrar la lectura del LDR
int umbral=330;   // valor umbral de luminosidad

Una vez comienza el ejemplo, realizamos la lectura analógica en el pin 0, y lo almacenamos en la la variable luminosidad.

luminosidad= analogRead(LDR_Pin); 

En el siguiente bloque usamos una forma condicional, IT THEN, ( lo podéis repasar aquí), para comparar el valor leído con lo que queremos que sea nuestro umbral de luminosidad.

if (luminosidad > umbral)

Si es mayor, apagaremos el led ( entendemos que hay suficiente luz ambiental).
Por otro lado cuando cae por debajo de nuestra consigna encendemos nuestro led.

if (luminosidad > umbral)// valor experimental
    {
      digitalWrite(ledPin,LOW);// si la luminosidad es mayor apagamos el led
    }    
    else
    {
      digitalWrite(ledPin,HIGH);// en caso contrario encendemos el led
    }
      

El valor que que he usado es experimental. Dependerá del valor que uséis en la resistencia para hacer el PULL, del LDR, de la temperatura, etc.

Por eso es interesante el uso del monitor serial para monitorizar los valores obtenidos y ajustar de forma empírica.

Como procederíamos?

Cargamos el sketch,




y activamos el monitor serial (Heramientas > Monitor serie):


Simulando la luminosidad que queremos obtener y observando el monitor serial tendremos una idea de que valor aproximado podemos usar para nuestro circuito.

Un último consejo, para un ajuste de "campo" más sencillo, en el caso que quisiéramos cambiar este valor de forma más sencilla sin necesidad de conectarnos, sería sustituir la resistencia de 10kΩ por un potenciómetro.

Un video de ejemplo:




6 comentarios:

  1. Si quisiéramos actuar sobre dos leds distintos a distinta luminosidad?
    Podríamos nombrar otro umbral para el led 2?

    ResponderEliminar
  2. Hola, poder puedes. La forma más sencilla es definir dos nuevas variables, una para definir donde conectarás el led ( esta noe¡ es obligatoria), y otra para el nuevo umbral. Añade por ejemplo estas dos líneas:

    int ledPin2=10; //pin conectado al nuevo led
    int umbral2; // nuevo umbral

    Además añade en el void setup esta línea:

    pinMode( ledPin2, OUTPUT );//definición nuevo led
    digitalWrite(ledPin2,LOW);// e inicialmente lo apagamos.

    Ahora solo faltaría añadir el nuevo código, que sería un copy paste del que ya tienes tan solo cambiando el nombre de las variables mencionadas.

    Comenta si tienes alguna dificultad en este punto.

    Un saludo

    ResponderEliminar
  3. hola me funciona bien lo que no consigo es que tenga un retardo

    int LDR_Pin = 0; //pin conectado al fotoresistor LDR
    int ledPin=13; //pin conectado al led
    int ledPin2=12; //pin conectado al rele
    int luminosidad; // variable para registrar la lectura del LDR
    int umbral=330; // valor umbral de luminosidad
    int umbral2=730; // valor umbral de luminosidad2
    void setup()
    {
    Serial.begin(9600); //Begin serial communcation
    pinMode( ledPin, OUTPUT );// Lo usaremos para ver la lectura real
    digitalWrite(ledPin,LOW);// y ajustar si necesario
    pinMode( ledPin2,OUTPUT );//RELE
    digitalWrite(ledPin2,LOW);
    }

    void loop()
    {

    luminosidad= analogRead(LDR_Pin);
    Serial.println(analogRead(luminosidad)); //Escribimos el valor en monitor serie
    //monitorizando este valor podemos ajustar el umbral para encender el led
    //en funci´n de la luminosidad
    if (luminosidad > umbral)// valor experimental
    {
    digitalWrite(ledPin,LOW);// si la luminosidad es mayor apagamos el led
    }
    else
    {
    digitalWrite(ledPin,HIGH);// en caso contrario encendemos el led
    }
    if (luminosidad > umbral2)// valor experimental
    {
    digitalWrite(ledPin2,LOW);// si la luminosidad es mayor apagamos el led
    }
    else
    {
    digitalWrite(ledPin2,HIGH);// en caso contrario encendemos el led
    }
    delay(10); // A mayor valor mas lenta sera la respuesta a los cambios de luminosidad
    }

    ResponderEliminar
    Respuestas
    1. ¿Qué tal? No consigo entender bien lo del retardo. Si quieres que sea más lento actuando a los cambios de luminosidad puedes subir el tiempo de delay. Pero no es la mejor solución puesto que durante ese tiempo , el Arduino estará inactivo,y por tanto no atenderá ningún cambio de luminosidad, ni cualquier otra función que se te ocurriese encomendarle.
      Pero puedes probar a subir el tiempo, por ejemplo un

      delay(1000);

      Supondrá un retardo de un segundo. Un valor de 10000 para 10 segundos, etc,
      Ya me dirás si este es el efecto que buscabas, y entonces buscaremos un sistema mejor para solucionarlo.

      Un saludo

      Eliminar
    2. Delay 10000 y todo ok
      Muchas gracias
      Eres un maquina

      Eliminar
  4. muchas gracias por tu ayuda

    ResponderEliminar