Positionnement moteur pas à pas avec des contact

Portrait de lamy971

Bonjour,

  Voilà je voudrai pouvoir positionner un moteur pas à pas nema17 sur un nombre de pas précis après avoir appuyer sur un contact. J'ai déjà câblé ma plaque d'essais avec un EasyDriver et un NANO. J'ai déjà une partie de mon code qui fonctionne mais quand je rajoute mes 4 contacts pour 4 positions différente cela ne fonctionne plus. Merci pour votre aide. 

Portrait de wolfram69

Bonjour lamy971

Je trouve ton code assez compliqué et pour le comprendre il en est de même.

Pourrais tu nous décrire le fonctionnement que tu veux obtenir, ce serait plus simple !

De plus un schéma de l'installation serait aussi le bienvenu !

J'ai essayé de corriger quelques erreurs mais je ne suis pas sûr du résultat !

Voir le code plus bas

Portrait de lamy971

Bonjour, 

Merci wolfram69 pour ta correction. Je n'ai pas encore essayé le code avec ta correction. 

Pour ce qui est des explications les voici :

Je suis en train de fabriquer un banc de mesure (projet perso). Un moteur Nema 17 entraîne une courroie qui se déplace comme un axe Y sur une imprimante 3D. Cette courroie entraîne donc le déplacement d'un plateau avec 4 points d'arrêts à quatre distances différentes et commandé par 4 boutons poussoirs. Chaques boutons activés correspond à une valeur fixe ou le chariot doit s'arrê​ter. le chariot peut se déplacer à nouveau quand le bouton est relâché et que le bouton suivant est appuyé. . 

En début de séquence le moteur tourne pour ramener systématiquement le chariot contre un contact pour marquer la position zéro (homing).

Le moniteur série est ouvert et sert à envoyé des commandes de déplacement en nombre de pas indépendamment des boutons poussoirs. Le zéro renvoie à la position "home"

Le moniteur serie ne me sert que pour faire les réglages des distances pour pouvoir assigner un nombre de pas aux quatre boutons de déplacement. Il pourra très bien être supprimer quand les quatre boutons seront calibré. 

Sans activation des boutons poussoirs le chariot reste en position "home"

Voilà voilà j'espère que c'est plus clair

Merci encore

Portrait de lamy971

Voici le schéma de la platine d'essais

Portrait de wolfram69

Merci lamy971 je vais pouvoir être beaucoup efficace à t'aider sur ce projet.

Mais dans un premier temps pour que mon code fonctionne il faut que tu changes le point commun de tous les bouton poussoir du Vcc (+) vers GND (-). De même le fin de course (home_switch) doit être branché d'un coté à la pin 9 comme c'est le cas mais l'autre coté doit être aussi au GND (-).

Portrait de wolfram69

Voici mon code non testé car je n'ai pas ton matériel mais si il y  a des dysfonctionnement merci de me les décrire !

//  Code de référencement du moteur à l'aide d'AccelStepper et du moniteur série

#include "AccelStepper.h"
// Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/

// Configuration d'AccelStepper
AccelStepper stepperX(1, 2, 3);
// 1 = Easy Driver interface
// NANO Pin 2 connectée à la broche STEP de Easy Driver
// NANO Pin 3 connectée à la broche DIR de Easy Driver

// Définissez les broches utilisées
#define home_switch 9 // Pin 9 connecté au Home Switch (MicroSwitch)

// Deux constantes pour identifier les numéros des broches
const int buttonPin1 = 14;     // le numéro de la broche du bouton-poussoir 1
const int buttonPin2 = 15;     // le numéro de la broche du bouton-poussoir 2
const int buttonPin3 = 16;     // le numéro de la broche du bouton-poussoir 3
const int buttonPin4 = 17;     // le numéro de la broche du bouton-poussoir 4

// Variables de déplacement pas à pas
int CibleX, PositionX;  // Utilisé pour stocker la valeur X entrée dans le moniteur série

void setup() {
  Serial.begin(9600);  // Démarrez le moniteur série avec une vitesse de 9600 bauds
  pinMode(home_switch, INPUT_PULLUP); // Initialise la broche du home_switch en entrée:
  pinMode(buttonPin1, INPUT);         // Initialise la broche du bouton-poussoir en entrée:
  pinMode(buttonPin2, INPUT);         // Initialise la broche du bouton-poussoir en entrée:
  pinMode(buttonPin3, INPUT);         // Initialise la broche du bouton-poussoir en entrée:
  pinMode(buttonPin4, INPUT);         // Initialise la broche du bouton-poussoir en entrée:

  // Recherche du point Zero
  Serial.print("Initialisation point zero");
  PointZero();
  Serial.println("Le point Zero est defini");
  Serial.println();
  // Afficher les instructions sur le moniteur série au démarrage
  Serial.println("Entrer la  position desiree");
} //setup()

void loop() {

  while (Serial.available() > 0)  { // Vérifier si les valeurs sont disponibles dans le Serial Buffer
    CibleManu();
  } // while (Serial.available() > 0)

  // Lit l’état du bouton-poussoir1
  if (digitalRead(buttonPin1) == LOW) {
    // Déplacer le stepper à la position 1
    CibleX = 500;
  } //if (digitalRead(buttonPin1)

  // Lit l’état du bouton-poussoir2
  else if (digitalRead(buttonPin2) == LOW) {
    // Déplacer le stepper à la position 2
    CibleX = 1500;
  }// if (digitalRead(buttonPin2)

  // Lit l’état du bouton-poussoir3
  else if (digitalRead(buttonPin3) == LOW) {
    // Déplacer le stepper à la position 3
    CibleX = 2500;
  }// if (digitalRead(buttonPin3)

  // Lit l’état du bouton-poussoir4
  else if (digitalRead(buttonPin4) == LOW) {
    // Déplacer le stepper à la position 4
    CibleX = 5000;
  } //if (digitalRead(buttonPin4)

  if (CibleX != PositionX) {
    // Atteindre la position CibleX
    stepperX.moveTo(CibleX);  stepperX.run();
    // Afficher le message sur le moniteur série
    Serial.println("Position " + String(CibleX) + " Atteinte");
    Serial.println();  Serial.println("Entrer une nouvelle Position ");
  } //if (CibleX != PositionX)
  PositionX = CibleX;
} // loop()

void CibleManu() {
  CibleX = Serial.parseInt(); // Mettez la valeur numérique du  tampon  dans la  variable CibleX
  if (CibleX < 0 || CibleX > 10000) {  // Assurez-vous que la position saisie n'est pas au-delà de la position HOME ou MAX
    Serial.println();
    Serial.println("Veuillez saisir une valeur supérieure à zéro et inférieure ou égale à 10000.....");
    Serial.println();
    CibleX = PositionX;
  } // if (CibleX < 0 || CibleX > 10000)
  else {
    Serial.print("Déplacement du moteur à la  position: ");
    Serial.println(CibleX);
  } //else
} // CibleManu()

void PointZero() {
  int Pull = 2;
  int Dir = 3;

  digitalWrite(Dir, LOW); // sens de marche vers le point zero
  bool Etat = 0;

  while (digitalRead(home_switch)) {  // Faire avancer le moteur CCW jusqu'à ce que le commutateur soit activé vitesse rapide
    digitalWrite(Pull, Etat);
    Etat = !Etat;
   delayMicroseconds(200);
  } //while (digitalRead(home_switch))

  stepperX.setMaxSpeed(30.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
  stepperX.setAcceleration(75.0);  // Définir l'accélération de Stepper
  stepperX.moveTo(20);
  stepperX.run();
  while (digitalRead(home_switch)) {  // Faire avancer le moteur CCW jusqu'à ce que le commutateur soit activé en vitesse lente
    digitalWrite(Pull, Etat);
    Etat = !Etat;
    delayMicroseconds(1000);
  } // while (digitalRead(home_switch))

  stepperX.setCurrentPosition(0);  // Définit la position actuelle à zéro pour l' instant
  stepperX.setMaxSpeed(100.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
  stepperX.setAcceleration(100.0);  // Définir l'accélération de moteur
} //void PointZero()

Portrait de lamy971

Merci wolfram69

Bon je viens d'essayer ton code mais malheureusement cela ne fonctionne pas. Au début de la séquence le moteur tourne bien en CCW pour aller chercher le point zéro. J'appuie sur le switch et il se stop puis redémarre tout seul tout doucement dans un sens CW sans être vraiment continu car il s'arrête par moment. Seul un appuie sur le bouton 1 l'arrête puis il redémarre dès qu'on  relâche. Sur le moniteur série les lignes défilent sans interruption en suivant dans l'ordre les demandes de déplacement des boutons 1,2,3,4 avec les valeurs de pas qui correspondent. Il est par contre impossible de saisir un valeur dans la ligne de commande. J'ai bien évidemment fait les modifs que tu m'as demandé à savoir tout à GND (bouton + switch).

Juste pour infos le code ci dessous fonctionne mais sans les boutons poussoirs

   /*  Code pour banc de mesure utilisé avec homing et moniteur série
 

*/

#include "AccelStepper.h" 
// Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/

// AccelStepper Setup
AccelStepper stepperX(1, 2, 3);   // 1 = Easy Driver interface
                                  // broche NANO 2 connectée à la broche STEP de Easy Driver
                                  // broche NANO 3 connectée à la broche DIR de Easy Driver

// Définissez les broches utilisées
#define home_switch 9 // Pin 9 connecté au Home Switch (MicroSwitch)

// Variables de déplacement pas à pas
long TravelX;  // Utilisé pour stocker la valeur X entrée dans le moniteur série
int move_finished=1;  // // Utilisé pour vérifier si le déplacement est terminé
long initial_homing=-1;  // Utilisé pour Home Stepper au démarrage

void setup() {
   Serial.begin(9600);  // Démarrez le moniteur série avec une vitesse de 9600 bauds
   
   pinMode(home_switch, INPUT_PULLUP);
   
   delay(5);  // Attendez pour réveiller EasyDriver

   //   Définir la vitesse maximale et l' accélération de chaque Steppers au démarrage pour le référencement
  stepperX.setMaxSpeed(100.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
  stepperX.setAcceleration(100.0);  // Définir l'accélération de Stepper
 

// Démarrer la procédure de référencement du moteur pas à pas au démarrage

  Serial.print("Le chariot va à sa position d'origine HOME. . . . . . . . . . . ");

  while (digitalRead(home_switch)) {  // Faire avancer le Stepper CCW jusqu'à ce que le commutateur soit activé
    stepperX.moveTo(initial_homing);  // Définit la position vers laquelle se déplacer
    initial_homing--;  // Diminue de 1  pour le  prochain coup si nécessaire
    stepperX.run();  // Commencez à déplacer le stepper
    delay(5);
}

  stepperX.setCurrentPosition(0);  // Définit la position actuelle à zéro pour l' instant
  stepperX.setMaxSpeed(100.0);      // Définir la vitesse maximale du moteur pas à pas (plus lente pour obtenir une meilleure précision)
  stepperX.setAcceleration(100.0);  // Définir l'accélération de Stepper
  initial_homing=1;

  while (!digitalRead(home_switch)) { // Faire avancer le Stepper CW jusqu'à ce que le commutateur soit désactivé
    stepperX.moveTo(initial_homing);  
    stepperX.run();
    initial_homing++;
    delay(5);
  }
  
  stepperX.setCurrentPosition(0);
  Serial.println("Homing Completed");
  Serial.println("");
  stepperX.setMaxSpeed(1000.0);      // Définir la vitesse maximale du stepper (plus rapide pour les mouvements réguliers)
  stepperX.setAcceleration(1000.0);  // Définir l'accélération de Stepper

// Imprimer les instructions sur le moniteur série au démarrage
  Serial.println("Entrer la distance de déplacement ou 0 pour retourner à la position HOME:");
}

void loop() {

 while (Serial.available()>0)  { // Vérifier si les valeurs sont disponibles dans le Serial Buffer

  move_finished=0;  // Définir une variable pour vérifier le déplacement du Stepper
  
  TravelX= Serial.parseInt();  // Mettez la valeur numérique du  tampon  dans la  variable TravelX
  if (TravelX < 0 || TravelX > 20000) {  // Assurez-vous que la position saisie n'est pas au-delà de la position HOME ou MAX
    Serial.println("");
    Serial.println("Veuillez saisir une valeur supérieure à zéro et inférieure ou égale à 20000 .....");
    Serial.println("");
  } else {
    Serial.print("Déplacement du chariot en position:");
    Serial.println(TravelX);
  
  stepperX.moveTo(TravelX);  // Définit la nouvelle position de déplacement de Stepper
  
  delay(1000);  // Attendez 1 seconde avant de déplacer le Stepper
  }
  }

  if (TravelX >= 0 && TravelX <= 20000) {

// Vérifiez si le Stepper a atteint la position souhaitée
  if ((stepperX.distanceToGo() != 0)) {
    
    stepperX.run();  // Déplacer le charriot en position
    
  }

// Si le déplacement est terminé, afficher le message sur le moniteur série
  if ((move_finished == 0) && (stepperX.distanceToGo() == 0)) {
    Serial.println("TERMINE!");
    Serial.println("");
     Serial.println("Entrer la distance de déplacement ou 0 pour retourner à la position HOME:");
    move_finished=1;  // Réinitialiser la variable de déplacement
  }
  }
}

Portrait de wolfram69

Je vais faire un petit montage chez moi pour piger le problème et le corriger mais pas avant cet après midi !

Mais as-tu bien réalisé les modifications de câblage que je t'ai demandé de faire ?

Les voici de nouveau !

Mais dans un premier temps pour que mon code fonctionne il faut que tu changes le point commun de tous les bouton poussoir du Vcc (+) vers GND (-). De même le fin de course (home_switch) doit être branché d'un coté à la pin 9 comme c'est le cas mais l'autre coté doit être aussi au GND (-).

Si non il se passera complètement autre chose !

Normalement il y a en initialisation un premier mouvement vers le point zéro à une certaine vitesse puis un léger déplacement, suivi d'un second mouvement vers le point zéro à vitesse réduite pour avoir une plus grande fiabilité dans ce point zéro !

Portrait de wolfram69

Désolé mais avec mon driver cette library ne fonctionne pas et elle est beaucoup trop lente !

Si tu veux je peux te faire un programme sans library AccelStepper

Portrait de lamy971

Bonjour, 

 Alors oui j'avais fais les modifs sur ma planche d'essais. Si tu veux essayer avec une autre library pas de soucis pour moi. C'est plus le résultat qui compte. 

Portrait de wolfram69

Voilà mon code cette fois il est testé et 100 fonctionnel. Pour chaque BP tu peux donner la position et la vitesse !

int Vitesse ;//nombre de pas par seconde
unsigned long InterStep;
int Step = 2, Dir = 3, Ena = 4, Zero = 9, BP1 = 14, BP2 = 15, BP3 = 16, BP4 = 17, Pas, X, XPos;
bool Etat;

void setup() {
  Serial.begin(9600);
  pinMode(Dir,  OUTPUT);
  pinMode(Step, OUTPUT);
  pinMode(Ena,  OUTPUT);
  pinMode(Zero, INPUT_PULLUP);
  pinMode(BP1,  INPUT_PULLUP);
  pinMode(BP2,  INPUT_PULLUP);
  pinMode(BP3,  INPUT_PULLUP);
  pinMode(BP4,  INPUT_PULLUP);
  pinMode(Ena,  OUTPUT);
  digitalWrite(Dir, LOW);
  Serial.println("Recherche du point Zero");
  PointZero();
  Serial.println();
  Serial.println();
  Serial.println("Le point zero est initialisé");
  Messages();
}

void loop() {

  if (Serial.available() > 0) {
    int CibleX = Serial.parseInt();
    Serial.readString();
    if ( CibleX < 0 || CibleX > 10000) {
      Serial.println("La valeur " + String(CibleX) + " n'est pas autorisée");
      Messages();
    }
    else
      PositionX(CibleX, 200);

  }
  if (digitalRead(BP1) == LOW)
    PositionX(500, 100);// PositionX( POSTION, VITESSE en pas par seconde)
  if (digitalRead(BP2) == LOW)
    PositionX(1500, 200);
  if (digitalRead(BP3) == LOW)
    PositionX(2500, 300);
  if (digitalRead(BP4) == LOW)
    PositionX(5000, 400);

}

void Messages() {
  Serial.println();
  Serial.println();
  Serial.println("Entrez une Valeur entre 0 et 10000");
  Serial.println();
  Serial.println("Ou appuyez sur un Bouton Poussoir");
}

void PositionX( int CibleX, int vitesse) {

 Etat=1;
  Serial.println("Le point "+String(CibleX)+" est demande");
  digitalWrite(Ena, LOW);
  InterStep = 1000000 / vitesse;
  if (CibleX - XPos < 0) {
    digitalWrite(Dir, LOW);
    Pas = -1;
  }
  else {
    digitalWrite(Dir, HIGH);
    Pas = 1;
  }

  while (XPos != CibleX) {
    digitalWrite(Step, Etat);
    Etat = !Etat;
    delayMicroseconds(InterStep );
    digitalWrite(Step, Etat);
    Etat = !Etat;
    delayMicroseconds(InterStep );
    XPos += Pas;

  }
  digitalWrite(Ena, HIGH);
    Serial.println();

  Serial.println("Le point " + String(XPos) + " est atteint");
  for (int n = 0; n <4; n++)
    Serial.println();
  Messages();
}

void PointZero() {

  digitalWrite(Ena, LOW);
  Vitesse = 200;
  InterStep = 1000000 / Vitesse;
  digitalWrite(Dir, HIGH);
  while (digitalRead(Zero) == HIGH) {
    digitalWrite(Step, Etat);
    Etat = !Etat;
    delayMicroseconds(InterStep);
    digitalWrite(Step, Etat);
    Etat = !Etat;
    delayMicroseconds(InterStep);
  }
  Vitesse = 50;
  InterStep = 1000000 / Vitesse;
  digitalWrite(Dir, LOW);
  while (digitalRead(Zero) == LOW) {
    digitalWrite(Step, Etat);
    Etat = !Etat;
    delayMicroseconds(InterStep);
    digitalWrite(Step, Etat);
    Etat = !Etat;
    delayMicroseconds(InterStep);
  }
  digitalWrite(Ena, HIGH);

  XPos = 0;
}

Portrait de lamy971

Bonjour,

Merci pour ton code. Je viens de l'essayer. De mon coté je n'y arrive pas. Le moteur tourne mais ne trouve pas la position zéro. La requête s'affiche bien dans le moniteur série.  C'est sans doute moi qui n'arrive pas à l'intégrer. Tu as changé de library?

Portrait de wolfram69

Je n'ai pas besoin de library.

J'ai modifié un détail sur le code essaye de nouveau !

Quand je suis en ligne on peut chatter regarde en bas à droite de cette page !

Portrait de lamy971

Bon c'est cool ça commence à être bon c'est super. Voilà ce que j'ai remarqué :

- Le point zéro se fait avec le moteur en CW (est t il possible qu'il se fasse en CCW pour revenir au début de la rampe?

 C'est super tu es vraiment un pro .... 

La finalité sera que je puisse afficher les messages de positionnement sur un LCD deux lignes une fois que les positions exactes seront trouvée. Je n'aurai plus besoin du moniteur serie ni d'être raccordé à un pc.... mais ça je vais essayer de le faire tout seul au niveau du code....