Problème Moteur Nema 17 (0.59nm) et driver Tb6600 sur arduino uno

OK trop bien ! Je commence a saisir le fonctionnement du tableau, en effet c’est plus clair.
J’ai essayer de le prendre en main et voila ce que j’ai pour l’instant.

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};



void setup(){
  startMillis = millis();  //initial start time
}

void loop(){

Evenement evenement[]={
    (0,         800.0, 1500.0,  1,            0.0,      0.0,  0), // Le moteur 1 démarre seul 
    (5000,       0.0,      0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s

  
};
for (mouvement = 0; mouvement < N; mouvement++)
{
  if (millis() - startMillis < evenements[mouvement].temps; // attente de l'instant de début du mouvement
}
  {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
       stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
       stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);

    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

Mais j’ai le message d’erreur suivant : ‘mouvement’ was not declared in this scope
Et je ne vois pas où/comment je declare ‘mouvement’.

EDIT : j’ai essayé la commande ‘byte mouvement’ et en modifiant deux trois trucs mais je reviens à la même erreur :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};



void setup(){
  startMillis = millis();  //initial start time
}

void loop(){

Evenement evenements[]={
    (0,         800.0, 1500.0,  1,            0.0,      0.0,  0), // Le moteur 1 démarre seul 
    (5000,       0.0,      0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s

  
};
for (byte mouvement = 0; mouvement < 2; mouvement++)
{
  if (millis() - startMillis < evenements[mouvement].temps); // attente de l'instant de début du mouvement
}
  {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
       stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
       stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);

    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

Et est-ce que je dois bien mettre le tableau dans void loop ?

EDIT EDIT :

J’ai enlever le byte mouvelent et je l’ai déclaré au début en int mouvement = 0, comme ceci :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 23, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 25, 24);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;


void setup(){
  startMillis = millis();  //initial start time

  
}

void loop(){

Evenement evenements[]={
    (0,         800.0, 1500.0,  1,            0.0,      0.0,  0), // Le moteur 1 démarre seul 
    (5000,       0.0,      0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s

  
};
for ( mouvement = 0; mouvement < 2; mouvement++)
{
  if (millis() - startMillis < evenements[mouvement].temps); // attente de l'instant de début du mouvement
}
  {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
       stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
       stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);

    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

Je n’ai plus de message d’erreur, mais il ne se passe rien au niveau des moteurs…

Réponse trop rapide de ma part, je n’avais guère le temps de bien vérifier, mais cela pouvait te permettre de voir cette structure globale, et l’utilisation de tableau.

Je repart sur le dernier code:

  • le tableau evenements peut se mettre global en dehors de loop ou dedans cela n’a pas une importance au niveau de son utilisation vu que c’est des constantes et qu’il n’est utilisé que dans loop. Si ce n’était pes des constantes, loop devrait l’initialiser à chaque passage. UNe fois que le programme tourne, il faut faire la chorégraphie et plus cette déclaration est en haut, plus on y a accès rapidement. Il faut toutefois qu’elle soit après la déclaration de la structure vu qu’elle l’utilise. Le mieux est alors de la mettre en haut. Je n’ai pas vérifié, mais il est possible que pour accéder aux variables globales, ce soit plus économique et plus rapide que si elle sont locales à loop. Autant la mettre le plus au début possible.
  • currentMillis n’est pas utilisé, je l’ai enlevé.
  • pour la boucle principale, je l’ai complètement réagencé (je ne dis pas que cela est juste maintenant, mais c’était complètement faux avant).

A) Avec une boucle for, soit on ne fait la choré qu’une seule fois, et on mettra la boucle for dans le setup, soit on la répète et on la mettra dans loop, mais en réinitialisant la variable startMillis avant le for.
Pour la boucle, on va faire une itération pour chaque départ de mouvement (boucle for fait N itérations). Tant que l’instant de départ du mouvement n’est pas arrivé, on attend, mais il faut cependant appeler les fonctions run des moteurs au cas ou ils auraient besoin de tourner. C’est donc une boucle d’attente while qu’il faut.
Si l’instant du nouveau moment est arrivé, on sort de la boucle d’attente, on lance le ou les mouvements
La boucle est terminé, on a lancé les mouvements au bon moment. On va donc refaire cette boucle pour le mouvement suivant.

B) On peut aussi profiter de loop qui boucle sans arrêt. On va alors ne rien faire tant que l’instant du mouvement n’est pas atteint, et si il l’est, on gère les départs des moteurs. Puis après dans tous les cas on appelle les fonctions run. Dans cette boucle, il faut incrémenter mouvement. Cela va faire un programme plus courant avec une loop qui ressemblera à:

loop() {
  if (millis() - startMillis > evenements[mouvement].temps) // le temps est atteint, on s'occupe du mouvement
  {
     if (evenements[mouvement].vitesseMoteur1 > 0)....
     if (evenements[mouvement].vitesseMoteur2 > 0)....
     mouvement++; // on a traité ce mouvement, on passe au suivant
  }
 stepper1.run(); // Qu'il tourne ou pas
 stepper2.run();
}

Les deux méthodes sont quasi équivalentes.

En reprenant plutôt ce qui a été fait, et en ne faisant la choré plusieurs fois:

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 23, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 25, 24);

unsigned long startMillis;

struct Evenement
{
  uint32_t temps;
  float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
};

Evenement evenements[] = {
  (0,         800.0, 1500.0,  1,           0.0,    0.0,  0), // Le moteur 1 démarre seul
  (5000,        0.0,    0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
};


void setup() {
}


void loop() {
  startMillis = millis();  //initial start time
  for (int mouvement = 0; mouvement < 2; mouvement++)
  {
    while (millis() - startMillis < evenements[mouvement].temps) // attente de l'instant de début du mouvement
    {
      stepper1.run(); // Qu'il tourne ou pas
      stepper2.run();
    }
    if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
    if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
  }
}

Soit cela marche comme on le voudrait, mais cela arrive très rarement, soit il faut débugger. La méthode la plus courant consiste à mettre un Serial.begin dans le setup, et d’utiliser des Serial.print a certains endroits pour afficher:

  • que l’on passe par ce point
  • le contenu de certaines variables (dans notre cas mouvement est intéressante, mais il peut y en avoir d’autres)

Pour la lecture du tableau, il y a aussi une autre possibilité de "voir la fin sans compter. Si le tableau décrit tous les mouvements et qu’il y en a que deux, ce n’est pas un problème. Mais si il y en a une centaine, si on se trompe en croyant qu’il y en a moins, les derniers mouvement ne seront pas exécutés et si on croit qu’il y en a plus on risque de lire en dehors du tableau. Mis au moment de l’exécution, le micro ne peut pas le signaler et on risque d’avoir des mouvements en trop qui sont du n’importe quoi. On peut faire ainsi:

  • on rempli le tableau en se moquant du nombre de mouvements
  • Pour indiquer que c’est la fin, on rajoute un mouvement identifé comme marque de fin, par exemple en mettant le temps à 0, et on rajoute un mouvement qu’avec des 0.

Cela va donner quelque chose du type:

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 23, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 25, 24);

unsigned long startMillis;

struct Evenement
{
  uint32_t temps;
  float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
};

Evenement evenements[] = {
  (0,         800.0, 1500.0,  1,           0.0,    0.0,  0), // Le moteur 1 démarre seul
  (5000,        0.0,    0.0,  0,         800.0, 1500.0,  1), //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
  (0,           0.0,    0.0,  0,           0.0,    0.0,  0)  // Marque de fin
};


void setup() {
}


int mouvement = 0;

void loop() {
  startMillis = millis();  //initial start time
  {
    while (millis() - startMillis < evenements[mouvement].temps) // attente de l'instant de début du mouvement
    {
      stepper1.run(); // Qu'il tourne ou pas
      stepper2.run();
    }
    if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
    if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
    mouvement++;
    if (evenements[mouvement].temps == 0) // Le prochain mouvement c'est une marque de fin 
      mouvement = 0; // on recommence au début
  }
}

A vérifier

Ok, alors réponse un peu rapide, (j’était sur le point de me coucher mais j’avais trop envie d’essayer les codes). Je vais regarder un peu mieux dans la matinée.

Premier cas : avec la boucle for

Juste pour info, dans le code final il y aura quelque action en plus de la chorégraphie, comme une musique qui se lance via un module YX5300 juste avant la chorégraphie et joue pendant (j’ai tésté, normalement ça marche, des relais et un autre moteur avec une chorégraphie beaucoup plus simple.
dans l’ordre ca donne à peu près :
mp3 PLAY => relai1 HIGH =>chorégraphie 4 moteurs => relai1 LOW => relai2 HIGH => chorégraphie 1 moteur => relai 2 LOW =>relai3 High => relai3 LOW => mp3 PLAY => relai1 HIGH …
et ainsi de suite, donc en loop.
Je dis cela par rapport à

vileroi:
A) Avec une boucle for, soit on ne fait la choré qu’une seule fois, et on mettra la boucle for dans le setup, soit on la répète et on la mettra dans loop, mais en réinitialisant la variable startMillis avant le for.

si jamais ca devait être une gêne.
Donc j’ai tester ça :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 3, 2);
AccelStepper stepper2(AccelStepper::DRIVER, 5, 4);

unsigned long startMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    (0,         800.0, 1500.0,  1,            0.0,      0.0,  0), // Le moteur 1 démarre seul 
    (5000,       0.0,      0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
};

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

void loop(){

   startMillis = millis();

for ( int mouvement = 0; mouvement < 2; mouvement++)
{
  while (millis() - startMillis > evenements[mouvement].temps); // attente de l'instant de début du mouvement
}
  {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
       stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);

    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

Mais il ne se passe rien. J’ai essayer aussi en deplaçant la ligne for ( int mouvement = 0; mouvement < 2; mouvement++); dans le setup mais pareil.
Je regarde à nouveau demain matin.

Deuxième cas :

la première fois que je l’ai modifié, en gardant if (millis()… et en ajoutant l’increment,
le moteur 1 c’est mis à tourner de manière lente et très saccadé et le 2 ne tournais pas ( les deux ne respectant pas les temps et le nombre de tours). Mais je ne sais plus ce que j’ai ecris car quand je met ce code :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 3, 2);
AccelStepper stepper2(AccelStepper::DRIVER, 5, 4);

unsigned long startMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    (0,         800.0, 1500.0,  1,            0.0,      0.0,  0), // Le moteur 1 démarre seul 
    (5000,       0.0,      0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
    
};

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
}

void loop(){

   if (millis() - startMillis > evenements[mouvement].temps)
  {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  
}

ca ne fait rien. Pareil je re regarde demain matin
3eme cas :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 23, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 25, 24);

unsigned long startMillis;

struct Evenement
{
  uint32_t temps;
  float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
};

Evenement evenements[] = {
  (0,         800.0, 1500.0,  1,           0.0,    0.0,  0), // Le moteur 1 démarre seul
  (5000,        0.0,    0.0,  0,         800.0, 1500.0,  1), //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
  (0,           0.0,    0.0,  0,           0.0,    0.0,  0)  // Marque de fin
};


void setup() {
}


int mouvement = 0;

void loop() {
  startMillis = millis();  //initial start time
  {
    while (millis() - startMillis < evenements[mouvement].temps) // attente de l'instant de début du mouvement
    {
      stepper1.run(); // Qu'il tourne ou pas
      stepper2.run();
    }
    if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
    if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
    mouvement++;
    if (evenements[mouvement].temps == 0) // Le prochain mouvement c'est une marque de fin
      mouvement = 0; // on recommence au début
  }
}

il ne se passe rien aussi. Encore: je m’y replonge demain

Le fait qu’il y ait d’autres dispositifs ne bloque rien,le programme déclenche une action à des instants précis. Si il s’agit de moteur, on va lui donner 3 paramètres, ce qui occupe pour l’instant 3 colonnes dans la table. La première colonne c’est le temps, si on a deux pas à pas, cela fait 7 colonnes (1+3+3). Si on veut faire coller un relais, on rajoute une colonne, avec par exemple 1 pour coller, 0 pour repos. Pareil pour la musique, je crois avoir vu qu’il suffisait d’envoyer une commande pour démarrer la musique. On aura des lignes en plus du style:

     digitalWrite(pinRelai, evenements[mouvement].relais);
     if (evenements[mouvement].musique > 0) // On demande à cet instant un départ de la musique
          Serial?.print(<commande>); // Demande pour jouer le morceau

J’ai noté une loterie dans les pins des moteurs:

AccelStepper stepper1(AccelStepper::DRIVER, 3, 2);

indique au gestionnaire du moteur qu’il y a un moteur qui utilise un driver (par exemple un TB6600) commandé par deux broches step sur la broche 3, et dir sur la broche 2. Pour que le moteur tourne, il faut que les commandes de l’Arduino (les broches) aillent sur les bonnes commandes du TB6600. Mais je note en fonction des posts des broches plutôt aléatoires (elles peuvent changer au fur et à mesure de l’évolution et de la modification de la maquette, mais difficilement à chaque fois). Si on intervertit par exemple dir et step le moteur va progresser d’un pas tous les deux changements de pas. si dir est sur la mauvaise broche, le poteur ne va tourner que dans un seul sens. Si dir et steps sont ailleurs, le moteur ne tourne pas. Je note un moteur en:
dir=2, step=3 (post 1, 9, 11, 13, 20)
dir=3, step=2 (post 23)
dir=4, step=5 (post 7)
dir=53, step=52 (post 18)
dir=23, step=23 (post 20, 21, 23) ceci ne permet pas le fonctionnement quel que soit le câblage
Le deuxième moteur se ballade sur les broches (2, 3), (8, 9), (8, 28), (25, 24)…
Comment sont branchés les moteurs?
Quelle carte Arduino est utilisée? Méga?


Suite au prochain moment de libre, j’ai de la famille à m’occuper.

Oui les pins varie parce que je modifie la maquette assez souvent, parfois avec uno, parfois avec mega.
Du coup j'ai pris l'habitude d'avoir un code test pour check les pins. Donc oui oui pin 23 et 23 ça marchait pas, mais les derniers codes envoyés on été vérifiés.

Pour le code, il faut avoir une structure qui teste si il y a quelque mouvement à démarrer, si c'est le cas, cela ne va pas durer longtemps. sinon, il faut boucler sur les deux fonctions run.

Dans le premier code, il y a une erreur de boucle, on ne peut pas attendre qu'il y ait un ordre ans rien faire, et en plus la condition est à l'envers. On laisse tomber.

Le deuxième code dit
repéter indéfiniment (loop)

  • si il y un mouvement à faire on le déclenche
  • run
    On a bien la boucle qui va régulièrement appeler run

le troisième code est le même avec la condition inversée
repéter indéfiniment (loop)

  • si il n'y a pas de mouvement à faire on appelle run
  • on déclenche le mouvement à faire

Il vaut peut être mieux garder le deuxième qui est plus "standard". Cela simplifie pour une autre personne qui viendrait lire le code.

Mais les deux codes ,n'ont pas les mêmes pins. Comme c'est à peu près au même moment, il y en a forcément un qui ne fonctionne pas.


Va arriver un moment ou il faudra passer au débuggage. quand un code ne fait pas ce que l'on veut un Serial.println permet de voir si on passe à un point du programme ou pas, et de voir la valeur d'une ou plusieurs variable. Ainsi si la valeur est correcte, le problème se situe après, sinon elle se situe avant.

Ok alors j’en suis là :
(les pin 2,3,4, et 5 ont été testé)

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    (0,         800.0, 1500.0,  1,            0.0,      0.0,  0), // Le moteur 1 démarre seul
    (5000,       0.0,      0.0,  0,         800.0, 1500.0,  1) //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
   
};

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

void loop(){

   if (millis() - startMillis > evenements[mouvement].temps)
   Serial.println ("go");
  {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
 
}

Ca fait comme hier soir, le moteur 1 est lent et saccadé, le 2 à l’arrêt. Pas de respect du tableau.
Et le moniteur imprime “go” toute les millisecondes ( en tout cas pas quand il devrait à 5000 ms par exemple)
Donc un premier problème se situe sans doute sur la ligne if (millis() - startMillis > evenements[mouvement].temps)
. Je continue de regarder

EDIT
en fait plutôt que la ligne " if (millis… " il s’agirait plutôt de l’accès a la lecture du temps dans le tableau.

EDIT EDIT

Ok alors j’ai essayer en remplaçant les parenthèses du tableau pour des “{ }”

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    {5000,         800.0, 1500.0,  1,            0.0,      0.0,  0}, // Le moteur 1 démarre seul
    {12000,       0.0,      0.0,  0,         800.0, 1500.0,  1} //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
   
};

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

void loop(){
   if (millis() - startMillis >= evenements[mouvement].temps)
   {
   Serial.println ("go");
    {
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
 
}
}

Maintenant, les temps du tableau sont respectés mais seulement par le moteur 1 qui ne fait qu’un seul pas.

Le premier programme présent une erreur de bloc. C'est assez facilement détectable surtout si on met les { systématiquement sur une nouvelle ligne au lieu de les mettre à la fin d'une ligne.
Il y a principalement deux conventions pour une fonction:

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

et

void setup()
{
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

Dans la deuxième écriture, cela prend une ligne en plus, mais les accolades qui vont par paire sont alignées verticalement. Du coup la partie entre accolade apparait plus facilement. La plupart des codes sur ce forum utilise la première convention, je trouve que c'est dommage, c'est plus difficile à voir pour celui qui ne connait pas le code. C'est entre autre la présentation par défaut de l'IDE pour un programme vide.

Sous l'IDE, cnt-T permet de réaligner les codes, rajoute des espaces qui sont pratiques. On conseille, avant de poster u code de faire un cnt-T. Cela évite aussi les

}
}
}
}

Ou l'on ne sait plus quel bloc se ferme.
Cela permet aussi de savoir si un bloc qui a été ouvert par { est bien refermé et ou car c'est aligné verticalement.

Enfin, dans l'IDE, placer le curseur juste avant ou juste après ( ) { ou } entoure le caractère correspondant ce qui permet de savoir ou l'on en est (en particulier si on a des conditions complexes).

Je reprend le loop avec { seule et après avoir réaligné avec cnt-T:

void loop()
{
  if (millis() - startMillis > evenements[mouvement].temps)
    Serial.println ("go");
  {
    if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
    if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
  stepper1.run(); // Qu'il tourne ou pas
  stepper2.run();
}

On voit mieux ainsi que la ligne
Serial.println ("go");
est en retrait par rapport à la ligne qui suit. La ligne qui suit, qui ne contient que { n'est donc pas dans le même bloc que le Serial.println. La condition (le if) ne va donc porter que sur la ligne Serial.println et pas sur le bloc délimité par { }. Si je sépare les blocs entre eux par des lignes vides, cela donnerait:

void loop()
{


  if (millis() - startMillis > evenements[mouvement].temps)
    Serial.println ("go");


  {
    if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
    if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }


  stepper1.run(); // Qu'il tourne ou pas


  stepper2.run();

}

Il s'en suit qu'à chaque tour de loop on traite tout le bloc délimité par { } et en particulier l'instruction

 mouvement++; // on a traité ce mouvement, on passe au suivant

Ce code va faire partir le moteur, comme la boucle loop ne va durer que quelque ms, mouvement vaudra 0 puis 1 puis 2... très rapidement. On va donc lancer les deux moteurs puis au bout de 65536 boucles mouvement sera de nouveau à 0 (il dépasse et revient à -32768 juste après 32785 car c'est un entier qui déborde), cela relance le moteur 1, et 2...
Comme la boucle est plus longue que l'espace qu'il faudrait entre les deux appels à run, il peut se passer n'importe quoi.

Si le bloc était dans la condition, on aurait du avoir après cnt-T

void loop()
{
  if (millis() - startMillis > evenements[mouvement].temps)
    Serial.println ("go");
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
  stepper1.run(); // Qu'il tourne ou pas
  stepper2.run();
}

Ce qui est bon:

void loop()
{
  if (millis() - startMillis > evenements[mouvement].temps)
  {
    Serial.println ("go");
    if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
    if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
  stepper1.run(); // Qu'il tourne ou pas
  stepper2.run();
}

Et la on voit bien que l'affichage doit être fait à chaque mouvement seulement.
On peut ici en profiter pour regarder la valeur de mouvement en mettant plutôt:

Serial.println (mouvement);

Ok alors j'ai essayer en remplaçant les parenthèses du tableau pour des "{ }"

Là je crois que c'est toi qui a raison. Vu que le compilateur n'a pas râlé avec des ( ), je ne me suis pas méfier. Mais pour initialiser une structure, il faut des { }.

A suivre...

EDIT
Ok j’ai cleané le code.

Je comprend pas bien ça :

vileroi:
Ce code va faire partir le moteur, comme la boucle loop ne va durer que quelque ms, mouvement vaudra 0 puis 1 puis 2… très rapidement. On va donc lancer les deux moteurs puis au bout de 65536 boucles mouvement sera de nouveau à 0 (il dépasse et revient à -32768 juste après 32785 car c’est un entier qui déborde), cela relance le moteur 1, et 2…
Comme la boucle est plus longue que l’espace qu’il faudrait entre les deux appels à run, il peut se passer n’importe quoi.

EDIT EDIT
J’ai oublié de preciser que le void loop n’effectue qu’une fois les mouvements (bons et mauvais) dans les précédents codes.

En changeant quelque “{ }” dans la loop :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    {5000,         800.0, 1500.0,  1,            0.0,      0.0,  0}, // Le moteur 1 démarre seul
    {12000,       0.0,      0.0,  0,         800.0, 1500.0,  1} //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
   
};

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

void loop(){
   if (millis() - startMillis >= evenements[mouvement].temps)
   {
   Serial.println ("go");
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
 

}

Le premier moteur tourne comme il faut (bon temps, bonne vitesse…) et le deuxième ne fait qu’un seul pas a la 12eme seconde.

En changeant le tableau comme ceci :

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    {5000,         800.0, 1500.0,  1,            800.0, 1500.0,  1}, // Le moteur 1 démarre seul
    {7000,       0.0,      0.0,  0,         0.0,      0.0,  0,} //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
   
};

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

void loop(){
   if (millis() - startMillis >= evenements[mouvement].temps)
   {
   Serial.println ("go");
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
 

}

Les deux moteur font 1 tours a la 5 ème seconde, mais le deuxième moteur fait un tours en arrière à la 7ème seconde.

Il me semble que soit les deux moteur ne sont pas indépendant et qu’il y à un problème avec le fait d’écrire if (evenements[mouvement].vitesseMoteur1 > 0) car dès que la vitesse inscrite est a zéro, ca l’arrête. Logique.
Ou plutôt il faut vieux ne pas mettre la vitesse la vitesse à zéro et laisser le nbPasMoteur sur sont nombre d’avant pour ne pas qu’il bouge.

En remodifiant les vitesse dans les vitesses et les nbPasMoteur dans le tableau

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
uint32_t temps;
float vitesseMoteur1;
float accelerationMoteur1;
uint8_t nbPasMoteur1;
float vitesseMoteur2;
float accelerationMoteur2;
uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    {5000,         800.0, 1500.0,  1,            0.0,      0.0,  0}, // Le moteur 1 démarre seul
    {5500,       0.0,     1500.0,  1,         800.0, 1500.0,  1}, //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
    {10000,       800.0, 1500.0,  2,         800.0, 1500.0,  2}
};

void setup(){
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.println (millis());
}

void loop(){
   if (millis() - startMillis >= evenements[mouvement].temps)
   {
   Serial.println ("go");
     if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
     if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
    mouvement++; // on a traité ce mouvement, on passe au suivant
  }
  
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
}

Là les deux premiers mouvements sont correct (et les moteurs tournent indépendamment) mais le troisième non. le moteur 1 ne fait rien et le moteur 2 fait un tour en arrière.

EDIT EDIT EDIT

quand je rajoute une ligne au tableau, pareil :
les deux premiers mouvements sont correct (et les moteurs tournent indépendamment) mais le troisième non. le moteur 1 ne fait rien et le moteur 2 fait un tour en arrière.

Evenement evenements[]=
{
    {5000,        800.0, 1500.0,  1,          800.0, 1500.0,  0}, 
    {5500,        800.0, 1500.0,  1,          800.0, 1500.0,  1}, 
    {10000,       800.0, 1500.0,  2,          800.0, 1500.0,  3},
    {10000,       800.0, 1500.0,  4,          800.0, 1500.0,  4}
};

Il dois y avoir quelque chose à modifier dans le bloc de la loop.

J’ai essayé quelque chose comme ca :

{
  if (millis() - startMillis >= evenements[mouvement].temps)
    {
     Serial.println ("go");
       if ((evenements[mouvement].vitesseMoteur1 > 0) && (evenements[mouvement].vitesseMoteur2 > 0)) // On demande à cet instant un départ de mouvement sur le moteur 1
         stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1*turn);
         stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2*turn);
       mouvement++; // on a traité ce mouvement, on passe au suivant
    }
  
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
}

Mais ca fait bugger le premier moteur au deuxième mouvement

Suite…

Maintenant, les temps du tableau sont respectés mais seulement par le moteur 1 qui ne fait qu’un seul pas.

La structure me semble bonne, mais cela ne donne pas l’effet escompté, c’est la phase de débuggage qui commence. Je n’avais pas pu tester le code, n’ayant pas les moteurs sous la main, et j’avais de la famille…

Je vis faire quelques modifications:

  • passer à 115200 bauds. Dans ce forum, on considère que 9600bauds c’est de la préhistoire, et qu’on peut aller plus vite pour pas cher. Si on passe l’ide à 115200 on ne le fait qu’une fois, l’ide mémorise le dernier choix. Passer à 115200 bauds permet à plus de personnes de tester sans changer.
  • je remplace le “Go” par l’affichage de la valeur de mouvement que je remets à sa place
  • je divise le nombre de pas par 10 et les temps par 10. Pour les essais, j’attends moins et quand cela fonctionnera, on multiplie tout par 10. J’en profite pour réaligner les nombres en colonnes

Cela donne:

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
  uint32_t temps;
  float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[] = {
  {500,      80.0, 150.0,  1,          0.0,   0.0,  0}, // Le moteur 1 démarre seul
  {1200,      0.0,   0.0,  0,         80.0, 150.0,  1} //on laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
};

void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.print ("millis() = ");
  Serial.println (millis());
}

void loop()
{
  if (millis() - startMillis >= evenements[mouvement].temps)
  {
    Serial.print("mouvement = ");
    Serial.println (mouvement);
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

On obtient à la console:

millis() = 0
mouvement = 0
mouvement = 1
mouvement = 2

On ne devrai pas avoir mouvement = 2, il n’y a que deux mouvements programmés le 0 et le 1. Quand on fait le mouvement 1, on a encore une incrémentation qui cherche le mouvement suivant, le 2 qui n’existe pas. On lit en dehors du tableau, et on peut lire n’importe quoi. Il faut donc arrêter la lecture . C’était fait avec

    if (evenements[mouvement].temps == 0) // Le prochain mouvement c'est une marque de fin
      mouvement = 0; // on recommence au début

Mais on ne l’a pas encore remis dans la choré. Pour l’instant, on va tout bloquer si mouvement=2 par:

  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))

Si on exécute, on a bien les deux mouvements, mais le fonctionnement n’est toujours pas bon.

Il y a par ma faute une erreur de bloc. Il est bon dans ce cas de ne mettre qu’une instruction par ligne, et il y en a plusieurs dans la demande d’avancer des moteurs. Je corrige pour avoir qu’une instruction par ligne. Voici loop:

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))
  {
    Serial.print("mouvement = ");
    Serial.println (mouvement);
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1); 
        stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1); 
        stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2); 
        stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2); 
        stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

On refait un petit cnt-T:

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))
  {
    Serial.print("mouvement = ");
    Serial.println (mouvement);
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
      stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
      stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
      stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
      stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

et c’est la que 4 lignes stepper… ont changé de place par rapport à ce que je voulais. Le if ne porte que sur la première instruction. Il faut mettre des { }:

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))
  {
    Serial.print("mouvement = ");
    Serial.println (mouvement);
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      {
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
        stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
        stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      {
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
        stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
        stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      }
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

Suite et fin

Cela ne fonctionne toujours pas. Peut être que je ne passe pas les bons paramètres. on teste:

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))
  {
    Serial.println();
    Serial.println();
    Serial.print("mouvement = ");
    Serial.println(mouvement);
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      {
        Serial.println("moteur 1");
        Serial.print("  vitesse = ");
        Serial.println(evenements[mouvement].vitesseMoteur1);
        Serial.print("  acceleration = ");
        Serial.println(evenements[mouvement].accelerationMoteur1);
        Serial.print("  nbTours = ");
        Serial.println(evenements[mouvement].nbPasMoteur1);
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
        stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
        stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      {
        Serial.println("moteur 2");
        Serial.print("  vitesse = ");
        Serial.println(evenements[mouvement].vitesseMoteur2);
        Serial.print("  acceleration = ");
        Serial.println(evenements[mouvement].accelerationMoteur2);
        Serial.print("  nbTours = ");
        Serial.println(evenements[mouvement].nbPasMoteur2);
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
        stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
        stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      }
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
  }
}

On obtient:

millis() = 0

mouvement = 0
moteur 1
vitesse = 80.00
acceleration = 150.00
nbTours = 1

mouvement = 1
moteur 2
vitesse = 80.00
acceleration = 150.00
nbTours = 1

C’est correct. Peut être c’est les fonctions run qui ne sont pas appelées assez souvent:

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))
  {
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      {
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
        stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
        stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      {
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
        stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
        stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      }
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
    stepper1.run(); // Qu'il tourne ou pas
    stepper2.run();
    Serial.println(random(10));
  }
}

J’aime bien pour voir si on passe afficher un nombre au hasard entre 0 et 9 car si on affiche un caractère consant, on ne voit pas si cela défile ou pas.
Et là j’obtiens que 2 valeurs

7
9

C’est donc ces fonctions qui ne sont pas appelées. En regardant le code, on voit qu’elles sont dans le if. Il faut les sortir:

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 2))
  {
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      {
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
        stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
        stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      {
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
        stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
        stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      }
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
  }
  stepper1.run(); // Qu'il tourne ou pas
  stepper2.run();
  Serial.println(random(10));
}

Maintenant, j’ai bien un défilement de chiffres qui prouve que j’appelle bien les fonctions run, et l’anlyseur me donne un chronogramme qui doit être bon.

Je comprend pas bien ça :

Ce code va faire partir le moteur, comme la boucle loop ne va durer que quelque ms, mouvement vaudra 0 puis 1 puis 2… très rapidement. On va donc lancer les deux moteurs puis au bout de 65536 boucles mouvement sera de nouveau à 0 (il dépasse et revient à -32768 juste après 32785 car c’est un entier qui déborde), cela relance le moteur 1, et 2…
Comme la boucle est plus longue que l’espace qu’il faudrait entre les deux appels à run, il peut se passer n’importe quoi.

Dans le code en question, mouvement++ était appelé sans arrêt. il va donc s’incrémenter toutes les ms et va repasser régulièrement par 0. Cela va relancer le moteur qui ne va pas faire ce qu’il faut.

Pour un entier mouvement++ incrémente mouvement si c’est possible. Mais si mouvement vaut 32767, c’est l’entier le plus grand que l’on peut représenter. Il n’est donc pas possible d’en avoir un plus grand. Et faire dans les entiers 16 bits 32767+1 donne -32768. En ajoutant régulièrement 1, on va un jou repasser par 0. En fait on y passe toutes les 65536 fois.

En fait cela ne se produit pas parce que certainement une valeur en dehors du tableau va donner un temps tellement grand que pour nous, cela bloque. Mais ça je ne l’ai vu qu’après.

En changeant quelque “{ }” dans la loop…
Cela remet en place les fonctions run, mais il reste le démarrage du moteur qui n’est pas bon. Quand le code n’est pas correcte, il se passe un peu n’importe quoi, et c’est des fois long de savoir ce qu’il fait. Dans ce cas plutôt que de chercer le pourquoi, on cherche à faire en sorte qu’il fasse ce que nous voulons.
Il existe quand même des fois on on veut savoir pourquoi.

La remise en place correcte des fonction run permet au moteur 1 d’avancer.


Il y a quoi que l’on fasse un problème de blocs (par ma faute) dans le lancement de moteurs. Cela est rectifié dans mon dernier post. Il y avait deux erreurs, en en corrigeant qu’une on boite.

Du coup le code devient:

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 2, 3);
AccelStepper stepper2(AccelStepper::DRIVER, 4, 5);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
  uint32_t temps;
  float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
};
int mouvement = 0;

Evenement evenements[]={
    {5000,     800.0, 1500.0,  1,           0.0,    0.0,  0}, // Le moteur 1 démarre seul
    {5500,       0.0,    0.0,  1,         800.0, 1500.0,  1}, // On laisse le moteur 1 continuer, et on rajoute le moteur 2 après 5s
    {10000,    800.0, 1500.0,  2,         800.0, 1500.0,  2}
};
void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  startMillis = millis();
}

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 3))
  {
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
      {
        stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
        stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
        stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
      }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
      {
        stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
        stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
        stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
      }
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
  }
  stepper1.run(); // Qu'il tourne ou pas
  stepper2.run();
}

Evenement evenements=
{
{5000, 800.0, 1500.0, 1, 800.0, 1500.0, 0},
{5500, 800.0, 1500.0, 1, 800.0, 1500.0, 1},
{10000, 800.0, 1500.0, 2, 800.0, 1500.0, 3},
{10000, 800.0, 1500.0, 4, 800.0, 1500.0, 4}
};

Attention, les deux derniers évènements ont la même date, le deuxième va sans doute écraser le premier.


Il reste encore

  • à remettre un évènement nul à la fin, ce qui permet de ne pas avoir à compter les mouvements.
  • à rajouter dans la structure une colonne pour le relais et une colonne pour la musique, ainsi que pour les deux autres moteurs
  • à faire la chorégraphie complète.

OK ! Et bah chapeau bas ! c'est une merveille.
Je vais avancé le reste maintenant.

Petit question : est ce que dans ton code final le chronomètre s'affiche (et défile) ?
Il me donne ca :

Y⸮millis() = 0

Il me donne ca :

Y⸮millis() = 0

C’était dans une version antérieure. Quand on débug, on met des Serial.print un peu partout, à la fin on les enlève. Je n'en vois plus dans le dernier code.
En principe on laisse le Serial.begin parce que l'on s'attend à en avoir besoin.

D’accord, merci.

Donc so far,

voici le code avec tout les éléments présents ( 5 steppers, 3 relais, 1 module mp3)

#include <DFPlayerMini_Fast.h>

#if !defined(UBRR1H)
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 5); // RX, TX
#endif

DFPlayerMini_Fast myMP3;


#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 22, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 28, 29);
AccelStepper stepper3(AccelStepper::DRIVER, 34, 35);
AccelStepper stepper4(AccelStepper::DRIVER, 40, 41);
AccelStepper stepper5(AccelStepper::DRIVER, 10, 11);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
  uint32_t temps;
  float relay1;
  float mp3;
  
   float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  
   float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
  
   float vitesseMoteur3;
  float accelerationMoteur3;
  uint8_t nbPasMoteur3;
  
   float vitesseMoteur4;
  float accelerationMoteur4;
  uint8_t nbPasMoteur4;
  
   float vitesseMoteur5;
  float accelerationMoteur5;
  uint8_t nbPasMoteur5;
  
  float relay2;
  float relay3;
};
int mouvement = 0;

Evenement evenements[] = {
 
//temps    mp3  Rel1          stepper1                  stepper2                  stepper3                  stepper4               Rel2            stepper5             Rel3
  {0000,    0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0},
  {4000,    1,   1,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0}, 
  {8000,    0,   1,      1500.0, 800.0,   4,       1500.0, 800.0,   4,       1500.0, 800.0,   4,       1500.0, 800.0,   4,          0,        0.0,    0.0,     0,        0},
  {12000,   0,   1,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0}, 
  {16000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0},
  {20000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0},
  {24000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          1,        0.0,    0.0,     0,        0},
  {28000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          1,        0.0,    0.0,     0,        0},
  {32000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          1,        0.0,    0.0,     0,        0},
  {36000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        1500.0, 800.0,   5,        0},
  {40000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0},
  {44000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        1},
}; 

void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.print ("millis() = ");
  Serial.println (millis());

  #if !defined(UBRR1H)
  mySerial.begin(9600);
  myMP3.begin(mySerial);
#else
  Serial.begin(9600);
  myMP3.begin(Serial1);
#endif

  pinMode(51,OUTPUT);
  pinMode(52,OUTPUT);
  pinMode(53,OUTPUT);

}

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 4))
  {
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
        {
          stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
          stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
          stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
        }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
          stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
          stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
        }
      if (evenements[mouvement].vitesseMoteur3 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper3.setMaxSpeed(evenements[mouvement].vitesseMoteur3);
          stepper3.setAcceleration(evenements[mouvement].accelerationMoteur3);
          stepper3.moveTo(evenements[mouvement].nbPasMoteur3 * turn);
        }
      if (evenements[mouvement].vitesseMoteur4 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper4.setMaxSpeed(evenements[mouvement].vitesseMoteur4);
          stepper4.setAcceleration(evenements[mouvement].accelerationMoteur4);
          stepper4.moveTo(evenements[mouvement].nbPasMoteur4 * turn);
        }
      if (evenements[mouvement].vitesseMoteur5 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper5.setMaxSpeed(evenements[mouvement].vitesseMoteur5);
          stepper5.setAcceleration(evenements[mouvement].accelerationMoteur5);
          stepper5.moveTo(evenements[mouvement].nbPasMoteur5 * turn);
        }

      
      if (evenements[mouvement].relay1 == 1) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          digitalWrite(10,HIGH);
        }
      if (evenements[mouvement].relay1 == 0 ) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          digitalWrite(10,LOW);
        }
      if (evenements[mouvement].relay2 == 1) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          digitalWrite(11,HIGH);
        }
      if (evenements[mouvement].relay2 == 0 ) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          digitalWrite(11,LOW);
        }
      if (evenements[mouvement].relay3 == 1) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          digitalWrite(12,HIGH);
        }
      if (evenements[mouvement].relay3 == 0 ) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          digitalWrite(12,LOW);
        }

      
      if (evenements[mouvement].mp3 > 0 ) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
        myMP3.volume(30);      
        myMP3.play(1);
        }

      
      mouvement++; // on a traité ce mouvement, on passe au suivant
    }
  }
  stepper1.run(); 
  stepper2.run();
  stepper3.run(); 
  stepper4.run();
  stepper5.run(); 

}

Je suis passé sur le Mega (un Elegoo Mega pour être precis).

Les moteurs fonctionnent, visiblement les moteur n’iront pas plus vite que set MaxSpeed (1500); ce qui correspond a je ne sais combien de rpm (j’essaierais de le calculer) mais quelque chose de moins rapide que ce que l’ont pouvais faire jusqu’à présent. Probablement la surcharge ?
Je pense que ca fera quand même l’affaire. Les moteur sont connectés via les driver à une alim 12v 10A.

Après quelque difficulté, j’ai pu rajouter le module mp3 au mega. Et ca marche.

Les relays marchent aussi.

Par contre je viens d’essayer plusieurs fois de lui ajouter la ligne pour le looper mais ca fonctionne pas beaucoup

donc j’ai essayé ca :

  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 4))
  {

    ...


      mouvement++; // on a traité ce mouvement, on passe au suivant
      if (mouvement > 4) // Le prochain mouvement c'est une marque de fin
      mouvement = 0;
    }
  }

Mais ca le fait bugger au redemarrage

Supposons que nous ayons 3 mouvements bien définis. On vient de faire le mouvement N°2 depuis un certain temps.

A l’instant evenements[3].temps plein de choses vont s’enchainer en quelques instants:

  • on rentre dans la boucle et cela lance le mouvement N°3. 0 la fin de la boucle mouvement s’incrémente, passe à 4 et le test le fait passer à 0
  • comme (millis() - startMillis >= evenements[0].temps) && (0 < 4) est vrai car le temps du mouvement 0 est passé depuis longtemps, on va rentrer dans la boucle et demander le mouvement 0, puis nouvelle incrémentation de mouvement
  • comme (millis() - startMillis >= evenements[1].temps) && (1 < 4) est vrai, on va rentrer dans la boucle et demander le mouvement 0, puis nouvelle incrémentation de mouvement…
  • on va aussi demander le mouvement 3, qui remettra en fin de boucle le mouvement à 0…

Si on veut boucler, il faut

  • avoir fini le mouvement 3, par exemple lui demander d’attendre un mouvement supplémentaire qui ne fait plus rien:
    {20000, 0.0, 0.0, 0, 0.0, 00.0, 0}
    et tester sur un de plus.
  • remettre la pendule à zéro par startMillis=0;

Au passage, dans
if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 4))
la condition (mouvement < 4) est toujours vraie, elle ne sert à rien. On peut donc écrire
if (millis() - startMillis >= evenements[mouvement].temps)
seulement

Pour éviter de compter les boucles, c’est plus facile de tester si on est arrivé à la fin (t=20000 avec l’évènement de dessus qui ne fait rien). Au lieu de:

mouvement++; // on a traité ce mouvement, on passe au suivant
if (mouvement > 4) mouvement = 0;

mettre

if (evenements[mouvement].temps == 20000)
{
  mouvement = 0; // On  repart au début des mouvements
  startMillis=0; // Remet le chornomètre à 0
}
mouvement++; // on a traité ce mouvement, on passe au suivant

Il faut faire l’incrémentation après, pour que ce test soit bon à t=20000. Si on met l’incrémentation avant, au temps du mouvement 3, lors de ce test mouvement vaudra 4 et on n’aura pas attendu.

Ok alors j’ai essayé comme ca :

#include "SerialMP3Player.h"
#define TX 15
#define RX 14
SerialMP3Player mp3(RX,TX);

#include <AccelStepper.h>
#define turn 800
AccelStepper stepper1(AccelStepper::DRIVER, 22, 23);
AccelStepper stepper2(AccelStepper::DRIVER, 28, 29);
AccelStepper stepper3(AccelStepper::DRIVER, 34, 35);
AccelStepper stepper4(AccelStepper::DRIVER, 40, 41);
AccelStepper stepper5(AccelStepper::DRIVER,  8,  9);

unsigned long startMillis;
unsigned long currentMillis;

struct Evenement
{
  uint32_t temps;
  
  float relay1;
  float mp3;
  
   float vitesseMoteur1;
  float accelerationMoteur1;
  uint8_t nbPasMoteur1;
  
   float vitesseMoteur2;
  float accelerationMoteur2;
  uint8_t nbPasMoteur2;
  
   float vitesseMoteur3;
  float accelerationMoteur3;
  uint8_t nbPasMoteur3;
  
   float vitesseMoteur4;
  float accelerationMoteur4;
  uint8_t nbPasMoteur4;

  float relay2;
  
   float vitesseMoteur5;
  float accelerationMoteur5;
  uint8_t nbPasMoteur5;
  
  float relay3;
};
int mouvement = 0;

Evenement evenements[] = {
 
//temps    rel1 mp3           stepper1                  stepper2                  stepper3                  stepper4               Rel2            stepper5             Rel3
  {0000,    0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0},
  {4000,    0,   1,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0}, 
  {8000,    1,   0,      2000.0, 1000.0,   4,      1500.0, 1000.0,  4,       1500.0, 1000.0,  4,       1500.0, 1000.0,  4,          0,        0.0,    0.0,     0,        0},
  {12000,   1,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          1,        1500.0, 800.0,   5,        1}, 
  {16000,   0,   0,      0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,       0.0,    0.0,     0,          0,        0.0,    0.0,     0,        0}
}; 

void setup()
{
  Serial.begin(115200);  //start Serial in case we need to print debugging info
  startMillis = millis();
  Serial.print ("millis() = ");
  Serial.println (millis());

  mp3.begin(9600);        // start mp3-communication
  delay(500);             // wait for init

  mp3.sendCommand(CMD_SEL_DEV, 0, 2);   //select sd-card
  delay(500);             // wait for init
  

  pinMode(3,OUTPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);

}

void loop()
{
  if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 5))
  {
    {
      if (evenements[mouvement].vitesseMoteur1 > 0) // On demande à cet instant un départ de mouvement sur le moteur 1
        {
          stepper1.setMaxSpeed(evenements[mouvement].vitesseMoteur1);
          stepper1.setAcceleration(evenements[mouvement].accelerationMoteur1);
          stepper1.moveTo(evenements[mouvement].nbPasMoteur1 * turn);
        }
      if (evenements[mouvement].vitesseMoteur2 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper2.setMaxSpeed(evenements[mouvement].vitesseMoteur2);
          stepper2.setAcceleration(evenements[mouvement].accelerationMoteur2);
          stepper2.moveTo(evenements[mouvement].nbPasMoteur2 * turn);
        }
      if (evenements[mouvement].vitesseMoteur3 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper3.setMaxSpeed(evenements[mouvement].vitesseMoteur3);
          stepper3.setAcceleration(evenements[mouvement].accelerationMoteur3);
          stepper3.moveTo(evenements[mouvement].nbPasMoteur3 * turn);
        }
      if (evenements[mouvement].vitesseMoteur4 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper4.setMaxSpeed(evenements[mouvement].vitesseMoteur4);
          stepper4.setAcceleration(evenements[mouvement].accelerationMoteur4);
          stepper4.moveTo(evenements[mouvement].nbPasMoteur4 * turn);
        }
      if (evenements[mouvement].vitesseMoteur5 > 0) // On demande à cet instant un départ de mouvement sur le moteur 2
        {
          stepper5.setMaxSpeed(evenements[mouvement].vitesseMoteur5);
          stepper5.setAcceleration(evenements[mouvement].accelerationMoteur5);
          stepper5.moveTo(evenements[mouvement].nbPasMoteur5 * turn);
        }

      
      if (evenements[mouvement].relay1 == 1) 
        {
         digitalWrite(3,LOW);
        }
      if (evenements[mouvement].relay1 == 0 ) 
        {
          digitalWrite(3,HIGH);
        }
      if (evenements[mouvement].relay2 == 1) 
        {
          digitalWrite(5,LOW);
        }
      if (evenements[mouvement].relay2 == 0 ) 
        {
          digitalWrite(5,HIGH);
        }
      if (evenements[mouvement].relay3 == 1) 
        {
          digitalWrite(6,LOW);
        }
      if (evenements[mouvement].relay3 == 0 ) 
        {
          digitalWrite(6,HIGH);
        }

      
      if (evenements[mouvement].mp3 > 0 ) 
        {
        mp3.setVol(30);      
        mp3.play(1);
        }

      if (evenements[mouvement].temps == 16000)
      {
        mouvement = 0; // On  repart au début des mouvements
        startMillis=0; // Remet le chornomètre à 0
      }
      
      mouvement++; // on a traité ce mouvement, on passe au suivant
     
    }
  }
  stepper1.run(); 
  stepper2.run();
  stepper3.run(); 
  stepper4.run();
  stepper5.run(); 

}

Mais ca ne marche pas.

j'ai encore fait une erreur, ce n'est pas:
startMillis = 0; // Remet le chronomètre à 0
mais
startMillis = millis(); // Remet le chronomètre à 0
On compte le temps à partir de startMillis,, il faut donc dire "compte le temps à partir de maintenant".


Mais ca ne marche pas.

Ce n'est pas assez précis, il faut que tu décrives ce qui marche, et ce qui ne marche pas, ce que tu observes....
Par exemple tout peut fonctionner sauf les relais. Dans ce cas, il faut que tu dises

  • le relais reste toujours décollé
  • le relais vibre
  • le relais colle mais pas au bon moment...
    D'autant plus qu'il serait possible que je pense à un fonctionnement et toi à un autre différent. Dans ce cas, je ne peux pas trouver, car pour moi, cela marche.