IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Problème commande Stepper


Sujet :

Arduino

  1. #1
    Nouveau candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juin 2024
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2024
    Messages : 1
    Par défaut Problème commande Stepper
    Bonjour à tous, je rencontre un problème pour la commande d'un moteur pas à pas bipolaire avec une carte Arduino. Je vous explique brièvement ma situation :
    Mon moteur pas à pas dispose d'un axe autour du quel est enroulé un fil. Je dispose d'un dipôle fournissant un tension variable. Cette tension prend un nombre finis de valeurs (16 au total). Pour limiter les aléas dus à la précision j'ai choisi de définir plutôt des intervalles de tension. Cette tension va être lue par ma carte Arduino. Ensuite, pour chaque valeur de tension, mon moteur doit avoir déroulé une certaine longueur de fil (relativement à la position de départ, à savoir quand 0mm de fil est déroulé). J'ai donc créé une liste qui donne (dans le bon ordre) les longueurs déroulées associées à chaque intervalle de tension lue. Le programme va donc lire la tension, regarder si elle se trouve dans un des intervalles que j'ai défini, et si oui, calculer le nombre de pas nécessaires (par rapport à l'état initial) pour dérouler la longueur associée. Ensuite, le programme fait la différence entre la position actuelle en pas et la position à atteindre, et le moteur se déplace d'autant de pas que la différence (dans le bon sens grâce à une condition sur le signe de la différence). La tension étant amenée à varier durant l'utilisation, l'opération est en loop.

    Or quand je lance mon code, le fil se déroule une seule fois, puis plus rien, alors que je fais pourtant à nouveau varier la tension.

    Mon Arduino est une UNO R3
    Mon moteur est un stepper bipolaire.
    Mon hacheur est un L298N
    Mon alimentation est de 15V

    Je peux vous communiquer mes branchements si besoin même si je pense qu'ils sont bons étant donné que l'opération s'effectue une fois à chaque lancement. Je pense que le problème réside dans le code mais je n'arrive pas à l'identifier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    #include <AccelStepper.h>
     
    // Définitions des pins de contrôle
    #define IN1 8
    #define IN2 9
    #define IN3 10
    #define IN4 11
    #define EN1 6
    #define EN2 5
    #define POT_PIN A0
     
    // Initialisation des étapes du moteur
    int stepsPerRevolution = 200; // Ajuster selon les spécifications du moteur
    float mmPerStep = (8.0 * 3.14159) / 200.0; // Diamètre de l'axe (8 mm) converti en mm par pas
     
    // Listes des intervalles de tension et des longueurs de fil correspondantes
    float debutIntervalles[] = {0,1,2,3,4}; // Début des intervalles de tension
    float finIntervalles[] = {1,2,3,4,5};   // Fin des intervalles de tension
    float longueurs[] = {3,5,6,9,10};         // Longueurs de fil déroulées correspondantes en mm
     
    // Variables pour la position
    long targetPosition = 0;
    long currentPosition = 0;
     
    void setup() {
      pinMode(IN1, OUTPUT);
      pinMode(IN2, OUTPUT);
      pinMode(IN3, OUTPUT);
      pinMode(IN4, OUTPUT);
      pinMode(EN1, OUTPUT);
      pinMode(EN2, OUTPUT);
     
      digitalWrite(EN1, HIGH);
      digitalWrite(EN2, HIGH);
     
      Serial.begin(9600);
    }
     
    // Fonction pour faire un pas du moteur
    void stepMotor(int step) {
      switch (step) {
        case 0:
          digitalWrite(IN1, HIGH);
          digitalWrite(IN2, LOW);
          digitalWrite(IN3, HIGH);
          digitalWrite(IN4, LOW);
          break;
        case 1:
          digitalWrite(IN1, LOW);
          digitalWrite(IN2, HIGH);
          digitalWrite(IN3, HIGH);
          digitalWrite(IN4, LOW);
          break;
        case 2:
          digitalWrite(IN1, LOW);
          digitalWrite(IN2, HIGH);
          digitalWrite(IN3, LOW);
          digitalWrite(IN4, HIGH);
          break;
        case 3:
          digitalWrite(IN1, HIGH);
          digitalWrite(IN2, LOW);
          digitalWrite(IN3, LOW);
          digitalWrite(IN4, HIGH);
          break;
      }
    }
     
    // Fonction pour faire tourner le moteur jusqu'à la position cible
    void moveToPosition(long target) {
      long stepsToMove = target - currentPosition;
      int direction = stepsToMove > 0 ? 1 : -1;
     
      stepsToMove = abs(stepsToMove);
     
      for (long i = 0; i < stepsToMove; i++) {
        stepMotor((currentPosition + i * direction) % 4);
        delay(10); // Ajuster pour contrôler la vitesse
      }
     
      currentPosition = target;
    }
     
    void loop() {
      int potValue = analogRead(POT_PIN);
      float voltage = potValue * (5.0 / 1023.0);
     
      // Map la tension lue aux intervalles de longueur de corde
      for (int i = 0; i < sizeof(debutIntervalles) / sizeof(debutIntervalles[0]); i++) {
        if (voltage >= debutIntervalles[i] && voltage < finIntervalles[i]) {
          targetPosition = longueurs[i] / mmPerStep;
          break;
        }
      }
     
      moveToPosition(targetPosition);
      delay(50);
    }

  2. #2
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 754
    Par défaut
    ---

  3. #3
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 884
    Par défaut
    Oui détaillez les branchements y compris sur l’alimentation des composants / moteur.
    Alimenter un uno en 15V c’est beaucoup pour le régulateur, la doc dit 7 à 12V.

  4. #4
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 582
    Par défaut
    Bonjour,

    Dans ce code, je ne comprends pas les intervalles de tensions qui correspondent respectivement à environ (0 mV, 5mv, 10mV, 15mV, 20 mV et 25 mV). Ils sont en effet comparés au voltage. Cela ne peut marcher correctement. La précision de la mesure n'est pas suffisante (on utilise que les 6 premières positions du convertisseur). Je pense qu'il y a un facteur de conversion étapes-tensions à définir.

    La targetPosition est le fruit d'un arrondi sauvage (troncature) par un cast implicite. Il sera donc en général en deçà de l'objectif. Donc à la fin d'une étape, on a bien été à targetPosition mais celui ci est avant la fin de l'intervalle cible.

    Je conseillerais de ne pas avoir d'intervalles mais des étapes non pas en tension mais en entiers représentant la sortie du CAN 0..1023 en la divisant par 205 on a directement un n° d'étape entier entre 0 et 4 (0 à 5 avec 171) sans test de fenêtre d'intervalle. Si c'est bien comme cela que c'est envisagé un codeur rotatif serait plus approprié.

    Avec 5 étapes il est possible de revenir à 0 car la cible s'identifie à l'étape.

    Je ne sais pas si les longueurs sont des cumuls (ce qui me paraîtrait mieux) ou le propre à chaque étape étape. Cependant si c'est un cumul, avec moins de 8 pas par mm, passer de 5m à 6m pourrait nécessiter 7 ou 8 pas ce qui présente une incertitude de plus de 10 %.

    Salutations

  5. #5
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    667
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 667
    Par défaut
    Salut,

    Citation Envoyé par Guesset Voir le message
    Dans ce code, je ne comprends pas les intervalles de tensions qui correspondent respectivement à environ (0 mV, 5mv, 10mV, 15mV, 20 mV et 25 mV)
    C'est les index des 5 plages de tentions calculées à la ligne 86 (5 portions de 1023).

  6. #6
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 582
    Par défaut
    Bonjour kaitlyn,

    Citation Envoyé par kaitlyn Voir le message
    C'est les index des 5 plages de tentions calculées à la ligne 86 (5 portions de 1023).
    Le problème justement est que voltage n'est pas un index mais une valeur flottante de tension située entre 0 et 5 (5 sur une seule position donc potentiellement fluctuante) qui va être comparée à 0, 1, 2, 3, 4. Or nous cherchons un indice de repère pour lequel il suffit d'écrire (sans passer par la tension) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int      iTarget   = analogRead(POT_PIN)/205; // iTarget  est l'indice recherché directement de 0 à 5
    Le seul tableau qu'il faut conserver est alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uint16_t longueurs[6]= { 0, 3, 5, 6, 9, 10};     // Longueurs totale de fil à dérouler en mm
    Il faut 6 longueurs qui correspondent aux indices 0 à 5 pour pouvoir revenir à zéro.

    Il est inutile d'utiliser des long pour les positions : un uint16_t permet déjà 8192 mm en 327 tours. Nous sommes très loin des 10 mm . Par ailleurs, 327 tours nécessiteraient un empilement du fil donc un diamètre variable.

    La boucle principale (intégrant la commande moteur) devient alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void loop() {
       int      iTarget   = analogRead(POT_PIN)/205; // 0 à 5
       uint16_t targetPos = uint16_t(round(longueurs[iTarget] * StepPer_mm));
       int      di        = targetPos > currentPos ? 1 : -1;
       for( ; currentPos != targetPos; currentPos += di) stepMotor(currentPos);
       delay(50);                     
    }
    C'est alors stepMotor qui s'assure de travailler modulo 4.

    Il est préférable de travailler avec step/mm au lieu de mm/step car il est toujours plus efficace de faire une multiplication qu'une division :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float StepPer_mm     = 25 / 3.14159;             // Diamètre axe 8mm, 200 pas/tour : 7.96 pas par mm
    Salut

  7. #7
    Membre Expert
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    667
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 95
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 667
    Par défaut
    Citation Envoyé par Guesset Voir le message
    Le problème justement est que .../... Il faut 6 longueurs qui correspondent aux indices 0 à 5 pour pouvoir revenir à zéro
    Dans son message, elle en a 16.. Son approche lui laisse l'avantage d'affiner ses réglages et combler les imprécisions. Les valeurs dans le tableau me semblent suspectes au regard du diamètre de l'axe, le switch, la ligne 1, la 71, le délai bloquant, etc ... mais rien qui explique son problème en une première lecture de son message. Du coup il faut d'abord qu'elle valide son montage et son fonctionnement correct avec un code simpliste, en supposant qu'elle suit la discussion.

  8. #8
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 582
    Par défaut
    Bonjour kaitlyn,

    Citation Envoyé par kaitlyn Voir le message
    Dans son message, elle en a 16.. Son approche lui laisse l'avantage d'affiner ses réglages et combler les imprécisions...
    Tu as raison, le texte dit 16, mais le code fait apparaître seulement 6 étapes (initialement réparties sur les deux tableaux). Le diviseur de la valeur convertie 0..1023 peut facilement être adapté en prenant 64 pour avoir 16 valeurs de 0 à 15. C'est même plus efficace car la division peut se remplacer par >> 6 (ou laisser le compilateur se charger de l'optimisation).

    Salut

Discussions similaires

  1. Interception des commandes in et out
    Par KDD dans le forum x86 16-bits
    Réponses: 13
    Dernier message: 18/12/2002, 16h55
  2. [TP]besoin d'aide pour commandes inconnues
    Par Upal dans le forum Turbo Pascal
    Réponses: 15
    Dernier message: 03/10/2002, 10h48
  3. [Kylix] Commandes linux ss kylix
    Par csnickos dans le forum EDI
    Réponses: 3
    Dernier message: 15/09/2002, 20h24
  4. Réponses: 3
    Dernier message: 02/09/2002, 18h49
  5. Réponses: 2
    Dernier message: 11/08/2002, 21h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo