Problema con detección de presencia con Sensor PIR

Hola gente…

Les explico un poco, mi caso es el siguiente hace poco empece a trabajar con Arduino pero vengo de la rama de desarrollo web. Tengo el siguiente caso, un control de acceso, un sensor pir de movimiento HC-SR505 que me detecta la persona que quiere ingresar y ejecutar la entrada… el tema es que me me toma la presencia bien, abre la puerta que la valido con un sensor magnético que al cerrar debería de detectar un segundo sensor pir de movimiento HC-SR505 interno digamos y ejecutar un sonido.

El tema es que este pir interno me detecta intermitente por decirlo de alguna forma. funciona uno si, uno no, uno si, uno no… y quisiera que fuese constate que al detectar presencia ejecute el sonido.

les adjunto el código, y les añado que trabajo con una placa Arduino UNO Atmega328p

Les pido si pudieran ayudarme a resolverlo…

Gracias y SALU2

#include <SoftwareSerial.h>
#include "DFRobotDFPlayerMini.h"
 
const int PIRe = 2;
const int PIRi = 3;
const int MG = A0;

int PIRvalueEx = 0;
int PIRvalueIn = 0;

SoftwareSerial mySoftwareSerial(4,5);
DFRobotDFPlayerMini myDFPlayer;

void setup()
{
   pinMode(PIRi,INPUT);
   pinMode(PIRe,INPUT);
   pinMode(MG, INPUT_PULLUP);

   Serial.begin(9600);
   mySoftwareSerial.begin(9600);
   if (!myDFPlayer.begin(mySoftwareSerialA))
   {
     Serial.println(F("No inicializado:"));
     Serial.println(F("1.Cheque las conexiones del DFPlayer Mini Interior"));
     Serial.println(F("2.Inserta una tarjeta MicroSD en el DFPlayer Mini Interior"));
     while (true);
   }
   Serial.println(F("DFPlayer Mini Externo online."));
   myDFPlayer.EQ(DFPLAYER_EQ_BASS);
   myDFPlayer.outputDevice(DFPLAYER_EQ_NORMAL);
   myDFPlayer.volume(30);
}  

 
void loop()
{
     if(PIRvalueEx == HIGH)  // detecto persona para entrar
     {
       myDFPlayer.play(1); // le doy la bienvenida
       delay(6000);
       digitalWrite(MG, HIGH); // le doy una señal de abrir el magnetico
       myDFPlayer.play(2);  // le digo que por favor entre
       delay(6000);

          if(digitalRead(MG) == HIGH)  // valido si la puerta esta abierta
         {  
             while(digitalRead(MG) == HIGH) // si queda la puerta abierta entra
             {     
                myDFPlayer.play(3); // pido que cierren la puerta
                delay(8000);
             };
             
              if(PIRvalueIn == HIGH) // al cerrar la puerta me detecta el pir interno
              {
                 myDFPlayer.play(4); // al validar la presencia suena unos pasos a seguir y se va
                 delay(15000);
              }
          } 
       }
  
  PIRvalueEx = digitalRead(PIRe); // Pir Exterior
  PIRvalueIn = digitalRead(PIRi);  // Pir Interior
}

Te funciona uno si uno no por esta razón

delay(6000);

debes eliminar los delay() y reemplazarlos por millis().

Ve a Documentación => Indice de temas tutoriales => millis()

Ni hablar de este

 delay(15000);

Cuando el código encuentra un delay() el micro deja de hacer algo y se queda tontamente esperando el tiempo indicado.

Sigue el consejo, lee en Documentación alguno de los tutoriales alli presentes.
Observa tambien como se usan las máquinas de estados.
Te hará falta.

Gracias por el consejo @surbyte mirare el tema millis(), ya lo había visto pero no supe usarlo, configure todos los delay que tengo como millis independizando cada tiempo con nombre diferente y no me andaba el código o se me quedaba pegado en algún punto y no le di mucha importancia después, no supe como usarlo.. Investigare sobre ello..

o quisiera aprovechar y corrígeme si estoy haciendo algo mal..

defino las variables para cada tiempo así

int interval6seg = 6000;
unsigned long previousMillis6seg = 0;

int interval6seg2 = 6000;
unsigned long previousMillis6seg2 = 0;

int interval8seg = 8000;
unsigned long previousMillis8seg = 0;

int interval15seg = 15000;
unsigned long previousMillis15seg = 0;

luego en en función loop() te pongo resumido solo donde aplico los millis y como

unsigned long currentMillis = millis();

if ((unsigned long)(currentMillis - previousMillis6seg) >= interval6seg) 
{
    myDFPlayer.play(1);
    previousMillis6seg = currentMillis;
}
digitalWrite(MG, HIGH);
if ((unsigned long)(currentMillis - previousMillis6seg2) >= interval6seg2) 
{
    myDFPlayer.play(2);
    previousMillis6seg2 = currentMillis;
}

if ((unsigned long)(currentMillis - previousMillis8seg) >= interval8seg) 
{
    myDFPlayer.play(3);
    previousMillis8seg = currentMillis;
}

if ((unsigned long)(currentMillis - previousMillis15seg) >= interval15seg) 
{
    myDFPlayer.play(4); 
    previousMillis15seg = currentMillis;
}

y no me funciona bien se quedan pegada las voces.. que estaré haciendo mal?

gracias adelantadas y SALU2

Hola, buen día...

Sigo peleando con los millis() pero nada que encuentro hacer que me funcione, otra posible solución que pudiera servirme y corrijanme, pudiera usar una interrupción al cerrar la puerta?

Cuando me cierre la puerta me ejecute directamente una función que me envíe directamente a detectar el PIR interior. Es prácticamente como esta pero no se si con la interrupción obligo a que ejecute si o si la función y me detecte el PIR si o si..

No se si es algo innecesario pero se me vino a la mente y quise preguntarlo para salir de la duda.

De ser positiva la respuesta, se puede hacer interrupciones a entradas analógicas?

Gracias y SALU2

Acá tienes un muy buen tutorial que usa millis() para reproducir adecuadamente los tracks.
Míralo detenidamente y adapta lo necesario a tu código y en todo caso luego lo conversamos.

Modulo DFplayer mini Reproductor mp3 para arduino, tutorial completo

Perfecto... Voy a mirarlo... Gracias @surbyte estoy avisando como me va, aviso y cualquier cosa lo conversamos..

Abrazo.. SALU2

Hola @surbyte buenismo el tutorial, el tema es que aplico la funcion millis() a cada una de las reproducciones en todo el codigo. Pero solo me ejecuta los 2 primeros, y el segundo forzado.

No tengo que ponerlos en todos? Sabras?

SALU2