Problème de rotation de moteur pas à pas

Bonjour !

Je suis actuellement sur un projet qui fait intervenir un moteur pas à pas. Il tourne, or quelque chose m'échappe : il ne tourne pas toujours dans le même sens alors que c'est l'instruction que je lui donne ; il n'effectue presque jamais la même rotation deux fois de suite alors que je lui dit d'effectuer le même nombre de pas...

Il est alimenté en 12V 2A, et utilise une Arduino Uno pour communiquer avec son driver, un A4988.

J'ai essayé de changer la tension du driver via le potentiomètre integré, une amélioration mais le problème persiste.

Si quelqu'un connaît l'origine du problème, je suis preneur...

Ci-joint le code de mon projet :

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

int counter;

// Affichage, potards et valeurs
const int POT1 = A0;
const int POT2 = A1;
const int POT3 = A3;
int pot1def = 0;
int pot2def = 0;
int pot3def = 0;
int HSujet = 0;
float EPhotos = 0;
int DPhotos = 0;
int PRestantes;

// Bouton poussoir Marche/Arrêt et LEDs
const int LED_VERTE = 13;
const int LED_ROUGE = 12;
const int BP_MA = 2;
boolean ETAT_BP_MA = 1;
boolean BOUTONAPPUYER_MA = 0;

// Bouton poussoir fin de course
const int BP_FDC
boolean ETAT_BP_FDC = 1;
boolean BOUTONAPPUYER_FDC = 0;

// Moteur pas a pas
int PPP = 0; // nb de Pas Par Photo
int tempo = 1; // tempo=1 moteur rapide, tempo = 100 moteur lent
const int DIR = 3; // HIGH = descendre, LOW = monter
const int STP = 4; // pin pour la commande des steps

// Relay
const int RELAY = 8;

// Définition LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);



void setup()
{
  // Potards
  pinMode(POT1, INPUT);
  pinMode(POT2, INPUT);
  pinMode(A2, INPUT);

  // LCD
  lcd.init(); 

  // Bouton poussoir marche/arrêt et LEDs
  pinMode(BP_MA, INPUT_PULLUP);
  pinMode(LED_ROUGE, OUTPUT);
  pinMode(LED_VERTE, OUTPUT);
  digitalWrite(LED_ROUGE, HIGH);
  
  // Bouton Poussoir Fin de Course
  pinMode(BP_FDC, INPUT_PULLUP);
  
  // Moteur pas a pas
  pinMode(DIR, OUTPUT);
  pinMode(STP, OUTPUT);
  
  // Relay
  pinMode(RELAY, OUTPUT);
  
  // INITIALISATION DES LEDS ET DU BP_FDC
  boolean ETAT_BP_FDC = digitalRead(BP_FDC) ; // Récupère l’état du bouton
  if(ETAT_BP_FDC == 0 and BOUTONAPPUYER_FDC == 0) { // On appuie sur le bouton

 BOUTONAPPUYER_FDC = 1;
  
if(ETAT_BP_FDC == 0) { // Si le système est à l'arret, on le lance    SYSTEME EN MARCHE

  // actualisation du pas à pas
  for (int i=0; i <= 50; i++) {      
  tempo = 2;
  digitalWrite(DIR, LOW);
  digitalWrite(STP, LOW);
  delay(tempo);  
  digitalWrite(STP, HIGH);
  delay(tempo);
  }
          ETAT_BP_FDC = 1;
        }
        
        else { // Si le systeme fonctionne, on l'arrete                SYSTEME A L'ARRET
            
            // actualisation des LEDs
            ETAT_BP_FDC = 0;
            }
    }
    if(ETAT_BP_FDC == 1 and BOUTONAPPUYER_FDC == 1) { // On arrête d’appuyer sur le bouton
        BOUTONAPPUYER_FDC = 0;
    }
}



void loop()
{
  lcd.backlight(); 

  // INITIALISATION DES LEDS ET DU BP_MA
  boolean ETAT_BP_MA = digitalRead(BP_MA) ; // Récupère l’état du bouton
  if(ETAT_BP_MA == 0 and BOUTONAPPUYER_MA == 0) { // On appuie sur le bouton

         BOUTONAPPUYER_MA = 1;

        if(ETAT_BP_MA == 0) { // Si le système est à l'arret, on le lance    SYSTEME EN MARCHE

            // actualisation des LEDs
            digitalWrite(LED_ROUGE, LOW);
            digitalWrite(LED_VERTE, HIGH);
            ETAT_BP_MA = 1;
        }

        else { // Si le systeme fonctionne, on l'arrete                SYSTEME A L'ARRET

            // actualisation des LEDs
            digitalWrite(LED_ROUGE, HIGH);
            digitalWrite(LED_VERTE, LOW);
            ETAT_BP_MA = 0;
            }
    }
    if(ETAT_BP_MA == 1 and BOUTONAPPUYER_MA == 1) { // On arrête d’appuyer sur le bouton
        BOUTONAPPUYER_MA = 0;
    }


  if(digitalRead(13) == 0) { // Si le système est à l'arrêt
    
    digitalWrite(DIR, LOW);
    for (int i=0; i < 0; i++) {
      tempo = 1;
      digitalWrite(STP, LOW);
      delay(tempo);
      digitalWrite(STP, HIGH);
      delay(tempo);
    }


    // DEFINITION DES VALEURS
    
    
    // Définition des valeurs de Hauteur du Sujet sur la valeur de Pot1
    analogRead(POT1);
    if (analogRead(POT1)<90) HSujet = 00;
    else { if (analogRead(POT1)<120) HSujet = 01;
    else { if (analogRead(POT1)<150) HSujet = 02;
    else { if (analogRead(POT1)<180) HSujet = 03;
    else { if (analogRead(POT1)<210) HSujet = 04;
    else { if (analogRead(POT1)<240) HSujet = 05;
    else { if (analogRead(POT1)<270) HSujet = 06;
    else { if (analogRead(POT1)<300) HSujet = 07;
    else { if (analogRead(POT1)<330) HSujet = 8;
    else { if (analogRead(POT1)<360) HSujet = 9;
    else { if (analogRead(POT1)<390) HSujet = 10;
    else { if (analogRead(POT1)<420) HSujet = 11;
    else { if (analogRead(POT1)<450) HSujet = 12; 
    else { if (analogRead(POT1)<480) HSujet = 13;
    else { if (analogRead(POT1)<510) HSujet = 14;
    else { if (analogRead(POT1)<540) HSujet = 15;
    else { if (analogRead(POT1)<570) HSujet = 16;
    else { if (analogRead(POT1)<600) HSujet = 17;
    else { if (analogRead(POT1)<630) HSujet = 18;
    else { if (analogRead(POT1)<660) HSujet = 19;
    else { if (analogRead(POT1)<690) HSujet = 20;
    else { if (analogRead(POT1)<720) HSujet = 21;
    else { if (analogRead(POT1)<750) HSujet = 22; 
    else { if (analogRead(POT1)<780) HSujet = 23;
    else { if (analogRead(POT1)<810) HSujet = 24;
    else { if (analogRead(POT1)<840) HSujet = 25;
    else { if (analogRead(POT1)<870) HSujet = 26;
    else { if (analogRead(POT1)<900) HSujet = 27;
    else { if (analogRead(POT1)<930) HSujet = 28;
    else { if (analogRead(POT1)<960) HSujet = 29;
    else { HSujet = 30;
    }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
    
    
    // Définition des valeurs d'Ecartement des Photos sur la valeur de Pot2  
    analogRead(POT2);
    if (analogRead(POT2)<98) {PPP = 10; EPhotos = 0.4;}
    else { if (analogRead(POT2)<136) {PPP = 20; EPhotos = 0.8;}
    else { if (analogRead(POT2)<174) {PPP = 30; EPhotos = 1.2;}
    else { if (analogRead(POT2)<212) {PPP = 40; EPhotos = 1.6;}
    else { if (analogRead(POT2)<250) {PPP = 50; EPhotos = 2.0;}
    else { if (analogRead(POT2)<288) {PPP = 60; EPhotos = 2.4;}
    else { if (analogRead(POT2)<326) {PPP = 70; EPhotos = 2.8;}
    else { if (analogRead(POT2)<364) {PPP = 80; EPhotos = 3.2;}
    else { if (analogRead(POT2)<402) {PPP = 90; EPhotos = 3.6;}
    else { if (analogRead(POT2)<440) {PPP = 100; EPhotos = 4.0;}
    else { if (analogRead(POT2)<478) {PPP = 110; EPhotos = 4.4;}
    else { if (analogRead(POT2)<516) {PPP = 120; EPhotos = 4.8;}
    else { if (analogRead(POT2)<554) {PPP = 130; EPhotos = 5.2;}
    else { if (analogRead(POT2)<592) {PPP = 140; EPhotos = 5.6;}
    else { if (analogRead(POT2)<630) {PPP = 150; EPhotos = 6.0;}
    else { if (analogRead(POT2)<668) {PPP = 160; EPhotos = 6.4;}
    else { if (analogRead(POT2)<706) {PPP = 170; EPhotos = 6.8;}
    else { if (analogRead(POT2)<744) {PPP = 180; EPhotos = 7.2;}
    else { if (analogRead(POT2)<782) {PPP = 190; EPhotos = 7.6;}
    else { if (analogRead(POT2)<820) {PPP = 200; EPhotos = 8.0;}
    else { if (analogRead(POT2)<858) {PPP = 210; EPhotos = 8.4;}
    else { if (analogRead(POT2)<896) {PPP = 220; EPhotos = 8.8;}
    else { if (analogRead(POT2)<934) {PPP = 230; EPhotos = 9.2;}
    else { if (analogRead(POT2)<960) {PPP = 240; EPhotos = 9.6;}
    else { if (analogRead(POT2)>=960) {PPP = 250; EPhotos = 10;}
    }}}}}}}}}}}}}}}}}}}}}}}}
            
            
    // Définition des valeurs d'Intervalle des Photos sur la valeur de Pot3
    analogRead(POT3);
    if (analogRead(POT3)<96) DPhotos = 00;
    else { if (analogRead(POT3)<192) DPhotos = 01;
    else { if (analogRead(POT3)<288) DPhotos = 02;
    else { if (analogRead(POT3)<384) DPhotos = 03;
    else { if (analogRead(POT3)<480) DPhotos = 04;
    else { if (analogRead(POT3)<576) DPhotos = 05;
    else { if (analogRead(POT3)<672) DPhotos = 06;
    else { if (analogRead(POT3)<768) DPhotos = 07;
    else { if (analogRead(POT3)<864) DPhotos = 8;
    else { if (analogRead(POT3)<920) DPhotos = 9;
    else { if (analogRead(POT3)>=920) DPhotos = 10;
    }}}}}}}}}}
            
            
    // Affichage menu et données sur le LCD
    lcd.setCursor(0, 0);
    lcd.print("Hauteur sujet     cm");
    lcd.setCursor(16, 0);
    lcd.print(HSujet);
    lcd.setCursor(0, 1);
    lcd.print("Ecart photos      mm");
    lcd.setCursor(15, 1);
    lcd.print(EPhotos);
    lcd.setCursor(0, 2);
    lcd.print("Duree photos       s");
    lcd.setCursor(18, 2);
    lcd.print(DPhotos);
    lcd.setCursor(0, 3);
    lcd.print("Prises rest. :      ");
    PRestantes = ((HSujet*10)/EPhotos); // def de PRestantes
    lcd.setCursor(17, 3);
    lcd.print(PRestantes);
    delay(100);
  }

  else { // Si le système est en marche
    
    // Tant qu'il reste des photos
    for (int i = PRestantes; i > -1; --i) {
      
    // A ffichage menu et données sur le LCD
    lcd.setCursor(0, 0);
    lcd.print("Hauteur sujet     cm");
    lcd.setCursor(16, 0);
    lcd.print(HSujet);
    lcd.setCursor(0, 1);
    lcd.print("Ecart photos      mm");
    lcd.setCursor(16, 1);
    lcd.print(EPhotos);
    lcd.setCursor(0, 2);
    lcd.print("Duree photos       s");
    lcd.setCursor(18, 2);
    lcd.print(DPhotos);
    lcd.setCursor(0, 3);
    lcd.print("Prises rest. :      ");
    // PRestantes = ((HSujet*10)/EPhotos); // def de PRestantes
    lcd.setCursor(17, 3);
    lcd.print(PRestantes);
    PRestantes = PRestantes-1;
    
    // Mouvement et déclenchement de l'appareil photo
    
    // Mouvement du pas à pas
    for (int i=0; i <= PPP; i++) {
      tempo = 1;
      digitalWrite(DIR, HIGH);
      digitalWrite(STP, LOW);
      delay(tempo);
      digitalWrite(STP, HIGH);
      delay(tempo);
    }
      
    // Déclenchement du relay
    digitalWrite(RELAY, HIGH);
    delay(200);
    digitalWrite(RELAY, LOW);
    
    // Intervalle photos
    delay(DPhotos*1000-200);
    
    // Changement d'état des LEDs quand la séquence est terminée
    if(PRestantes == 0) {
      if (ETAT_BP_MA == 0) {
        digitalWrite(LED_VERTE, HIGH);
        delay(500);
        digitalWrite(LED_VERTE, LOW);
        delay(500);
      }
     }
    }
  } 
}

Le passage qui concerne le pilotage du moteur :

  // Mouvement du pas à pas
    for (int i=0; i <= PPP; i++) {
      tempo = 1;
      digitalWrite(DIR, HIGH);
      digitalWrite(STP, LOW);
      delay(tempo);
      digitalWrite(STP, HIGH);
      delay(tempo);
    }

Merci beaucoup,
Léo

Salut Leo
Ce n'est pas un projet fini, il me semble... Un gentil modérateur peut-il mettre ce topic au bon endroit ?

Cordialement
Pandaroux007

Tu n'aurais pas un mauvais contact sur l'un des fils ?

C'est fait.

:warning: Je ne suis pas un expert, et je ne connais pas le driver A4988, ce que je dis en donc probablement erroné. N'hésitez pas à me reprendre si vous voyez que je raconte des bêtises ! :warning:
Plusieurs chose dans ton code :

  • beaucoup de delay(). C'est pas une bonne idée. Avec tous ça, ta loop dure plusieurs seconde...
  • beaucoup de if, else. Tu peux remplacer ça par des switch, case, break.
  • Des noms de variables incompréhensible. Pour si retrouver c'est l'enfer...

Ce que je te conseil :

  • Testes le moteur seul, sans l'écran et tous le fatra qui va avec...
  • Mets des noms a tes variables qui permettent de se retrouver dans ton code.
  • donnes un schéma de ton montage et la référence de ton moteur
  • Une photo, peut-être, car ça :

C'est un problème courant sur les moteurs pas à pas...
Quel est ton projet exactement et quels module utilises-tu ?
Cordialement
Pandaroux007

Il faudrait peut-être affecter une valeur à cette constante. Sinon, il n'est pas impossible qu'elle soit à 0 et comme D0 c'est le port de communication cela pourrait pourrir le fonctionnement de ton système.

c'est, AMTHA, la meilleure (la seule bonne) remarque exprimée sur ce sujet : en effet, déclarer une constante sans lui attribuer de valeur n'a (non seulement aucun intérêt, mais) que des conséquences néfastes sur la suite du programme

Bonjour leobnk

Peut-être une partie du problème.
Voilà l'indentation de la partie valPot1 j'ai fait une copie d'écran (une fois n'est pas coutume :wink:)


ça paraît bizarre, tu imbriques de if dans un else alors que tu devrais [écrire ainsi](https://docs.arduino.cc/built-in-examples/control-structures/ifStatementConditional):

	int valPot1 = analogRead(POT1);

	if (valPot1 < 90)
	{
		HSujet = 00;
	}
	else if (valPot1 < 120)
	{
		HSujet = 01;
	}
	else if (valPot1 < 150)
	{
		HSujet = 02;
	}
et ainsi de suite

et tu verra qu'à la fin la fonction map() du langage Arduino te fait tout ça en une ligne de code.

Cordialement
jpbbricole

non, ce n'est pas l'imbrication des if qui est débile (dans l'absolu ça devrait fonctionner si ...)
c'est la relecture du port analogique, qui peut varier entre deux lectures

donc HS de ta part

Hello !

Des noms qui me sont très clairs, étant sur ce projet depuis quelques semaines en tout cas...

Cependant, j'avais upload le mauvais code (celui qui n'était pas allégé, et qui contenait des lignes complètement inutiles... Voilà la version la plus récente :

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

int counter;

// Affichage, potards et valeurs
const int POT1 = A0;
const int POT2 = A1;
const int POT3 = A3;
int HSujet = 0;
float EPhotos = 0;
int DPhotos = 0;
int PRestantes;

// Bouton poussoir Marche/Arrêt et LEDs
const int LED_VERTE = 13;
const int LED_ROUGE = 12;
const int BP_MA = 2;
boolean ETAT_BP_MA = 1;
boolean BOUTONAPPUYER_MA = 0;

// Moteur pas a pas
int PPP = 0; // nb de Pas Par Photo
int tempo = 1; // tempo=1 moteur rapide, tempo = 100 moteur lent
const int DIR = 3; // HIGH = descendre, LOW = monter
const int STP = 4; // pin pour la commande des steps

// Relay
const int RELAY = A3;

// Définition LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);



void setup()
{
  // Potards
  pinMode(POT1, INPUT);
  pinMode(POT2, INPUT);
  pinMode(A2, INPUT);

  // LCD
  lcd.init(); 

  // Bouton poussoir marche/arrêt et LEDs
  pinMode(BP_MA, INPUT_PULLUP);
  pinMode(LED_ROUGE, OUTPUT);
  pinMode(LED_VERTE, OUTPUT);
  digitalWrite(LED_ROUGE, HIGH);
  
  // Bouton Poussoir Fin de Course
  pinMode(BP_FDC, INPUT_PULLUP);
  
  // Moteur pas a pas
  pinMode(DIR, OUTPUT);
  pinMode(STP, OUTPUT);
  
  // Relay
  pinMode(RELAY, OUTPUT);

void loop()
{
  lcd.backlight(); 

  // INITIALISATION DES LEDS ET DU BP_MA
  boolean ETAT_BP_MA = digitalRead(BP_MA) ; // Récupère l’état du bouton
  if(ETAT_BP_MA == 0 and BOUTONAPPUYER_MA == 0) { // On appuie sur le bouton

         BOUTONAPPUYER_MA = 1;

        if(ETAT_BP_MA == 0) { // Si le système est à l'arret, on le lance    SYSTEME EN MARCHE

            // actualisation des LEDs
            digitalWrite(LED_ROUGE, LOW);
            digitalWrite(LED_VERTE, HIGH);
            ETAT_BP_MA = 1;
        }

        else { // Si le systeme fonctionne, on l'arrete                SYSTEME A L'ARRET

            // actualisation des LEDs
            digitalWrite(LED_ROUGE, HIGH);
            digitalWrite(LED_VERTE, LOW);
            ETAT_BP_MA = 0;
            }
    }
    if(ETAT_BP_MA == 1 and BOUTONAPPUYER_MA == 1) { // On arrête d’appuyer sur le bouton
        BOUTONAPPUYER_MA = 0;
    }


  if(digitalRead(13) == 0) { // Si le système est à l'arrêt
    
    digitalWrite(DIR, LOW);
    for (int i=0; i < 0; i++) {
      tempo = 1;
      digitalWrite(STP, LOW);
      delay(tempo);
      digitalWrite(STP, HIGH);
      delay(tempo);
    }


    // DEFINITION DES VALEURS
    
    
    // Définition des valeurs de Hauteur du Sujet sur la valeur de Pot1
    analogRead(POT1);
    if (analogRead(POT1)<90) HSujet = 00;
    else { if (analogRead(POT1)<120) HSujet = 01;
    else { if (analogRead(POT1)<150) HSujet = 02;
    else { if (analogRead(POT1)<180) HSujet = 03;
    else { if (analogRead(POT1)<210) HSujet = 04;
    else { if (analogRead(POT1)<240) HSujet = 05;
    else { if (analogRead(POT1)<270) HSujet = 06;
    else { if (analogRead(POT1)<300) HSujet = 07;
    else { if (analogRead(POT1)<330) HSujet = 8;
    else { if (analogRead(POT1)<360) HSujet = 9;
    else { if (analogRead(POT1)<390) HSujet = 10;
    else { if (analogRead(POT1)<420) HSujet = 11;
    else { if (analogRead(POT1)<450) HSujet = 12; 
    else { if (analogRead(POT1)<480) HSujet = 13;
    else { if (analogRead(POT1)<510) HSujet = 14;
    else { if (analogRead(POT1)<540) HSujet = 15;
    else { if (analogRead(POT1)<570) HSujet = 16;
    else { if (analogRead(POT1)<600) HSujet = 17;
    else { if (analogRead(POT1)<630) HSujet = 18;
    else { if (analogRead(POT1)<660) HSujet = 19;
    else { if (analogRead(POT1)<690) HSujet = 20;
    else { if (analogRead(POT1)<720) HSujet = 21;
    else { if (analogRead(POT1)<750) HSujet = 22; 
    else { if (analogRead(POT1)<780) HSujet = 23;
    else { if (analogRead(POT1)<810) HSujet = 24;
    else { if (analogRead(POT1)<840) HSujet = 25;
    else { if (analogRead(POT1)<870) HSujet = 26;
    else { if (analogRead(POT1)<900) HSujet = 27;
    else { if (analogRead(POT1)<930) HSujet = 28;
    else { if (analogRead(POT1)<960) HSujet = 29;
    else { HSujet = 30;
    }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
    
    
    // Définition des valeurs d'Ecartement des Photos sur la valeur de Pot2  
    analogRead(POT2);
    if (analogRead(POT2)<98) {PPP = 10; EPhotos = 0.4;}
    else { if (analogRead(POT2)<136) {PPP = 20; EPhotos = 0.8;}
    else { if (analogRead(POT2)<174) {PPP = 30; EPhotos = 1.2;}
    else { if (analogRead(POT2)<212) {PPP = 40; EPhotos = 1.6;}
    else { if (analogRead(POT2)<250) {PPP = 50; EPhotos = 2.0;}
    else { if (analogRead(POT2)<288) {PPP = 60; EPhotos = 2.4;}
    else { if (analogRead(POT2)<326) {PPP = 70; EPhotos = 2.8;}
    else { if (analogRead(POT2)<364) {PPP = 80; EPhotos = 3.2;}
    else { if (analogRead(POT2)<402) {PPP = 90; EPhotos = 3.6;}
    else { if (analogRead(POT2)<440) {PPP = 100; EPhotos = 4.0;}
    else { if (analogRead(POT2)<478) {PPP = 110; EPhotos = 4.4;}
    else { if (analogRead(POT2)<516) {PPP = 120; EPhotos = 4.8;}
    else { if (analogRead(POT2)<554) {PPP = 130; EPhotos = 5.2;}
    else { if (analogRead(POT2)<592) {PPP = 140; EPhotos = 5.6;}
    else { if (analogRead(POT2)<630) {PPP = 150; EPhotos = 6.0;}
    else { if (analogRead(POT2)<668) {PPP = 160; EPhotos = 6.4;}
    else { if (analogRead(POT2)<706) {PPP = 170; EPhotos = 6.8;}
    else { if (analogRead(POT2)<744) {PPP = 180; EPhotos = 7.2;}
    else { if (analogRead(POT2)<782) {PPP = 190; EPhotos = 7.6;}
    else { if (analogRead(POT2)<820) {PPP = 200; EPhotos = 8.0;}
    else { if (analogRead(POT2)<858) {PPP = 210; EPhotos = 8.4;}
    else { if (analogRead(POT2)<896) {PPP = 220; EPhotos = 8.8;}
    else { if (analogRead(POT2)<934) {PPP = 230; EPhotos = 9.2;}
    else { if (analogRead(POT2)<960) {PPP = 240; EPhotos = 9.6;}
    else { if (analogRead(POT2)>=960) {PPP = 250; EPhotos = 10;}
    }}}}}}}}}}}}}}}}}}}}}}}}
            
            
    // Définition des valeurs d'Intervalle des Photos sur la valeur de Pot3
    analogRead(POT3);
    if (analogRead(POT3)<96) DPhotos = 00;
    else { if (analogRead(POT3)<192) DPhotos = 01;
    else { if (analogRead(POT3)<288) DPhotos = 02;
    else { if (analogRead(POT3)<384) DPhotos = 03;
    else { if (analogRead(POT3)<480) DPhotos = 04;
    else { if (analogRead(POT3)<576) DPhotos = 05;
    else { if (analogRead(POT3)<672) DPhotos = 06;
    else { if (analogRead(POT3)<768) DPhotos = 07;
    else { if (analogRead(POT3)<864) DPhotos = 8;
    else { if (analogRead(POT3)<920) DPhotos = 9;
    else { if (analogRead(POT3)>=920) DPhotos = 10;
    }}}}}}}}}}
            
            
    // Affichage menu et données sur le LCD
    lcd.setCursor(0, 0);
    lcd.print("Hauteur sujet     cm");
    lcd.setCursor(16, 0);
    lcd.print(HSujet);
    lcd.setCursor(0, 1);
    lcd.print("Ecart photos      mm");
    lcd.setCursor(15, 1);
    lcd.print(EPhotos);
    lcd.setCursor(0, 2);
    lcd.print("Duree photos       s");
    lcd.setCursor(18, 2);
    lcd.print(DPhotos);
    lcd.setCursor(0, 3);
    lcd.print("Prises rest. :      ");
    PRestantes = ((HSujet*10)/EPhotos); // def de PRestantes
    lcd.setCursor(17, 3);
    lcd.print(PRestantes);
    delay(100);
  }

  else { // Si le système est en marche
    
    // Tant qu'il reste des photos
    for (int i = PRestantes; i > -1; --i) {
      
    // A ffichage menu et données sur le LCD
    lcd.setCursor(0, 0);
    lcd.print("Hauteur sujet     cm");
    lcd.setCursor(16, 0);
    lcd.print(HSujet);
    lcd.setCursor(0, 1);
    lcd.print("Ecart photos      mm");
    lcd.setCursor(16, 1);
    lcd.print(EPhotos);
    lcd.setCursor(0, 2);
    lcd.print("Duree photos       s");
    lcd.setCursor(18, 2);
    lcd.print(DPhotos);
    lcd.setCursor(0, 3);
    lcd.print("Prises rest. :      ");
    // PRestantes = ((HSujet*10)/EPhotos); // def de PRestantes
    lcd.setCursor(17, 3);
    lcd.print(PRestantes);
    PRestantes = PRestantes-1;
    
    // Mouvement et déclenchement de l'appareil photo

    // Déclenchement du relay
    digitalWrite(RELAY, HIGH);
    delay(200);
    digitalWrite(RELAY, LOW);
    
    // Intervalle photos
    delay(DPhotos*1000-200);
    
    // Mouvement du pas à pas
    for (int i=0; i <= PPP; i++) {
      tempo = 1;
      digitalWrite(DIR, HIGH);
      digitalWrite(STP, LOW);
      delay(tempo);
      digitalWrite(STP, HIGH);
      delay(tempo);
    }
      
    // Changement d'état des LEDs quand la séquence est terminée
    if(PRestantes == 0) {
      if (ETAT_BP_MA == 0) {
        digitalWrite(LED_VERTE, HIGH);
        delay(500);
        digitalWrite(LED_VERTE, LOW);
        delay(500);
      }
    }
  }
} 
}

Le moteur utilisé : 17HD2011N-ETC (un Nema 17 récupéré sur une extrudeuse d'ender 3 pro).

Concernant cette piste, je ne pense pas, ayant essayé diverses connexions au cours du prototypage notamment, surtout que j'utilise actuellement un câble très propre avec d'un côté un JST-XH et de l'autre un Dupont 4 broches...

Je l'ai déja fait, et ça fonctionnait, ayant essayé de faire une alternance haut/bas qui ne buggait pas.

Mon projet : une machine qui permet notamment d'automatiser le stacking photo afin de photographier des fossiles coquilliers (voir photo sur ce lien).

J'ai finalement enlevé cette variable, inutile pour mon projet, simplement laissée là en attendant d'installer un capteur de fin de course (ce qui ne s'est jamais fait).

Alors oui, sauf qu'elle ne me permet pas de mapper les valeurs avec un incrément choisi par mes soins il me semble...

Ci-jointes des photos de mon montage électrique : ici

Merci d'avance,
Léo

pour l'instant je vois ça :

ça me paraît étrange.


ensuite, même si je pense à la lecture de tes if ... else que le problème ne vient pas de là, il serait judicieux de les remplacer (comme suggéré par d'autres) par des switch ... case qui rendraient la lecture de ton code plus facile.


et aussi, bien que tu forces une première lecture de l'ADC à chaque changement de port, ce qui est très bien pour éliminer la première (toujours considérée comme erronée), pourquoi en refaire une nouvelle pour chaque comparaison ?
si tu archivais une fois pour toute la valeur tu gagnerais du temps (env. 100µs par conversion) au lieu de refaire une acquisition pour chaque test.

de plus, il faut bien avoir en tête que l'ADC est une jeune fille capricieuse, dont les réponses varient au gré du temps :
même si ton potentiomètre est ''figé'' mécaniquement deux mesures successives ne donneront pas la même valeur à la lecture.

je te rassure, vu ta façon d'écrire tes tests successifs, ce n'est pas la raison pour laquelle ton programme ne répond pas à tes attentes.


fais déjà ces quelques modifs d'écriture, peut-être que ça permettra à d'autres de mieux te lire pour avoir envie de t'aider.

loop() qui fait dans les 200 lignes gagnerait à être découpée en fonctions ce qui améliorerait la lisibilité du code ainsi que sa testabilité. Chaque fonction pouvant être testée individuellement.


  if(ETAT_BP_MA == 0 and BOUTONAPPUYER_MA == 0) { // On appuie sur le bouton

         BOUTONAPPUYER_MA = 1;

        if(ETAT_BP_MA == 0) { // Si le système est à l'arret, on le lance    SYSTEME EN MARCHE

            // actualisation des LEDs
            digitalWrite(LED_ROUGE, LOW);
            digitalWrite(LED_VERTE, HIGH);
            ETAT_BP_MA = 1;
        }

        else { // Si le systeme fonctionne, on l'arrete                SYSTEME A L'ARRET

            // actualisation des LEDs
            digitalWrite(LED_ROUGE, HIGH);
            digitalWrite(LED_VERTE, LOW);
            ETAT_BP_MA = 0;
            }
    }

La condition d'entrée dans le if ETAT_BP_MA == 0 interdit de passer dans le else.


  if(digitalRead(13) == 0) { // Si le système est à l'arrêt

La logique voudrait que tu utilises LED_VERTE et non 13.


HSujet = 01;

Faire précéder les constantes numériques d'un 0 est une mauvaise habitude qui peut entrainer des dysfonctionnements difficiles à localiser.
Une constante numérique précédée d'un 0 et un nombre en octal.


    digitalWrite(DIR, LOW);
    for (int i=0; i < 0; i++) {
      tempo = 1;
      digitalWrite(STP, LOW);
      delay(tempo);
      digitalWrite(STP, HIGH);
      delay(tempo);
    }

Je ne comprends pas ce que tu veux faire ici.

Bonjour leobnk

Un petit test à faire, déconnecter le fil DIR venant de l'Arduino et forcer la pin DIR à HIGH ou LOW (pas important).
Est-ce que ton moteur tourne toujours dans le même sens? Si oui, c'est ton programme qui est en cause, si non, c'est un problème de câblage, est-ce que le GND de l'Arduino est bien connecté à celui de A4988?

Cordialement
jpbbricole

Bonjour leobnk

Oui, tout à fait, c'est pourquoi je te propose une méthode moins "encombrante" que la méthode des if().
Elle se compose d'un tableau, HSujetMapping[], contenant tout les seuils de la valeur à définir, qui dans cet exemple ont un incrément régulier mais qui peuvent être modifiés à ta guise.
Pour définir une valeur en fonction de celle du potentiomètre, il y a la fonction int HSsujetMap(int potVal) qui s'appelle par;

		HSujet = HSsujetMap(analogRead(POT1));

et le tout donne:

/*
Name:       ARDFR_HSujetMapping.ino
Created:	31.05.2023
Author:     jpbbricole
https://forum.arduino.cc/t/probleme-de-rotation-de-moteur-pas-a-pas/1132698/12
*/
const int POT1 = A0;
int HSujet = 0;

//------------------------------------- Tableau des seuils de 
const int HSujetMapping[] = {90, 120, 150, 180, 210, 240, 270, 300, 330, 360, 390, 420, 450, 480, 510, 540,
							 570, 600, 630, 660, 690, 720, 750, 780, 810, 840, 870, 900, 930, 960};
const int HSujetNombre = sizeof(HSujetMapping) / sizeof(HSujetMapping[0]);

//------------------------------------- Affichage périodique des valeurs
unsigned long displayTempo = 500;     // Rythme d'affichage
unsigned long displayMillis = millis();     // Chrono d'affichage

void setup()
{
	Serial.begin(115200);
	delay(500);
}

void loop()
{
	if (millis() - displayMillis >= displayTempo)
	{
		HSujet = HSsujetMap(analogRead(POT1));

		Serial.print("Pot = " + String(analogRead(POT1)));
		Serial.println("\tHSujet = " + String(HSujet));

		displayMillis = millis();
	}
}

int HSsujetMap(int potVal)
{
	for (int h = 0; h < HSujetNombre; h ++)
	{
		if (potVal < HSujetMapping[h])
		{
			return h;
		}
	}
	return 30;     // Si pas trouvé dans mapping, valeur par défaut
}

Cordialement
jpbbricole

Pour HSujet:

  1. Sachant que la carte Uno n'a pas énormément de mémoire, pourquoi prendre un int quand un byte suffit? Cela occupe moitié moins de mémoire vive et va plus vite pour les calculs tout en consommant moins de code.

  2. Les conventions du C recommandent d'utiliser des noms de variables en minuscules, avec une majuscule pour première lettre des mots suivants. Cela donne alors un nom de variable hSujet, ou mieux hauteurSujet. L'avantage des conventions est de faciliter la compréhension par une tierce personne, qui pensera à une variable et pas à un objet.

Bonjour à tous !

J'ai effectué quelques unes des modificaitons que vous m'avez conseillées :

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

int counter;

// Affichage, potards et valeurs
const int pot1 = A0;
const int pot2 = A1;
const int pot3 = A3;
int hSujet = 0;
float ePhotos = 0;
int dPhotos = 0;
int pRestantes;

// Bouton poussoir Marche/Arrêt et LEDs
const int ledVerte = 13;
const int ledRouge = 12;
const int BPMA = 2;
boolean etatBPMA = 1;
boolean boutonAppuiMA = 0;

// Moteur pas a pas
int pasParPhoto = 0; // nb de Pas Par Photo
int tempo = 1; // tempo=1 moteur rapide, tempo = 100 moteur lent
const int dir = 3; // HIGH = descendre, LOW = monter
const int stp = 4; // pin pour la commande des steps

// relay
const int relay = 8;

// Définition LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);



void setup()
{
  // Potards
  pinMode(pot1, INPUT);
  pinMode(pot2, INPUT);
  pinMode(pot3, INPUT);

  // LCD
  lcd.init(); 

  // Bouton poussoir marche/arrêt et LEDs
  pinMode(BPMA, INPUT_PULLUP);
  pinMode(ledRouge, OUTPUT);
  pinMode(ledVerte, OUTPUT);
  digitalWrite(ledRouge, HIGH);
  
  // Moteur pas a pas
  pinMode(dir, OUTPUT);
  pinMode(stp, OUTPUT);
  
  // relay
  pinMode(relay, OUTPUT);
}

void loop()
{
  lcd.backlight(); 

  // INITIALISATION DES LEDS ET DU BPMA
  boolean etatBPMA = digitalRead(BPMA) ; // Récupère l’état du bouton
  if(etatBPMA == 0 and boutonAppuiMA == 0) { // On appuie sur le bouton

         boutonAppuiMA = 1;

        if(etatBPMA == 0) { // Si le système est à l'arret, on le lance    SYSTEME EN MARCHE

            // actualisation des LEDs
            digitalWrite(ledRouge, LOW);
            digitalWrite(ledVerte, HIGH);
            etatBPMA = 1;
        }

        else { // Si le systeme fonctionne, on l'arrete                SYSTEME A L'ARRET

            // actualisation des LEDs
            digitalWrite(ledRouge, HIGH);
            digitalWrite(ledVerte, LOW);
            etatBPMA = 0;
            }
    if(etatBPMA == 1 and boutonAppuiMA == 1) { // On arrête d’appuyer sur le bouton
        boutonAppuiMA = 0;
    }

    // DEFINITION DES VALEURS
    
    
    // Définition des valeurs de Hauteur du Sujet sur la valeur de pot1
    analogRead(pot1);
    if (analogRead(pot1)<90) hSujet = 00;
    else { if (analogRead(pot1)<120) hSujet = 1;
    else { if (analogRead(pot1)<150) hSujet = 2;
    else { if (analogRead(pot1)<180) hSujet = 3;
    else { if (analogRead(pot1)<210) hSujet = 4;
    else { if (analogRead(pot1)<240) hSujet = 5;
    else { if (analogRead(pot1)<270) hSujet = 6;
    else { if (analogRead(pot1)<300) hSujet = 7;
    else { if (analogRead(pot1)<330) hSujet = 8;
    else { if (analogRead(pot1)<360) hSujet = 9;
    else { if (analogRead(pot1)<390) hSujet = 10;
    else { if (analogRead(pot1)<420) hSujet = 11;
    else { if (analogRead(pot1)<450) hSujet = 12; 
    else { if (analogRead(pot1)<480) hSujet = 13;
    else { if (analogRead(pot1)<510) hSujet = 14;
    else { if (analogRead(pot1)<540) hSujet = 15;
    else { if (analogRead(pot1)<570) hSujet = 16;
    else { if (analogRead(pot1)<600) hSujet = 17;
    else { if (analogRead(pot1)<630) hSujet = 18;
    else { if (analogRead(pot1)<660) hSujet = 19;
    else { if (analogRead(pot1)<690) hSujet = 20;
    else { if (analogRead(pot1)<720) hSujet = 21;
    else { if (analogRead(pot1)<750) hSujet = 22; 
    else { if (analogRead(pot1)<780) hSujet = 23;
    else { if (analogRead(pot1)<810) hSujet = 24;
    else { if (analogRead(pot1)<840) hSujet = 25;
    else { if (analogRead(pot1)<870) hSujet = 26;
    else { if (analogRead(pot1)<900) hSujet = 27;
    else { if (analogRead(pot1)<930) hSujet = 28;
    else { if (analogRead(pot1)<960) hSujet = 29;
    else { hSujet = 30;
    }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
    
    
    // Définition des valeurs d'Ecartement des Photos sur la valeur de pot2  
    analogRead(pot2);
    if (analogRead(pot2)<98) {pasParPhoto = 10; ePhotos = 0.4;}
    else { if (analogRead(pot2)<136) {pasParPhoto = 20; ePhotos = 0.8;}
    else { if (analogRead(pot2)<174) {pasParPhoto = 30; ePhotos = 1.2;}
    else { if (analogRead(pot2)<212) {pasParPhoto = 40; ePhotos = 1.6;}
    else { if (analogRead(pot2)<250) {pasParPhoto = 50; ePhotos = 2.0;}
    else { if (analogRead(pot2)<288) {pasParPhoto = 60; ePhotos = 2.4;}
    else { if (analogRead(pot2)<326) {pasParPhoto = 70; ePhotos = 2.8;}
    else { if (analogRead(pot2)<364) {pasParPhoto = 80; ePhotos = 3.2;}
    else { if (analogRead(pot2)<402) {pasParPhoto = 90; ePhotos = 3.6;}
    else { if (analogRead(pot2)<440) {pasParPhoto = 100; ePhotos = 4.0;}
    else { if (analogRead(pot2)<478) {pasParPhoto = 110; ePhotos = 4.4;}
    else { if (analogRead(pot2)<516) {pasParPhoto = 120; ePhotos = 4.8;}
    else { if (analogRead(pot2)<554) {pasParPhoto = 130; ePhotos = 5.2;}
    else { if (analogRead(pot2)<592) {pasParPhoto = 140; ePhotos = 5.6;}
    else { if (analogRead(pot2)<630) {pasParPhoto = 150; ePhotos = 6.0;}
    else { if (analogRead(pot2)<668) {pasParPhoto = 160; ePhotos = 6.4;}
    else { if (analogRead(pot2)<706) {pasParPhoto = 170; ePhotos = 6.8;}
    else { if (analogRead(pot2)<744) {pasParPhoto = 180; ePhotos = 7.2;}
    else { if (analogRead(pot2)<782) {pasParPhoto = 190; ePhotos = 7.6;}
    else { if (analogRead(pot2)<820) {pasParPhoto = 200; ePhotos = 8.0;}
    else { if (analogRead(pot2)<858) {pasParPhoto = 210; ePhotos = 8.4;}
    else { if (analogRead(pot2)<896) {pasParPhoto = 220; ePhotos = 8.8;}
    else { if (analogRead(pot2)<934) {pasParPhoto = 230; ePhotos = 9.2;}
    else { if (analogRead(pot2)<960) {pasParPhoto = 240; ePhotos = 9.6;}
    else { if (analogRead(pot2)>=960) {pasParPhoto = 250; ePhotos = 10;}
    }}}}}}}}}}}}}}}}}}}}}}}}
            
            
    // Définition des valeurs d'Intervalle des Photos sur la valeur de pot3
    analogRead(pot3);
    if (analogRead(pot3)<96) dPhotos = 0;
    else { if (analogRead(pot3)<192) dPhotos = 1;
    else { if (analogRead(pot3)<288) dPhotos = 2;
    else { if (analogRead(pot3)<384) dPhotos = 3;
    else { if (analogRead(pot3)<480) dPhotos = 4;
    else { if (analogRead(pot3)<576) dPhotos = 5;
    else { if (analogRead(pot3)<672) dPhotos = 6;
    else { if (analogRead(pot3)<768) dPhotos = 7;
    else { if (analogRead(pot3)<864) dPhotos = 8;
    else { if (analogRead(pot3)<920) dPhotos = 9;
    else { if (analogRead(pot3)>=920) dPhotos = 10;
    }}}}}}}}}}
            
            
    // Affichage menu et données sur le LCD
    lcd.setCursor(0, 0);
    lcd.print("Hauteur sujet     cm");
    lcd.setCursor(16, 0);
    lcd.print(hSujet);
    lcd.setCursor(0, 1);
    lcd.print("Ecart photos      mm");
    lcd.setCursor(15, 1);
    lcd.print(ePhotos);
    lcd.setCursor(0, 2);
    lcd.print("Duree photos       s");
    lcd.setCursor(18, 2);
    lcd.print(dPhotos);
    lcd.setCursor(0, 3);
    lcd.print("Prises rest. :      ");
    pRestantes = ((hSujet*10)/ePhotos); // def de pRestantes
    lcd.setCursor(17, 3);
    lcd.print(pRestantes);
    delay(100);
  }

  else { // Si le système est en marche
    
    // Tant qu'il reste des photos
    for (int i = pRestantes; i > -1; --i) {
      
    // A ffichage menu et données sur le LCD
    lcd.setCursor(0, 0);
    lcd.print("Hauteur sujet     cm");
    lcd.setCursor(16, 0);
    lcd.print(hSujet);
    lcd.setCursor(0, 1);
    lcd.print("Ecart photos      mm");
    lcd.setCursor(16, 1);
    lcd.print(ePhotos);
    lcd.setCursor(0, 2);
    lcd.print("Duree photos       s");
    lcd.setCursor(18, 2);
    lcd.print(dPhotos);
    lcd.setCursor(0, 3);
    lcd.print("Prises rest. :      ");
    // pRestantes = ((hSujet*10)/ePhotos); // def de pRestantes
    lcd.setCursor(17, 3);
    lcd.print(pRestantes);
    pRestantes = pRestantes-1;
    
    // Mouvement et déclenchement de l'appareil photo

    // Déclenchement du relay
    digitalWrite(relay, HIGH);
    delay(200);
    digitalWrite(relay, LOW);
    
    // Intervalle photos
    delay(dPhotos*1000-200);
    
    // Mouvement du pas à pas
    for (int i=0; i <= pasParPhoto; i++) {
      tempo = 1;
      digitalWrite(dir, HIGH);
      digitalWrite(stp, LOW);
      delay(tempo);
      digitalWrite(stp, HIGH);
      delay(tempo);
    }
      
    // Changement d'état des LEDs quand la séquence est terminée
    if(pRestantes == 0) {
      if (etatBPMA == 0) {
        digitalWrite(ledVerte, HIGH);
        delay(500);
        digitalWrite(ledVerte, LOW);
        delay(500);
      }
    }
  }
} 

Je viens également de tester une rotation sans la broche DIR de mon moteur : il semble tourner mieux dans le même sens (à peu près un mauvais sens toutes les 30-40 instructions), mais il arrive tout de même que celui-ci réalise quelques pas dans le mauvais sens, et change directement après...

Maintenant avec une vitesse moins élevée (un pas par seconde), j'observe qu'un pas se fait franchement toutes les deux secondes (un pas marqué dans un sens 1, un pas qui ne bouge pas et ne fait presque aucun bruit, un pas marqué dans un sens 2, un pas qui ne bouge pas)...

Je suis en full step... Est-ce que je gagnerai à me mettre en seizième de pas ? Comment ça fonctionne ? Cela veut-il dire que j'ai 16 x plus de précision en 1/16 de pas ?

J'en ai mis un...

J'ai mis tout ça plus haut, ainsi qu'une photo de mon projet, etc.

Bonsoir leobnk

Mais as-tu mis cette broche à un potentiel, 5V ou GND (pas en l'air). Parce qu'un moteur qui tourne à basse vitesse, avec le signal DIR forcé, qui tourne de temps en temps à l'envers ???
Est-tu sûre de tes GND?

Cordialement
jpbbricole

Bonjour leobnk

J'ai testé ton programme en mode full-step avec ce câblage:
image
par rapport au A4988.
La rotation est parfaite, fluide et sans inversions intempestives.

Cordilaement
jpbbricole

Bonjour à tous !

Et c'est jpbbricole qui a trouvé la solution !

Merci beaucoup !

Leçon retenue : vérifiez toujours le câblage de vos moteurs pas à pas...

Merci énormément,
Léo