code pour plusieurs moteurs , utilisation d'un tableau

J’ai mis “etat” à la place de “numPin”,mais le résultat est le mème,
qui va donc bien dire à maSequence.etat d’être LOW ou HIGH ? , c’est le fait qu’il passe en dessous des 11 cms ( donc représenté ici par t0 >= maSequence.debut) ; et la fin , c’est que le temps d’allumage est passé t0 > maSequence_.fin ) && que digitalWrite(maSequence*.etat, HIGH)ou (LOW) , mais ça veut pas; je dois rater quelque chose dans la logique du système !
```*_

*struct elementSequence_t {
  byte numPin;
  unsigned long debut;
  unsigned long fin;
  byte etat;
};
elementSequence_t maSequence = {  //  Initialiser la structure elementSequence_t avec les variables  maSequence
  {11, 0ul, 500ul, LOW},
  {6, 500ul, 8500ul, LOW},
  {13, 500ul, 6500ul, LOW},
  {10, 8500ul, 38500ul, LOW},
  {9, 8500ul, 18500ul, LOW},
  {7, 18500ul, 26500ul, LOW},
  {6, 38500ul, 46500ul, LOW},
  {12, 46500ul, 56500ul, LOW},
  {3, 56500ul, 62500ul, LOW},
  {7, 56500ul, 64500ul, LOW},
  {8, 64500ul, 84500ul, LOW}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);
unsigned long topDistanceCritique;

void setup() {
  Serial.begin(115200);
  topDistanceCritique = 2300ul; // on simule que l’on est passé sous 11cm à ce moment là
  for (byte i = 0; i < nbElementSequence; i++) {
    pinMode(maSequence[i].numPin, OUTPUT);
    digitalWrite(maSequence[i].numPin, maSequence[i].etat);
  }
}
void loop()
{
  unsigned long t0 = millis() - topDistanceCritique;

for (byte i = 0; i < nbElementSequence; i++) {
    if (maSequence[i].etat == LOW) {

// on regarde s’il faut l’allumer
      if ((t0 >= maSequence[i].debut) && (t0 <= maSequence[i].fin)) {
        // FAIRE DES TRUCS
        digitalWrite(maSequence[i].etat, HIGH);  //<-------------
      }
    } else {
      // on est HIGH on regarde s’il faut éteindre, c’est uniquement après la fin
      if ((t0 > maSequence[i].fin)) {
        // FAIRE DES TRUCS
        digitalWrite(maSequence[i].etat, LOW); //<----------------
      }
    }
  } // end for
}

_```*
Merci
Frida_

Toujours pas... à quoi sert la variable état dans la structure ?

A dire l'état
mais ayant mis : digitalWrite(maSequence_.etat, HIGH);, je pensais que l'état aurait dû changé, mais l'état ne change pas ,( toujours 0 sur le moniteur série) et c'est ça que je n'arrive pas à appréhender : pourquoi et où est mon erreur? il me semblait l'avoir mis au bon endroit, d'habitude, l’expression digitalWrite(maSequence*.etat, HIGH); fonctionne ..,que puis-je faire de plus pour transformer l’état LOW en HIGH ?(et inversement après)*_
En tout cas merci pour votre patience
Frida

Vous aviez fait juste plus haut dans un ancien code en#8 (enfin vous aviez oublié d’allumer la Led)

Bonjour,
Voilà ce que j’ai pu faire:

 struct elementSequence_t {
  byte numPin;
  unsigned long debut;
  unsigned long fin;
  byte etat;
};
elementSequence_t maSequence[] = {   //  Initialiser la structure elementSequence_t avec les variables  maSequence[]
  {11, 0ul, 500ul, LOW},
  {6, 500ul, 8500ul, LOW},
  {13, 500ul, 6500ul, LOW},
  {10, 8500ul, 38500ul, LOW},
  {9, 8500ul, 18500ul, LOW},
  {7, 18500ul, 26500ul, LOW},
  {6, 38500ul, 46500ul, LOW},
  {12, 46500ul, 56500ul, LOW},
  {3, 56500ul, 62500ul, LOW},
  {7, 56500ul, 64500ul, LOW},
  {8, 64500ul, 84500ul, LOW}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);
unsigned long topDistanceCritique;

void setup() {
  Serial.begin(115200);
  topDistanceCritique = 2300ul; // on simule que l'on est passé sous 11cm à ce moment là
  for (byte i = 0; i < nbElementSequence; i++) {
    pinMode(maSequence[i].numPin, OUTPUT);
    digitalWrite(maSequence[i].numPin, maSequence[i].etat);
 digitalWrite(maSequence[i].numPin,maSequence[i].debut);
  digitalWrite(maSequence[i].numPin,maSequence[i].fin);    
  }
}
void loop()
{
  unsigned long t0 = millis() - topDistanceCritique;
  for (byte i = 0; i < nbElementSequence; i++) {
    if (maSequence[i].etat == LOW) {

      // on regarde s'il faut l'allumer
      if ((t0 >= maSequence[i].debut) && (t0 <= maSequence[i].fin)) {
        // FAIRE DES TRUCS
        maSequence[i].etat = HIGH;
 
        digitalWrite(maSequence[i].numPin, HIGH);  
      }
      }
     else {
      // on est HIGH on regarde s'il faut éteindre, c'est uniquement après la fin
      if ((t0 > maSequence[i].fin)) {
        // FAIRE DES TRUCS
        maSequence[i].etat = LOW;
       digitalWrite(maSequence[i].numPin, LOW);  
      }
    }
  } // end for
}

Qu’en pensez vous ?
Et pour rajouter le capteur,( c’est là qu’une petite machine à état (ai-je déclenché sous 11cm ou pas) sera utilsée ), pourriez vous m’aiguiller ?
Merci
Frida

(enfin!) :slight_smile: bon si vous appuyez sur ctrl-T dans l'IDE pour que ce soit indenté correctement ce serait encore mieux...

Avez vous testé? imprimiez par exemple quelle pin passe à HIGH ou LOW et quand. ça devrait vous permettre de voir si c'est bien cela :slight_smile:

Pour la machine a état, on en avait rédigée une qui déclenchait quelque chose quand vous passiez sous 11cm.... faut prendre la même approche...

J'ai testé, ça va :slight_smile:

Je vais faire la même approche, et vous tiens au courant.

Bonsoir,
Voilà ce que j’ai pu écrire :

struct elementSequence_t {
  byte numPin;
  unsigned long debut;
  unsigned long fin;
  byte etat;
};
elementSequence_t maSequence[] = {   //  Initialiser la structure elementSequence_t avec les variables  maSequence[]
  {11, 0ul, 500ul, LOW},
  {6, 500ul, 8500ul, LOW},
  {13, 500ul, 6500ul, LOW},
  {10, 8500ul, 38500ul, LOW},
  {9, 8500ul, 18500ul, LOW},
  {7, 18500ul, 26500ul, LOW},
  {6, 38500ul, 46500ul, LOW},
  {12, 46500ul, 56500ul, LOW},
  {3, 56500ul, 62500ul, LOW},
  {7, 56500ul, 64500ul, LOW},
  {8, 64500ul, 84500ul, LOW}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);
unsigned long t0;
/* Partie "capteur ULTRASON"  */
int trig = 4;
int echo = 5;
long lecture_echo;
int cm;
int distanceCritique = 11; // en cm
int a = (cm - distanceCritique); ///<----------------------------- Pb !
/* Partie " fonctions " */
int lireDistance()
{
  static unsigned long topChronoMesure = 4294967154;
  const unsigned long tempoMesure = 100ul;
  unsigned long topMoinsTempo;
  topMoinsTempo = millis() - topChronoMesure;
  if (millis() - topChronoMesure >= tempoMesure) {
    // on a attendu assez longtemps, faire la mesure
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cm = lecture_echo / 58;
  }

  Serial.print(" millis()=" );
  Serial.println(millis());
  Serial.println( );
  Serial.print("topChronoMesure =" );
  Serial.println( topChronoMesure);
  Serial.println( );
  Serial.print(" tempoMesure2 =" );
  Serial.println(tempoMesure );
  Serial.print(" topMoinsTempo 1 = " );
  Serial.println( topMoinsTempo);
  Serial.println( );
  Serial.print(" cm =" );
  Serial.println( cm);
  Serial.println( );
  Serial.print(" distance= " );
  Serial.println( cm);
  Serial.println( );
  Serial.print(" cm- distanceCritique= " );
  Serial.println( a );
  Serial.println( );
  Serial.print(" distanceCritique= " );
  Serial.println(distanceCritique  );
  Serial.println( );

  topChronoMesure = millis();
  return cm;
}
long previousMillis = 0; // dans déclarations

void setup() {
  Serial.begin(115200);
  {
    pinMode(trig, OUTPUT);
    pinMode(echo, INPUT);
    digitalWrite(trig, LOW);
    delay (20);
  }

  for (byte i = 0; i < nbElementSequence; i++) {
    pinMode(maSequence[i].numPin, OUTPUT);
    digitalWrite(maSequence[i].numPin, maSequence[i].etat);
    digitalWrite(maSequence[i].numPin, maSequence[i].debut);
    digitalWrite(maSequence[i].numPin, maSequence[i].fin);
  }
}
void loop()
{
  lireDistance();
  delay(100); // <-- sans le délai 100, les mesures sont bloquées au meme nombre (ça ne doit pas pouvoir avoir le temps de lire? )
  {
    if ( cm < distanceCritique  )
    {
      unsigned long currentMillis = millis();
      for (byte i = 0; i < nbElementSequence; i++) {
        if (maSequence[i].etat == LOW) {

          // on regarde s'il faut l'allumer
          if ((currentMillis - previousMillis >= maSequence[i].debut) && ((currentMillis - previousMillis <= maSequence[i].fin))) {
            maSequence[i].etat = HIGH;
            digitalWrite(maSequence[i].numPin, HIGH);
          }
        }
        else {
          // on est HIGH on regarde s'il faut éteindre, c'est uniquement après la fin
          if (((currentMillis - previousMillis > maSequence[i].fin)) ) {
            maSequence[i].etat = LOW;
            digitalWrite(maSequence[i].numPin, LOW);
          }
        }
      } // end for
      previousMillis = currentMillis;
    }
    else {   }
  }
}

Problème (et je n’arrive pas à voir d’où ça vient) :

Sur la console, j’obtiens :
cm= 185
distance=185
distanceCritique= 11
cm- distanceCritique= -11

les autres données, ça va

alors, bien sur, je reste bloquée pour la suite et j’ai besoin de …votre aide.
Espérant tout de même ne pas trop vous agacer , merci.

Bonsoir,

Vous avez placé

int a = (cm - distanceCritique); ///<----------------------------- Pb !

dans la partie définition des variables.
Cette variable sera donc définie et calculée uniquement à ce moment là.

Le calcul doit être placé dans la partie loop(), donc dans une fonction ou autres, si vous voulez qu’il soit effectué plusieurs fois.

Merci Zlika
,
Votre intervention va me permettre de continuer .
Frida

J’ai donc refais le code, mais si cela fonctionne, cela ne marche que quand, il y a une distance < à 11 cms , et dès qu’on enlève la main, ça s’arrête de fonctionner .
D’autre part pour les valeurs de previousMillis = millis , c’est pas clair ( on dirait que ça s’emmêle les pinceaux ).
Pourriez vous m’éclairer ?

long previousMillis = millis();

struct elementSequence_t {
  byte numPin;
  unsigned long debut;
  unsigned long fin;
  byte etat;
};
elementSequence_t maSequence[] = {   //  Initialiser la structure elementSequence_t avec les variables  maSequence[]
  {11, 0ul, 500ul, LOW},
  {6, 500ul, 8500ul, LOW},
  {13, 500ul, 6500ul, LOW},
  {10, 8500ul, 38500ul, LOW},
  {9, 8500ul, 18500ul, LOW},
  {7, 18500ul, 26500ul, LOW},
  {6, 38500ul, 46500ul, LOW},
  {12, 46500ul, 56500ul, LOW},
  {3, 56500ul, 62500ul, LOW},
  {7, 56500ul, 64500ul, LOW},
  {8, 64500ul, 84500ul, LOW}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);
unsigned long t0;
/* Partie "capteur ULTRASON"  */
int trig = 4;
int echo = 5;
long lecture_echo;
int cm;
int distanceCritique = 11; // en cm
int a = (cm - distanceCritique); ///<----------------------------- Pb !
/* Partie " fonctions " */
int lireDistance()
{
  static unsigned long topChronoMesure = 4294967154;
  const unsigned long tempoMesure = 100ul;
  unsigned long topMoinsTempo;
  topMoinsTempo = millis() - topChronoMesure;
  if (millis() - topChronoMesure >= tempoMesure) {
    // on a attendu assez longtemps, faire la mesure
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cm = lecture_echo / 58;
  }
  topChronoMesure = millis();
  return cm;
}

void setup() {
  Serial.begin(115200);
  {
    pinMode(trig, OUTPUT);
    pinMode(echo, INPUT);
    digitalWrite(trig, LOW);
    delay (20);
  }

  for (byte i = 0; i < nbElementSequence; i++) {
    pinMode(maSequence[i].numPin, OUTPUT);
    digitalWrite(maSequence[i].numPin, maSequence[i].etat);
    digitalWrite(maSequence[i].numPin, maSequence[i].debut);
    digitalWrite(maSequence[i].numPin, maSequence[i].fin);
  }
}
void loop()
{
  a = (cm - distanceCritique);
  lireDistance();
  delay(100); // <-- sans le délai 100, les mesures sont bloquées au meme nombre (ça ne doit pas pouvoir avoir le temps de lire? )
  {
    if ( cm < distanceCritique  )
    {
      for (byte i = 0; i < nbElementSequence; i++) {
        if (maSequence[i].etat == LOW) {

          digitalWrite( previousMillis , 0);
          Serial.print("millis()- previousMillis =" );
          Serial.println( millis() - previousMillis);
          Serial.print(" previousMillis =" );
          Serial.println( previousMillis);

          // on regarde s'il faut l'allumer
          if ((millis() - previousMillis >= maSequence[i].debut) && ((millis() - previousMillis <= maSequence[i].fin))) {
            maSequence[i].etat = HIGH;
            digitalWrite(maSequence[i].numPin, HIGH);
          }
          else {
            // on est HIGH on regarde s'il faut éteindre, c'est uniquement après la fin
            if (((millis() - previousMillis > maSequence[i].fin)) ) {
              maSequence[i].etat = LOW;
              digitalWrite(maSequence[i].numPin, LOW);
            }
          }
          previousMillis = millis();
        } // end for
      }
    }
    else {   }
  }
}

Merci

Frida,

Quand je voislong previousMillis = millis(); ou int a = (cm - distanceCritique);mis nimporte où et que vous vous demandez ce qui ne va pas... c’est qu’il y a un soucis ailleurs...

Dsl mais il faut mettre le projet de côté et aller lire quelques tutos de C.. vous manquez de bases théoriques et vous ne vous en sortirez pas en balançant du code au petit bonheur...

Millis() est une fonction qui retourne un type unsigned long. Il est donc logique de stocker sa valeur dans une variable de type unsigned long sous peine d'avoir une erreur de calcul par la suite. Regarder la différence entre les différents types de variables ici.

int a = (cm - distanceCritique);

Posez-vous la question de savoir à quel moment vous avez besoin de calculer ceci. Si vous le faites n'importe quand, êtes vous sûr que le résultat est correct au moment où vous utilisez son résultat ?

Bonsoir,
Merci pour votre réponse,
J’ai donc rectifié le code; pouvez vous me dire si c’est mieux?

unsigned long previousMillis = millis();

struct elementSequence_t {
  byte numPin;
  unsigned long debut;
  unsigned long fin;
  byte etat;
};
elementSequence_t maSequence[] = {   //  Initialiser la structure elementSequence_t avec les variables  maSequence[]
  {11, 0ul, 500ul, LOW},
  {6, 500ul, 8500ul, LOW},
  {13, 500ul, 6500ul, LOW},
  {10, 8500ul, 38500ul, LOW},
  {9, 8500ul, 18500ul, LOW},
  {7, 18500ul, 26500ul, LOW},
  {6, 38500ul, 46500ul, LOW},
  {12, 46500ul, 56500ul, LOW},
  {3, 56500ul, 62500ul, LOW},
  {7, 56500ul, 64500ul, LOW},
  {8, 64500ul, 84500ul, LOW}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);
unsigned long t0;
/* Partie "capteur ULTRASON"  */
int trig = 4;
int echo = 5;
long lecture_echo;
int cm;
int distanceCritique = 11; // en cm
int a = (cm - distanceCritique); ///<----------------------------- Pb !
/* Partie " fonctions " */
int lireDistance()
{
  static unsigned long topChronoMesure = 4294967154;
  const unsigned long tempoMesure = 100ul;
  unsigned long topMoinsTempo;
  topMoinsTempo = millis() - topChronoMesure;
  if (millis() - topChronoMesure >= tempoMesure) {
    // on a attendu assez longtemps, faire la mesure
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cm = lecture_echo / 58;
  }
  topChronoMesure = millis();
  return cm;
}

void setup() {
  Serial.begin(115200);
  {
    pinMode(trig, OUTPUT);
    pinMode(echo, INPUT);
    digitalWrite(trig, LOW);
    delay (20);
  }

  for (byte i = 0; i < nbElementSequence; i++) {
    pinMode(maSequence[i].numPin, OUTPUT);
    digitalWrite(maSequence[i].numPin, maSequence[i].etat);
    digitalWrite(maSequence[i].numPin, maSequence[i].debut);
    digitalWrite(maSequence[i].numPin, maSequence[i].fin);
  }
}
void loop()
{
  a = (cm - distanceCritique);
  lireDistance();
  delay(100); // <-- sans le délai 100, les mesures sont bloquées au meme nombre (ça ne doit pas pouvoir avoir le temps de lire? )



  for (byte i = 0; i < nbElementSequence; i++) {
    if (maSequence[i].etat == LOW) {

      digitalWrite( previousMillis , 0);
      Serial.print("millis()- previousMillis =" );
      Serial.println( millis() - previousMillis);
      Serial.print(" previousMillis =" );
      Serial.println( previousMillis);

      // on regarde s'il faut l'allumer
      if ( cm < distanceCritique  ) {
        if ((millis() - previousMillis >= maSequence[i].debut) && ((millis() - previousMillis <= maSequence[i].fin))) {
          maSequence[i].etat = HIGH;
          digitalWrite(maSequence[i].numPin, HIGH);
        }
        else {
          // on est HIGH on regarde s'il faut éteindre, c'est uniquement après la fin
          if (((millis() - previousMillis > maSequence[i].fin)) ) {
            maSequence[i].etat = LOW;
            digitalWrite(maSequence[i].numPin, LOW);

          }

        }
        // end for
        previousMillis = millis();
      }
    }
    else {   }
  }
}

j’ai pensé ( mais peut-être à tort ) que int a = (cm - distanceCritique); était à placé quand on " regarde s’il faut l’allumer".
j’ai aussi remarqué que ( millis() - previousMillis) ne s’écrivait plus de la mème manière après avoir passé la main près du capteur , et aussi qu’une fois sur 11 (il y a 11 items dans le tableau) il donnait la valeur de 792 alors que les autres fois , il donne 1,2,ou 3 ?

Cependant jai toujours ce comportement erratique sur la console , et à l’allumage des leds.

Merci de votre aide .
Frida

bonjour,

a = (cm - distanceCritique);
  lireDistance();

il semble que vous n'ayez pas compris que la relation A = B + C dans un code n'est valable qu'au moment de l'exécution de la ligne. si vous modifiez la valeur de B ou C par la suite, il est évident que la relation n'est plus valable car la valeur de A ne changera que sur réassignation explicite dans le code.

D'où vient la variable cm? ou est-il calculé? A quoi sert d'exécuter lireDistance() si vous ne stockez pas le résultat pour un calcul futur!!!

static unsigned long topChronoMesure = 4294967154;

d'où vient cette valeur et pourquoi?

Édit: prenez le temps de commenter chaque ligne de code. Cela vous permettra de mieux étudier et comprendre le fonctionnement de celui-ci. Vous aurez plus de faciliter à détecter vos erreurs.
Chaques lignes de code à un but précis. Si vous ne pouvez pas expliquer ce qu'elle fait ainsi que son utilité par la suite, c'est que quelque chose vous a échappée. Prenez le temps de comprendre ce que vous faites.

Bonjour,
J’ai donc revu ma copie,
et vous ai mis les commentaires .

 int a; // distance qui sépare distance de la distance de declenchement des séquences d'action
unsigned long previousMillis = millis(); //  variable pour stocker la valeur du compteur au moment du                 début de l’action

struct elementSequence_t {  // déclaration de la tructure tableau
  byte numPin;              //  déclaration des numéros des pin
  unsigned long debut;       // pour déclrer le début (temps) des actions dans le tableau
  unsigned long fin;         //  pour déclrer la fin (temps) des actions dans le tableau
  byte etat;                 // déclaration etat HIGH ou LOW des sorties pin
};
elementSequence_t maSequence[] = {   //  Initialiser la structure elementSequence_t avec les variables  maSequence[]
  {11, 0ul, 500ul, LOW},             //  pin 11 , acton débute à 0 , fini à 500 , est stockée à LOW , : idem pour les 11 lignes
  {6, 500ul, 8500ul, LOW},
  {13, 500ul, 6500ul, LOW},
  {10, 8500ul, 38500ul, LOW},
  {9, 8500ul, 18500ul, LOW},
  {7, 18500ul, 26500ul, LOW},
  {6, 38500ul, 46500ul, LOW},
  {12, 46500ul, 56500ul, LOW},
  {3, 56500ul, 62500ul, LOW},
  {7, 56500ul, 64500ul, LOW},
  {8, 64500ul, 84500ul, LOW}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);  //variable de type octet (8 bits) qui stocke les elements du tableau

/* Partie "capteur ULTRASON"  */
int trig = 4;   //  declare numéro du pin de l'emetteur ultason
int echo = 5;    //  declare numéro du pin du recepteur ultason
long lecture_echo;   // lecture de l'echo (variable type long)
static int cm;              //  declaration d'une variable de type static int pour les cms
int distanceCritique = 11; // en cm   // declaration d'une variable de type int pour déclarer à 11 " la valeur critique qui déclenchera les actions)

/* Partie " fonctions " */

int lireDistance()         //  fonction qui permet de lire la distance correspondant au capteur ultrasons
{
  static unsigned long topChronoMesure = 4294967154;  //  variable liée à la fonction et qui persiste, nbre tres grand//4294967154 permet :lors du 1er appel où
  //l'équation est 0 - topChronoMesure > 100, permet de donner une valeur initiale de topChronoMesure
  //garantissant que le test est vrai. on fait donc appel à la notion de complément
  const unsigned long tempoMesure = 100ul;    // tempo qui vérifie si 100ms sont passées Avant de déclencher des ultrasons
  //(ça pourrait être mis avec des variables static dans la fonction de lecture de distance,)

  if (millis() - topChronoMesure >= tempoMesure)    // si tempo mesure est ecoulé
  {
    // on a attendu assez longtemps, faire la mesure
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cm = lecture_echo / 58;                    // lecture du capteur ultrasons
    return cm;                                 //  donne la ditance
  }
  else {
    return 100 ;  //  si le temps n'est pas écoulé, on retourne un nombre arbitraire (100 ici )
  }


  topChronoMesure = millis();                    // après la mesure on remet à jour le chronometre
}

void setup() {
  Serial.begin(9600);                          // vitesse 9600 , car à 115200 il y a des problemes sur le moniteur serie (caracteres bizzares)
  alors qu'à 9600, ça ne se produit pas
  {
  pinMode(trig, OUTPUT);    //emetteur en sortie
  pinMode(echo, INPUT);     // recepteur en entrée
  digitalWrite(trig, LOW);  // emmetteur en attente (LOW)
  delay (20);petit delay conseillé pour ce capteur
}

  for (byte i = 0; i < nbElementSequence; i++) {      // on fait défiler les pins
  pinMode(maSequence[i].numPin, OUTPUT);             // on met les pins en sortie
  digitalWrite(maSequence[i].numPin, maSequence[i].etat);  // on met la pin au niveau logique (  elle est LOW au démarrage )
  digitalWrite(maSequence[i].numPin, maSequence[i].debut);  //  on met le temps de début
  digitalWrite(maSequence[i].numPin, maSequence[i].fin);  //on met le temps de fin
}
}
  void loop()
  {
  a = (lireDistance() - distanceCritique);           // la variable "a" est la distance entre la distance totale lue et la distance où se déclenche l'action

  delay(100); // <-- sans le délai 100, les mesures sont bloquées au meme nombre (ça ne doit pas pouvoir avoir le temps de lire? )



  for (byte i = 0; i < nbElementSequence; i++)       // on fait tourner les pins
  {
    if (maSequence[i].etat == LOW)               //  si c'est eteint
    {

      digitalWrite( previousMillis , 0);          // on met le chronometre indexé sur milli jusqu'à present sur "0"
      Serial.print("millis - previousMillis =" );  // on ecrit la difference avec milli
      Serial.println( millis() - previousMillis);  // on ecrit sur le moniteur la valeur de cette difference
      Serial.print(" previousMillis =" );           //
      Serial.println( previousMillis);              // on ecrit sur le moniteur la valeur du chronometre indexé
      Serial.print("a =");
      Serial.println(a);                            // on ecrit sur le moniteur la valeur de la distance entre la distance totale lue et la distance où se déclenche l'action
      // puis on regarde s'il faut l'allumer
      if ( lireDistance() < distanceCritique  )       //si   la valeur de la distance entre la distance totale lue est inferieure à la distance où se déclenche l'action
      {
        if ((millis() - previousMillis >= maSequence[i].debut) && ((millis() - previousMillis <= maSequence[i].fin))) // et que on est
          // dans la période entre le début et la fin où doit se faire l'action
        {
          maSequence[i].etat = HIGH;      // l'état de la pin correspondante passe à HIGH
          digitalWrite(maSequence[i].numPin, HIGH);  //on met la pin au niveau logique  => ça allume
        }
        else                                   // sinon
        {
          // on est HIGH on regarde s'il faut éteindre, c'est uniquement après la fin
          if (((millis() - previousMillis > maSequence[i].fin)) )   // si le temps de la période où doit se faire l'action  est dépassé
          {
            maSequence[i].etat = LOW;      // l'état de la pin correspondante passe à LOW     //
            digitalWrite(maSequence[i].numPin, LOW);   // //on met la pin au niveau logique  => ça éteint

          }

        }
        // end for
        previousMillis = millis();  // et on remet le chronometre utilisé à la valeur de milli
        // et la boule recommence
      }
    }
    ///  else {   }
  }

}

Vos remarques m’ont bien été utiles dans mon approche d’écriture du code.
Je vous remercie de me donner votre avis.
Amicalement

Frida

Bonjour Frida,

Comme vous avez pu le constater, ajouter des commentaires permet de mieux mettre en évidence les incohérences du code. Je vais m'en servir pour argumenter quelques remarque ;).

unsigned long previousMillis = millis(); //  variable pour stocker la valeur du compteur au moment du début de l'action

Comme vous l'avez précisé en remarque, on stock la valeur au moment du début de l'action.
Il n'est donc pas nécessaire d'assigner la valeur de millis() au moment de la déclaration de previousmillis. On le fera au début de l'action.

static int cm;              //  declaration d'une variable de type static int pour les cms

Une variable déclarée static garde sa valeur entre deux appels de fonction ou elle a été déclarée.
Hors là, vous n'êtes pas à l'intérieur d'une fonction mais dans les déclarations dites globales (par opposition à locales donc dans une fonction). Ces variables globales ne perdent pas leur valeur et sont accessibles à tout endroit du code. L'ajout du mot clé static n'a aucun sens à cette position du code.

if (millis() - topChronoMesure >= tempoMesure)    // si tempo mesure est ecoulé
  {
    // on a attendu assez longtemps, faire la mesure
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cm = lecture_echo / 58;                    // lecture du capteur ultrasons
    return cm;                                 //  donne la ditance
  }
  else {
    return 100 ;  //  si le temps n'est pas écoulé, on retourne un nombre arbitraire (100 ici )
  }


  topChronoMesure = millis();                    // après la mesure on remet à jour le chronometre
}

Attention, l'utilisation de l'instruction return vous fait sortir de la fonction immédiatement. La dernière ligne de code (topChonoMesure = millis(); ) ne sera jamais exécutée car vous avez placé un return dans les deux cas du if.

La variable cm étant une variable globale, il serait plus propre d'utiliser une autre variable locale dans cette fonction puis de retourner sa valeur dans le but de la stocker dans cm. Mais on verra cela plus tard.

return 100 ;  //  si le temps n'est pas écoulé, on retourne un nombre arbitraire (100 ici )

Quitte a choisir un nombre arbitraire, prenez en un qui n'a aucune chance d'être un résultat possible. Vous retournez une variable de type int donc le choix de -1 me semble plus approprié. Vous saurez ainsi que le retour de la valeur -1 indiqué que la mesure est en attente.

digitalWrite(maSequence[i].numPin, maSequence[i].debut);  //  on met le temps de début
  digitalWrite(maSequence[i].numPin, maSequence[i].fin);  //on met le temps de fin

La valeur de value dans l'instruction digitalWrite(pin, value) ne peut pas être que LOW ou HIGH. Êtes vous sur de ce que vous faîtes ? À quoi servent ces lignes de code ?

 a = (lireDistance() - distanceCritique);

Haa... Enfin :slight_smile:
C'est plus logique comme cela.
Par contre pour le reste, cela ne fonctionne pas.
Vous devez comprendre que lorsque vous appelez la fonction lireDistance(), vous allez obtenir deux valeurs possibles:
Si la mesure a été faite la distance dans cm.
Si la mesure n'est pas disponible car en attente de tempoMesure, la valeur -1 (ou 100 actuellement dans ton code)
Il vous faut donc gérer ces deux cas.
Dans le premier vous pouvez travailler avec le résultat pour l'afficher.
Dans le second, ne rien faire car vous n'avez rien pour vos calculs suivants.

Bonsoir,Merci d'avoir pris le temps de bien m'expliquer le code. :slight_smile:
J'ai donc corriger en fonction de vos remarques, avec quelques modifications :

  • les leds après les relais s'allumant à LOW, j'ai interverti HIGH et LOW
  • j'ai mis un while pour faire tourner la loop qu'une fois , et ne la refaire tourner qu'à la prochaine rencontre d'un autre obstacle , évitant de la faire tourner plusieurs fois de suite pour le meme obstacle ( c'est ce que je veux que ça fasse ), à ce propos je rencontre une difficulté, c'est que ça s'arrete à 64500 au lieu des 84500.
  • autre problème , les leds témoins s'allument bien aux moments maSequence.debut) ( enfin il me semble ), mais ensuite ne s'éteignent plus , et restent allumées à la fin de la boucle loop .
    Et la led n°4 (pin 10) ne s'allume pas ( j'ai vérifié, elle n'est pas grillée )
    J'espère pouvoir compter sur vos conseils avisés pour me faire avancer .
    Amicalement
    Frida
    ps : comme il y a refus de ma réponse car plus de 9000 caractères, je vous le poste en 2 fois
 int a;                              // la variable "a" est la distance entre la distance totale lue et la distance où se déclenche l'action

unsigned long previousMillis ;    //  variable pour stocker la valeur du compteur au moment du début de l'action

struct elementSequence_t
{
  // déclaration de la tructure tableau
  byte numPin;                     //  déclaration des numéros des pin
  unsigned long debut;             // pour déclrer le début (temps) des actions dans le tableau
  unsigned long fin;              //  pour déclrer la fin (temps) des actions dans le tableau
  byte etat;                      // déclaration etat HIGH ou LOW des sorties pin
};
elementSequence_t maSequence[] =   //  Initialiser la structure elementSequence_t avec les variables  maSequence[]
{
  {11, 0ul, 500ul, HIGH},          //  pin 11 , acton débute à 0 , fini à 500 , est stockée à HIGH , : idem pour les 11 lignes
  {6, 500ul, 8500ul, HIGH},        //  car j'ai remarqué que les leds derriere  les relais s'allument quand c'est à LOW , et sont éteintes quand c'est à HIGH
  {13, 500ul, 6500ul, HIGH},
  {10, 8500ul, 38500ul, HIGH},
  {9, 8500ul, 18500ul, HIGH},
  {7, 18500ul, 26500ul, HIGH},
  {6, 38500ul, 46500ul, HIGH},
  {12, 46500ul, 56500ul, HIGH},
  {3, 56500ul, 62500ul, HIGH},
  {7, 56500ul, 64500ul, HIGH},
  {8, 64500ul, 84500ul, HIGH}
};
const byte nbElementSequence = sizeof(maSequence) / sizeof(maSequence[0]);         //variable de type octet (8 bits) qui stocke les elements du tableau

/* Partie "capteur ULTRASON"  */
int trig = 4;                     //  declare numéro du pin de l'emetteur ultason
int echo = 5;                     //  declare numéro du pin du recepteur ultason
long lecture_echo;                // lecture de l'echo (variable type long)
int cm;                          //  declaration d'une variable de type static int pour les cms
int distanceCritique = 11;        // en cm   // declaration d'une variable de type int pour déclarer à 11 " la valeur critique qui déclenchera les actions)

/* Partie " fonctions " */

int lireDistance()         //  fonction qui permet de lire la distance correspondant au capteur ultrasons
{
  static unsigned long topChronoMesure = 4294967154;        //  variable liée à la fonction et qui persiste, nbre tres grand//4294967154 permet :lors du 1er appel où
  //l'équation est 0 - topChronoMesure > 100, permet de donner une valeur initiale de topChronoMesure
  //garantissant que le test est vrai. on fait donc appel à la notion de complément
  const unsigned long tempoMesure = 100ul;                  // tempo qui vérifie si 100ms sont passées Avant de déclencher des ultrasons
  //(ça pourrait être mis avec des variables static dans la fonction de lecture de distance,)
  int cme;
  if (millis() - topChronoMesure >= tempoMesure)              // si tempo mesure est ecoulé
  {
    // on a attendu assez longtemps, faire la mesure
    digitalWrite(trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(trig, LOW);
    lecture_echo = pulseIn(echo, HIGH);
    cme = lecture_echo / 58;                                // // lecture du capteur ultrasons

    topChronoMesure = millis();                          // après la mesure on remet à jour le chronometre " topChronoMesure "   juste avant de faire la lecture
    return cme;                                            //  donne la ditance
  }
  else
  {
    return 5555 ;                   //  si le temps n'est pas écoulé, on retourne un nombre arbitraire (5555 ici , car si je met - 1 , cm<= distanceCritique calculé après
    //peut etre négatif jusqu'à -11 , donc je préfère 55555 nbre jamais atteint par la lecture du capteur qui va jusqu'à maxi 4 m
    //et facilement repérable
  }


}

void setup()
{
  Serial.begin(9600);                                      // vitesse 9600 , car à 115200 il y a des problemes sur le moniteur serie (caracteres bizzares)
  // alors qu'à 9600, ça ne se produit pas

  pinMode(trig, OUTPUT);                                   //emetteur en sortie
  pinMode(echo, INPUT);                                    // recepteur en entrée
  digitalWrite(trig, LOW);                                 // emmetteur en attente (LOW)
  delay (20);// petit delay conseillé pour ce capteur

  for (byte i = 0; i < nbElementSequence; i++)            // on fait défiler les pins
  {
    pinMode(maSequence[i].numPin, OUTPUT);                    // on met les pins en sortie
    digitalWrite(maSequence[i].numPin, maSequence[i].etat ) ;   // on met la pin au niveau logique (  elle est HIGH au démarrage )
  }

}
void loop()
{



  delay(100);                // <-- sans le délai 100, les mesures sont bloquées au meme nombre (ça ne doit pas pouvoir avoir le temps de lire? )

  cm = lireDistance();                                    // mesure la distance du capteur à l'obstacle

  if (cm <= distanceCritique)                            // si la distance est inférieure à la distance de déclenchement
  {

    previousMillis = millis();                              // avant la mesure on remet à jour le chronometre " previousMillis " juste avant de faire la lecture
    // on fait tourner les pins
    while (millis() - previousMillis <= maSequence[10].fin)  //  while pour faire un tour jusqu'à la fin de l'élément 10
    {


      for (byte i = 0; i < nbElementSequence; i++)             // on fait tourner
      {

        if (maSequence[i].etat == HIGH)                         //  si c'est eteint
        {


          Serial.print("millis - previousMillis =" );           // on ecrit la difference avec millis
          Serial.println( millis() - previousMillis);           // on ecrit sur le moniteur la valeur de cette difference
          Serial.print(" previousMillis =" );
          Serial.println( previousMillis);                  // on ecrit sur le moniteur la valeur du chronometre indexé
          Serial.print("a =");
          Serial.println(a);                               // on ecrit sur le moniteur la valeur de la distance entre la distance totale lue et la distance où se déclenche l'action
          // puis on regarde s'il faut l'allumer
          if ( cm < distanceCritique  )                   //si   la valeur de la distance entre la distance totale lue est inferieure à la distance où se déclenche l'action
          {
            if ((millis() - previousMillis >= maSequence[i].debut) && ((millis() - previousMillis <= maSequence[i].fin)))    // et que on est dans la période
              //  entre le début et la fin où doit se faire l'action
            {
              maSequence[i].etat = LOW;                               // l'état de la pin correspondante passe à LOW
              digitalWrite(maSequence[i].numPin, LOW);               //on met la pin au niveau logique LOW => ça allume
            }
            else                                                      // sinon
            {
              // on est LOW on regarde s'il faut éteindre, c'est uniquement après la fin
              if (((millis() - previousMillis > maSequence[i].fin)) )     // si le temps de la période où doit se faire l'action  est dépassé
              {
                maSequence[i].etat = HIGH;                                // l'état de la pin correspondante passe à HIGH    //
                digitalWrite(maSequence[i].numPin, HIGH);                //on met la pin au niveau logique HIGH => ça éteint

              }

            }



          }
        }

      }
    }
  }  else {   }
}  // et la boucle recommence

Mais non si le temps entre deux lecture de distance n’est pas écoulé, c’est qu’il s’est passé peu de temps et que votre environnement a sans doute peu changer... il faut simplement retourner la distance de la dernière lecture, pas un nombre inventé... c’est. Pour cela que dans la fonction cm était static et que l’on s’assurait d’avoir un topChronoMesure chois -i pour que lors du premier appel, même si millis() vaut 0 ou 1 on fasse une première lecture quand même afin d’initialiser cm... (et donc faut virer delay(100))

on avait déjà travaillé cela, pourquoi vous ne réutilisez qu’à moitié le travail précédent.. ?

Pour les caractères bizarres sur le moniteur série à 115200 c’est sans doute parce que vous n’avez pas réglé la vitesse du moniteur série et qu’il reste en 9600...il y a un bouton pop up en bas du moniteur série, choisissez 115200 et tout ira bien

On avait travaillétat sur la notion de machine à état, je ne vois rien de tel ici... juste un hack pour rester dans une seule et même loop...