Encendido de luces mediante relés y fotocelulas

Buenos días,

Estoy realizando un proyecto el cual consta de 2 fotocélulas que, dependiendo del estado de estas (según detectan o no) tiene que encender unas luces u otras. Van conectadas a unos relés para encender luces de 24V pero estoy probando el código con LEDs (verde, ámbar, rojo) que, a priori, debería de ser más que suficiente.

La señal que sale de las fotocélulas la envío previamente desde el Arduino y solo cuando el relé interno de la fotocélula actúa recibo de vuelta dicha señal y con eso es con lo que trabajo.

Usando un Arduino R4 Wifi con dos fotocélulas (P1 y P2) y los estados deseables son los siguientes:

  • Si P1 = detecta Y P2 = detecta --> LED verde = 1 | LED ámbar = 0 | LED rojo = 0
  • Si P1 = detecta Y P2 = NO detecta --> LED verde = 1 | LED ámbar = 1 | LED rojo = 1
  • Si P1 = NO detecta Y P2 = detecta --> LED verde = 0 | LED ámbar = 1 | LED rojo = 0
  • Si P1 = NO detecta Y P2 = NO detecta --> LED verde = 0 | LED ámbar = 0 | LED rojo = 1

El código que utilizo es el siguiente:

void setup() {
  Serial.begin(9600);
  connectWifi();
  setupEmail();
  smtp.debug(1);
  smtp.callback(smtpCallback); // Activar callback
  // sendEmail(); // Enviar email al iniciar

  // configuracion INICIAL de los pines
  pinMode(OUT_P1, OUTPUT);      // Configura el pin 2 como salida
  pinMode(IN_P1, INPUT_PULLDOWN); // Configura el pin 3 como entrada con resistencia pull-down
  pinMode(GREEN_LED, OUTPUT);         // Configura el pin 4 como salida
  pinMode(OUT_P2, OUTPUT);    // Configura el pin 5 como salida
  pinMode(IN_P2, INPUT_PULLDOWN); // Configuracion el pin 6 como entrada con resistencia pull-down
  pinMode(AMBAR_LED, OUTPUT);  // Configura el pin 7 como salida
  pinMode(RED_LED, OUTPUT);    // Configura el pin 8 como salida


  digitalWrite(OUT_P1, HIGH);   // Envía señal HIGH por el pin 2
  digitalWrite(OUT_P2, HIGH);   // Envía señal HIGH por el pin 5

  Serial.println("OUT_P1 (2) and OUT_P2 (5) set to HIGH at startup");  // Mensaje para indicar el estado inicial


}




#define OUT_P1 2
#define IN_P1 3
#define GREEN_LED 13
#define OUT_P2 5
#define IN_P2 6
#define AMBAR_LED 7
#define RED_LED 8  // Definir el pin para RED_LED



void loop() {
  if (digitalRead(IN_P1) == HIGH && digitalRead(IN_P2) == HIGH) {
    pinMode(GREEN_LED, OUTPUT);
    digitalWrite(GREEN_LED, HIGH);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, LOW);
    digitalWrite(RED_LED, LOW);
  } else if (digitalRead(IN_P1) == HIGH && digitalRead(IN_P2) == LOW) {
    pinMode(GREEN_LED, OUTPUT);
    digitalWrite(GREEN_LED, HIGH);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, HIGH);
    digitalWrite(RED_LED, HIGH);
  } else if (digitalRead(IN_P1) == LOW && digitalRead(IN_P2) == HIGH) {
    pinMode(GREEN_LED, INPUT);      // Apaga y desconecta el LED verde
    digitalWrite(AMBAR_LED, HIGH);
    digitalWrite(RED_LED, LOW);
  } else if (digitalRead(IN_P1) == LOW && digitalRead(IN_P2) == LOW) {
    pinMode(GREEN_LED, INPUT);      // Apaga y desconecta el LED verde
    digitalWrite(AMBAR_LED, LOW);
    digitalWrite(RED_LED, HIGH);
  }
}

Veréis en el código que, además de cambiar los estados digitalWrite de cada PIN entre LOW y HIGH, existen unas líneas que cambian el pin "GREEN_LED" a INPUT. Esto es el último intento que he realizado para solventar el problema que ahora describiré (con esto quiero decir que sin esas líneas y solo usando digitalWrite HIGH/LOW tampoco funciona correctamente).

Problema:

1- En el primer estado el LED verde se enciende correctamente mientras el ámbar y el rojo permanecen apagados. (esto es lo que tiene que ocurrir y ahora ocurre)
2- En el segundo estado aparece los problemas: el LED ámbar se enciende correctamente, el LED rojo se mantiene apagado (correcto) pero el LED verde se atenúa, no se apaga del todo, sigue recibiendo voltaje (y no es un voltaje continuo, sino oscilante, como que tintinea, esto lo he verificado adeemás porque al conectarlo a un relé este se apaga y se enciende rapidísimo)
3- En el tercer estado el LED verde continua igual cuando tendría que estar apagado desde antes, el LED ámbar se apaga correctamente del todo y el LED rojo se enciende correctamente.

He probado a conectarle una resistencia pull-down por si hubiese algo de ruido o interferencia o alguna cosa que continuase enviando corriente al LED verde pero no encuentro nada. Y lo más curioso de todo es lo que os indicaba en el código: a pesar de cambiar el estado del pin de OUTPUT a INPUT sigue haciendo que el LED verde se encienda, lo cual me rompe ya todos los esquemas.

Espero haber expresado correctamente el problema y todo lo necesario para que me puedan ayudar, de no ser así, háganmelo saber y les proporcionare toda la información necesaria para encontrar la solución.

Muchas gracias.

Saludos.

Muestra cómo lo alimentas con 24 V.
Elimina tres líneas "pinMode(GREEN_LED, INPUT)" en "loop()".
Te faltan dos "digitalWrite(GREEN_LED, HIGH);"

No te acabo de entender:

Las líneas "pinMode(GREEN_LED, INPUT)" en "loop()" son para intentar (sin éxito) apagar el LED verde. Como decía antes no las tenia puesta y tenia puesta "digitalWrite(GREEN_LED, LOW);",también sin éxito.
Y cuando dices que me falta dos "digitalWrite(GREEN_LED, HIGH);" imagino que te refieres en los dos ultimos "else if" no falta, no quiero que en esos estados el LED verde este encendido.

La alimentación de 24V la hago es independiente al Arduino. Los 24V solo sirven para hacer funcionar las fotocélulas (modelo XUK9ARCNL2) porque la tensión mínima que necesitan es esa. Luego esos 24V también servirán para alimentar unas bombillas por un circuito totalmente independiente y serán accionada por unos relés (Los LEDs del código imitan estas luces) Estos 24V interfieren en ningún momento, ni con los LEDS ni con el Arduino.

Saludos.

Bien. Dices que lo tienes cableado y codificado correctamente. No voy a interferir.

El pin 13 ya tiene conectado el LED de la placa, ¿no puedes probar usando otro pin y ver si ocurre lo mismo?

Tu lógica esta mal, tienes 2 estados repetidos, que envian respuestas distintas a los led.
En una prendes el led Verde y en la otra lo apagas, y lo mismo con el led rojo. Todo pasa tan rapido que lo ves atenuado.

Si P1 = NO detecta Y P2 = detecta --> LED verde = LOW | LED ámbar = HIGH | LED rojo = LOW
Si P1 = NO detecta Y P2 = detecta --> LED verde = HIGH | LED ámbar = HIGH | LED rojo = HIGH

Cuando armas una tabla de verdad con entradas y salidas se ve mas claro

P1 P2 V A R
1 1 1 0 0
0 1 0 1 0 <= mal
0 0 0 0 1
0 1 1 1 1 <= mal
P1 y P2 los LCR
V verde
A ambar
R Rojo

Evidentemente, no. No he dicho eso. Lo que he dicho que para probar el código estoy utilizando 3 LEDs que simulan el efecto que luego tendrán 3 bombillas de 24V (en una baliza tipo semáforo). No he dicho que tengo el cableado bien (y menos aun el código). Lo que he dicho es que la parte de los 24V no interfieren en el resto del sistema (3 LEDs + 1 Arduino R4 Wifi).

Le meto tensión de 24V a las fotocélulas porque es como funciona y al relé de dichas fotocélulas le conecto el Arduino (OUT_P1 y OUT_P2). Lo conecto de forma que cuando no se corte el circuito el relé se active y dichas señales de salida del Arduino se conviertan en entradas (IN_P1 e IN_P2). Las pongo con INPUT_PULLDOWN para intentar garantizar que no se activan esos pines hasta que el relé de las fotocélulas no es activado (no se si es útil o no, pero he probado de todo, de todo lo conocido que yo conozco, claro).

Es cuando recibo esa señal a los IN_P1 e IN_P2 empiezo a "jugar" con los condicionales para encender y apagar los LEDs.

Y de echo, "funciona". Pero mal, por eso estoy aqui. Funciona como he puesto en el primer post.

Algo le pasa al loop y por eso creo que entra y sale una y otra vez, estoy pensando en ponerle un delay grande para ver si se mitiga el efecto que describia en el anterior post.

Saludos.

Si, también lo he pensado. De echo, el pin 13 lo he usado precisamente porque estaba usando el pin 4 (queria hacerlos todos correlativos) por si el problema estaba en el hardware pero sigue haciendo lo mismo.

Lo he escrito mal antes al "interpretar" el codigo para escribirlo.

El código es el que debería de estar bien.

Siguiendo tu consejo y mirando el código que estoy usando, la tabla de la verdad que me sale es esta:

P1 P2 V A R
1 1 1 0 0
1 0 1 1 1
0 1 0 1 0
0 0 0 0 1

Y es la que quiero conseguir que funcione correctamente.
Voy a modificar el post original.
Gracias

Si las señales a los interruptores de las fotocélulas se mantienen fijas puedes conectarlos directamente a Vcc o GND en lugar de a 2 pines.

Es una opción. ¿Crees que el problema esta ahí?

No, solo me parece más lógico hacerlo así.

No me quedó claro si en el pin 4 te hacía lo mismo que en el 13.

Agrego:

La simulación en wokwi no presenta la falla, funciona bien.

Cuando presentes un código, hazlo con uno que esté completo y ordenado.
Las sentencias #define no van en cualquier lado, van al principio.
Y si el código es parcial, como éste, quita las llamadas a las funciones que le pasaste "la tijera".
Nosotros no tenemos por qué quitar la "basura" de tu código para poder probarlo.

Una cosa es ofrecerte nuestro tiempo para ayudarte y otra muy distinta es tener que perder tiempo para poder ayudarte.

Si si, me hace exactamente lo mismo por lo que descarto un fallo de hardware, al menos en esos pines. (o que falle todo, más raro)

Aqui el codigo más limpio:

// Datos de los pines

#define OUT_P1 2       // Pin de salida para enviar señal
#define IN_P1 3        // Pin de entrada para recibir señal
#define OUT_P2 5       // Pin de salida para enviar señal
#define IN_P2 6        // Pin de entrada para recibir señal
#define GREEN_LED 13    // Pin de salida para el LED VERDE
#define AMBAR_LED 7    // Pin de salida para el LED AMBAR
#define RED_LED 8      // Pin de salida para el LED ROJO

void setup() {
 
  // Configuración inicial de los pines
  pinMode(OUT_P1, OUTPUT);
  pinMode(IN_P1, INPUT_PULLDOWN);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(OUT_P2, OUTPUT);
  pinMode(IN_P2, INPUT_PULLDOWN);
  pinMode(AMBAR_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);

  digitalWrite(OUT_P1, HIGH); // Envía señal HIGH por el pin 2
  digitalWrite(OUT_P2, HIGH); // Envía señal HIGH por el pin 5
  
}

void loop() {
  if (digitalRead(IN_P1) == HIGH && digitalRead(IN_P2) == HIGH) {
    pinMode(GREEN_LED, OUTPUT);
    digitalWrite(GREEN_LED, HIGH);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, LOW);
    digitalWrite(RED_LED, LOW);
  } else if (digitalRead(IN_P1) == HIGH && digitalRead(IN_P2) == LOW) {
    pinMode(GREEN_LED, OUTPUT);
    digitalWrite(GREEN_LED, HIGH);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, HIGH);
    digitalWrite(RED_LED, HIGH);
  } else if (digitalRead(IN_P1) == LOW && digitalRead(IN_P2) == HIGH) {
    pinMode(GREEN_LED, INPUT);      // Apaga y desconecta el LED verde
    digitalWrite(AMBAR_LED, HIGH);
    digitalWrite(RED_LED, LOW);
  } else if (digitalRead(IN_P1) == LOW && digitalRead(IN_P2) == LOW) {
    pinMode(GREEN_LED, INPUT);      // Apaga y desconecta el LED verde
    digitalWrite(AMBAR_LED, LOW);
    digitalWrite(RED_LED, HIGH);
  }
}

Saludos

Por alguna razón olvidé postear el código que había hecho
Ahora agregué los cambios en la tabla de verdad

#define OUT_P1      2
#define IN_P1       3
#define GREEN_LED   13
#define OUT_P2      5
#define IN_P2       6
#define AMBAR_LED   7
#define RED_LED     8  // Definir el pin para RED_LED
int estadoP1, estadoP1Ant = 0;
int estadoP2, estadoP2Ant = 0;

void setup() {
  Serial.begin(9600);
  
  // configuracion INICIAL de los pines
  pinMode(OUT_P1, OUTPUT);      // Configura el pin 2 como salida
  pinMode(OUT_P2, OUTPUT);    // Configura el pin 5 como salida
  digitalWrite(OUT_P1, HIGH);   // Envía señal HIGH por el pin 2
  digitalWrite(OUT_P2, HIGH);   // Envía señal HIGH por el pin 5

  pinMode(IN_P1, INPUT); // Configura el pin 3 como entrada con resistencia pull-down
  pinMode(IN_P2, INPUT); // Configuracion el pin 6 como entrada con resistencia pull-down

  pinMode(GREEN_LED, OUTPUT);         // Configura el pin 4 como salida
  pinMode(AMBAR_LED, OUTPUT);  // Configura el pin 7 como salida
  pinMode(RED_LED, OUTPUT);    // Configura el pin 8 como salida

  Serial.println("OUT_P1 (2) and OUT_P2 (5) set to HIGH at startup");  // Mensaje para indicar el estado inicial
}

void loop() {
  estadoP1 = digitalRead(IN_P1);
  estadoP2 = digitalRead(IN_P2);
  if (estadoP1 != estadoP1Ant ) {
      Serial.println(estadoP1?"P1 ON ":"P1 OFF");
      estadoP1Ant = estadoP1;
  }
  if (estadoP2 != estadoP2Ant ) {
      Serial.println(estadoP2?"P2 ON ":"P2 OFF");
      estadoP2Ant = estadoP2;
  }

  /*
  P1 P2 V A R
  1 1 1 0 0
  1 0 1 1 1
  0 1 0 1 0
  0 0 0 0 1
*/

  if (estadoP1 && estadoP2) {
    digitalWrite(GREEN_LED, HIGH);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, LOW);
    digitalWrite(RED_LED, LOW);
  } else if (estadoP1 && !estadoP2) {
    digitalWrite(GREEN_LED, HIGH);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, HIGH);
    digitalWrite(RED_LED, HIGH);
  } else if (!estadoP1 && estadoP2) {
    digitalWrite(GREEN_LED, LOW);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, HIGH);
    digitalWrite(RED_LED, LOW);
  } else if (!estadoP1 && !estadoP2) {
    digitalWrite(GREEN_LED, LOW);  // Enciende el LED verde
    digitalWrite(AMBAR_LED, LOW);
    digitalWrite(RED_LED, HIGH);
  }
}

Pareciera que el sensor de wokwi trabaja al revés de lo que lo hace tu código.
Si es así niega las dos primeras líneas.

  estadoP1 = !digitalRead(IN_P1);
  estadoP2 = !digitalRead(IN_P2);

He probado el código pero falla mas que antes. No se explicarlo así que como dicen que una imagen dice más que mil palabras...pues he hecho un video (espero que se puedan poner enlaces a videos)

En el video sigue sucediendo lo que explicaba al principio: cada vez que la fotocélula "se activa", el led ámbar se enciende (esto lo hace bien) pero el verde no se apaga. En el video se puede apreciar como se atenúa y gracias a la frecuencia de grabación hasta se aprecia como parpadea. En el video lo hago varias veces seguidas para que se note la diferencia.

Después, cuando es el turno de la siguiente fotocélula y se tiene que apagar el led verde, apagar el ámbar y encender el rojo...bueno...en el video aparece.

Fiesta leds
Saludos.

Yo te mandé una simulación y en la simulación no falla.
Eso no tiene forma de discutirse. Algo tienes mal en tu circuito.

Yo también te dije en #13

Revisa que los contactos de los interruptores de las fotocelulas no estén sucios o quemados (sobre todo si son usadas), de modo que generen rebotes y/o falsos contactos que, obviamente, se van a reflejar en las lecturas de los pines.

Hola @nitoino

Las salidas OUT_P1 y la OUT_P2 , que realizan ???
Un saludo !! ... :cocktail:... :cocktail:

Envian señal a las foto células que luego uso para IN_P1 e IN_P2. Si vuelven es porque el relé interno de la foto célula a cambiado de estado (detecta/no detecta).

Saludos