[Resolu] Problème de relais qui bloque des actions

C’est pas sorcier de dessiner des boites et des flèches - montrez nous ce que vous avez fait « tout le week end » et où ça coince... une chose est sûre, c’est votre projet et on ne va pas le faire pour vous ni à votre place...

Je n'ai pas dis cela. Mais j'ai trouvé se week-end que pas mal de monde parlais de la fonction "millis" et j'aimerais dire que si mon bouton est à l'état "LOW" pendant 1sec alors exécuter le programme. Mais là est justement le problème, comment écrire cela.

J’ai oublié de mettre la partie concerné que j’ai faite :

{
  etatbouton = digitalRead(bouton);
  time = millis();
  if (etatbouton == LOW, millis() => 1000)
  {
      // Moniteur série pour vérifier valeur
int valeur=analogRead(pincapteur); // on lit la valeur transmise par le capteur
  Serial.print("Valeur Capteur : ");
  Serial.print(valeur);
  Serial.println();
  delay(1000); 
  if ((valeur >=502) && (valeur <= 514))   // Valeur Moy
{
  Serial.println("Test centre OK");
  etatRelais=!etatRelais;
  digitalWrite(RELAIS,!etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
else if ((valeur >=0) && (valeur <= 501))              // Valeur Min
{
  Serial.println("Test NORD OK");
  digitalWrite(RELAIS,etatRelais);
  etatRelais2=!etatRelais2;
  digitalWrite(RELAIS2,!etatRelais2);
}

else if ((valeur >=515) && (valeur <= 1023))
{
  Serial.println("Test SUD OK");
  digitalWrite(RELAIS,etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
}
else (etatbouton == HIGH);
{
  digitalWrite(LEDB,HIGH);
}
}

if (etatbouton == LOW, millis() => 1000)

Est ce que ça compile?
Est ce que ce ne serait pas plus lisible sous la forme (si c'est bien ce que vous voulez)
if ((LOW == etatbouton) && (millis >= 1000)).

Par ailleurs, buis je vous signaler (il vous reste un ou deux week ends... et même semaines) que ce forum donne accés à des tutoriels, parmi ceux ci, les liens de Tuto pour code non bloquant et FreeRTOS - Tutoriels et cours - Arduino Forum et le tutoriel sur les machines d'etat Programmation Automate fini / Machine à état - Tutoriels et cours - Arduino Forum pourraient vous être plus fructueux que des tâtonnements dans l'etrange toile....

Cela compile mais malheureusement ma LED rouge reste allumé et je ne suis pas sur que il prend vraiment compte le temps. ^^"

Vos notations avec les virgules sont tellement bizarroides que vous feriez mieux de réécrire, ou au moins de mettre en commentaire ce que c'est censé faire.... (JML a reussi à en traduire une ....)

Désolé si ce n’étais pas trop claire. Voici avec quelque notations :

int pincapteur=A0; // pin Capteur magnétique

const int pinLed=7; 
const int pinLed1=8;
const int pinLed2=9;

const int LEDB=10; // Led bouton
const int bouton=11;
int etatbouton=0; // état du bouton mis à 0

const int RELAIS = 6; // pin relais 1
const int RELAIS2 = 5; // pin relais n°2
boolean etatRelais = 0; // état relais à 0
boolean etatRelais2 = 0; // état relais à 0

unsigned long time;

void setup() 
{
Serial.begin(9600);

pinMode(LEDB,OUTPUT);      
pinMode(bouton,INPUT_PULLUP); // résistance pull up mise

pinMode(pinLed,OUTPUT);
pinMode(pinLed1,OUTPUT);
pinMode(pinLed2,OUTPUT);

pinMode(RELAIS,OUTPUT);
pinMode(RELAIS2,OUTPUT);
}

void loop() 
{
  valeurcapteur();
  capteurled();
  }

void valeurcapteur()
{
  etatbouton = digitalRead(bouton);                     // on lit l'état du bouton
  time = millis();
  if (etatbouton == LOW, millis()>=1000)                 // si bouton est à LOW pendant 1000 sec alors lancer le programme
  {
      // Moniteur série pour vérifier valeur
int valeur=analogRead(pincapteur);                      // on lit la valeur transmise par le capteur
  Serial.print("Valeur Capteur : ");
  Serial.print(valeur);
  Serial.println();
  delay(1000); 
  if ((valeur >=502) && (valeur <= 514))               // Valeur rechercher pour l'état du milieu du capteur
{
  Serial.println("Test centre OK");
  etatRelais=!etatRelais;                               // on inverse l'état du relais 1
  digitalWrite(RELAIS,!etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
else if ((valeur >=0) && (valeur <= 501))              // Valeur rechercher pour l'état du Minimum du capteur
{
  Serial.println("Test NORD OK");
  digitalWrite(RELAIS,etatRelais);
  etatRelais2=!etatRelais2;                              // on inverse l'état du relais 2
  digitalWrite(RELAIS2,!etatRelais2);
}

else if ((valeur >=515) && (valeur <= 1023))              // Valeur rechercher pour l'état du Maximum du capteur
{
  Serial.println("Test SUD OK");
  digitalWrite(RELAIS,etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
}
else (etatbouton == HIGH);                                // si le programme ne sais pas lancé alors on allume la LED rouge
{
  digitalWrite(LEDB,HIGH);
}
}

Merci pour vos réponses et votre aide :slight_smile:

Ma reco était:

  • lisez mon tuto sur les machines a états et comprenez le code.
  • dessinez vos états
  • codez quelque chose
  • postez le dessin et votre tentative d'implémentation

si vous avez passé le week end à lire le web et voir que tout le monde parle de millis() mais sans rien comprendre ni essayer et continué à écrire du code avec des virgules à la noix - ça c'est du grand n'importe quoi, un espoir de magie noire....
  if (etatbouton == LOW, millis()>=1000)  // si bouton est à LOW pendant 1000 sec alors lancer le programme alors que je vous ai expliqué plus haut en #10 que c'était n'importe quoi...

millis() c'est le nombre de millisecondes depuis que vous avez allumé votre arduino. au bout d'une demi seconde ça vaut 500, une seconde ça vaut 1000, au bout de 2 seconde ça vaut 2000, au bout de 3 secondes ça vaut 3000 etc...

je ne vais pas me bouger bcp...

Comme je l'ai certainement dis plus haut, je suis un débutant. Je n'ai pas compris votre "tuto" il y a des librairies et j'ai l'impression que cela me complique. Si juste votre rôle est de me dire que cela est du grand n'importe quoi et que vous ne comprenez pas mes difficultés et bien c'est votre choix mais pas le peine dans rajouter et de continuer à commenter le topic.

Et pour se qui est de Millis je me suis tromper dans mon commentaire, je savais que cela signifiait des ms et que 1000 = 1 sec.

mon rôle est le même que le votre, contribuer bénévolement de temps en temps et en fonction de mes envies au débat.

Il me semble avoir déjà expliqué cette notion de virgule plus haut dans le post 10... on dirait que vous n'écoutez pas. Nouvelle tentative:
En C ou C++, la virgule sert à combiner 2 expression. ça demande au compilateur d'évaluer les 2 expressions (gauche d'abord, puis droite) qui sont de part et d'autre de la virgule et ça donne comme valeur de l'expression globale ce qu'a retourné l'expression de droite.
En plus clair si vous écrivez Z = (A,B)le compilateur va évaluer (exécuter) A, puis B et mettra dans Z ce que l'expression B a donné. Si vous écrivez if (A,B) {...} c'est comme si vous aviez écrit

A;
if (B) {...}

en gros on exécute A puis on teste si l'expression B est évaluée à vrai ou faux.

Donc if (etatbouton == LOW, millis()>=1000)  {...} ça revient à écrire

etatbouton == LOW;
if (millis()>=1000)  {...}

la première expression étant juste un test sans affectation ni effets de bord, ça va être viré par l'optimiseur du compilateur et le if sera toujours vrai au bout d'une seconde de fonctionnement de votre arduino (pour environ 50 jours quand millis() reviendra à 0 et recommencera son cycle).

--> je maintiens donc que c'est du grand n'importe quoi de croire que cela veut dire "si bouton est à LOW pendant 1000 sec" (ou 1000ms). Ne prenez pas cela personnellement, c'est un jugement de valeur sur le code, pas sur votre personne. On a tous commencé quelque part, mais on a aussi tous bossé pour ne plus faire ces erreurs...

Si vous n'aimez pas mon tuto (pas de pb) - en voici un autre par eskimon sur introduire le temps. ça vous aidera à comprendre millis()

Cela dit - vous ne souhaitez pas aller dans la direction que je vous propose et d'apprendre ce qu'est une programmation par machine à état, c'est votre choix et je n'ai pas de soucis avec cela.

Il y a aussi moyen de faire sans mais c'est plus compliqué à mon sens pour un débutant... mais chacun est libre de faire comme il l'entend et je ne souhaite absolument rien imposer.

Et donc effectivement je cesse de contribuer sur ce fil.

D’accord déjà je comprend mieux cela. Merci pour l’explication. Mais si je comprend bien il faudrait que je change mon écriture et mettre celle-ci ? Puisque si je comprend bien cela serais plus lisible pour Arduino.

etatbouton == LOW;
if (millis()>=1000)  {...}

Le problème n’est pas que je n’aime pas votre tuto ou autre. C’est juste que j’ai l’impression de voir compliqué et d’utiliser des librairies que je ne suis pas sur de comprendre complètement.

Merci pour votre aide

Hikashiro:
Mais si je comprend bien il faudrait que je change mon écriture et mettre celle-ci ? Puisque si je comprend bien cela serais plus lisible pour Arduino.

Non... Votre problème c'est de croire que vous pouvez écrire en une seule ligne de code "Si le bouton est appuyé pendant plus d'une seconde alors faire ceci"....

ça ne marche pas comme cela...

il faut enregistrer en mémoire le moment où le bouton est appuyé puis surveiller quand le bouton est relâché et calculer la différence de temps entre ces deux moments.

On doit donc détecter l'évenement "bouton appuyé" (et là on enregistre l'heure) puis attendre l'évènement "bouton relâché" et là on teste la différence entre l'heure courante et l'heure enregistrée. Si c'est plus d'une seconde alors on fait quelque chose sinon on fait autre chose

--> il faut donc un code de gestion des événements et des différents états (état "attente appui" et état "attente relâche") --> c'est ce que l'on appelle une machine à état.

en utilisant une librairie (qui implémente pour vous la machine à état du bouton) vous pouvez avoir une gestion plus simple, éventuellement utilisez la librairie de @bricoleau mais là encore faudra bosser un peu pour comprendre comment ça fonctionne

D'accord j'aurais pensé que cela aurais pu être simplifier, je vais devoir encore réfléchir à cela et écrire le code et voir si cela fonctionne comme je veux.
Mais bon le dernier point qui me fais peur seras surtout de faire comprendre à l'arduino que si j'appuie sur le bouton pendant tant de temps et bien le programme dois se lancer et que si il y a des tests faux et bien il faut arrêter mettre la LED rouge à l'état haut.

Mais merci déjà pour l'aide, je vais d'abord y aller part étape.

c'est vraiment que du code.... faut pas avoir peur, mais faut construire lentement et bien gérer ses états.... c'est pour cela qu'une machine à état est bien utile pour gérer ce genre de projet.

C'est sûr que vu comme ça tout paraît plus simple ^^"

Je vais reprendre ton tuto, vu que là je commence à vraiment comprendre la nécessité des machines à état.

Merci pour ton temps.

Alors après avoir relu ton tuto, voilà se que j’ai fais mais là si je n’appuie pas une fois toute les secondes rien ne se fais automatiquement alors que ça devrais lancer le programme complet.

Voilà le code, j’espère ne pas avoir fais trop de merde

#include <OneButton.h>
const byte bouton=11;
OneButton button(bouton,true);
int pincapteur=A0; // pin Capteur magnétique

const byte pinLed=7; 
const byte pinLed1=8;
const byte pinLed2=9;

const byte LEDB=10; // Led bouton

const int RELAIS = 6; // pin relais 1
const int RELAIS2 = 5; // pin relais n°2
boolean etatRelais = 0; // état relais à 0
boolean etatRelais2 = 0; // état relais à 0

unsigned long time;

enum :unsigned long {REPOS, boutonAppuyez, boutonRelacher} etatbouton;

void capteurled()
{
int valeur=analogRead(pincapteur);                        // on lit la valeur transmise par le capteur

if ((valeur >=0) && (valeur <= 501))                    // Valeur Min
 {
    digitalWrite(pinLed,HIGH);                         // on allume la LED emplacement 7
    digitalWrite(pinLed1,LOW);
    digitalWrite(pinLed2,LOW);
  } 
else if ((valeur >=502) && (valeur <= 514))             // Valeur Moy
{
    digitalWrite(pinLed,LOW);                   
    digitalWrite(pinLed1,HIGH);                     // on allume la LED emplacement 8
    digitalWrite(pinLed2,LOW);
  }  
else if ((valeur >=515) && (valeur <= 1023))         // Valeur Max
{
    digitalWrite(pinLed,LOW);                  
    digitalWrite(pinLed1,LOW);
    digitalWrite(pinLed2,HIGH);                    // on allume la LED emplacement 9
  }
}

void valeurcapteur()
{
      // Moniteur série pour vérifier valeur
int valeur=analogRead(pincapteur);                      // on lit la valeur transmise par le capteur
    Serial.print("Valeur Capteur : ");
    Serial.print(valeur);
    Serial.println();
    delay(1000); 
if ((valeur >=502) && (valeur <= 514))               // Valeur rechercher pour l'état du milieu du capteur
{
  Serial.println("Test centre OK");
  etatRelais=!etatRelais;                               // on inverse l'état du relais 1
  digitalWrite(RELAIS,!etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
else if ((valeur >=0) && (valeur <= 501))              // Valeur rechercher pour l'état du Minimum du capteur
{
  Serial.println("Test NORD OK");
  digitalWrite(RELAIS,etatRelais);
  etatRelais2=!etatRelais2;                              // on inverse l'état du relais 2
  digitalWrite(RELAIS2,!etatRelais2);
}
else if ((valeur >=515) && (valeur <= 1023))              // Valeur rechercher pour l'état du Maximum du capteur
{
  Serial.println("Test SUD OK");
  digitalWrite(RELAIS,etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
}


void CarteRepos()
{
  digitalWrite(pinLed, LOW);
  digitalWrite(pinLed1, LOW);
  digitalWrite(pinLed2, LOW);
  digitalWrite(LEDB, LOW);
  digitalWrite(RELAIS, LOW);
  digitalWrite(RELAIS2, LOW);
  etatbouton = REPOS;
}

void simpleclick()
{
  switch (etatbouton)
{
 case REPOS:
 valeurcapteur();
 etatbouton = boutonAppuyez;   
 break;

 case boutonAppuyez:
 digitalWrite(LEDB, HIGH);
 etatbouton = boutonRelacher;
 break;

 case boutonRelacher:
 CarteRepos();
 break;
}
}

void setup() 
{
Serial.begin(9600);

pinMode(LEDB,OUTPUT);      

pinMode(pinLed,OUTPUT);
pinMode(pinLed1,OUTPUT);
pinMode(pinLed2,OUTPUT);

pinMode(RELAIS,OUTPUT);
pinMode(RELAIS2,OUTPUT);

CarteRepos();
valeurcapteur();
button.attachClick(simpleclick);
}

void loop() {
capteurled();
button.tick();

}

Et donc je ne vois pas où mettre une ligne qui me permettrait de tout lancé et non une fois part seconde si j’appuie sur le bouton

C'est un peu ce que vous espériez, sinon, pourquoi avoir mis (laissé?) un delai -bloquant- d'une seconde dans valeurcapteur()? Il est evident que ce delai -bloquant- vous bloque pendant une seconde....

Oui mais pour moi mon "delay(1000)" sers juste à que se sois plus lisible dans le moniteur série. Et je viens d'essayer en l'enlevant et cela ne change rien ^^"

re-expliquez en français ce que vous souhaitez faire en utilisant la notion d’états

Je souhaite faire que si l’on appui sur le bp pendant plus de 1 sec et bien le programme se lance. Donc je dois calculer le temps entre quand le bouton est appuyez et relâcher pour savoir si cela est supérieur à se que je demande et si c’est le cas, le programme dois se lancer sinon il dois retourner à son état initial ou allumer une LED rouge pour dire que le bp à un problème.

Je te passe le code que j’ai pu faire grâce à ton tuto.

#include <OneButton.h>
const byte bouton=11;
OneButton button(bouton,true);
int pincapteur=A0; // pin Capteur magnétique

const byte pinLed=7; 
const byte pinLed1=8;
const byte pinLed2=9;

const byte LEDB=10; // Led bouton

const int RELAIS = 6; // pin relais 1
const int RELAIS2 = 5; // pin relais n°2
boolean etatRelais = 0; // état relais à 0
boolean etatRelais2 = 0; // état relais à 0

unsigned long chrono;
const unsigned long TimeOut = 10000ul;

enum :unsigned long {REPOS, boutonAppuyez, boutonRelacher} etatbouton;

void capteurled()
{
int valeur=analogRead(pincapteur);                        // on lit la valeur transmise par le capteur

if ((valeur >=0) && (valeur <= 501))                    // Valeur Min
 {
    digitalWrite(pinLed,HIGH);                         // on allume la LED emplacement 7
    digitalWrite(pinLed1,LOW);
    digitalWrite(pinLed2,LOW);
  } 
else if ((valeur >=502) && (valeur <= 514))             // Valeur Moy
{
    digitalWrite(pinLed,LOW);                   
    digitalWrite(pinLed1,HIGH);                     // on allume la LED emplacement 8
    digitalWrite(pinLed2,LOW);
  }  
else if ((valeur >=515) && (valeur <= 1023))         // Valeur Max
{
    digitalWrite(pinLed,LOW);                  
    digitalWrite(pinLed1,LOW);
    digitalWrite(pinLed2,HIGH);                    // on allume la LED emplacement 9
  }
}

void valeurcapteur()
{
      // Moniteur série pour vérifier valeur
int valeur=analogRead(pincapteur);                      // on lit la valeur transmise par le capteur
    Serial.print("Valeur Capteur : ");
    Serial.print(valeur);
    Serial.println();
    delay(1000); 
if ((valeur >=502) && (valeur <= 514))               // Valeur rechercher pour l'état du milieu du capteur
{
  Serial.println("Test centre OK");
  etatRelais=!etatRelais;                               // on inverse l'état du relais 1
  digitalWrite(RELAIS,!etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
else if ((valeur >=0) && (valeur <= 501))              // Valeur rechercher pour l'état du Minimum du capteur
{
  Serial.println("Test NORD OK");
  digitalWrite(RELAIS,etatRelais);
  etatRelais2=!etatRelais2;                              // on inverse l'état du relais 2
  digitalWrite(RELAIS2,!etatRelais2);
}
else if ((valeur >=515) && (valeur <= 1023))              // Valeur rechercher pour l'état du Maximum du capteur
{
  Serial.println("Test SUD OK");
  digitalWrite(RELAIS,etatRelais);
  digitalWrite(RELAIS2,etatRelais2);
}
}

void CarteRepos()
{
  digitalWrite(pinLed, LOW);
  digitalWrite(pinLed1, LOW);
  digitalWrite(pinLed2, LOW);
  etatbouton = REPOS;
}

void simpleclick()
{
  switch (etatbouton)
{
 case REPOS:
 valeurcapteur();
 etatbouton = boutonAppuyez;   
 break;

 case boutonAppuyez:
 digitalWrite(LEDB, HIGH);
 etatbouton = boutonRelacher;
 break;

 case boutonRelacher:
 CarteRepos();
 break;
}
chrono = millis();
}

void timeOut()
{
  switch (etatbouton)
  { 
    digitalWrite(LEDB, HIGH);
    break;
  }
}
void setup() 
{
Serial.begin(9600);

pinMode(LEDB,OUTPUT);      

pinMode(pinLed,OUTPUT);
pinMode(pinLed1,OUTPUT);
pinMode(pinLed2,OUTPUT);

pinMode(RELAIS,OUTPUT);
pinMode(RELAIS2,OUTPUT);

CarteRepos();
valeurcapteur();
button.attachClick(simpleclick);
}

void loop() 
{
capteurled();
button.tick();
if (millis() - chrono < TimeOut)
{
timeOut();
chrono = millis();
}
}

Je ne sais pas exactement si cela correspond à vos attentes comme explications. Merci pour votre aide.