Allumer une led avec retardement avec millis

Bonjour bonjour !

Je suis sur un projet d’automatisation d’un portail mais il me manque une étape essentielle, je ne comprend pas la fonction millis().Pour commencer voici un schéma de mon montage:

(PS: Le câble bleu qui va du GND au pin 2 est pour simuler un détecteur de passage par zéro (zero crossing detector))

Et mon code côté récepteur:

#include <RH_ASK.h>
#include <SPI.h>

#define IN1 18
#define IN2 19
#define IN3 20
#define IN4 21

#define buffsize 10
uint8_t buf[buffsize];
uint8_t buflen = buffsize;
 
RH_ASK driver(2000, 3);
 
void setup() 
{
  Serial.begin(9600);
  driver.init();

    initialisation_interruption ();
    pinMode(2, INPUT);
    digitalWrite(2, HIGH);
    pinMode(13, OUTPUT);
    digitalWrite(13, LOW);
    pinMode(IN1, OUTPUT);
    digitalWrite(IN1, LOW);
    pinMode(IN2, OUTPUT);
    digitalWrite(IN2, LOW);
    pinMode(IN3, OUTPUT);
    digitalWrite(IN3, LOW);
    pinMode(IN4, OUTPUT);
    digitalWrite(IN4, LOW);
}
void loop() 
{
 delay (2000);
}


void initialisation_interruption ()
{
    attachInterrupt(digitalPinToInterrupt(2), del, CHANGE);
    attachInterrupt(digitalPinToInterrupt(3), remote, CHANGE);
}

void remote () //contrôle via une télécommande RF 433 MHz
{
    uint8_t buf[4]; 
  uint8_t buflen = sizeof(buf); 
    if (driver.recv(buf, &buflen))
     { 
            if ( !strcmp ((char*) buf, "A") ) //Allume la LED 18 quand on reçoit le caractère "A"
       { 
         digitalWrite(IN1, HIGH);
         delay (2000);
         digitalWrite(IN1, LOW);
       }

             if ( !strcmp ((char*) buf, "B") )//Allume la LED 19 quand on reçoit le caractère "B"
       { 
         digitalWrite(IN2, HIGH);
         delay (2000);
         digitalWrite(IN2, LOW);
       }

             if ( !strcmp ((char*) buf, "C") )
       { 
         digitalWrite(IN3, HIGH);
         delay (2000);
         digitalWrite(IN3, LOW);
       }

            if ( !strcmp ((char*) buf, "D") )
       { 
         digitalWrite(IN4, HIGH);
         delay (2000);
         digitalWrite(IN4, LOW);
       }
         Serial.print("Bouton: "); 
         Serial.println((char*)buf); 
         Serial.println("----------");
     }
}

void del () //Zero crossing
{
        if (digitalRead(2))   
   {
    digitalWrite(13, LOW);
   }  
     else if (!digitalRead(2)) 
      { 
       digitalWrite(13, HIGH);
      } 
}

Sauf qu’il me faudrait instaurer un laps de temps entre le moment où la carte détecte le passage par zéro et le moment où la LED s’allume pour que ça ressemble à ça :

Et donc gérer la vitesse du portail selon le temps entre la détection et l’activation.

Il me faut utiliser la fonction millis car le delay stop le programme ce qui n’est pas envisageable pour un portail.

J’ai essayé d’être le plus clair possible afin de vous faciliter vos réponses donc je remercie d’avance ceux qui ont pris la peine de tout lire :smiley:

J'ai peu l'habitude des interruptions, mais je sais que le code d'une interruption doit être aussi court que possible. Dans ton cas, il est très long et comporte en effet des delay, ce qui n'arrange pas les choses.

Pour del, c'est simple :

void del () //Zero crossing
{
        if (digitalRead(2))   
   {
    digitalWrite(13, LOW);
   } 
     else if (!digitalRead(2))
      {
       digitalWrite(13, HIGH);
      }
}

peut être simplifié en

void del () //Zero crossing
{
   digitalWrite(13, !digitalRead(2));
}

Pour l'autre fonction, je te conseille de trouver des exemples de mise en oeuvre d'interruptions pour savoir quoi mettre dans la fonction et quoi mettre dans la loop. Ensuite, tu pourras jouer avec millis...

Pour millis(), il y a pas mal de tutos, dont une liste se trouve ici

Tu peux aussi t'inspirer de projets similaires au tien.

Alors déjà merci pour tes réponses! Je viens de changer le void del et ça marche niquel en revanche je savais déjà qu'il fallait être le plus concis possible dans les interruptions et éviter les delay() mais comme ça marche plutôt bien je n'ose pas trop le modifier, après je peux faire une interruption pour chaque bouton de ma télécommande:

mais du coup je pense qu'il faudrait mettre la fonction millis() dans le void del sachant que j'ai fait exprès de brancher le module relais sur des broches interruptable.

Mais maintenant faut que je trouve comment déclencher le relais quand il y a un passage par zéro avec millis() que je mettrais dans les void del je pense mais en tant que débutant c'est vraiment pas simple :confused:

Quand on veut faire un code non bloquant à partir d'un code bloquant (c'est à dire changer les delay par millis), ça implique le plus souvent le changement radical de l'architecture du code.

C'est pour ça que je te conseillais de lire les tutos, pour comprendre comment te servir de millis. Ensuite de réfléchir à ce qui doit être dans la routine d'interruption au minimum. Tout le reste sera dans la loop.

Mais d'abord tu dois te familiariser avec la tournure des codes non bloquants.

Oui merci c’est ce que je suis en train de faire, un collègue vient de me conseiller de regarder les docs officielles d’Arduino et du langage C :sweat_smile: il m’a parlé de la fonction timestamp présente dans de nombreux langage de programmation du coup j’espère y arriver :’( :smiley:

Pour ceux qui passeront (peut-être) par là plus tard j'ai finalement réussi alors je met un code qui allume une LED avec un retardement, en revanche je n'ai pas de bouton donc je me contente d'un câble qui fera office de détecteur de passage par zéro :

long temps; //création de la variable temps

void setup()
{  
    pinMode(2, INPUT); //pin du zero crossing définie en entrée
    digitalWrite(2, HIGH); //le pin mit à l'état logique haut
    pinMode(19, OUTPUT); //initialise le pin de la LED en sortie
    digitalWrite(19, LOW); //met la LED au niveau logique bas
    temps = millis(); //on récupère le temps qu'on "stocke" dans la variable temps
}

void loop()
{
        if (digitalRead(2))   
   {
    digitalWrite(19, LOW); 
   }  
     else if (!digitalRead(2)) 
      { 
               if((millis() - temps) > 20)
        {
            digitalWrite(19, HIGH); 
            temps = millis();
        }
      } 
}