Detector de presencia con una resistenicia fotoeléctrica (LDR) -Tiene otros usos

Muchas gracias por aportar otro ejemplo al foro. :slight_smile: :slight_smile: :slight_smile:

Como en el anterior ejemplo que pusiste, me gustaría comentarte otro par de cosas para mejorarlo:

No inicializas ultimamedicion, con lo que probablemente se inicie a cero y el código empiece con una activación por no estar la medida en el rango.

Una vez activas la salida, utilizas un delay para parar el programa. Durante ese tiempo la señal de entrada ha podido variar mucho y en ambos sentidos, esos cambios los has perdido y no los tienes controlados. Haces una medida cada ciclo (supongamos que el ciclo del programa que propones tardar 2-4 milisegundos), cuando activas la salida paras el bucle durante 1000 milisegundos. En ese tiempo podrías haber detectado de 250 a 500 cambios en el valor leído que se te han escapado.

Al poner un delay de 1 segundo, supongo que el tiempo de reacción del código no es crítico y pretendes detectar variaciones de la tensión de entrada, no picos ni fluctuaciones rápidas. Como en el ejemplo de los leds que pusiste, utilizas una única lectura para actuar. Para evitar problemas con picos y fluctuaciones (como pasaba en ese ejemplo también) deberías realizar una media de medidas y actuar a partir de ese valor.

Por último, me gusta mucho :smiley: (de verdad) que hayas puesto casi tantas líneas de comentarios como de código y hayas dejado las llamadas a serial.print comentadas (aunque no has comentado el begin :stuck_out_tongue: ) . Esa es la forma de que todos los que quieren utilizar estos ejemplos puedan entenderlos rápidamente y aprender.

Permíteme que aplique estos cambios y me dices que te parece el resultado (a lo mejor no es lo que tú esperabas que hiciese, así que no dudes en decirmelo).

/*
- Este programa es un disparador, que activa una salida lógica si detecta un cambio de tensión en su entrada analógica, dentro de un rango establecido por el usuario.
- Las aplicaciones pueden ser por ejemplo, como detector en alguna aplicación que use un sensor que pueda producir variaciones de tensión.
- El circuito de ejemplo usa una resistencia fotoeléctrica (LDR) para hacer un detector de presencia o de movimiento, de los del tipo PIR.

CONEXIONADO.

CONECTAR LA LDR AL TERMINAL POSITIVO
CONECTAR UNA RESISTENCIA DE 33k EN SERIE CON LA RESISTENCIA FOTOELÉCTRICA (LDR) Y CONECTAR EL EXTREMO LIBRE A MASA.
CONECTAR LA ENTRADA ANALÓGICA "CERO" DEL ARDUINO ENTRE LA RESISTENCIA LDR Y LA RESISTENCIA DE 33k. ES DECIR, ENTRE LOS DOS COMPONENTES.

CONECTAR UN EL ÁNODO DE UN DIODO LED AL TERMINA DIGITAL 2
CONECTAR EL CÁTODO DEL DIODO LED A UNA RESISTENCIA DE 220 OHMIOS Y LA RESISTENCIA A MASA.

FUNCIONAMIENTO

EL LED SE ENCENDERÁ SI LA VARIACIÓN DE TENSIÓN DETECTADA POR LA ENTRADA ANALÓGICA 0 DEL ARDUINO SUPERA UN DETERMINADO RANGO, ESTABLECIDO POR LA CONSTANTE.

Si pasamos la mano frente a la resistencia LDR el LED se encenderá, por la variación de tensión detectada por el arduino en su entrada.
Si al LDR lo colocamos en el interior de un capuchón de un bolígrafo BIC (de esos que tienen un agujero), usaremos el capuchón como cámara oscura rudimentaria, que permitirá a la LDR detectar el movimiento a distancias mayores.

ESTE CIRCUITO A SIDO PROBADO Y FUNCIONA CORRECTAMENTE
EL USUARIO TENDRÁ QUE AJUSTAR LA SENSIBILIDAD DEL DISPOSITIVO, CAMBIANDO EL VALOR DE LA VARIABLE LLAMADA RANGO QUE POR DEFECTO ESTÁN EN 5, PUDIENDO SE PONER ENTRE 1 (MÁXIMA SENSIBILIDAD) O VALORES MAYORES, QUE DEPENDERÁN DE LA TENSIÓN DE ENTRADA Y LAS VARIACIONES.

*/

const long rango=5; // este es el rango por el que se disparará la salida 2 y pasa a estado lógico 1
const long tiempo=1000; // tiempo que permanecerá activa la salida 2 en caso de pasar a estado lógico 1
const char num_medidas_media=128;  // numero de medidas a tomar para hacer la media
long ultimamedicion; // contiene el valor de la última medición que disparó a lógico 1, la salida 2
char num_medidas; // número de medidas tomadas para la media
long valor_medio; // valor medio para comparar con los umbrales
unsigned long inicio_pulso;  // momento en el que se detecta la salida del rango;

void setup() {
//  Serial.begin(9600);
  // inicialización de los pines
  pinMode(A0, INPUT);
  pinMode(2, OUTPUT);
  
  // inicilización de variables
  inicio_pulso = 0;
  num_medidas = 0;
  valor_medio = 0;
  
  // inicialización de ultimamedicion mediante una primera media
  while(num_medidas<num_medidas_media)
  {
    valor_medio +=analogRead(A0);
    num_medidas++;
    delay(10);
  }
  ultimamedicion = valor_medio/num_medidas_media;

  num_medidas = 0;
  valor_medio = 0;
}

void loop() 
{ 
  valor_medio += analogRead(A0); // vamos sumando valores (Cuidado!!! Si se utilizan muchas medidas para la media podría desbordar)
  num_medidas++;
  
  if(num_medidas == num_medidas_media)  // ya tenemos las "num_medidas_media" medidas
  {
    valor_medio = valor_medio/num_medidas_media; // Dividimos para calcular la media

    if (valor_medio >= (ultimamedicion+rango)) // La salida 2 pasa a 1 lógico si la tensión medida en la entrada analógica 0 es mayor que la anterior lectura + la tensión de RANGO
    {
      digitalWrite(2, HIGH);
      ultimamedicion = valor_medio;
      inicio_pulso = millis();
    }
   
    if (valor_medio <= (ultimamedicion-rango))  // La salida 2 pasa a 1 lógico si la tensión medida en la entrada analógica 0 es menor que la anterior lectura - la tensión de RANGO
    {
      digitalWrite(2, HIGH);      
      ultimamedicion = valor_medio;
      inicio_pulso = millis();
    }

    // Serial.println(valor_medio); // Por si quieres ver por el puerto serie las lecturas tomadas
    // Serial.println(ultimamedicion); // Por si quieres ver por el puerto serie las lecturas tomadas

    // inicializamos los valores para calcular la siguiente media
    num_medidas = 0;  // inicializamos las medidas
    valor_medio = 0;  // inicializamos el valor para la siguiente media
    // Si quesieramos utilizar la media que acabamos de calcular como primer valor para la siguiente media:
    // no reiniciamos valor_medio y num_medidas = 1;
  }
  
  if((inicio_pulso+tiempo) >= millis()) // Ha pasado "tiempo" desde la última detección
    digitalWrite(2, LOW); // La salida 2 pasa a 0 si la tensión medida en la entrada analógica 0 no esta fuera de rango
}