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 :

Travelling X Z pour Raspberry Pi Camera Module 3 via arduino mega 2560


Sujet :

Arduino

  1. #1
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut Travelling X Z pour Raspberry Pi Camera Module 3 via arduino mega 2560
    Bonjour à tous,

    Je souhaite faire glisser une Raspberry Pi Camera Module 3, sur l'axe x, puis l'axe Z, afin d'être au centre du sujet cible, pour un timelapse.
    Pour ce faire, je dispose de deux Micro moteur CH-SM1545-M3xP0.5 (2 phases, 4 fils bipolaires – 12V – dont la course de l'arbre fileté = 80mm), et chacun d'eux sera piloter par son propre contrôleur de moteur type A4988. La sélection ou la mise sous tension d'un des deux moteur, sera faite par un interrupteur à bascule type KCD3 ON-OFF-ON SPDT 3Positions. Selon la position de l'interrupteur (droite ou gauche), le moteur cible sera sous tension, alors que l'autre sera hors circuit.

    Voici le schéma électrique pour un seul moteur et son code arduino. Cela fonctionne bien avec les capteurs de limite IR.

    Nom : Schema_CH-SM1545-M3xP0.5 _Potentiomètre - MSx - EndStop.jpg
Affichages : 275
Taille : 153,1 Ko
    Nom : Schema_Tableau PINs connexion.jpg
Affichages : 255
Taille : 92,5 Ko

    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    /* 
    Arduino Mega + A4988
    Capteurs (IR en U) + potentiomètre contrôle distance et direction après recul
     
    --- Diagramme d’état : Moteur + Potar + Capteurs ---
     
    [START / Moteur immobile]
             |
             | Potar bougé → au-delà zone morte
             v
    [Déplacement par potar]
             |
             | Capteur déclenché (IR)
             v
    [Recul 1 cm en micro-pas]
             |
             | Recul terminé
             v
    [Moteur en PAUSE après recul]
             |
             | Potar manipulé par l'utilisateur (delta > zone morte)
             v
    [Reprise contrôle par potar]
             |
             +--> [Déplacement par potar]
     
    */
     
    // Moteur PIN
    const int MOTOR_DIR_PIN = 2;
    const int MOTOR_STEP_PIN = 3;
    const int MOTOR_ENABLE_PIN = 6;
     
    // EndStop PIN signal
    const int ENDSTOP_IR0 = 7;
    const int ENDSTOP_IR1 = 11;
     
    // EndStop MSx PIN
    const int MS1_PIN = 8;
    const int MS2_PIN = 9;
    const int MS3_PIN = 10;
     
    // Potentiomètre PIN Signal
    const int POT_PIN = A0;
     
    // Paramètres moteur
    const int Nb_Recul = 200;        // 1cm en full-step=400pas --- 0.5cm en full-step=200pas
    const int microStepFactor = 16;   // micro-pas pour recul
     
    /* 
    Le moteur avance d’un pas à chaque impulsion STEP.
    La vitesse du moteur dépend uniquement du temps entre deux impulsions.
    motorDelayMax est grand, plus le mouvement minimal est lent et précis.
    Plus motorDelayMin est petit, plus le moteur va vite.
    */
    const int motorDelayMax = 1500;   // microsecondes max STEP µs (lent)  1500 ≈ 1 mm/s
    const int motorDelayMin = 400;    // microsecondes min STEP µs (rapide) 400 ≈ 3,9 mm/s
     
    /* 
    La zone morte (deadZone) est un intervalle central autour de la valeur neutre du potar où aucun mouvement du moteur n’est déclenché.
    Exemple : const int deadZone = 50;
    Si le potentiomètre est entre -50 et +50 autour du centre, le moteur reste immobile.
    */
    const int deadZone = 200;          // zone morte du potar
     
    const int accelStep = 1;          // incrément de lissage pour acceleration 2  4
     
    bool reculEffectue = false;       // vrai après recul
    bool pauseAfterRecul = false;     // moteur en pause après recul
    int potRef = 0;                   // valeur de référence du potar après recul
    int ir0LastState = 0;
    int ir1LastState = 0;
     
     
    int currentDelay = motorDelayMax;
    bool potInverted = false;         // true = inverser la direction du potar
     
    // Fonction STEP simple
    void stepMotor(int delayMicro) {
      digitalWrite(MOTOR_STEP_PIN, HIGH);
      delayMicroseconds(delayMicro);
      digitalWrite(MOTOR_STEP_PIN, LOW);
      delayMicroseconds(delayMicro);
    }
     
    void setup() {
      pinMode(MOTOR_DIR_PIN, OUTPUT);
      pinMode(MOTOR_STEP_PIN, OUTPUT);
      pinMode(MOTOR_ENABLE_PIN, OUTPUT);
     
      // pinMode(ENDSTOP_MECA, INPUT_PULLUP);
      pinMode(ENDSTOP_IR0, INPUT);
      pinMode(ENDSTOP_IR1, INPUT);
     
      pinMode(MS1_PIN, OUTPUT);
      pinMode(MS2_PIN, OUTPUT);
      pinMode(MS3_PIN, OUTPUT);
     
      // Micro-pas 1/16 pour recul
      digitalWrite(MS1_PIN, HIGH);
      digitalWrite(MS2_PIN, HIGH);
      digitalWrite(MS3_PIN, HIGH);
      digitalWrite(MOTOR_ENABLE_PIN, LOW);
     
      delay(100); // stabilisation capteurs
      ir0LastState = digitalRead(ENDSTOP_IR0);
      ir1LastState = digitalRead(ENDSTOP_IR1);
    }
     
    void loop() {
      // ===== Lecture potar =====
      int potValue = analogRead(POT_PIN) - 512;
      int potAbs = abs(potValue);
     
      // Détermination direction potar avec inversion si activé
      bool direction = potInverted ? (potValue < 0) : (potValue > 0);
     
      // ===== Lecture capteurs =====
      int ir0State = digitalRead(ENDSTOP_IR0);
      int ir1State = digitalRead(ENDSTOP_IR1);
     
      bool ir0Triggered  = (ir0State == HIGH && ir0LastState == LOW);
      bool ir1Triggered  = (ir1State == HIGH && ir1LastState == LOW);
     
      // ===== Recul 1 cm si capteur déclenché =====
      if(!reculEffectue && (ir0Triggered || ir1Triggered)){
        delay(50);
     
        // Micro-pas pour recul
        digitalWrite(MS1_PIN, HIGH);
        digitalWrite(MS2_PIN, HIGH);
        digitalWrite(MS3_PIN, HIGH);
        digitalWrite(MOTOR_DIR_PIN, !direction); // reculer dans sens opposé au potar
        for(int i=0; i<Nb_Recul*microStepFactor; i++){
          stepMotor(motorDelayMin);
        }
     
        // Recul terminé → moteur en pause
        reculEffectue = true;
        pauseAfterRecul = true;
        potRef = potValue; // mémoriser la valeur du potar après recul
     
        // Mise à jour états capteurs
        ir0LastState = digitalRead(ENDSTOP_IR0);
        ir1LastState = digitalRead(ENDSTOP_IR1);
     
        return; // ne rien faire d'autre
      }
     
      // ===== Vérification pause après recul =====
      if(pauseAfterRecul){
        int deltaPot = abs(potValue - potRef);
        if(deltaPot > deadZone){
          // l'utilisateur a bougé le potar → reprise
          pauseAfterRecul = false;
        } else {
          return; // moteur reste en pause
        }
      }
     
      // ===== STEP proportionnel au potar avec acceleration =====
      if(potAbs >= deadZone){
        // Micro-pas 1/16 pour recul
        digitalWrite(MS1_PIN, HIGH);
        digitalWrite(MS2_PIN, HIGH);
        digitalWrite(MS3_PIN, HIGH);
        /* 
        // Passer en full-step pour potar
        digitalWrite(MS1_PIN, LOW);
        digitalWrite(MS2_PIN, LOW);
        digitalWrite(MS3_PIN, LOW); 
        */
        digitalWrite(MOTOR_DIR_PIN, direction);
     
        // Calcul vitesse cible selon potar
        int targetDelay = map(potAbs, deadZone, 512, motorDelayMax, motorDelayMin);
        targetDelay = constrain(targetDelay, motorDelayMin, motorDelayMax);
     
        // Lissage acceleration/déceleration
        if(currentDelay < targetDelay)
          currentDelay += accelStep;
        else if(currentDelay > targetDelay)
          currentDelay -= accelStep;
     
        currentDelay = constrain(currentDelay, motorDelayMin, motorDelayMax);
     
        stepMotor(currentDelay);
     
        // Autoriser un nouveau recul si le potar est utilisé après recul
        if(reculEffectue){
          reculEffectue = false;
        }
      }
     
      // Mise à jour derniers états des capteurs
      ir0LastState = ir0State;
      ir1LastState = ir1State;
    }


    J'ai plusieurs questions pour le schéma électrique.
    Je ne veux pas répliquer mon schéma pour chaque moteur. Je vais me retrouver avec deux alimentations 12V et deux potentiomètres pour le positionnement du moteur X sur l'axe X et la même chose pour l'axe Z.
    Peut-on alimenter en 12V, les deux A4988 via un troisième A4988?
    Ou dois-je placer l'interrupteur à bascule? À la entre le 3ème A4988 et les deux autres, ou est-ce faisable, directement sur l'arduino mega 2560.

    Merci pour votre temps, et vos idées. J'ai peux d'expérience et curieux.

  2. #2
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 354
    Billets dans le blog
    48
    Par défaut
    Bonjour,

    L'alimentation semble suffisamment dimensionnée, une seule suffira et tu alimentes les deux A4988 en parallèle sur cette alimentation (pas besoin d'un 3è driver).

    Pour sélectionner le moteur, il faut laisser les deux drivers alimentés en permanence (jouer sur leur alimentation pour sélectionner l'un ou l'autre n'est pas recommandé). Tu relies une sortie de l'Arduino vers la broche Enable (EN) du driver du moteur X, et une autre sortie de l'Arduino vers la broche Enable (EN) du driver du moteur Z. Selon l'état de l'interrupteur câblé à l'Arduino, tu actives la broche Enable du moteur choisi (après avoir désactivé l'autre).
    Ainsi, les entrées STEP et DIR peuvent être communes, les deux drivers recevront les mêmes signaux mais un seul sera actif grâce à l'Enable. Les broches MS1, MS2 et MS3 peuvent aussi être communes si les deux moteurs emploient la même résolution.

  3. #3
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    Merci pour votre réponse.
    voici le schéma de câblage de deux contrôleurs de moteur A4988.
    Par contre, je ne suis pas sûr, des liaisons de mise en parallèle de la tension 12V entre VMOT et l’interrupteur à bascule de 3 pins.

    Nom : A4988 en parallèle_1.jpg
Affichages : 203
Taille : 145,4 Ko

  4. #4
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 354
    Billets dans le blog
    48
    Par défaut
    - Les deux VDD des A4988 doivent être directement reliés au 5V de l'Arduino.
    - Les VMOT des deux A4988 doivent être directement reliés au 12V (avec leur condensateur).
    - Les GND sont communs (masse unique pour tout le système).

    Surtout, l'interrupteur ne devrait pas être dans le chemin du 12V, il faut le câbler aux entrées de l'Arduino. L'interrupteur ne coupe pas l'alimentation (cela créerait des "chocs électriques" dans le circuit, des surtensions ...), il informe l'Arduino qui sélectionne ensuite le moteur voulu en activant sa broche Enable.
    Par exemple, le COM de l'interrupteur est relié à GND, NC est relié à une entrée de l'Arduino, NO est relié à une autre entrée de l'Arduino. Dans le code, il faut configurer ces deux entrées en INPUT_PULLUP.

  5. #5
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    j'ai appliqué ce dont vous préconisés.

    pouvez vous, s'il vous plaît, vérifier s'il n'y a pas d'erreurs?
    merci de votre aide.

    Nom : A4988 en parallèle_2.jpg
Affichages : 199
Taille : 144,0 Ko

    je ne suis pas sûr du faisceau GND. d'après les lecture que j'ai parcouru, cela s'appelle une plan de masse, afin que le voltage soit à zéro.

  6. #6
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 354
    Billets dans le blog
    48
    Par défaut
    On parle de "plan de masse" pour les circuits imprimés avec une grande surface de cuivre commune pour la masse. Sur ton schéma, on voit bien que toutes les masses sont reliées ensemble.

    Le schéma me semble correct

    Yapluka

  7. #7
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    merci pour aide,

    j'ai bien avancé. j'ai implémenté les 4 capteur optique pour les deux moteurs pas à pas bipolaire.

    Faut-il ajouter un condensateur à la sortie du 5V et GND de l'arduino mega 2560? si oui, un 100µF ou 470µF?

    je souhaite ajouter, pour contrôle visuel, à chaque moteur, une paire de diode (rouge = OFF -- vert = ON) indiquant le mise sous tension.
    Dois brancher la diode avec sa résistance de 220Ω entre NC et la borne 9 arduino et une autre NO et la borne 10 arduino?

    Nom : A4988 en parallèle_3a.jpg
Affichages : 183
Taille : 183,7 Ko

    merci pour votre temps

  8. #8
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 354
    Billets dans le blog
    48
    Par défaut
    Bonjour,

    Citation Envoyé par LS_Soleil Voir le message
    Faut-il ajouter un condensateur à la sortie du 5V et GND de l'arduino mega 2560? si oui, un 100µF ou 470µF?
    Inutile, la sortie 5V de l'Arduino est déjà régulée.

    Citation Envoyé par LS_Soleil Voir le message
    je souhaite ajouter, pour contrôle visuel, à chaque moteur, une paire de diode (rouge = OFF -- vert = ON) indiquant le mise sous tension.
    Dois brancher la diode avec sa résistance de 220Ω entre NC et la borne 9 arduino et une autre NO et la borne 10 arduino?
    Tu vas perturber les niveaux logiques des entrées de l'Arduino de la sorte.

    Par contre tu peux mettre les leds sur le chemin des Enable, par exemple (pour un moteur) :
    Nom : ledredoff-ledgreenon.jpg
Affichages : 179
Taille : 22,1 Ko
    Si Enable=0, led rouge allumée, led verte éteinte
    Si Enable=1, led verte allumée, led rouge éteinte

  9. #9
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    Merci pour votre réponse.

    le type schéma que vous avez posté, ce nomme bien, un schéma théorique?
    Etant novice, la lecture m'est pas facile.

    voici mon interprétation sur un plan de raccordement via EN du contrôleur moteur Z, si l'on peut appeler cela ainsi.
    j'ai fais attention au sens de l'anode de la résistance, pour recevoir le 5V+.

    merci d'avance de votre, si mon interprétation est erronée.

    Nom : A4988 en parallèle_4 - LEDs.jpg
Affichages : 157
Taille : 34,4 Ko

  10. #10
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 354
    Billets dans le blog
    48
    Par défaut
    Citation Envoyé par LS_Soleil Voir le message
    le type schéma que vous avez posté, ce nomme bien, un schéma théorique?
    C'est un schéma élec. normalisé (ici, norme US je crois).

    Tu l'as bien interprété en tout cas, ton montage me semble correct

  11. #11
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    merci pour aide.
    bonne fin de journée

  12. #12
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    bonjour f-leb,

    je suis passé sur Fritzing, pour faire la première étape "Platine d'essai".
    voici le schéma dessiné.
    Nom : Fritzing - Platine d'essais.jpg
Affichages : 116
Taille : 215,6 Ko

    j'ai branché GND arduino, directement sur GND du 12V. Est ce ainsi que l'on procède, pour le plan de masse?


    j'ai remarqué sur l'onglet "Vue schématique", lorsque par exemple, le GND des capteurs rejoindre indirectement, le GND 12V sur la platine d'essais, ils n’apparaissent pas.
    Afin, qu'il apparaisse, il faut faire une liaison direct. n'est ce pas?

    merci

  13. #13
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    j'ai effectué les connexions individuellement.il semble que soit la même chose, dans l'onglet "Vue schématique"
    Nom : Fritzing - Platine d'essais_TEST_GND.jpg
Affichages : 114
Taille : 199,0 Ko

  14. #14
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    Bonjour tout le monde,

    le premier point, après lecture sur le net, le Enable n'a pas assez de courant, pour la LED. alors j'ai opté pour une led indépendante sur une autre pin arduino.
    j'ai fais le labo avec un seul moteur voici le code qui fonctionne bien.

    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    /*
    LABO moteur X LED KCD3_SPDT
    */
     
    /* 
    Arduino Mega + A4988
    Capteurs (IR en U) + potentiomètre contrôle distance et direction après recul
     
    --- Diagramme d’état : Moteur + Potar + Capteurs ---
     
    [START / Moteur immobile]
             |
             | Potar bougé → au-delà zone morte
             v
    [Déplacement par potar]
             |
             | Capteur déclenché (IR)
             v
    [Recul 1 cm en micro-pas]
             |
             | Recul terminé
             v
    [Moteur en PAUSE après recul]
             |
             | Potar manipulé par l'utilisateur (delta > zone morte)
             v
    [Reprise contrôle par potar]
             |
             +--> [Déplacement par potar]
     
    */
     
    // Moteur PIN
    const int MOTOR_DIR_PIN = 2;
    const int MOTOR_STEP_PIN = 3;
    const int MOTOR_ENABLE_PIN = 6;
     
    // EndStop PIN signal
    const int ENDSTOP_IR0 = 7;
    const int ENDSTOP_IR1 = 11;
     
    // EndStop MSx PIN
    const int MS1_PIN = 8;
    const int MS2_PIN = 9;
    const int MS3_PIN = 10;
     
    // Potentiomètre PIN Signal
    const int POT_PIN = A0;
     
    // Interupteur KCD3SPDT ON-OFF-ON PIN Signal
    const int KCD3_SPDT_PIN_NO_D = A6;
    const int KCD3_SPDT_PIN_NO_G = A5;
     
    // LEDs
    const int ledPin_Green_X = 12;     // LED Green X
     
    // Paramètres moteur
    const int Nb_Recul = 200;        // 1cm en full-step=400pas --- 0.5cm en full-step=200pas
    const int microStepFactor = 16;   // micro-pas pour recul
     
    /* 
    Le moteur avance d’un pas à chaque impulsion STEP.
    La vitesse du moteur dépend uniquement du temps entre deux impulsions.
    motorDelayMax est grand, plus le mouvement minimal est lent et précis.
    Plus motorDelayMin est petit, plus le moteur va vite.
    */
    const int motorDelayMax = 1500;   // microsecondes max STEP µs (lent)  1500 ≈ 1 mm/s
    const int motorDelayMin = 400;    // microsecondes min STEP µs (rapide) 400 ≈ 3,9 mm/s
     
    /* 
    La zone morte (deadZone) est un intervalle central autour de la valeur neutre du potar où aucun mouvement du moteur n’est déclenché.
    Exemple : const int deadZone = 50;
    Si le potentiomètre est entre -50 et +50 autour du centre, le moteur reste immobile.
    */
    const int deadZone = 200;          // zone morte du potar
     
    const int accelStep = 1;          // incrément de lissage pour acceleration 2  4
     
    bool reculEffectue = false;       // vrai après recul
    bool pauseAfterRecul = false;     // moteur en pause après recul
    int potRef = 0;                   // valeur de référence du potar après recul
    int ir0LastState = 0;
    int ir1LastState = 0;
     
    int currentDelay = motorDelayMax;
    bool potInverted = false;         // true = inverser la direction du potar
     
    // Fonction STEP simple
    void stepMotor(int delayMicro) {
      digitalWrite(MOTOR_STEP_PIN, HIGH);
      delayMicroseconds(delayMicro);
      digitalWrite(MOTOR_STEP_PIN, LOW);
      delayMicroseconds(delayMicro);
    }
     
    void setup() {
        // LEDs
      pinMode(ledPin_Green_X, OUTPUT);
     
      // KCD3
      pinMode(KCD3_SPDT_PIN_NO_D, INPUT_PULLUP);
      pinMode(KCD3_SPDT_PIN_NO_G, INPUT_PULLUP);
     
      // Moteurs
      pinMode(MOTOR_DIR_PIN, OUTPUT);
      pinMode(MOTOR_STEP_PIN, OUTPUT);
      pinMode(MOTOR_ENABLE_PIN, OUTPUT);
     
      // pinMode(ENDSTOP_MECA, INPUT_PULLUP);
      pinMode(ENDSTOP_IR0, INPUT);
      pinMode(ENDSTOP_IR1, INPUT);
     
      pinMode(MS1_PIN, OUTPUT);
      pinMode(MS2_PIN, OUTPUT);
      pinMode(MS3_PIN, OUTPUT);
     
      // Micro-pas 1/16 pour recul
      digitalWrite(MS1_PIN, HIGH);
      digitalWrite(MS2_PIN, HIGH);
      digitalWrite(MS3_PIN, HIGH);
      //digitalWrite(MOTOR_ENABLE_PIN, LOW);
     
      // LED Etat OFF
      digitalWrite(ledPin_Green_X, LOW);
     
      delay(100); // stabilisation capteurs
      ir0LastState = digitalRead(ENDSTOP_IR0);
      ir1LastState = digitalRead(ENDSTOP_IR1);
    }
     
    void loop() {
      int etatNO_D = digitalRead(KCD3_SPDT_PIN_NO_D); // HIGH = ouvert, LOW = fermé
      int etatNO_G = digitalRead(KCD3_SPDT_PIN_NO_G);
     
     
      if (etatNO_D == HIGH && etatNO_G == HIGH){
        // LED OFF
        digitalWrite(ledPin_Green_X, LOW);
      }
     
      if (etatNO_G == LOW){
        // LED OFF
        digitalWrite(ledPin_Green_X, LOW);
      }
     
      if (etatNO_D == LOW){  
        // LED ON
        digitalWrite(ledPin_Green_X, HIGH);
     
        // ===== Lecture potar =====
        int potValue = analogRead(POT_PIN) - 512;
        int potAbs = abs(potValue);
     
        // Détermination direction potar avec inversion si activé
        bool direction = potInverted ? (potValue < 0) : (potValue > 0);
     
        // ===== Lecture capteurs =====
        int ir0State = digitalRead(ENDSTOP_IR0);
        int ir1State = digitalRead(ENDSTOP_IR1);
     
        bool ir0Triggered  = (ir0State == HIGH && ir0LastState == LOW);
        bool ir1Triggered  = (ir1State == HIGH && ir1LastState == LOW);
     
        // ===== Recul 1 cm si capteur déclenché =====
        if(!reculEffectue && (ir0Triggered || ir1Triggered)){
          delay(50);
     
          // Micro-pas pour recul
          digitalWrite(MS1_PIN, HIGH);
          digitalWrite(MS2_PIN, HIGH);
          digitalWrite(MS3_PIN, HIGH);
          digitalWrite(MOTOR_DIR_PIN, !direction); // reculer dans sens opposé au potar
          for(int i=0; i<Nb_Recul*microStepFactor; i++){
            stepMotor(motorDelayMin);
          }
     
          // Recul terminé → moteur en pause
          reculEffectue = true;
          pauseAfterRecul = true;
          potRef = potValue; // mémoriser la valeur du potar après recul
     
          // Mise à jour états capteurs
          ir0LastState = digitalRead(ENDSTOP_IR0);
          ir1LastState = digitalRead(ENDSTOP_IR1);
     
          return; // ne rien faire d'autre
        }
     
        // ===== Vérification pause après recul =====
        if(pauseAfterRecul){
          int deltaPot = abs(potValue - potRef);
          if(deltaPot > deadZone){
            // l'utilisateur a bougé le potar → reprise
            pauseAfterRecul = false;
          } else {
            return; // moteur reste en pause
          }
        }
     
        // ===== STEP proportionnel au potar avec acceleration =====
        if(potAbs >= deadZone){
          // Micro-pas 1/16 pour recul
          digitalWrite(MS1_PIN, HIGH);
          digitalWrite(MS2_PIN, HIGH);
          digitalWrite(MS3_PIN, HIGH);
          /* 
          // Passer en full-step pour potar
          digitalWrite(MS1_PIN, LOW);
          digitalWrite(MS2_PIN, LOW);
          digitalWrite(MS3_PIN, LOW); 
          */
          digitalWrite(MOTOR_DIR_PIN, direction);
     
          // Calcul vitesse cible selon potar
          int targetDelay = map(potAbs, deadZone, 512, motorDelayMax, motorDelayMin);
          targetDelay = constrain(targetDelay, motorDelayMin, motorDelayMax);
     
          // Lissage acceleration/déceleration
          if(currentDelay < targetDelay)
            currentDelay += accelStep;
          else if(currentDelay > targetDelay)
            currentDelay -= accelStep;
     
          currentDelay = constrain(currentDelay, motorDelayMin, motorDelayMax);
     
          stepMotor(currentDelay);
     
          // Autoriser un nouveau recul si le potar est utilisé après recul
          if(reculEffectue){
            reculEffectue = false;
          }
        }
     
        // Mise à jour derniers états des capteurs
        ir0LastState = ir0State;
        ir1LastState = ir1State;
     
      }  
    }
    sur la planche d'essais, j'ai effectué les raccordements du deuxième A4988, de son moteur et des deux capteur de proximité IR.
    les MS1 MS2 MS3 sont commun.
    les STEP sont commun.
    les DIR sont commum.

    une fois le code téléversé dans l'arduino. l'interupteur KCD3 fonctionne bien, en allumant la led correspondant au moteur X ou Z.
    Par contre, le moteur cible ne réagit pas.
    je n’entends de bruit quelconques.
    Le code contient uniquement le code pour le moteur X, pour le Z, seul la led confirme le bon choix via KCD3.

    voici le code :

    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
     
    /*
    LABO moteur X LED KCD3_SPDT
    */
     
    /* 
    Arduino Mega + A4988
    Capteurs (IR en U) + potentiomètre contrôle distance et direction après recul
     
    --- Diagramme d’état : Moteur + Potar + Capteurs ---
     
    [START / Moteur immobile]
             |
             | Potar bougé → au-delà zone morte
             v
    [Déplacement par potar]
             |
             | Capteur déclenché (IR)
             v
    [Recul 1 cm en micro-pas]
             |
             | Recul terminé
             v
    [Moteur en PAUSE après recul]
             |
             | Potar manipulé par l'utilisateur (delta > zone morte)
             v
    [Reprise contrôle par potar]
             |
             +--> [Déplacement par potar]
     
    */
     
    // Moteur PIN
    const int MOTOR_DIR_PIN = 2;
    const int MOTOR_STEP_PIN = 3;
    const int MOTOR_ENABLE_PIN = 6;
    const int MOTOR_ENABLE_PIN_Z = 13;
     
    // EndStop PIN signal
    const int ENDSTOP_IR0 = 7;
    const int ENDSTOP_IR1 = 11;
    const int ENDSTOP_IR0_Z = 4;
    const int ENDSTOP_IR1_Z = 5;
     
    // EndStop MSx PIN
    const int MS1_PIN = 8;
    const int MS2_PIN = 9;
    const int MS3_PIN = 10;
     
    // Potentiomètre PIN Signal
    const int POT_PIN = A0;
     
    // Interupteur KCD3SPDT ON-OFF-ON PIN Signal
    const int KCD3_SPDT_PIN_NO_D = A6;
    const int KCD3_SPDT_PIN_NO_G = A5;
     
    // LEDs
    const int ledPin_Green_X = 12;     // LED Green X
    const int ledPin_Green_Z = A8;     // LED Green Z
     
    // Paramètres moteur
    const int Nb_Recul = 200;        // 1cm en full-step=400pas --- 0.5cm en full-step=200pas
    const int microStepFactor = 16;   // micro-pas pour recul
     
    /* 
    Le moteur avance d’un pas à chaque impulsion STEP.
    La vitesse du moteur dépend uniquement du temps entre deux impulsions.
    motorDelayMax est grand, plus le mouvement minimal est lent et précis.
    Plus motorDelayMin est petit, plus le moteur va vite.
    */
    const int motorDelayMax = 1500;   // microsecondes max STEP µs (lent)  1500 ≈ 1 mm/s
    const int motorDelayMin = 400;    // microsecondes min STEP µs (rapide) 400 ≈ 3,9 mm/s
     
    /* 
    La zone morte (deadZone) est un intervalle central autour de la valeur neutre du potar où aucun mouvement du moteur n’est déclenché.
    Exemple : const int deadZone = 50;
    Si le potentiomètre est entre -50 et +50 autour du centre, le moteur reste immobile.
    */
    const int deadZone = 200;          // zone morte du potar
     
    const int accelStep = 1;          // incrément de lissage pour acceleration 2  4
     
    bool reculEffectue = false;       // vrai après recul
    bool pauseAfterRecul = false;     // moteur en pause après recul
    int potRef = 0;                   // valeur de référence du potar après recul
    int ir0LastState = 0;
    int ir1LastState = 0;
     
    int currentDelay = motorDelayMax;
    bool potInverted = false;         // true = inverser la direction du potar
     
    // Fonction STEP simple
    void stepMotor(int delayMicro) {
      digitalWrite(MOTOR_STEP_PIN, HIGH);
      delayMicroseconds(delayMicro);
      digitalWrite(MOTOR_STEP_PIN, LOW);
      delayMicroseconds(delayMicro);
    }
     
    void setup() {
        // LEDs
      pinMode(ledPin_Green_X, OUTPUT);
      pinMode(ledPin_Green_Z, OUTPUT);
     
      // KCD3
      pinMode(KCD3_SPDT_PIN_NO_D, INPUT_PULLUP);
      pinMode(KCD3_SPDT_PIN_NO_G, INPUT_PULLUP);
     
      // Moteurs
      pinMode(MOTOR_DIR_PIN, OUTPUT);
      pinMode(MOTOR_STEP_PIN, OUTPUT);
      pinMode(MOTOR_ENABLE_PIN, OUTPUT);
      pinMode(MOTOR_ENABLE_PIN_Z, OUTPUT);
     
      // pinMode(ENDSTOP_MECA, INPUT_PULLUP);
      pinMode(ENDSTOP_IR0, INPUT);
      pinMode(ENDSTOP_IR1, INPUT);
      pinMode(ENDSTOP_IR0_Z, INPUT);
      pinMode(ENDSTOP_IR1_Z, INPUT);
     
      pinMode(MS1_PIN, OUTPUT);
      pinMode(MS2_PIN, OUTPUT);
      pinMode(MS3_PIN, OUTPUT);
     
      // Micro-pas 1/16 pour recul
      digitalWrite(MS1_PIN, HIGH);
      digitalWrite(MS2_PIN, HIGH);
      digitalWrite(MS3_PIN, HIGH);
      //digitalWrite(MOTOR_ENABLE_PIN, LOW);
     
      // LED Etat OFF
      digitalWrite(ledPin_Green_X, LOW);
      digitalWrite(ledPin_Green_Z, LOW);
     
      delay(100); // stabilisation capteurs
      ir0LastState = digitalRead(ENDSTOP_IR0);
      ir1LastState = digitalRead(ENDSTOP_IR1);
    }
     
    void loop() {
      int etatNO_D = digitalRead(KCD3_SPDT_PIN_NO_D); // HIGH = ouvert, LOW = fermé
      int etatNO_G = digitalRead(KCD3_SPDT_PIN_NO_G);
     
     
      if (etatNO_D == HIGH && etatNO_G == HIGH){
        // LED OFF
        digitalWrite(ledPin_Green_X, LOW);
        digitalWrite(ledPin_Green_Z, LOW);
      }
     
      if (etatNO_G == LOW){
        // LED OFF
        digitalWrite(ledPin_Green_X, LOW);
        digitalWrite(ledPin_Green_Z, HIGH);
      }
     
      if (etatNO_D == LOW){  
        // LED ON
        digitalWrite(ledPin_Green_X, HIGH);
        digitalWrite(ledPin_Green_Z, LOW);
     
        // ===== Lecture potar =====
        int potValue = analogRead(POT_PIN) - 512;
        int potAbs = abs(potValue);
     
        // Détermination direction potar avec inversion si activé
        bool direction = potInverted ? (potValue < 0) : (potValue > 0);
     
        // ===== Lecture capteurs =====
        int ir0State = digitalRead(ENDSTOP_IR0);
        int ir1State = digitalRead(ENDSTOP_IR1);
     
        bool ir0Triggered  = (ir0State == HIGH && ir0LastState == LOW);
        bool ir1Triggered  = (ir1State == HIGH && ir1LastState == LOW);
     
        // ===== Recul 1 cm si capteur déclenché =====
        if(!reculEffectue && (ir0Triggered || ir1Triggered)){
          delay(50);
     
          // Micro-pas pour recul
          digitalWrite(MS1_PIN, HIGH);
          digitalWrite(MS2_PIN, HIGH);
          digitalWrite(MS3_PIN, HIGH);
          digitalWrite(MOTOR_DIR_PIN, !direction); // reculer dans sens opposé au potar
          for(int i=0; i<Nb_Recul*microStepFactor; i++){
            stepMotor(motorDelayMin);
          }
     
          // Recul terminé → moteur en pause
          reculEffectue = true;
          pauseAfterRecul = true;
          potRef = potValue; // mémoriser la valeur du potar après recul
     
          // Mise à jour états capteurs
          ir0LastState = digitalRead(ENDSTOP_IR0);
          ir1LastState = digitalRead(ENDSTOP_IR1);
     
          return; // ne rien faire d'autre
        }
     
        // ===== Vérification pause après recul =====
        if(pauseAfterRecul){
          int deltaPot = abs(potValue - potRef);
          if(deltaPot > deadZone){
            // l'utilisateur a bougé le potar → reprise
            pauseAfterRecul = false;
          } else {
            return; // moteur reste en pause
          }
        }
     
        // ===== STEP proportionnel au potar avec acceleration =====
        if(potAbs >= deadZone){
          // Micro-pas 1/16 pour recul
          digitalWrite(MS1_PIN, HIGH);
          digitalWrite(MS2_PIN, HIGH);
          digitalWrite(MS3_PIN, HIGH);
          /* 
          // Passer en full-step pour potar
          digitalWrite(MS1_PIN, LOW);
          digitalWrite(MS2_PIN, LOW);
          digitalWrite(MS3_PIN, LOW); 
          */
          digitalWrite(MOTOR_DIR_PIN, direction);
     
          // Calcul vitesse cible selon potar
          int targetDelay = map(potAbs, deadZone, 512, motorDelayMax, motorDelayMin);
          targetDelay = constrain(targetDelay, motorDelayMin, motorDelayMax);
     
          // Lissage acceleration/déceleration
          if(currentDelay < targetDelay)
            currentDelay += accelStep;
          else if(currentDelay > targetDelay)
            currentDelay -= accelStep;
     
          currentDelay = constrain(currentDelay, motorDelayMin, motorDelayMax);
     
          stepMotor(currentDelay);
     
          // Autoriser un nouveau recul si le potar est utilisé après recul
          if(reculEffectue){
            reculEffectue = false;
          }
        }
     
        // Mise à jour derniers états des capteurs
        ir0LastState = ir0State;
        ir1LastState = ir1State;
     
      }  
    }
    je pense que le câblage est correcte.
    la source du problème, doit être le code, mais je vois d'anomalies.

    merci pour votre temps.

  15. #15
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 3 094
    Par défaut
    Est-ce que vous pouvez préciser à quel niveau logique se trouve la broche ENABLE de chaque A4988 pendant le test, et confirmer qu’elle est bien forcée à LOW pour activer le driver, ainsi que vérifier que VMOT et GND du second driver sont correctement alimentés avec une masse commune à l’Arduino, et enfin indiquer si le moteur devient dur à la main sous tension ou reste complètement libre ?

  16. #16
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    merci de votre aide.

    lorsque l’interrupteur KCD3 est en position pour le moteur X --> le moniteur de série, affiche 0
    lorsque l’interrupteur KCD3 est en position pour le moteur Z --> le moniteur de série, affiche 0

    concernant le câblage, le VMOT X et VMOT Z sont sur le 12V+
    concernant le câblage, le GND X et GND Z sont sur le GND 12V-
    Le GND 12V- et relié au GND 5V arduino.
    pour ma part, le plan de masse est OK.

    j'ai à nouveau vérifié, toute les câblages - rien à signalé.

    Le moteur hors tension ou sous tension, l'arbre ne tourne pas. (j'ai testé chaque moteur avec le code pour un seul moteur).

    --> [Hier, 11h31] mon post
    j'ai fais le labo avec un seul moteur voici le code qui fonctionne bien.

    les deux moteurs sont fonctionnels.

    la question que je me pose, dans la boucle loop, la configuration du potentiomètre doit être en dehors de a condition IF?

    voici le code que l'on test

    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
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    /*
    LABO moteur X LED KCD3_SPDT
    */
     
    /* 
    Arduino Mega + A4988
    Capteurs (IR en U) + potentiomètre contrôle distance et direction après recul
     
    --- Diagramme d’état : Moteur + Potar + Capteurs ---
     
    [START / Moteur immobile]
             |
             | Potar bougé → au-delà zone morte
             v
    [Déplacement par potar]
             |
             | Capteur déclenché (IR)
             v
    [Recul 1 cm en micro-pas]
             |
             | Recul terminé
             v
    [Moteur en PAUSE après recul]
             |
             | Potar manipulé par l'utilisateur (delta > zone morte)
             v
    [Reprise contrôle par potar]
             |
             +--> [Déplacement par potar]
     
    */
     
    // Moteur PIN
    const int MOTOR_DIR_PIN = 2;
    const int MOTOR_STEP_PIN = 3;
    const int MOTOR_ENABLE_PIN = 6;
    const int MOTOR_ENABLE_PIN_Z = 13;
     
    // EndStop PIN signal
    const int ENDSTOP_IR0 = 7;
    const int ENDSTOP_IR1 = 11;
    const int ENDSTOP_IR0_Z = 4;
    const int ENDSTOP_IR1_Z = 5;
     
    // EndStop MSx PIN
    const int MS1_PIN = 8;
    const int MS2_PIN = 9;
    const int MS3_PIN = 10;
     
    // Potentiomètre PIN Signal
    const int POT_PIN = A0;
     
    // Interupteur KCD3SPDT ON-OFF-ON PIN Signal
    const int KCD3_SPDT_PIN_NO_D = A6;
    const int KCD3_SPDT_PIN_NO_G = A5;
     
    // LEDs
    const int ledPin_Green_X = 12;     // LED Green X
    const int ledPin_Green_Z = A8;     // LED Green Z
     
    // Paramètres moteur
    const int Nb_Recul = 200;        // 1cm en full-step=400pas --- 0.5cm en full-step=200pas
    const int microStepFactor = 16;   // micro-pas pour recul
     
    /* 
    Le moteur avance d’un pas à chaque impulsion STEP.
    La vitesse du moteur dépend uniquement du temps entre deux impulsions.
    motorDelayMax est grand, plus le mouvement minimal est lent et précis.
    Plus motorDelayMin est petit, plus le moteur va vite.
    */
    const int motorDelayMax = 1500;   // microsecondes max STEP µs (lent)  1500 ≈ 1 mm/s
    const int motorDelayMin = 400;    // microsecondes min STEP µs (rapide) 400 ≈ 3,9 mm/s
     
    /* 
    La zone morte (deadZone) est un intervalle central autour de la valeur neutre du potar où aucun mouvement du moteur n’est déclenché.
    Exemple : const int deadZone = 50;
    Si le potentiomètre est entre -50 et +50 autour du centre, le moteur reste immobile.
    */
    const int deadZone = 200;          // zone morte du potar
     
    const int accelStep = 1;          // incrément de lissage pour acceleration 2  4
     
    bool reculEffectue = false;       // vrai après recul
    bool pauseAfterRecul = false;     // moteur en pause après recul
    int potRef = 0;                   // valeur de référence du potar après recul
    int ir0LastState = 0;
    int ir1LastState = 0;
     
    int currentDelay = motorDelayMax;
    bool potInverted = false;         // true = inverser la direction du potar
     
    // Fonction STEP simple
    void stepMotor(int delayMicro) {
      digitalWrite(MOTOR_STEP_PIN, HIGH);
      delayMicroseconds(delayMicro);
      digitalWrite(MOTOR_STEP_PIN, LOW);
      delayMicroseconds(delayMicro);
    }
     
    void setup() {
        // LEDs
      pinMode(ledPin_Green_X, OUTPUT);
      pinMode(ledPin_Green_Z, OUTPUT);
     
      // KCD3
      pinMode(KCD3_SPDT_PIN_NO_D, INPUT_PULLUP);
      pinMode(KCD3_SPDT_PIN_NO_G, INPUT_PULLUP);
     
      // Moteurs
      pinMode(MOTOR_DIR_PIN, OUTPUT);
      pinMode(MOTOR_STEP_PIN, OUTPUT);
      pinMode(MOTOR_ENABLE_PIN, OUTPUT);
      pinMode(MOTOR_ENABLE_PIN_Z, OUTPUT);
     
      // pinMode(ENDSTOP_MECA, INPUT_PULLUP);
      pinMode(ENDSTOP_IR0, INPUT);
      pinMode(ENDSTOP_IR1, INPUT);
      pinMode(ENDSTOP_IR0_Z, INPUT);
      pinMode(ENDSTOP_IR1_Z, INPUT);
     
      pinMode(MS1_PIN, OUTPUT);
      pinMode(MS2_PIN, OUTPUT);
      pinMode(MS3_PIN, OUTPUT);
     
      // Micro-pas 1/16 pour recul
      digitalWrite(MS1_PIN, HIGH);
      digitalWrite(MS2_PIN, HIGH);
      digitalWrite(MS3_PIN, HIGH);
      digitalWrite(MOTOR_ENABLE_PIN, LOW);
     
      // LED Etat OFF
      digitalWrite(ledPin_Green_X, LOW);
      digitalWrite(ledPin_Green_Z, LOW);
     
      delay(100); // stabilisation capteurs
      ir0LastState = digitalRead(ENDSTOP_IR0);
      ir1LastState = digitalRead(ENDSTOP_IR1);
      Serial.begin(9600);
     
    }
     
    void loop() {
      int etatNO_D = digitalRead(KCD3_SPDT_PIN_NO_D); // HIGH = ouvert, LOW = fermé
      int etatNO_G = digitalRead(KCD3_SPDT_PIN_NO_G);
      int Enable_X = digitalRead(MOTOR_ENABLE_PIN);
      int Enable_Z = digitalRead(MOTOR_ENABLE_PIN_Z);
     
     
     
      if (etatNO_D == HIGH && etatNO_G == HIGH){    
        // LED OFF
        digitalWrite(ledPin_Green_X, LOW);
        digitalWrite(ledPin_Green_Z, LOW);
      }
     
      if (etatNO_G == LOW){
        Serial.print("Enable Z -->  ");
        Serial.println(Enable_Z);
     
        // LED OFF
        digitalWrite(ledPin_Green_X, LOW);
        digitalWrite(ledPin_Green_Z, HIGH);
      }
     
      if (etatNO_D == LOW && Enable_X == LOW){  
        Serial.print("Enable X -->  ");
        Serial.println(Enable_X);
     
        // LED ON
        digitalWrite(ledPin_Green_X, HIGH);
        digitalWrite(ledPin_Green_Z, LOW);
     
        // ===== Lecture potar =====
        int potValue = analogRead(POT_PIN) - 512;
        int potAbs = abs(potValue);
     
        // Détermination direction potar avec inversion si activé
        bool direction = potInverted ? (potValue < 0) : (potValue > 0);
     
        // ===== Lecture capteurs =====
        int ir0State = digitalRead(ENDSTOP_IR0);
        int ir1State = digitalRead(ENDSTOP_IR1);
     
        bool ir0Triggered  = (ir0State == HIGH && ir0LastState == LOW);
        bool ir1Triggered  = (ir1State == HIGH && ir1LastState == LOW);
     
        // ===== Recul 1 cm si capteur déclenché =====
        if(!reculEffectue && (ir0Triggered || ir1Triggered)){
          delay(50);
     
          // Micro-pas pour recul
          digitalWrite(MS1_PIN, HIGH);
          digitalWrite(MS2_PIN, HIGH);
          digitalWrite(MS3_PIN, HIGH);
          digitalWrite(MOTOR_DIR_PIN, !direction); // reculer dans sens opposé au potar
          for(int i=0; i<Nb_Recul*microStepFactor; i++){
            stepMotor(motorDelayMin);
          }
     
          // Recul terminé → moteur en pause
          reculEffectue = true;
          pauseAfterRecul = true;
          potRef = potValue; // mémoriser la valeur du potar après recul
     
          // Mise à jour états capteurs
          ir0LastState = digitalRead(ENDSTOP_IR0);
          ir1LastState = digitalRead(ENDSTOP_IR1);
     
          return; // ne rien faire d'autre
        }
     
        // ===== Vérification pause après recul =====
        if(pauseAfterRecul){
          int deltaPot = abs(potValue - potRef);
          if(deltaPot > deadZone){
            // l'utilisateur a bougé le potar → reprise
            pauseAfterRecul = false;
          } else {
            return; // moteur reste en pause
          }
        }
     
        // ===== STEP proportionnel au potar avec acceleration =====
        if(potAbs >= deadZone){
          // Micro-pas 1/16 pour recul
          digitalWrite(MS1_PIN, HIGH);
          digitalWrite(MS2_PIN, HIGH);
          digitalWrite(MS3_PIN, HIGH);
          /* 
          // Passer en full-step pour potar
          digitalWrite(MS1_PIN, LOW);
          digitalWrite(MS2_PIN, LOW);
          digitalWrite(MS3_PIN, LOW); 
          */
          digitalWrite(MOTOR_DIR_PIN, direction);
     
          // Calcul vitesse cible selon potar
          int targetDelay = map(potAbs, deadZone, 512, motorDelayMax, motorDelayMin);
          targetDelay = constrain(targetDelay, motorDelayMin, motorDelayMax);
     
          // Lissage acceleration/déceleration
          if(currentDelay < targetDelay)
            currentDelay += accelStep;
          else if(currentDelay > targetDelay)
            currentDelay -= accelStep;
     
          currentDelay = constrain(currentDelay, motorDelayMin, motorDelayMax);
     
          stepMotor(currentDelay);
     
          // Autoriser un nouveau recul si le potar est utilisé après recul
          if(reculEffectue){
            reculEffectue = false;
          }
        }
     
        // Mise à jour derniers états des capteurs
        ir0LastState = ir0State;
        ir1LastState = ir1State;
     
      }
    }
    merci de votre temps

  17. #17
    Membre averti
    Homme Profil pro
    manutentionnaire
    Inscrit en
    Décembre 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : manutentionnaire

    Informations forums :
    Inscription : Décembre 2020
    Messages : 42
    Par défaut
    Effectivement, sur le schéma du --> 13/03/2026, 17h28 <-- , comporte une erreur.
    GND à droite de VDD n'est pas dessiné.
    Sur ma breadboard, la liaison est faite, pour les deux contrôleurs A4988.

    J'ai mesure, avec un ampèremètre le voltage sur la breadboard côté 12V(alimentation externe pour VMOT) et côté 5V (arduino).
    j'ai bien du 12V et du 5V.

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 841
    Par défaut
    Bon, j'ose.

    Citation Envoyé par LS_Soleil Voir le message
    J'ai mesure, avec un ampèremètre le voltage ....
    Really ?
    On écrit "J'ai tort" ; "tord" est la conjugaison du verbre "tordre" à la 3ème personne de l'indicatif présent ;)

Discussions similaires

  1. Caméra pour Raspberry Pi 3
    Par frederic13870 dans le forum Raspberry Pi
    Réponses: 6
    Dernier message: 31/08/2019, 09h13
  2. Module GSM pour Raspberry Pi 3 Model B
    Par xe4b4ct dans le forum Raspberry Pi
    Réponses: 0
    Dernier message: 10/02/2017, 11h27
  3. makefile pour code divisé en module
    Par mencaglia dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 05/12/2006, 12h05

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