SENSOR + 2 RELÉS (UNO DE ELLOS CRÍTICOS)

Por favor si alguien puede aportar ideas lo agradecería:
Necesito en la rutina que controla el RELEUVC me funcione durante un tiempo pero no lo consigo. Gracias.

Gracias y un saludo.

El primer relé lo tengo solucionado con una rutina delay() porque no es crítico.

El segundo ya me vuelve loco porque no me funciona como quiero que lo haga, introduzco código con delay() porque los otros no ha funcionado ninguno. No quiero usar una placa de tiempo real adicional sino hacerlo con software, ayuda por favor:

int RELEPURIF = 4;           
int RELEUVC = 5;              
int SENSORM = 6; 
int ESTADOSENSORM = LOW; 
int PRESENCIA = LOW;                


void setup() {
  pinMode(SENSORM, INPUT);    
  pinMode(RELEPURIF, OUTPUT); 
  pinMode(RELEUVC, OUTPUT); 
  digitalWrite(RELEPURIF, HIGH);
  digitalWrite(RELEUVC, HIGH);
  delay(1000);
  PRESENCIA = LOW;
  ESTADOSENSORM = LOW; 
}

void loop() {
ESTADOSENSORM = digitalRead(SENSORM);
  if (ESTADOSENSORM == HIGH){
    digitalWrite(RELEUVC,HIGH);
    digitalWrite(RELEPURIF,LOW);
    delay(5000);// ESTA PUESTO A 5 SEGUNDOS, EN LA PRÁCTICA SERÁN 15 MINUTOS.
    digitalWrite(RELEPURIF,HIGH);
    PRESENCIA=HIGH;
    }
  if ((ESTADOSENSORM == LOW) && PRESENCIA == HIGH){ // ESTE ES EL BUCLE QUE NO QUIERO USAR DELAY Y QUIERO TEMPORIZAR CON MILLIS() POR EJEMPLO, METER EL MILLIS EN EL IF Y QUE ACTUA DURANTE UN TIEMPO QUE POR EJEMPLO SEAN 10 SEGUNDOS Y EN LA PRÁCTICA 20 MINUTOS
      digitalWrite(RELEUVC,LOW);
      digitalWrite(RELEPURIF,HIGH); 
      delay(100);
      digitalWrite(RELEUVC,HIGH);
      PRESENCIA=LOW;
  }   
   
  }/code]

Y este es el código tras seguir el tutorial de milis() pero que no me funciona, no desactiva RELEUVC

int RELEPURIF = 4;           
int RELEUVC = 5;              
int SENSORM = 6; 
int ESTADOSENSORM = LOW; 
int PRESENCIA = LOW;                
unsigned long t; 

void setup() {
  pinMode(SENSORM, INPUT);    
  pinMode(RELEPURIF, OUTPUT); 
  pinMode(RELEUVC, OUTPUT); 
  digitalWrite(RELEPURIF, HIGH);
  digitalWrite(RELEUVC, HIGH);
  delay(1000);
  PRESENCIA = LOW;
  ESTADOSENSORM = LOW; 
}

void loop() {
ESTADOSENSORM = digitalRead(SENSORM);
  if (ESTADOSENSORM == HIGH){
    digitalWrite(RELEUVC,HIGH);
    digitalWrite(RELEPURIF,LOW);
    delay(5000);
    digitalWrite(RELEPURIF,HIGH);
    PRESENCIA=HIGH;
    }
  else { 
      if (PRESENCIA == HIGH){
      digitalWrite(RELEUVC,LOW);
      t=millis();
      if ( millis()-t > 6000){
        digitalWrite(RELEUVC,HIGH);
        PRESENCIA=LOW;
  }   
  } 
  }
}

Bueno, creo que tengo ya el código y me funciona, ¿algún comentario?

int RELEPURIF = 4;           
int RELEUVC = 5;              
int SENSORM = 6; 
int ESTADOSENSORM = LOW; 
int PRESENCIA = LOW;                
unsigned long t; 

void setup() {
  pinMode(SENSORM, INPUT);    
  pinMode(RELEPURIF, OUTPUT); 
  pinMode(RELEUVC, OUTPUT); 
  digitalWrite(RELEPURIF, HIGH);
  digitalWrite(RELEUVC, HIGH);
  delay(1000);
  PRESENCIA = LOW;
  ESTADOSENSORM = LOW; 
}

void loop() {
ESTADOSENSORM = digitalRead(SENSORM);
  if (ESTADOSENSORM == HIGH){
    digitalWrite(RELEUVC,HIGH);
    digitalWrite(RELEPURIF,LOW);
    delay(5000);
    digitalWrite(RELEPURIF,HIGH);
    PRESENCIA=HIGH;
    t=millis();
    }
  else { 
      if (PRESENCIA == HIGH){
      digitalWrite(RELEUVC,LOW);
     // t=millis();
      if ( millis()-t > 10000){
        digitalWrite(RELEUVC,HIGH);
        PRESENCIA=LOW;
  }   
  } 
  }
}

Si no das un poco mas de informacion de lo que estas haciendo y lo que quieres conseguir va ser dificil opinar.

Bueno, creo que tengo ya el código y me funciona, ¿algún comentario?

Mi comentario: Es una aberración combinar delay con millis

Gracias por tu comentario, los recursos de software aportan soluciones en función de las necesidades y bien no es un software depurado también es cierto que desde que puse la consulta estuve viendo distintos manuales con el fin de aportar alguna solución y no esperar que otros usuarios lo revisen y solucionen. Fue muy útil la parte sobre manuales, concretamente entender millis().

¿Alguna idea de optimización del código?

Un saludo.

1 Like

jose:
Si no das un poco mas de informacion de lo que estas haciendo y lo que quieres conseguir va ser dificil opinar.

Buenas, la idea es que con un sensor de movimiento se consiga desinfectar un área donde transitan personas. Un relé activa un sistema inocuo para la salud por lo que no es conflictivo pero el otro un sistema tóxico para las personas por lo que no debe haber nadie en las inmediaciones en la desinfección.

El inócuo actuará el primero en caso de detección y hasta 15 minutos depués de que no exista presencia de personas.
El segundo actuará cuando el primero deje de hacerlo y por un tiempo de 30 minutos.

La idea es no introducir hardware sino hacrerlo por software debido a el bajo espacio del que dispongo para implementar la solución.
Había pensado en ARDUNIO MINI PRO + MODULO DE RELE ESTADO SOLIDO + RCWL0516.

Un saludo.

Hola de nuevo...

¿Alguna idea de optimización del código?

Bueno. ¿que tal así?

const byte relePurif = 4;           
const byte releUvc = 5;             
const byte sensorM = 6;
const unsigned long tiempoEncendidoPurif=900000;    //15 minutos 
const unsigned long tiempoEncendidoUvc=1800000;      //30 minutos
unsigned long t1, t2;
bool estadoSensorM, presencia;            



void setup() {
  pinMode(sensorM, INPUT);   
  pinMode(relePurif, OUTPUT);
  pinMode(releUvc, OUTPUT);
  digitalWrite(relePurif, HIGH);    //**asumo que utilizas relays con logica inversa**
  digitalWrite(releUvc, HIGH);
  delay(1000);
  }

void loop() {

  estadoSensorM = digitalRead(sensorM);
  
  if (estadoSensorM){
  	digitalWrite(relePurif,LOW);
        digitalWrite(releUvc, HIGH);
  	presencia=true; //esto evitara que se active el releUVC cuando se enciende el arduino y pasa el tiempo sin detectarse movimiento
  	    t1=millis();   
      }

  if(millis() - t1 >= tiempoEncendidoPurif && presencia){
         digitalWrite(relePurif,HIGH);
         digitalWrite(releUvc, LOW);
         t2=millis();
     } 
   
  if(millis() - t2 >= tiempoEncendidoUvc)
         digitalWrite(releUvc, HIGH);
    
    
}

Un código optimizado y muy sencillito pero el RELEUVC nunca se apaga y presencia nunca pasa a false.

Gracias.

Vaya!!! olvide una linea :slight_smile:

const byte relePurif = 4;           
const byte releUvc = 5;             
const byte sensorM = 6;
const unsigned long tiempoEncendidoPurif=900000;    //15 minutos 
const unsigned long tiempoEncendidoUvc=1800000;      //30 minutos
unsigned long t1, t2;
bool estadoSensorM, presencia;            



void setup() {
  pinMode(sensorM, INPUT);   
  pinMode(relePurif, OUTPUT);
  pinMode(releUvc, OUTPUT);
  digitalWrite(relePurif, HIGH);    //**asumo que utilizas relays con logica inversa**
  digitalWrite(releUvc, HIGH);
  delay(1000);
  }

void loop() {

  estadoSensorM = digitalRead(sensorM);
  
  if (estadoSensorM){
  	    digitalWrite(relePurif,LOW);
        digitalWrite(releUvc, HIGH);
  	    presencia=true;            //esto evitara que se active el releUVC cuando se enciende el arduino y pasa el tiempo sin detectarse movimiento
  	    t1=millis();   
      }

  if(millis() - t1 >= tiempoEncendidoPurif && presencia){
         digitalWrite(relePurif,HIGH);
         digitalWrite(releUvc, LOW);
         presencia=false;   //faltaba esta**
         t2=millis();
     } 
   
  if(millis() - t2 >= tiempoEncendidoUvc)
         digitalWrite(releUvc, HIGH);
    
    
}

Listo! ya tiene que apagar

Si, ahora si, perfecto. Gracias.

Tengo una duda RIG

Al entrar en el bucle

 if(millis() - t1 >= tiempoEncendidoPurif && presencia){
         digitalWrite(relePurif,HIGH);
         digitalWrite(releUvc, LOW);
         presencia=false;   //faltaba esta**
         t2=millis();

Si está en la rutina de arriba ahí de forma cíclica y forzamos presencia=false ¿por qué sigue entrando al bucle if? ¿es que se queda la rutina ahí en el if sin salir hasta que no se cumpla el condicionado if? pero dentro pasamos a false una de las condiciones y por tanto ya no se cumple... umm

Por otra parte, ¿cómo de fiable es millis()? ¿Sería recomendable usar una placa de tiempo real externa?

Vale, en ese bucle solo entra una vez y es el siguiente el que apaga el UVC o el que la señal de presencia vuelva a ser true entrando en la rutina if que enciende el RelePurif, muy elegante el código.

Gracias.

Para el caso que quiera introducir un nuevo sensor de movimiento S1 y gobernar un subsistema que no tenga nada que ver con este donde solo exista un ReléUVC1 y que su accionamiento fuese tras un tiempo de espera sin que este subsistema tenga que atender a nada más sería:

const byte relePurif = 4;           
const byte releUvc = 5;             
const byte sensorM = 6;
const byte sensorM1 = 7;
const byt releUVC1 = 8;
const unsigned long tiempoEncendidoPurif=900000;    //15 minutos
const unsigned long tiempoEncendidoUvc=1800000;      //30 minutos
const unsigned long tiempoEspera = 120000;                 //2 minutos
unsigned long t1, t2, t3, t4;
bool estadoSensorM, estadoSensorM1, presencia, presencia1;           



void setup() {
  pinMode(sensorM, INPUT);   
  pinMode(sensorM1, INPUT);
  pinMode(relePurif, OUTPUT);
  pinMode(releUvc, OUTPUT);
  pinMode(releUVC1, OUTPUT);
  digitalWrite(relePurif, HIGH);    //**asumo que utilizas relays con logica inversa**
  digitalWrite(releUvc, HIGH);
  digitalWrite(releUVC1, HIGH);
  delay(1000);
  }

void loop() {

  estadoSensorM = digitalRead(sensorM);
  estadoSensorM1 = digitalRead(sensorM1);

  if (estadoSensorM){
  	    digitalWrite(relePurif,LOW);
        digitalWrite(releUvc, HIGH);
  	    presencia=true;            //esto evitara que se active el releUVC cuando se enciende el arduino y pasa el tiempo sin detectarse movimiento
  	    t1=millis();   
      }

  if(millis() - t1 >= tiempoEncendidoPurif && presencia){
         digitalWrite(relePurif,HIGH);
         digitalWrite(releUvc, LOW);
         presencia=false;   //faltaba esta**
         t2=millis();
     }
   
  if(millis() - t2 >= tiempoEncendidoUvc)
         digitalWrite(releUvc, HIGH);
   
// RUTINA PARA NUEVO SENSOR Y RELE
   if (estadoSensorM1){
  	    digitalWrite(releUVC1, HIGH);
  	    presencia1=true;            //esto evitara que se active el releUVC cuando se enciende el arduino y pasa el tiempo sin detectarse movimiento
  	    t3=millis();   
      }

  if(millis() - t3 >= tiempoEspera && presencia1){
         digitalWrite(releUvc, LOW);
         presencia1=false;  
         t4=millis();
     }
   
  if(millis() - t4 >= tiempoEncendidoUvc)
         digitalWrite(releUVC1, HIGH);
   


}

Vale, en ese bucle solo entra una vez y es el siguiente el que apaga el UVC o el que la señal de presencia vuelva a ser true entrando en la rutina if que enciende el RelePurif,

Así es, entra una sola vez porque cambia el estado de la variable presencia.
Se podría hacer igual de esta forma:

if(presencia) 
     if(millis() - t1 >= tiempoEncendidoPurif ){
           digitalWrite(relePurif,HIGH);
           digitalWrite(releUvc, LOW);
           presencia=false;   //faltaba esta**
           t2=millis();
     }

¿cómo de fiable es millis()? ¿Sería recomendable usar una placa de tiempo real externa?

Por confiable te refieres a preciso?? si te refieres a eso, es muy preciso, no veo necesidad de utilizar algún reloj externo

Bueno respondo al post 11 ya que al parecer publicamos al mismo tiempo y se cruzaron los post

Básicamente seria lo mismo y si, quedaría como lo hiciste.
Y lo podrías repetir muchas veces con mas sensores gracias a millis(), cosa que con delay() nunca podrías lograr

Si, me refería a preciso (post#12).
En cuanto a los if anidados donde aclaras que entra al buble una sola vez queda reseñado claramente que solo entra una vez en la rutina. (post#12)
En cuanto al post 11 que hago sobre rutina adicional de un ReléUVC1, asociado a un sensor sensorM1, el subsistema para encender el reléUVC1 debe tener un retardo de encendido sin bloquear el procesador y por tanto por ello evitamos usar los delay como bien apuntabas al principio del hilo.

Cuestiones:

  1. En el caso hipotético de desbordamiento del milis en el 50 día sin uso, poco probable, ¿qué implicación podría tener en las comparaciones que hacemos?

  2. Si queremos controlar en vez de 1 relé adicional (post#11) "n" relés adicionales asociados cada uno a "n" sensores adicionales (un sensor gobierna un relé unicamente y pueden funcionar a la vez (N1 con S1, N2 con S2.... NN con SN), deberíamos de usar funciones que llamásemos para optimizar nuestro código, ¿verdad? En estas funciones para "n" relés se comparían con milis un valor de ("n" x 2) tiempos de comparación "t", ¿sería viable usar funciones?

En el caso hipotético de desbordamiento del milis en el 50 día sin uso, poco probable, ¿qué implicación podría tener en las comparaciones que hacemos?

No pasaría nada, el sistema seguiría trabajando con normalidad.

¿sería viable usar funciones?

Claro, en el caso que fueses a usar muchos sensores y relay que hacen básicamente lo mismo, lo mejor es hacer funciones y evitar un código con muchas repeticiones de lo mismo, ya que eso aumenta la probabilidad de errores

mira un ejemplo de lo que te digo: mira este post mira el codigo de la respuesta #2 después mira la #9 y veras la diferencia, incluso después modifique el código aun mas.

Excelente, gracias.

La idea es dotar de mayor seguridad el sistema, para ello voy a:

  • Controlar UVC con fis relés independientes, por un lado la fase del 220V por el otro lado el neutro.
  • Introducir un sensor ultrasónico medidor de distancias, si la distancia es menor a una umbral no actúan el UVC
  • E interactuar con el exterior con una pantalla LCD indicando tres estados: Reposo, Purificando, UVC en ejecución.

Me pongo a ello y presentó resultados.

Hola, tengo un problema con el código. Debido a que las luces UVC son muy peligrosas quieron controlar que nos se quede pegado un relé y funcionen, para ello la fase y el neutro las comando por relés independientes con el siguiente código:

const byte relePurif = 3;           
const byte releUvcFASE = 2;
const byte releUvcNEUTRO = 4;            
const byte sensorM = 5;
const unsigned long tiempoEncendidoPurif=900;    //15 minutos
const unsigned long tiempoEncendidoUvc=3800;      //30 minutos
unsigned long t1, t2;
bool estadoSensorM, presencia;           



void setup() {
pinMode(sensorM, INPUT);   
pinMode(relePurif, OUTPUT);
pinMode(releUvcFASE, OUTPUT);
pinMode(releUvcNEUTRO, OUTPUT);
digitalWrite(relePurif, HIGH);    //**asumo que utilizas relays con logica inversa**
digitalWrite(releUvcFASE, HIGH);
digitalWrite(releUvcNEUTRO, HIGH);
delay(1000);
}

void loop() {

estadoSensorM = digitalRead(sensorM);

if (estadoSensorM){
      digitalWrite(relePurif,LOW);
      digitalWrite(releUvcFASE, HIGH);
      digitalWrite(releUvcNEUTRO, HIGH);
      presencia=true;            //esto evitara que se active el releUVC cuando se enciende el arduino y pasa el tiempo sin detectarse movimiento
      t1=millis();   
    }

if(millis() - t1 >= tiempoEncendidoPurif && presencia){
       digitalWrite(relePurif,HIGH);
       digitalWrite(releUvcFASE, LOW);
       digitalWrite(releUvcNEUTRO, LOW);
       presencia=false;   //faltaba esta**
       t2=millis();
   }
 
if(millis() - t2 >= tiempoEncendidoUvc)
       digitalWrite(releUvcFASE, HIGH);
       digitalWrite(releUvcNEUTRO, HIGH);
 
}

El problema que tengo es que no se activan los dos relés UVC sino uno de ellos, en este caso en concreto el que está conectado al pin 2. Los tiempos indicados no son reales.

Lo he solucionado de la siguiente forma pero no entiendo realmente qué es lo que pasa, parece que la señal de presencia y los tiempos millis() están involucrados.

const byte relePurif = 3;           
const byte releUvcFASE = 2;
const byte releUvcNEUTRO = 4;  //ESTE SE LO SALTA          
const byte sensorM = 5;
const unsigned long tiempoEncendidoPurif=900;    //15 minutos
const unsigned long tiempoEncendidoUvc=3800;      //30 minutos
unsigned long t1, t2, t3;
bool estadoSensorM, presencia;           



void setup() {
  pinMode(sensorM, INPUT);   
  pinMode(relePurif, OUTPUT);
  pinMode(releUvcFASE, OUTPUT);
  pinMode(releUvcNEUTRO, OUTPUT);
  digitalWrite(relePurif, HIGH);    //**asumo que utilizas relays con logica inversa**
  digitalWrite(releUvcFASE, HIGH);
  digitalWrite(releUvcNEUTRO, HIGH);
  delay(1000);
  }

void loop() {

  estadoSensorM = digitalRead(sensorM);
 
  if (estadoSensorM){
        digitalWrite(relePurif,LOW);
        digitalWrite(releUvcFASE, HIGH);
        digitalWrite(releUvcNEUTRO, HIGH);
        presencia=true;            //esto evitara que se active el releUVC cuando se enciende el arduino y pasa el tiempo sin detectarse movimiento
        t1=millis();   
      }

  if(millis() - t1 >= tiempoEncendidoPurif && presencia){
         digitalWrite(relePurif,HIGH);
         digitalWrite(releUvcFASE, LOW);
         digitalWrite(releUvcNEUTRO, LOW);
         //delay(500);
         presencia=false;   //faltaba esta**
         t2=millis();
         t3=millis();
     }
   
  if(millis() - t2 >= tiempoEncendidoUvc)
         digitalWrite(releUvcFASE, HIGH);
           
  if(millis() - t3 >= tiempoEncendidoUvc)
         digitalWrite(releUvcNEUTRO, HIGH);
   
}

Si alguien me puede explicar qué ocurre sería de agradecer. Un saludo.