Tempo sur relais

Bonjour,

j'essaie tant bien que mal de paramétrer une tempo sur l'ouverture ou la fermeture d'un relais mais j'ai l'impression qu'il me manque quelque chose ... Je ne suis pas certain d'avoir compris la fonction "millis()"

J'aimerais que mon relais se ferme un temps donné à 2000ms dans //procédure d'extinction.

Quelqu'un peut il éclairer ma lanterne ?

/*
   Démarrage automatique pour Onan Cummins depuis relais Victron
*/

int OnanSTART = 7;
int OnanSTOP = 8;
int VictronNO = 2;
int VictronNC = 4;

int duree = 2000;
unsigned long chrono_actuel = 0;
unsigned long chrono_precedent = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(OnanSTART, OUTPUT);

  pinMode(OnanSTOP, OUTPUT);


  pinMode(VictronNO, INPUT_PULLUP);

  pinMode(VictronNC, INPUT_PULLUP);

  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

  chrono_actuel = millis();
  chrono_precedent = chrono_actuel;

  Serial.print("NO : ");
  Serial.print(digitalRead(VictronNO));
  Serial.print(" - NC : ");
  Serial.print(digitalRead(VictronNC));
  Serial.print(" - Chrono Actuel : ");
  Serial.println(chrono_actuel);

  //Procedure de demarrage

  while (digitalRead(VictronNO) == 0) {
    digitalWrite(OnanSTART, HIGH);

  }
  digitalWrite(OnanSTART, LOW);

  //Procedure d'extinction

  while (digitalRead(VictronNO) == 1) {
    digitalWrite(OnanSTOP, HIGH);
    if (chrono_actuel - chrono_precedent > duree) {
      digitalWrite(OnanSTOP, LOW);
    }

  }
  digitalWrite(OnanSTOP, LOW);


  delay (50);



}```

bonjour
il faut mettre a jour chrono_precedent lorsque la condition est rempli
sinon a chaque tour de boucle il sera effacé par ce morceau de code

chrono_precedent = chrono_actuel;

ou alors vous devait relire milli() dans la boucle while

Merci pour votre réponse mais je n'ai pas de meilleurs résultats en déplaçant le chrono_precedent dans le while ...

vous pouvez essayer ce code
cela implique de maintenir VictronNO à 1 durant toute la durée
ne connaissant pas la logique que vous souhaitez je ne peux faire que des suppositions

1 Like

Merci mille fois !! ça fonctionne exactement comme il faut !

Hum il va me falloir tout reprendre à 0 car je réalise que tout fonctionne à l'envers ... à cause du PULLUP mes relais restent sous tension en permanence alors que je n'en n'ai besoin que ponctuellement. En tous cas merci de m'avoir mis sur la piste des tempos. Je ne suis pas près de le faire tourner mon groupe ...

Seulement les 1 sont à reprendre à 0:
(digitalRead(VictronNO) == 1) est à remplacer par (digitalRead(VictronNO) == 0)
et aussi l'inverse.
D'ailleurs préférer HIGH à 1 et LOW à 0 dans ce cas là.

Je crois que j'ai essayé toutes les combinaisons ... mais rien n'y fait ...
Plus sérieusement, je vais essayer de mieux détailler ce qu'il m'arrive.
Je simule le relais de mon onduleur avec un interrupteur à bascule tout simple ON/OFF avec la variable VictronNO (Je me suis aperçu que la variable VictronNC ne servirait à rien). L'inerrupteur me sert à connecter la masse sur le port D2 de mon UNO qui me renvoie un signal HIGH lorsqu'il est allumé.
Le programme actuel qui fonctionne (à l'envers) avec les solenoid des relais toujours alimentés ne convient pas car beaucoup trop énergivore et je ne pense pas que les relais de ce type vivent longtemps s'ils sont allumés en permanence.

Depuis mon monitor lorsque le VictronNO est HIGH les deux solenoids sont alimentés et la procédure se fait bien. Lorsque le VictronNO est LOW le relais INT1 se coupe mais le second relais reste sous tension. Si je bascule VctronNO à HIGH le relais se coupe 2sec puis se rallume. Ok pour tout ça j'ai réussi à allumer et à éteindre mon groupe.
Maintenant j'aimerais pouvoir inverser tout ça CAD que les relais au repos soient éteints et qu'ils se déclenche à la demande ...

Voici mon code :

/*
   Démarrage automatique pour Onan Cummins depuis relais Victron
*/

int OnanSTART = 7; //Relais INT1 servant à démarrer le groupe
int OnanSTOP = 8; //Relais INT2 servant à éteindre le groupe
int VictronNO = 2; //Interrupteur à bascule simulant le relai de l'onduleur
int VictronNC = 4; //inutilisé

int duree = 2000; //duree pour relacher le relais d'extinction
unsigned long chrono_actuel = 0;
unsigned long chrono_precedent = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(OnanSTART, OUTPUT);

  pinMode(OnanSTOP, OUTPUT);

  pinMode(VictronNO, INPUT_PULLUP);

  pinMode(VictronNC, INPUT_PULLUP);

  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

  chrono_precedent = millis();

  Serial.print("NO : ");
  Serial.print(digitalRead(VictronNO));
  Serial.print(" - Chrono Actuel : ");
  Serial.println(chrono_actuel);

  //Procedure de demarrage

  while (digitalRead(VictronNO) == LOW) {
    digitalWrite(OnanSTART, HIGH);
    digitalWrite(OnanSTOP, LOW);
  }

  //Procedure d'extinction
  while (digitalRead(VictronNO) == HIGH) {
    chrono_actuel = millis();
    digitalWrite(OnanSTART, LOW);
    digitalWrite(OnanSTOP, HIGH);
    if (chrono_actuel - chrono_precedent > duree) {
      digitalWrite(OnanSTOP, LOW);
    }

  }

  delay (50);

}

Un regard averti et un coup de main ne serait pas de refus :sweat_smile:

Bon j'avance un peu, j'ai mis à jour mon code qui fonctionnerais presque mais ...

Cette fois les relais se comportent bien mis à part qu'a la fin de la tempo le solenoid du relais ne se décolle pas. Je vois bien sur le module de relais la LED correspondante diminuer d'intensité mais elle ne se coupe pas :confused:

Par ce qu'une video vaut mieux que des longs discours :

Mon code mis à jour

/*
   Démarrage automatique pour Onan Cummins depuis relais Victron
*/

int OnanSTART = 7; //Relais INT1 servant à démarrer le groupe
int OnanSTOP = 8; //Relais INT2 servant à éteindre le groupe
int VictronNO = 2; //Interrupteur à bascule simulant le relai de l'onduleur
int VictronNC = 4; //inutilisé

int dureeSTART = 15000; //duree pour relacher le relais d'extinction
int dureeSTOP = 2000;
unsigned long chrono_actuel = 0;
unsigned long chrono_precedent = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(OnanSTART, OUTPUT);
  
  pinMode(OnanSTOP, OUTPUT);
  
  pinMode(VictronNO, INPUT_PULLUP);

  pinMode(VictronNC, INPUT_PULLUP);

  Serial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

  chrono_precedent = millis();

  Serial.print("NO : ");
  Serial.println(digitalRead(VictronNO));

  //Procedure de demarrage

  while (digitalRead(VictronNO) == LOW) {
    chrono_actuel = millis();
    digitalWrite(OnanSTART, LOW);
    if (chrono_actuel - chrono_precedent > dureeSTART) {
      digitalWrite(OnanSTART, HIGH);
    }
    digitalWrite(OnanSTOP, HIGH);
        
  }

  //Procedure d'extinction
  while (digitalRead(VictronNO) == HIGH) {
    chrono_actuel = millis();
    digitalWrite(OnanSTART, HIGH);
    digitalWrite(OnanSTOP, LOW);
    if (chrono_actuel - chrono_precedent > dureeSTOP) {
      digitalWrite(OnanSTOP, HIGH);
    }

  }

  delay (50);

}

Il me faudrait pouvoir inhiber le courant résiduel qui maintient le solenoid

J'y suis presque ...

Bonjour,
comme la fonction loop() est lu et relu en permanence, faut utiliser des variables pour figer les états.
De plus si on peut éviter les fonctions bloquantes et activer les relais pour le juste nécessaire...

Par exemple :

bool relais1 = false;
bool relais2 = false;
unsigned long chrono1 = 0;
unsigned long chrono2 = 0;

// pour simplifier j'utilise if(!relais1) au lieu de if(relais1 == 0)
void loop() {
  if (!relais1 && !digitalRead(VictronNO)) {
    // la condition n'est plus lu dès que le relais1 est activé
    chrono1 = millis();
    digitalWrite(OnanSTART, HIGH);// active le relais
    relais1 = true;
    relais2 = false;
  }

  if (relais1 && millis() - chrono1 > dureeSTART) {
    digitalWrite(OnanSTART, LOW);// relais1 remis au repos
    chrono1 = 0;// évite les répétions
  }

  if (!relais2 && digitalRead(VictronNO)) {
    chrono2 = millis();
    digitalWrite(OnanSTOP, HIGH);// active le relais stop
    relais1 = false;
    relais2 = true;
  }

  if (relais2 && millis() - chrono2 > dureeSTOP) {
    digitalWrite(OnanSTOP, LOW);// relais2 remis au repos
    chrono2 = 0;
  }
}```

Bonjour,

Merci beaucoup, j'avoue avoir un peu de mal avec les variables ! Ne codant pas tous les jours j'ai essayé d'aller au plus simple.

Tout fonctionne à la perfection, testé ce matin en situation réelle c'est juste impeccable, je suis trop content !!

Voici le code finalisé :

/*
   Démarrage automatique pour Onan Cummins depuis relais Victron Multiplus/Quattro
*/

int OnanSTART = 7; //Relais INT1 servant à démarrer le groupe sur D7
int OnanSTOP = 8; //Relais INT2 servant à éteindre le groupe sur D8
int VictronNO = 2; //Relais NO sur D2 Victron Multiplus, Quattro ...

int dureeSTART = 15000; //duree pour procédure de préchauffe/démarrage en ms
int dureeSTOP = 2000; //duree pour procédure d'extinction en ms

bool relais1 = false;
bool relais2 = false;
unsigned long chrono1 = 0;
unsigned long chrono2 = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(OnanSTART, OUTPUT);
  
  pinMode(OnanSTOP, OUTPUT);
  
  pinMode(VictronNO, INPUT_PULLUP);

}

void loop() {

  //Procédure de démarrage
  if (!relais1 && !digitalRead(VictronNO)) {
    // la condition n'est plus lu dès que le relais1 est activé
    chrono1 = millis();
    digitalWrite(OnanSTART, LOW);// active le relais
    relais1 = true;
    relais2 = false;
    chrono2 = 0;
  }

  if (millis() - chrono1 > dureeSTART) {
    digitalWrite(OnanSTART, HIGH);// relais1 remis au repos
  }

  //Procédure d'extinction
  if (!relais2 && digitalRead(VictronNO)) {
    chrono2 = millis();
    digitalWrite(OnanSTOP, LOW);// active le relais stop
    relais1 = false;
    relais2 = true;
    chrono1 = 0;
  }

  if (millis() - chrono2 > dureeSTOP) {
    digitalWrite(OnanSTOP, HIGH);// relais2 remis au repos
  }

}

Matériel utilisé :

  • Arduino Uno/Nano
  • Module 2 relais 5v

Améliorations futures :

  • Remplacer le délais de démarrage par le capteur de pression d'huile ...

Merci beaucoup !!

Ce n'est pas encore parfait.
le but est qu'une condition réalisée ne doit pas être répétée pour ne pas créer d'évènements parasites comme tu as eu.

 if (!relais1 && !digitalRead(VictronNO)) { 
    // la condition n'est plus lu dès que le relais1 est activé
    chrono1 = millis();
    digitalWrite(OnanSTART, LOW);// active le relais
    relais1 = true;
    relais2 = false;
    chrono2 = 0; // est inutile
  }

Cette condition détecte le basculement de l'interrupteur sur on
Quand la condition !digitalRead(VictronNO)) est réalisée, passer relais1 = true fait qu'à la prochaine boucle loop(), la condition ne peut plus être répétée.
C'est le principe d'inclure une variable dans la condition pour la changer dès la condition est réalisée.

  if (millis() - chrono1 > dureeSTART) {
    digitalWrite(OnanSTART, HIGH);// relais1 remis au repos
  }

Va être exécutée par la suite à chaque boucle loop(). ce n'est pas génant puisque ça confirme la fermeture du relais1, mais ça pourrait créer un problème dans certaine conditions.

Pour l'exécuter qu'un fois, il faut aussi une variable bool supplémentaire, arretRelais1 me semble adéquate :

  if (! arretRelais1 && millis() - chrono1 > dureeSTART) {
    digitalWrite(OnanSTART, HIGH);// relais1 remis au repos
   arretRelais1 = true;
  }

Il faudra la déclarer en entête.

J'espère que c'est plus clair pour toi :wink: