1 Pir con 2 millis (50seg. y 90seg.) Solucionado

Buenos dias a todos, gracias a Surbyte (miles de gracias), tengo el siguente codigo que con un sensor PIR enciende un Led durante 50 segundos . Si hay movimiento dentro de los 50 segundos calculará los millis hasta que hizo movimiento + los 50 segundos. Hasta aqui todo bien.
Me gustaria añadir un Led2 el cual se encienda y el tiempo es superior a los 50 seg. (no importa si el 1 se quedara encendido o no). Me podeis ayudar con el codigo, me cuesta entender los millis y no se como poner algo como " if LED_1 millis > 90000 , digitalWrite(LED_2, HIGH) ".
Un saludo a todos. El codigo creo que esta bien explicado para que se entienda muy bien cada funccion.

// si se detecta movimiento Pir activa LED_1 50 segundos, 
// si hay movimiento dentro de los 50 segundos =>  millis + los 50 segundos
// si no hay movimiento en los 50 segundos se apaga led 1
// si el movimiento es 90 seg. activa LED_2 

#define PIR_MOTION_SENSOR_1 5     //pin D5 es la señal del PIR
#define LED_1               11    //LED2 conectado al D11
#define LED_2               12    //LED2 conectado al D12

bool sensor1, sensor1ant, ;         
bool turnOnLED_1 = false;
bool turnOnLED_2 = false;

unsigned long tonLED_1;           
unsigned long tonLED_2;      
long sensor1longtime = 90000;          // millis para 90" del del LED_2

void setup() {
  pinMode(PIR_MOTION_SENSOR_1, INPUT);
  pinMode(LED_1,OUTPUT);          // Salida para LED 2
  pinMode(LED_2,OUTPUT);          // Salida para LED 2
}

void loop() {

  /*****************************************************************/
  /* Function: Detect whether anyone moves in it's detecting range */
  /* Return:-boolean, ture is someone detected.                    */
  /*****************************************************************/
  sensor1 = digitalRead(PIR_MOTION_SENSOR_1);

  if (sensor1 && !sensor1ant) {   //si sensor1(PIR digital read) no es sensor1ant
     turnOnLED_1 = false;
     turnOnLED_2 = false;
     digitalWrite(LED_1, HIGH);   // rele Led ON
     tonLED_1 = millis() + 50000UL;//tonLED_1 = millis de hasta ahora + 50 sec

  }
  sensor1ant = sensor1;
  

//   if tonLED_1 millis > sensor1longtime
//   digitalWrite(LED_2, HIGH);



     if (millis() > tonLED_1) {    //si millis (50") > millis y no hay movimiento
        digitalWrite(LED_1, LOW);  //LED1 OFF
        digitalWrite(LED_2, LOW);  //LED2 OFF
        turnOnLED_1 = false;
        turnOnLED_2 = false;


     }
  }

Aclárame esta duda y te atiendo:

Si detecta movimiento, se encienden los LEDs y se inicia el conteo; hasta aquí todo bien.
Pero, que pasa si se sigue detectando movimiento? Los contadores se reinician cada vez que esto ocurre? O se reinician solo si ya no lo sensa y luego lo vuelve a hacer?

Esta es la duda que me deja la variable sensor1ant

Gracias Lucario448, quizas me expresé mal.
Veras cuando se detecta movimiento ahora mismo solo se enciende el Led_1. (si hay movimiento se recalcula el tiempo del Led_1).
Tienes razón , cuando el Pir detectaría movimiento durante mas de 50" que encienda el Led_2 y recalcular el tiempo. El contador creo que se podria usar el mismo tanto para el 1 como para el 2.

Explico mi proyecto:
Entro en la habitacion, cojo una camiseta, se enciende una tira de led (LED_1), se hace el recuento por si tardo mas, salgo... y se apaga.
En caso de que no encuentro la camiseta en mi armario jjjj, digamos pasados 1,5 min se enciende la luz (LED_2). (habria que modificar...poner 1,5 min)
(me gustaria dejar el recuento del LED_1 y usarlo para el LED_2 en caso de modificar el tiempo poner mas de 50" en un futuro), es posible? Tras probarlo me di cuenta de que el pir aveces se apagaba cuando todavia estaba en la hab. por eso es muy importante el recuento.

Los contadores se reinician cada vez que esto ocurre? -> Sip

Gracias, un saludo.

Usando el criterio de Serafín (@noter) intentará concentrarme en que entiendas millis() mejor que hasta ahora.
millis() es un cronómetro con milésimas.
Si quieres saber un tiempo o iniciar una cuenta que haces.
un evento debe iniciar la toma de un tiempo T1 (variable que llamas como quieras pero debe ser unsigned long o mas corto uint32_t que es lo mismo). Supongamos que ese evento sea el que tu quieres, entonces esa variable T1 tendra ese valor parcial de millis().
Luego tu quieres que a los tantos mseg haga algo entonces le dices

if (millis() - T1 > INTERVALO) {
    // accionas lo que quieres o apagas lo que quieres.
}

Entonces tenemos dos situaciones.

  1. La que dispara nuestro conteo parcial y lo registramos tomando el valor de millis() y
  2. la que lo detiene que puede ser otro evento o bien transcrrido un lapso como en tu caso.

Muchas gracias Surbyte, definitivamente voy progresando…cambie esto pero esta mal.
He añadido:
unsigned long sensor1longtime = 100000; // que sera mi T1

y cambiando esto

   if (tonLED_1 > sensor1longtime ) {
       digitalWrite(LED_2, HIGH);  //LED2 ON
   } else {
       digitalWrite(LED_2, LOW);  //LED2 OFF
   }

no tengo lo que quiero, porque el esta calculando el tiempo transcurrido en total. Me pasa esto:
Muevo la mano delante del sensor, LED_1 se enciende, lo dejo que se apague y se apaga. En cuanto paso la mano otra vez se enciende el LED_2 tambien. (porque se enciende a los 150 seg., yo quieria poner que se encienda a los 150 segundos despues de que esta esta el LED_1 encendido, y no que se encienda cuando esta el LED_1 encendido + apagado )

Como puedo hacer para que cada vez que se apaga el LED_1 se reinicie los el tiempo del sensor1longtime

Se que esto puede resultar dificil entenderlo, y dar consejos sin probarlo con el arduino. Muchas gracias a todos, un saludo

// si se detecta movimiento Pir activa LED_1 50 segundos, 
// si hay movimiento dentro de los 50 segundos =>  millis + los 50 segundos
// si no hay movimiento en los 50 segundos se apaga led 1
// si el movimiento es 100 seg. activa LED_2 

#define PIR_MOTION_SENSOR_1 5     //pin D5 es la señal del PIR
#define LED_1               11    //LED2 conectado al D11
#define LED_2               12    //LED2 conectado al D12

bool sensor1, sensor1ant ;         
bool turnOnLED_1 = false;
bool turnOnLED_2 = false;

unsigned long tonLED_1;           
unsigned long tonLED_2;      
unsigned long sensor1longtime = 100000;          // millis para 90" del del LED_2

void setup() {
  pinMode(PIR_MOTION_SENSOR_1, INPUT);
  pinMode(LED_1,OUTPUT);          // Salida para LED 2
  pinMode(LED_2,OUTPUT);          // Salida para LED 2
}

void loop() {

  /*****************************************************************/
  /* Function: Detect whether anyone moves in it's detecting range */
  /* Return:-boolean, ture is someone detected.                    */
  /*****************************************************************/
  sensor1 = digitalRead(PIR_MOTION_SENSOR_1);

  if (sensor1 && !sensor1ant) {   //si sensor1(PIR digital read) no es sensor1ant
     turnOnLED_1 = false;
     turnOnLED_2 = false;
     digitalWrite(LED_1, HIGH);   // rele Led ON
     tonLED_1 = millis() + 50000UL;//tonLED_1 = millis de hasta ahora + 50 sec

  }
  sensor1ant = sensor1;
  
    if (tonLED_1 > sensor1longtime ) {
       digitalWrite(LED_2, HIGH);  //LED2 ON
   } else {
       digitalWrite(LED_2, LOW);  //LED2 OFF
   }

     if (millis() > tonLED_1) {    //si millis (50") > millis y no hay movimiento
        digitalWrite(LED_1, LOW);  //LED1 OFF
        digitalWrite(LED_2, LOW);  //LED2 OFF
        turnOnLED_1 = false;
        turnOnLED_2 = false;
     }
  }

Es muy importante antes de lanzarte a programar con millis (más si no estás muy ducho en la materia aún) parar y reflexionar la operación primordial qué utilizamos en el trabajo con millis, que básicamente es:

Tiempo_transcurrido = Momento_actual - Momento_desde

Entonces lo más importante es saber desde cuándo necesito medir el tiempo (habitualmente el hasta cuando será momento_actual). En tu caso, entiendo que necesitas "recordar" los siguientes momentos:

- Momento en el que se produjo la primera detección (la que dispara el primer led).
- Momento en el que se produjo la última detección.

Luego procederemos de la siguiente forma:

- Si se detecta movimiento:
  - Si el led1 estaba apagado, actualizamos momento de primera detección al actual 
    y lo encendemos.
  - Si no estaba apagado, comprobamos cuánto ha pasado desde la primera detección.
    Si más de 50 segundos, procedemos con led2.
  - En todo caso actualizamos momento de última detección al actual.
- Si no se detecta movimiento:
  - Si led1 encendido y han transcurrido más de 50 segundos desde último encendido, 
    apagamos led1.

Con estas indicaciones casi tienes el programa hecho, a mi parecer.

Si quieres que se encienda a los 150 segundos del evento que disparo a LED_1 entonces usa el mismo disparo para calcular tonLED_2
Si quieres que encienda a los 150 seg de haberse apagado LED_1 entonces cuando apaga LED_1 calculas ese tonLED_2

Gracias Surbyte y Noter por vuestros consejos, sigo intentadolo, cambiando lineas una y otra vez, añadiendo otro temporizador pero no me sale, me parece muy complicado, porque son varios procesos distintos y uno interfiere con el otro...no me sale.
Un saludo a todos y gracias por vuestro apoyo.

Está sin probar, pero por ahí van los tiros. Como puedes ver, no se desvía mucho de los pasos que te describí. Debes tener muy claras las condiciones que se dan en cada punto del código (por eso he marcado bastante las llaves).

#define PIR_MOTION_SENSOR_1 5     //pin D5 es la señal del PIR
#define LED_1               11    //LED2 conectado al D11
#define LED_2               12    //LED2 conectado al D12

// Momento en el que se produjo la primera detección (la que dispara el primer led).
unsigned long millis_primera_deteccion;
// Momento en el que se produjo la última detección.
unsigned long millis_ultima_deteccion;
// tiempo de disparo del segundo led / apagado del primero
const unsigned long sensor1longtime = 50000;

void setup() {
	pinMode(PIR_MOTION_SENSOR_1, INPUT);
 	pinMode(LED_1,OUTPUT);          // Salida para LED 2
 	pinMode(LED_2,OUTPUT);          // Salida para LED 2
 }

void loop() {
	if (digitalRead(PIR_MOTION_SENSOR_1)){
		//- Si se detecta movimiento:
		if (digitalRead(LED_1)) {
			//- Si led1 no estaba apagado, comprobamos cuánto ha pasado desde la primera detección. Si más de 50 segundos, procedemos con led2.
			if (millis()-millis_primera_deteccion>sensor1longtime) {
				digitalWrite(LED_2, HIGH);
			}
		} else {
			//- Si el led1 estaba apagado, actualizamos momento de primera detección al actual y lo encendemos.
			millis_primera_deteccion=millis();
			digitalWrite(LED_1,HIGH);
		}
		//- En todo caso actualizamos momento de última detección al actual.
		millis_ultima_deteccion=millis();
	} else {
		//- Si no se detecta movimiento:
		//- Si led1 encendido y han transcurrido más de 50 segundos desde último encendido, apagamos led1.
		if (digitalRead(LED_1) && !digitalRead(LED_2) && (millis()-millis_ultima_deteccion)>sensor1longtime) {
			digitalWrite (LED_1, LOW);
		}

	}

}

juycce:
Gracias Surbyte y Noter por vuestros consejos, sigo intentadolo, cambiando lineas una y otra vez, añadiendo otro temporizador pero no me sale, me parece muy complicado, porque son varios procesos distintos y uno interfiere con el otro...no me sale.
Un saludo a todos y gracias por vuestro apoyo.

Puedes dibujar un diagrama de tiempos, sabes lo que es?
Eje horizontal tiempos en segundos
Eje vertical 0 o 1. OFF o ON.

Entonces dibujas un disparo.... y luego a los 50 segundos indicas que debe hacer.. y acá lo importante. en que momento debe dispararse el 2do timer, porque yo no te comprendo.

Gracias por vuestra ayuda Surbyte y Noter. Bien, he creado unos graficos, se entiende mejor, asi de esta manera queda explicado el post que seguramente vendra bien a mas de uno. Lo he dividido por etapas.
El codigo actualmente hace la 1a y 2a etapa.

// si se detecta movimiento el sensor Pir activa LED_1 50 segundos,
// si hay movimiento dentro de los 50 segundos =>  millis + los 50 segundos
// si no hay movimiento en los 50 segundos se apaga led 1
// si el movimiento es 90 seg. activa LED_2

#define PIR_MOTION_SENSOR_1 5     //pin D5 es la señal del PIR
#define LED_1               11    //LED2 conectado al D11
#define LED_2               12    //LED2 conectado al D12

bool sensor1, sensor1ant, ;         
bool turnOnLED_1 = false;
bool turnOnLED_2 = false;

unsigned long tonLED_1;           
unsigned long tonLED_2;     
long sensor1longtime = 90000;          // millis para 90" del del LED_2

void setup() {
  pinMode(PIR_MOTION_SENSOR_1, INPUT);
  pinMode(LED_1,OUTPUT);          // Salida para LED 2
  pinMode(LED_2,OUTPUT);          // Salida para LED 2
}

void loop() {

  /*****************************************************************/
  /* Function: Detect whether anyone moves in it's detecting range */
  /* Return:-boolean, ture is someone detected.                    */
  /*****************************************************************/
  sensor1 = digitalRead(PIR_MOTION_SENSOR_1);

  if (sensor1 && !sensor1ant) {   //si sensor1(PIR digital read) no es sensor1ant
     turnOnLED_1 = false;
     turnOnLED_2 = false;
     digitalWrite(LED_1, HIGH);   // rele Led ON
     tonLED_1 = millis() + 50000UL;//tonLED_1 = millis de hasta ahora + 50 sec

  }
  sensor1ant = sensor1;
 

//   if tonLED_1 millis > sensor1longtime
//   digitalWrite(LED_2, HIGH);



     if (millis() > tonLED_1) {    //si millis (50") > millis y no hay movimiento
        digitalWrite(LED_1, LOW);  //LED1 OFF
        digitalWrite(LED_2, LOW);  //LED2 OFF
        turnOnLED_1 = false;
        turnOnLED_2 = false;


     }
  }

Etapa 1:

El sensor detecta presencia, enciende LED_1 50 segundos, despues se apaga

Etapa 2:

El sensor detecta presencia y enciende LED_1 50 seg. Si dentro de los 50 seg. se produce movimiento devuelve el Boolean y se reinicia el temporizador.

Etapa 3:

El sensor detecta presencia y enciende LED_1 50 seg. igual que etapa 2. Pero si el tiempo total en el que LED_1 esta encendido es mayor de 50 de seg. se enciende LED_2

Etapa 4:

Si sigue habiendo movimiento, LED_1 + LED_2 estan encendidos 50 seg, (teniendo tambien el return del Boolean para que no se apaguen los led mientras estamos en la habitacion) y si no hay mas movimientos se apagan.

Gracias otra vez a todos. Un saludo.

Ves que fácil!! Ahora se entiende y nadie dudará de nada.
Yo no se donde leí 150 segundos y ahora no hablas de 150 segundos sino de 50 segundos acumulados..? Bueno a ver como se resuelve la cuestión.

Bueno ha quedado clarísimo.
A ver como ayudamos a @yuicce a resolver su dilema..
Si no se apuran en 30 min lo hago yo!!

// si se detecta movimiento el sensor Pir activa LED_1 50 segundos,
// si hay movimiento dentro de los 50 segundos =>  millis + los 50 segundos
// si no hay movimiento en los 50 segundos se apaga led 1
// si el movimiento es 90 seg. activa LED_2

#define PIR_MOTION_SENSOR_1 5     //pin D5 es la señal del PIR
#define LED_1               11    //LED2 conectado al D11
#define LED_2               12    //LED2 conectado al D12

bool sensor1, sensor1ant;
bool turnOnLED_1 = true; // Activa el contador de tonLED_1. La idea es evitar que se reinicie junto con led1Timer
bool turnOnLED_2 = false;

unsigned long led1Timer = 0; // Antiguo tonLED_1
unsigned long tonLED_1;  // Lleva el conteo para encender LED 2
unsigned long tonLED_2;
// unsigned long sensor1longtime = 90000UL;          // millis para 90" del del LED_2. En desuso

void setup() {
  pinMode(PIR_MOTION_SENSOR_1, INPUT);
  pinMode(LED_1, OUTPUT);         // Salida para LED 2
  pinMode(LED_2, OUTPUT);         // Salida para LED 2
}

void loop() {

  /*****************************************************************/
  /* Function: Detect whether anyone moves in it's detecting range */
  /* Return:-boolean, ture is someone detected.                    */
  /*****************************************************************/
  sensor1 = digitalRead(PIR_MOTION_SENSOR_1);

  if (sensor1 && !sensor1ant) {   //si sensor1(PIR digital read) no es sensor1ant
    digitalWrite(LED_1, HIGH);   // rele Led ON
    led1Timer = millis() + 50000UL;//led1Timer = millis de hasta ahora + 50 sec
    if (turnOnLED_1) {
      turnOnLED_1 = false;
      tonLED_1 = led1Timer;
      turnOnLED_2 = true; // Indica que el conteo inició, entonces que encianda el LED 2 si ya pasaron los 50 segundos
    }
  }
  sensor1ant = sensor1;

  if ((millis() > led1Timer) && !turnOnLED_1) {
    //si millis (50") > millis y no hay movimiento. !turnOnLED_1 evita que todo esto se ejecute una y otra vez mientras todo siga apagado
    digitalWrite(LED_1, LOW);  //LED1 OFF
    digitalWrite(LED_2, LOW);  //LED2 OFF
    turnOnLED_1 = true; // Ya que todo se apagó, reactivar el conteo tonLED_1 la próxima vez que sense movimiento
    turnOnLED_2 = false; // Si no sobrepasaron los 50 segundos, entonces que ya no encienda LED 2
  }

  if ((millis() > tonLED_1) && turnOnLED_2) {
    // Si LED 1 lleva más de 50 segundos encendido (millis() > tonLED_1), y si es permitido hacer esto (urnOnLED_2)
    digitalWrite(LED_2, HIGH);
    turnOnLED_2 = false; // No volver a ejecutar esto hasta que todo se apague y LED 1 otra vez tarde más de 50 segundos encendido
    }
}

Prueba esto.

Una cosa más, creo que la 4ta etapa no involucra esto (si no me equivoco):

unsigned long sensor1longtime = 90000UL;

surbyte:
Si no se apuran en 30 min lo hago yo!!

LO LOGRÉ!!! jaja :smiley:

Hay que estimular a la gente, jajaja!!!

Pues lograste muy bien tu objetivo... :o

PD: no puse el quote esta vez, porque sino después Hector_A me edita el post...

Esto tiene buena pinta...me muero de ganas por llegar acasa y probarlo :slight_smile:
Muchisimas gracias chicos!!!

Madre mia!!! estoy pegando saltos de alegria !!!!!!
Soys unos genios, estuve una semana dandole vuelta y no me salia. Me quito el sombrero ...soys unos cracks. Gracias chicos, soys estupendos, miles de gracias por aclararmelo... me gusta como quedó explicada cada linea, es un ejemplo muy bueno.

Un abrazo fuerte a todos. 1 Karma X hora :slight_smile:

Finalmente ¿qué código utilizaste?
Sería interesante que pusieras tu código final para que pueda servir a alguien más. Máxime teniendo en cuenta que una de las dudas que más se plantean en este foro son las relacionadas con el uso de millis.
Saludos.

Bien creo que ya quedó bastante claro cual es la funccion del codigo. Cuando el sensor PIR (yo utilizé el Groove PIR) detecta movimiento una vez enciende el Led_1 durante 50 seg., si hay movimiento durante mas de 50 seg, el Led_1 seguira encendido y aprate de eso se encendera el Led_2. Cuando no hay mas movimiento se apagarán los 2 Leds.
Aqui esta el codigo:

// si se detecta movimiento el sensor Pir activa LED_1 50 segundos,
// si hay movimiento dentro de los 50 segundos =>  millis + los 50 segundos
// si no hay movimiento en los 50 segundos se apaga led 1
// si el movimiento es 90 seg. activa LED_2

#define PIR_MOTION_SENSOR_1 5     //pin D5 es la señal del PIR
#define LED_1               11    //LED2 conectado al D11
#define LED_2               12    //LED2 conectado al D12

bool sensor1, sensor1ant;
bool turnOnLED_1 = true; // Activa el contador de tonLED_1. La idea es evitar que se reinicie junto con led1Timer
bool turnOnLED_2 = false;

unsigned long led1Timer = 0; // Antiguo tonLED_1
unsigned long tonLED_1;  // Lleva el conteo para encender LED 2
unsigned long tonLED_2;

void setup() {
  pinMode(PIR_MOTION_SENSOR_1, INPUT);
  pinMode(LED_1, OUTPUT);         // Salida para LED 1
  pinMode(LED_2, OUTPUT);         // Salida para LED 2
}

void loop() {

  /*****************************************************************/
  /* Function: Detect whether anyone moves in it's detecting range */
  /* Return:-boolean, ture is someone detected.                    */
  /*****************************************************************/
  sensor1 = digitalRead(PIR_MOTION_SENSOR_1);

  if (sensor1 && !sensor1ant) {   //si sensor1(PIR digital read) no es sensor1ant
    digitalWrite(LED_1, HIGH);   // Led_1 ON
    led1Timer = millis() + 50000UL;//led1Timer = millis de hasta ahora + 50 sec
    if (turnOnLED_1) {
      turnOnLED_1 = false;
      tonLED_1 = led1Timer;
      turnOnLED_2 = true; // Indica que el conteo inició, entonces que encianda el LED 2 si ya pasaron los 50 segundos
    }
  }
  sensor1ant = sensor1;

  if ((millis() > led1Timer) && !turnOnLED_1) {
    //si millis (50") > millis y no hay movimiento. !turnOnLED_1 evita que todo esto se ejecute una y otra vez mientras todo siga apagado
    digitalWrite(LED_1, LOW);  //LED1 OFF
    digitalWrite(LED_2, LOW);  //LED2 OFF
    turnOnLED_1 = true; // Ya que todo se apagó, reactivar el conteo tonLED_1 la próxima vez que sense movimiento
    turnOnLED_2 = false; // Si no sobrepasaron los 50 segundos, entonces que ya no encienda LED 2
  }

  if ((millis() > tonLED_1) && turnOnLED_2) {
    // Si LED 1 lleva más de 50 segundos encendido (millis() > tonLED_1), y si es permitido hacer esto (turnOnLED_2)
    digitalWrite(LED_2, HIGH);
    turnOnLED_2 = false; // No volver a ejecutar esto hasta que todo se apague y LED 1 otra vez tarde más de 50 segundos encendido
    }
}

f16e9fb6fd3b921c1a7666c3f37e050676ca39c2.jpg

Un saludo a todos.