Pages: [1]   Go Down
Author Topic: Programme de commande de moteur pas à pas avec accélération  (Read 576 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour à tous,

Je dois commander un moteur pas à pas de taille Nema 23 (200 pas) avec un driver MS542. Le driver est configuré en 400 pas
Il s'agit d'une simple rotation avec une variation de vitesse.

J'ai fait des essais avec AccelStepper et avec le programme ConstantSpeed.pde
Si j'ai bien compris, avec AccelStepper et une vitesse constante, il n'est pas possible de gérer les accélérations --> commande "stepper.runSpeed();"
Les accélérations sont gérées dans le cas ou la distance entre en jeux et non la vitesse --> commande "stepper.run();"

Finalement, j'ai fait un petit programme avec une boucle.

J'ai une variable de vitesse de démarrage "VitesseDemar1" qui est placée dans le loop.
A chaque passage de la boucle, la variable augmente d'un pas "PasAccel1" jusqu'à atteindre la vitesse de marche du moteur "VitesseMax1"

Ce programme simple fonctionne parfaitement, mon moteur se lance et accélère sans problème.
Reste à faire la même chose pour la décélération.

Qu'en pensez-vous ?

Code:

const int Pul1 = 26; // pas du moteur
const int Dir1 = 28; // direction du moteur
int CapteurMarche = 1; // interuuption N°1 --> pin N°3 mega 2560
int CapteurArret = 2; // interuuption N°2 --> pin N°21  mega 2560
const int Enable = 30; // enable driver

int pulseWidthMicros1 = 5;  // variable delaymicroseconds
float VitesseMax1 = 400 ;// variable delaymicroseconds -- >  pour la vitesse de fonctionnement maximun. Plus la valeur est grande, plus rapide est la vitesse
float VitesseDemar1 = 1000; // variable delaymicroseconds --> pour la vitesse de démarrage
float Vitesse1 = VitesseDemar1; // varable utilisée dans la fonction "moteur1"
float PasAccel1 = 0.7;  // pas pour l'acceleration
volatile int VolatileMarche = LOW; // varle volatile utilisée dans l'interruption



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

  pinMode(Dir1, OUTPUT);
  pinMode(Pul1, OUTPUT);
  pinMode(Enable, OUTPUT);
  digitalWrite(Dir1, HIGH);
  digitalWrite(Enable, HIGH); // desactive enable

}

void loop()
{
   attachInterrupt(CapteurMarche,CycleMarche, CHANGE); // interruption bouton marche
   attachInterrupt(CapteurArret,CycleArret, CHANGE); // interruption bouton arret
  
  
   if (VolatileMarche  == HIGH) // test si l'interruption est activée
     {
        if (Vitesse1 < VitesseDemar1) // test si la variable vitesse est < que la vitesse de démarrage
         {
            VitesseDemar1 = VitesseDemar1 - PasAccel1; // ajustement à chaque boucle de la vitesse
            Vitesse1 = VitesseDemar1; // renseigne la vitesse pour la fonction Moteur1
            Moteur1(); // lance la fonction qui fait tourner le moteur
          }
  else
     {
       Vitesse1 = VitesseMax1; // dans ce cas la vitesse du moteur = la vitesse maximum
       Moteur1();// lance la fonction qui fait tourner le moteur
      }  
   }
}



void CycleMarche() // fonction interruption
{
  Serial.println("Moteur marche"); // message
  VolatileMarche = HIGH ; // active la variable
  digitalWrite(Enable, LOW); // active enable
}



void CycleArret() // fonction interruption
{
  Serial.println("Moteur arret"); // message
  VolatileMarche = LOW ; // désactive la variable
  digitalWrite(Enable, HIGH); // desactive enable
  digitalWrite(Pul1, LOW); // desactive la sortie Pul du driver
  VitesseDemar1 = 1000;  // recharge la variable de vitesse de démarrage
}


void Moteur1()
{
    digitalWrite(Pul1, HIGH); // Active la sortie Pul du driver
    delayMicroseconds(pulseWidthMicros1); // pause en Microsecondes
    digitalWrite(Pul1, LOW);  // desactive la sortie Pul du driver
    delayMicroseconds(Vitesse1); // pause en Microsecondes
}



« Last Edit: August 19, 2014, 11:48:51 pm by lapenduledargent » Logged

Online Online
Full Member
***
Karma: 2
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

le rapport cyclique devrai etre voisin de 50%, mais tu gere la vitesse en jouant sur la durée de l'état bas.

tu devrai plutot adapter genre
Code:

void Moteur1()
{
    pulseWidthMicros1=Vitesse1/2;
    digitalWrite(Pul1, HIGH); // Active la sortie Pul du driver
    delayMicroseconds(pulseWidthMicros1); // pause en Microsecondes
    digitalWrite(Pul1, LOW);  // desactive la sortie Pul du driver
    delayMicroseconds(pulseWidthMicros1); // pause en Microsecondes
}

en fonction de la vitesse du moteur et de ton code, tu risque d'avoir quand meme des dérapages car cette fonction n'est pas elle meme cyclique a la vitesse du moteur.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonsoir Jean,

Si j'ai bien compris tes explications, je fais :

Code:
void Moteur1()
{
    pulseWidthMicros1  = Vitesse1 *0.5;
    digitalWrite(Pul1, HIGH); // Active la sortie Pul du driver
    delayMicroseconds(pulseWidthMicros1); // pause en Microsecondes
    digitalWrite(Pul1, LOW);  // desactive la sortie Pul du driver
    delayMicroseconds(pulseWidthMicros1); // pause en Microsecondes
}

Bien je n'ai aucun changement de vitesse ou dans le comportement du moteur ?

@+ Pierre
Logged

Offline Offline
Full Member
***
Karma: 3
Posts: 184
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour a tous,
Pierre
- il faut utiliser les balises codes (#) pour inserer du ... code et pas les balises "quote".
- les drivers comme ceux que tu utilises sont commandes par des impulsions. Le MS542 a besoin d'une impulsion de plus de 1,5uS. Il n'est nulle part question d'un rapport cyclique de 50%.
- tu es tres confiant de demarrer un moteur pas-a-pas dans une application PROFESSIONNELLE qui fonctionne dans un milieu INDUSTRIEL avec une seule transition sur une entree. Moi, je choisirais plutot : 2 boutons enfonces simultanement pendant 1 seconde. Ceinture et bretelles. !!
- on place les instructions attachinterrupt dans le setup plutot que dans la boucle.
- prend l'habitude de ne pas placer dans tes fonctions d'interruptions des instructions longues a executer comme un Serial.println. Ici ce n'est pas important mais c'est une bonne habitude a prendre.
Jacques

N.B.: 2 petits liens vers un peu de lecture, il faudra peut-etre t'inscrire pour consulter mais cela vaut la peine
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=37891&highlight=stepper+motor+controller

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=78603
« Last Edit: August 19, 2014, 04:13:12 pm by JMe87 » Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour JME87,

J'ai modifié la balise de mon premier message  smiley

Pour le temps d'impulsion pour connaître le temps optimal, hier, j'ai demandé l'avis de Leadshine.
J'attends la réponse.


Un extrait du manuel du MS542

Quote
Remarque:
(1) t1: ENA doit être positionné au moins 5μs avant l’apparition du signal DIR. Si la
fonction Enable n’est pas utilisée, les broches ENA+ et ENA- n’ont pas à être
raccordée.
(2) t2: Le signal DIR doit être positionné au moins 5μs avant l’apparition d’un pulse sur
l’entrée PUL ;
(3) t3: Les pulses sur l’entrée PUL doivent durer au moins 1.5μs ;
(4) t4: Le niveau bas des pulses doit avoir une durée minimum de 1.5μs


Merci pour tes remarques pour mon code, autant prendre de bonnes habitudes dès le début.

Quote
avec une seule transition sur une entree.

Que veux-tu dire par une seule transition ?


Je vais regarder tes liens ...

« Last Edit: August 20, 2014, 01:01:07 am by lapenduledargent » Logged

Offline Offline
Full Member
***
Karma: 3
Posts: 184
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour a tous,
pas besoin de demander au fabricant, il n'y a pas de temps optimal.
L'entree de ton driver est un opto-coupleur. Le minimum c'est 1,5uS pour etre sur que le transistor est sature. Il n'y a pas de maximum. L'electronique de ton driver est sensible a la transition du signal pulse pas a sa duree.

Si ton uP recoit une "crasse", perturbation ou autre sur son entree, le moteur se met en marche. Pas de securite !!. Le minimum a faire serai de confirmer la pression sur le bouton en allant lire l'etat de ce bouton 1 fois ou 2 apres quelques dizaine de milisecondes pour verifier qu'il a bien ete enfonce.

A mon avis tu inverse les priorites, c'est dans une routine d'interruption declenchee par  le timer qu'il faut generer tes impulsions et laisser la boucle principale gerer les "basses besognes" comme la lecture des boutons par pooling et la modification de la "duree" du timer pour gerer acceleration et deceleration, l'envoi de messages sur la console etc. Comme ton programme est fait, tu ne peux rien ajouter de consequent dans ta boucle sans perturber le fonctionnement du moteur.

Jacques
 
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonsoir Jacques,

Quote
Si ton uP recoit une "crasse", perturbation ou autre sur son entree, le moteur se met en marche. Pas de securite !!. Le minimum a faire serai de confirmer la pression sur le bouton en allant lire l'etat de ce bouton 1 fois ou 2 apres quelques dizaine de milisecondes pour verifier qu'il a bien ete enfonce.

J'avais donné un exemple avec un bouton poussoir qui lançait le moteur mais en réalité, c'est un capteur qui commande l'interruption.

Par contre, c'est une sage précaution et simple à mettre en œuvre, certainement un retour d'expérience. J'en prends note ! Merci.

Quote
c'est dans une routine d'interruption declenchee par  le timer qu'il faut generer tes impulsions

Là je comprends le principe mais tu n'as pas un bout de code pour me mettre sur la piste ?
Je connais les interruptions classique à partie d'une entrée mais à partir d'un timer ?

Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Je viens de trouvé ça :

http://www.mon-club-elec.fr/pmwiki_mon_club_elec/pmwiki.php?n=MAIN.ArduinoInitiationInterruptionsTemporisationTimer2UneSeconde

C'est au sujet de "MsTimer2"
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour Jme87,

Si tu passes par là, peux-tu svp m'indiquer  si je suis sur la bonne voie pour la routine d'interruption avec "MsTimer2" ?

Merci d'avance.

Pierre
Logged

Offline Offline
Full Member
***
Karma: 3
Posts: 184
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour Pierre,
je te conseille plutot ceci comme lecture :
https://code.google.com/p/stepper-robot-arduino-lib/wiki/Reference
et cette librairie gere l'acceleration qui est parametrable !
Jacques
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Rétrofit et conception de machines et d'équipements pour l'industrie et l'agro-alimentaire.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour Jacques,

Merci pour le lien, je ne connaissais pas.
Je vais essayer mais j'aimais bien la simplicité de mon code et tenant compte de tes remarques.
Mes tests sont plutôt concluant.
Logged

Online Online
Full Member
***
Karma: 2
Posts: 160
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

je ne connais pas le MS542, néanmoins, j'ai utilisé plusieurs drives de différentes puissances et marques. ce qui s'y dit (a la valeur des durée pres, exemple de la GAC de RTA):
"...step input: signal must be present for at least 30µS and should be ideally 50% duty cycle
dir input: for at least 50µS berfore 1st step and at least 50µS after last step ..."
Les cartes GAC gèrent le demi-pas et quart de pas. à 1500trs/minutes, on a 50µS pour générer un pas dans les cas les plus défavorables.
D'autres models vont jusqu'au 32eme de pas. à 1500trs/minutes, on a 6,25µS pour générer un pas dans les cas les plus défavorables.
je suppose que les FPGA montés necessitent un front montant et descendant. j'ai deja eu des problemes sur les seuils limites (perte de pas).
tous les fabricant n'ont pas obligatoirement des entrées optocouplés. et quand bien meme, ca dépend du traitement hard et soft en aval.
et encore une fois, ca ne concerne pas le MS542.

voici un exemple de routine de positionnement, avec rampe d'acelleration/decelleration, et vitesse max:
Code:
//////////////////////////////////////
// TRAIN DE PULS AVEC RAMPES        //
void pls3(int pin, int pinSens, int acel, int fmax, int plsNbr1, int sens) {
// modifie posActu, la position en cours du moteur
  int factu = acel;
  int plsacel = plsNbr1/2;
  int finacel = plsNbr1/2;

  pinMode (pin, OUTPUT);
  digitalWrite (pin, 0);
  pinMode (pinSens, OUTPUT);
  digitalWrite (pinSens, sens);
  delay(1);
  
  for (int pls=0; pls<plsNbr1; pls++) {
//500+500=1sec
//factu mini=50 pour optimiser a basse vitesse
    if (factu<50) {factu=50;}
    if (factu>fmax) {factu=fmax;}
    digitalWrite (pin, 1);
    delayMicroseconds(100000/factu);
    digitalWrite (pin, 0);
    delayMicroseconds(100000/factu);
    if (sens==1) {posActu++;}
    if (sens==0) {posActu--;}
    
    //accelerate
    if (factu<fmax){
      if (pls<(plsNbr1/2)){
        factu=factu+acel;
        plsacel=pls;
      }
    }

    //decelerate
    if (pls>(plsNbr1-plsacel-1)){
      if (factu>acel){
        factu=factu-acel;
      }
    }

  }
  digitalWrite (pin, 0); // optional, au cas ou ...
  delay(1);
}
« Last Edit: August 29, 2014, 07:17:07 am by jean-I » Logged

Pages: [1]   Go Up
Jump to: