[Résolu] Timer pour led

Bonjour à tous, je débute dans l'Arduino et je rencontre un petit problème lorsque j'essaie de développer mon petit projet. Donc sur une platine d'essai est branché une LED ainsi qu'un capteur de contact magnétique. Mon but serais alors que lorsque que le contact magnétique n'est plus établi au bout de 4 minutes alors la LED s'allume. Pour le moment j'arrive bien à faire marcher le programme mais sans le petit "timer" de 4 minutes, je ne sais pas comment m'y prendre. Merci d'avance.

Code :

const int L1 = 5; 
const int capteur = 4;
int etat; 

void setup()
{
  pinMode(capteur, INPUT_PULLUP);
  pinMode(3, OUTPUT);
}

void loop()
{
  etat = digitalRead(capteur);
  if (etat == HIGH)
    analogWrite(L1, 50);
  else
    analogWrite(L1, 0);
  delay(200);
}

Salut! Je ne suis pas un expert, mais essaye de creuser vers la fonction millis().

Ya ce tuto, mais je sais pas si il est bien...
TUTO millis

:slight_smile:

Très bien je vais chercher, merci beaucoup :slight_smile:

c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

on utilisera effectivement millis() pour déclencher un évènement de transition au bout des 4 minutes : au moment de la détection du capteur on mémorise la valeur de millis() dans une variable globale T0 et on passe en état ALERTE. dans cet état on teste d'abord si on est revenu aux conditions initiales sinon on teste si le temps est écoulé
if (millis() - T0 >= 240000ul) { ... // plus de 4 minutes

il faut ensuite pouvoir sortir du mode LED allumée pour retourner à l'état initial, sans doute sur désactivation du capteur ?

ça ressemblerait à cela:

Super, merci je vais essayer.

Voici le résultat, j'ai testé, ça fonctionne plutôt bien, mais j'aimerais avoir votre avis pour savoir si j'ai pu quand même faire des erreurs dans le code, merci.

const int L1 = 5; 
const int capteur = 4;
int etat;
int tempo = 0;
unsigned long T0 = 0; 

void setup()
{
  pinMode(capteur, INPUT_PULLUP);
  pinMode(5, OUTPUT);
}

void loop()
{
  etat = digitalRead(capteur);
  if (etat == LOW) {
     tempo = 1;
     T0 = millis();
  }
  if (tempo) {
    if ((millis()- T0) >= 5000) {
      analogWrite(L1, 50);
      tempo = 0;
    }
    else {
      analogWrite(L1, 0);
  delay(200);
    }
  }
}

vous n'avez pas du bien lire le tuto sur les machines à états :slight_smile: - je ne vois pas les 3 états de mon diagramme

votre souci c'est que si le capteur est LOW vous remettez constamment à jour T0. Il ne faut plus le faire une fois qu'il est déclenché ➜ c'est le passage dans mon état 'ALERTE' du dessin

Très bien, désolé, je vais essayer de corriger.

faut pas s'excuser, pas de souci. Vous débutez. Essayez de faire comme dans le tuto, un enum pour les 3 états et une seule variable d'état avec un switch()

Re-Bonjour, j'ai essayé d'appliquer vos conseils, mais je dois dire que je mouline et que je mélange un peu tout haha, voici le code :


const int L1 = 5; 
const int capteur = 4;
int etat;
unsigned long T0 = 0;
enum {ledEteinte, Alerte, ledAllumee} etatLed;

void ledOff()
{
  analogWrite(L1, 0);
  etatLed = ledEteinte;
}

void action()
{
  switch(etatLed) {
    case ledEteinte:
      analogWrite(L1, 0);
        if ((millis()- T0) >= 5000) 
          etatLed = Alerte;
          break;
        
    case ledAllumee:
      if (etatLed == Alerte) ;
        analogWrite(L1, 50);
  }
}

void setup()
{
  pinMode(capteur, INPUT_PULLUP);
  pinMode(5, OUTPUT);
}

void loop()
{
  etat = digitalRead(capteur);
  delay(200);
}

y'a du progrès mais ce n'est pas encore cela

  • la fonction action n'est jamais appelée :slight_smile:
  • il n'y a que deux états dans le switch
  • le switch doit tester chaque évènement possible pour un état donné et réaliser les actions associées avant de changer d'état

Pour moi, utiliser une machine à état ici est un peu superflu.
On peut utiliser un petit timer de 4 minutes:
~ quand il arrive à échéance, on allume la led
~ si le contact est établi, on remet le timer à zéro et on éteint la led (que cette dernière soit allumée ou éteinte)

En reprenant le code au plus près:

void loop()
{
  etat = digitalRead(capteur);
  if (etat == HIGH) // Le capteur n'est pas activé
  {
    if (millis() - T0 > 5L*60*1000)
      analogWrite(L1, 50);
  }
  else // Le capteur est activé
  {
    T0 = millis(); // Réinitialiser le timer 
    analogWrite(L1, 0);  // Eteindre la led
  }
}

Pour la led:
~ soit on allume la led en tout ou rien, alors pinMode(3, OUTPUT); est obligatoire, mais pour l'allumer il faut digitalWrite(L1);
~soit on l'allume pas à fond, et c'est bien analogWrite(L1, 50); qui l'allume, mais le pinMode(3, OUTPUT); ne sert plus à rien:
Page Reference > Language > Functions > Analog io > Analogwrite il est dit:

You do not need to call pinMode() to set the pin as an output before calling analogWrite().

Attention aussi que ce n'est pas pour détecter un arrêt mécanique genre arbre en rotation, car si l'arrêt se fait lorsque le contact est établi, le timer serait constamment remis à 0 et la led ne s'allumerait pas. Il faut dans ce cas non pas remettre à 0 le timer "quand le contact est établi" mais "quand le contact vient d'être établi". Autrement dit non pas quand il est HIGH, mais quand il vient de passer à HIGH (il est HIGH et juste avant il était LOW).

Cela fait 5000 millisecondes soit 5s. C'est bien pour les essais, mais on est loin des 5 minutes. Attention 5000 * 60 sur une Uno ne fait pas 5 minutes car le calcul est fait avec des entiers. Il faut alors écrire 5000L * 60

C’est une machine à états :slight_smile:

Ne te mets pas dans tous ces états!
Je suis d'accord, mais on n'a pas besoin dans ce cas de la formule générale avec le "case"

LOL :slight_smile:

Vous avez raison, dans les cas simple on peut faire simple, mais c'est juste une bonne façon d'apprendre et de rendre le code assez évolutif si ensuite on veut rajouter d'autres conditions / transitions / états

Merci pour votre aide :slight_smile:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.