Relacionar la respuesta de una fotoresistencia LDR GL55 con la intensidad de un led monocolor

Buenas noches a tod@s,

Intento programar en el IDE Arduino relacionando la respuesta del LDR con la intensidad con la que brilla el led (mayor brillo cuanta menor iluminación) a través de analogWrite pero no estoy teniendo suerte.

Agradecería cualquier idea.

¿Dónde tienes el problema?

¿Lees correctamente el valor del LDR?
¿Se enciende el LED con alguna intensidad?

Hola Miguel Angel,

El problema lo tengo en el código que he creado. Básicamente, como creía identificar que la respuesta de la iluminancia y la resistencia era más o menos lineal, asigné a todos los valores una función para tratar de emular una respuesta del led (0-255).

Sí, recibo sus valores.


En el caso de Arduino lo he conectado físicamente y con el monitor de puerto serie de Arduino desde el que saqué una fórmula para hacer la equivalencia de luminosidad (intensidad de corriente que circula por la fotoresistencia LDR pasada a lux) con la respuesta del LED… En la foto de arriba ya figura la simulaciónen Proteus con el código .hex cargado.

Pongo la fórmulas que realicé…


/* FUNCIÓN CONVERSIÓN_A_LUX
*  CONVIERTE A LUX LA VARIACIÓN DE INTENSIDAD DE CORRIENTE QUE CIRCULA POR EL LDR UNA VEZ QUE INCIDE LUZ SOBRE ELLA
*  Matemáticamente, la relación entre la iluminancia y la resistencia de una LDR sigue una función potencial: I/I_o = (R/R_o)^{-gamma}
*   R_o es la resistencia a una intensidad I_o, ambas conocidas.
*   Constante gamma es la pendiente de la gráfica logarítmica, o la pérdida de resistencia por década (típicamente 0.5 a 0.8).
*  Frecuentemente las gráficas que relacionan ambos valores se representan en escalas logarítmicas para ambos ejes y, es bajo esta representación, que 
*  la relación se muestra como una gráfica lineal, de ahí nuestra ecuación.
*/
float conversionAlux(float voltaje)
{
  const long Roscuridad = 1000;     //Resistencia en oscuridad en KΩ
  const int Rluminosidad = 15;        //Resistencia a la luz (10 Lux) en KΩ
  const int Rcalibrada = 10;       //Resistencia calibracion en KΩ
  return (float)((long)voltaje*Roscuridad*10)/((long)2*Rluminosidad*Rcalibrada*(1024-voltaje)); 
 }// FIN CONVERSIÓN A LUX



----------

/* ESTABLECE UN VALOR DEL BRILLO EN FUNCIÓN DE LA SITUACIÓN DE VOLTAJE O LUX QUE HAY EN EL LDR
*  Funcionamiento: establece un valor de brillo LED en función del valor LDR transformado en LUX
*  AnalogWrite concede un valor a la salida digital PWM entre 0 y 255. Hay que casar eso con la escala de iluminación (lux) que va desde casi 0 (oscuridad) hasta 3000 en un día soleado
*  Hemos establecido correspondencias donde desde 0 hasta 250 luxes el valor del LED esté entre 200 y 180; en [250,500) se corresponde con un valor led (130,180); en [500,750) está en [130,80) de led y por último en [750,1000] tendrá un valor [30,80) y más de ese valor, dado que las condiciones de luminosidad son excelentes, será al menos de 30
*  Reservamos un plus de 55 para las condiciones de velocidad
*  La ecuación ha sido extraída de la tabla de valores, según los incrementos en y sobre x.
*/
float establecerBrilloLED(float luxs)
{
  float brillo = (int) -luxs /5+200; // Ecuación de proporcionalidad inversa correspondiente a los incrementos de luminosidad (y) en proporcionalidad indirecta con la iluminación de la vía
  if (brillo <=60){brillo=60.0;} // factor de corrección para que nunca se apague el LED mientras se esté circulando en la vía con el dispositivo
  return brillo;
 } // FIN DETERMINAR BRILLO INICIAL


Sí, se enciende pero parece que la luminosidad es siempre la misma. Sé que el PWM no hace milagros y juega con los tiempos para emular una respuesta analógica pero creo que el fallo debe estar en la fórmula.

Lo siento por la aberración de mi código :roll_eyes:

He visto las funciones constrain y map pero no consigo una respuesta normal. Al observar el valor mínimo de la resistencia (11) y el máximo (1011) y asignarle valores entre 0 y 255 termina asignándolos bastante mal… básciamente le asigna 255 y siguientes a los primeros valores (de 0 lumenes a 40) pero luego decrece en un segundo y asigna directamente 60 al resto (ver código)

 // OBJETIVO 1: Circuito de luminosidad (fotoresistencia)
  const int LDRPin = A0;         // Pin de entrada de datos de la fotoresistencia (sensor LDR)
  const int valorLDRmin = 11;   // Valor mínimo obtenido por A0
  const int valorLDRmax = 1018;  // Valor maximo obtenido por A0
  int brilloLED;         // El dispositivo, por seguridad, siempre partirá de una iluminación de 30, en una escala de 255 a la que puede llegar
  float datosLDR;        // Variable para almacenar los datos sensor LDR
  float lux;             // Iluminacion de la vía 

...

/* FUNCIÓN ILUMINACION
* Cumple con el objetivo de adaptar la luminosidad a un LED monocolor según el nivel de iluminación que llega al sensor LDR
*/
void iluminacionLED(float datosLDR, int ledpin)
{
  int lux;
  int brilloLED;
  
  datosLDR = analogRead(LDRPin);// Leemos el puerto serie
  brilloLED = constrain(datosLDR, valorLDRmin, valorLDRmax); // Normalizamos el valor.
  brilloLED=255-map(brilloLED, valorLDRmin, valorLDRmax, 0, 255);// Re-mapeamos pero al revés porque la luminosidad debe ser mayor y no menor
  if(brilloLED < 60) {brilloLED  = 60;} // Factor de corrección
      // Comprobación LDR
  /*if(datosLDR ==0.0){Serial.println(" Controlar funcionamiento LDR. Apague el dispositivo y vuelva a encenderlo. Si ve esta advertencia de nuevo puede que el LDR esté dañado");}
      // convertimos a lux la lectura LDR y establecemos el brillo LED
  lux=conversionAlux(datosLDR); // Convertimos los datos de LDR en luminosidad
  brilloLED=(int)establecerBrilloLED(lux); // Establecemos el brillo LED en función de la luminosidad exterior*/
  analogWrite(ledPin, brilloLED);
  imprimirResultado(datosLDR, 0, brilloLED);
  // Esperamos 30 milisegundos
  delay(30);
}

  brilloLED=255-map(brilloLED, valorLDRmin, valorLDRmax, 0, 255);// Re-mapeamos pero al revés porque la luminosidad debe ser mayor y no menor

Se puede simplificar con

  brilloLED=map(brilloLED, valorLDRmin, valorLDRmax, 255, 0);// Re-mapeamos pero al revés porque la luminosidad debe ser mayor y no menor

Lo primero que deberías hacer es mirar si los valores son los esperados enviándolos por puerto serie y viéndolos desde el ordenador.

Por otro lado, el contrains suele aplicarse al final del todo,

  datosLDR = analogRead(LDRPin);// Leemos el puerto analógico
  brilloLED=map(brilloLED, valorLDRmin, valorLDRmax, 255, 0); //Mapeamos
  brilloLED = constrain(brilloLED, 60, 255); //Mínimo 60 y máximo 255

No termino de ver porque quieres mínimo 60, pero bueno.

Eso es lo que he hecho pero la asignación de valores con map se desploma de repente, desde 0 a 35 de la resistencia. En teoría debería ir asignando y estirando los valores de 255 a 0 para con los valores de intensidad mínima y máxima de la resistencia, ¿no?

Si la función map fuera bien sería genial… me ahorraría esto… ¿Qué pensais?

Lo que quiero es que exista un mínimo de luminosidad siempre que el dispositivo esté encendido. Le asigné 60 por poder verlo representado porque menos no veía demasiado si estaba encendido.

Vale, ya lo he solucionado codificando mi propio map.

Gracias Miguel Ángel!