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 :

Interruption moteur lors du fonctionnement


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de legrandse
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2010
    Messages
    354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 354
    Par défaut Interruption moteur lors du fonctionnement
    Bonjour à tous,

    Je coince sur le développement de la gestion de mon stepper utilisant la librairie AccelStepper
    Je n'ai pas soucis pour faire avancer ou reculer le moteur en utilisant l'accélération/décélération car c'est pour moi la seule raison d'exploiter cette librairie

    Par contre je souhaitais par sécurité ajouter des switches pour la fin de course et c'est là que les problèmes surviennent.
    Je n'arrive pas à interrompre le moteur lorsque celui est en marche malgré que le switch de fin de course soit appuyé.

    Pourtant mon code me parait correct mais peut-être ais-je omis qqch.

    En vous remerciant pour l'aide.

    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
     
    #include <ezButton.h>
    #include <AccelStepper.h>
     
     
     
    //Variable won't change. They're used here to set pin numbers:
    ezButton ForwardButton(12);                // create ezButton object that attach to pin 12;
    ezButton StopForwardButton(8);             // create ezButton object that attach to pin 8;
    ezButton BackwardButton(11);               // create ezButton object that attach to pin 11;
    ezButton StopBackwardButton(9);            // create ezButton object that attach to pin 9;
     
    const int SHORT_PRESS_TIME = 500;          // 500 milliseconds
     
     
    int smDirectionPin = 2;                    //Direction pin
    int smStepPin = 3;                         //Stepper pin
    int ledpin = 13;                           //Internal Led
     
    // Define a stepper and the pins it will use
    AccelStepper stepper(AccelStepper::DRIVER,smStepPin,smDirectionPin);
     
     
    // variables will change:
    int stepPinStateForward = LOW;             // the current forward state of motor
    int stepPinStateBackward = LOW;            // the current backward state of motor    
    int manualMode = LOW;                        // the current Manual Mode state  
    unsigned long pressedTime  = 0;            // Variable for long press detection (Manual Mode)
    unsigned long releasedTime = 0;            // Variable for long press detection (Manual Mode)
     
     
    void setup() {
      ForwardButton.setDebounceTime(50);      // set debounce time to 50 milliseconds
      StopForwardButton.setDebounceTime(50);  // set debounce time to 50 milliseconds
      BackwardButton.setDebounceTime(50);     // set debounce time to 50 milliseconds
      StopBackwardButton.setDebounceTime(50); // set debounce time to 50 milliseconds
     
     
      /**
       * The use of EZButton librairies
       */
      // initialize the pin as an inputs/output:
      pinMode(smDirectionPin, OUTPUT);
      pinMode(smStepPin, OUTPUT);
      pinMode(ledpin,OUTPUT);
      pinMode(relay_pin, OUTPUT);  
     
     
     
      /**
       * Basic motor setup 
       */
      stepper.setMaxSpeed(1000);
      stepper.setAcceleration(300);
     
     
      Serial.begin(9600);
     
    }
     
     
     
     
     
    void loop() {
     
     
    /** 
     *  ezButton library
     */
     
      ForwardButton.loop(); // MUST call the loop() function first
      StopForwardButton.loop(); // MUST call the loop() function first
      BackwardButton.loop(); // MUST call the loop() function first
      StopBackwardButton.loop(); // MUST call the loop() function first
     
     
      // read the state of the switches value:
      int StateForwardButton = ForwardButton.getState();
      int StateStopForwardButton = StopForwardButton.getState();
      int StateBackwardButton = BackwardButton.getState();
      int StateStopBackwardButton = StopBackwardButton.getState();
     
     
    /**
     * Auto/Manual Mode detection. 
     * If a long press button is detected then active Manual Mode for opening door
     */
      if(ForwardButton.isPressed() || BackwardButton.isPressed()){
        pressedTime = millis(); //time value at pressed button
        }
         else if(ForwardButton.isReleased() || BackwardButton.isReleased()) { // button is released
          releasedTime = millis(); //time value at released button
             long pressDuration = releasedTime - pressedTime;
     
          if( pressDuration > SHORT_PRESS_TIME ){
             manualMode = !manualMode;
             //Serial.println(manualMode);
             }
         }
     
      /**
     * Since the ezButton library used the internal pull-up resistor, 
     * the state will be HIGH when no press, and LOW when pressed.
     * If Forward button is pressed and limit switch is released in manual mode then move stepper
     */
          //MANUAL MODE
             //MOVE FORWARD
              if(ForwardButton.isPressed() && StateStopForwardButton == HIGH && manualMode == HIGH) {
                    stepPinStateForward = !stepPinStateForward; //pass state from LOW to HIGH
                    digitalWrite(ledpin, stepPinStateForward);  //Led ON
                    if(stepPinStateForward == HIGH ){
                        stepper.moveTo(5000);
                        stepper.runToPosition();
                        stepPinStateForward = !stepPinStateForward; //reverse the state of the pin
                        digitalWrite(ledpin, stepPinStateForward);  //Led OFF
                      }   
               } 
     
    /**           
     *  If limit switch is pressed and stepper is running in manual mode, then stop motor          
     */
               if (StopForwardButton.isPressed() && stepper.isRunning() && manualMode == HIGH){
                    stepPinStateForward = !stepPinStateForward; //pass from HIGH to LOW
                    digitalWrite(ledpin, stepPinStateForward);  //Led OFF
                    Serial.println("stop");
                    stepper.setCurrentPosition(0);
                    stepper.stop();
     
                  }
     
     
              //MOVE BACKWARD
              if(BackwardButton.isPressed() && StateStopBackwardButton == HIGH && manualMode == HIGH) {
     
                   stepPinStateBackward = !stepPinStateBackward; //pass state from LOW to HIGH
                   digitalWrite(ledpin, stepPinStateBackward);        // led ON
                   if(stepPinStateBackward == HIGH ){
                      stepper.moveTo(0);
                      stepper.runToPosition();
                      stepPinStateBackward = !stepPinStateBackward;  //reverse the pin state
                      digitalWrite(ledpin, stepPinStateBackward);         // Led OFF
                    }
               }
     
    /**           
     *  If limit switch is pressed and stepper is running in manual mode, then stop motor          
     */  
               if (StopBackwardButton.isPressed() && stepper.isRunning() && manualMode == HIGH) {
                    stepPinStateBackward = !stepPinStateBackward; 
                    digitalWrite(ledpin, stepPinStateBackward);
                    stepper.setCurrentPosition(0);
                    stepper.stop();
                }
     
     
     
    }

  2. #2
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    c'est un peu plat de spaghetti toutes ces conditions

    pouvez vous expliquez pourquoi vous faites cela par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      if (ForwardButton.isPressed() && StateStopForwardButton == HIGH && manualMode == HIGH) {
        stepPinStateForward = !stepPinStateForward; //pass state from LOW to HIGH
        digitalWrite(ledpin, stepPinStateForward);  //Led ON
    le commentaire ne correspond pas à l'action et pourquoi inverser? si le bouton forward est appuyé et qu'on n'appuie pas sur le bouton StopForwardButton et qu'on n'est pas en mode manuel on devrait avancer non? donc stepPinStateForward devrait juste être HIGH et non pas inversée à chaque tour de loop

  3. #3
    Membre éclairé Avatar de legrandse
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2010
    Messages
    354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 354
    Par défaut
    Hello,

    Merci pour ta réponse.
    J'utilise un push button et son état ne reste donc pas enfoncé.
    Le fait de passer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    stepPinStateForward = !stepPinStateForward; //pass state from LOW to HIGH
    permet de simuler un bouton enfoncé.

    J'ai tout de même réussi à solutionner le problème en modifiant comme ceci:
    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
     
    if(ForwardButton.isPressed() && StateStopForwardButton == HIGH && manualMode == HIGH) {
                    stepPinStateForward = !stepPinStateForward; //pass state from LOW to HIGH
                    digitalWrite(ledpin, stepPinStateForward);  //Led ON
     
     } 
      if(stepPinStateForward == HIGH ){
                    stepper.moveTo(5000);
                    stepper.run();
                    if(stepper.currentPosition() == 5000){
                            stepPinStateForward = !stepPinStateForward; //pass state from HIGH to LOW
                            digitalWrite(ledpin, stepPinStateForward);  //Led OFF
     
                     }
      } 
    /**           
     *  If stop switch is pressed and stepper is running in manual mode, then stop motor          
     */
               if (StopForwardButton.isPressed() && stepper.isRunning() && manualMode == HIGH){
                    stepPinStateForward = !stepPinStateForward; //pass from HIGH to LOW
                    if(stepPinStateForward == LOW){
                    digitalWrite(ledpin, stepPinStateForward);  //Led OFF
                    Serial.println("stop");
                    //stepper.setCurrentPosition(0);
                    stepper.stop();
                    }
                  }
    La fonction stepper.runToPosition() ne permet pas l'interruption tandis que stepper.run() le permet.
    J'ai simplement adapté un peu le reste des conditions.


    Par contre ce que je ne comprend pas ce que cette condition ne fonctionne pas si je l'écris comme ci-dessous.
    ici le moteur ne démarre pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if(stepPinStateForward == HIGH ){
                    stepper.moveTo(5000);
                    stepper.run()
                    stepPinStateForward = !stepPinStateForward; //pass state from HIGH to LOW
                    digitalWrite(ledpin, stepPinStateForward);  //Led OFF
     
      }
    alors que ceci fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    if(stepPinStateForward == HIGH ){
                    stepper.moveTo(5000);
                    stepper.run();
                    if(stepper.currentPosition() == 5000){
                            stepPinStateForward = !stepPinStateForward; //pass state from HIGH to LOW
                            digitalWrite(ledpin, stepPinStateForward);  //Led OFF
     
                     }
      }
    Je suis obligé de déclarer que "Si la position est de 5000 alors change l'état à LOW et éteint la LED".
    Pourquoi est-ce que je ne peut pas simplement placer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    stepPinStateForward = !stepPinStateForward; //pass state from HIGH to LOW
    digitalWrite(ledpin, stepPinStateForward);  //Led OFF
    juste en en dessous de stepper.run() ?

  4. #4
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    Par contre ce que je ne comprend pas ce que cette condition ne fonctionne pas si je l'écris comme ci-dessous....
    En supposant que stepPinStateForward reste HIGH, si vous ne faites pas de test pour voir si vous êtes arrivé, à chaque tour de loop vous effectuez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    stepPinStateForward = !stepPinStateForward; //pass state from HIGH to LOW
    digitalWrite(ledpin, stepPinStateForward);  //Led OFF
    donc vous faites clignoter la LED super vite.

    si le moteur ne démarre pas c'est que vous ne rentrez pas dans le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if(stepPinStateForward == HIGH ){
    sans doute.

    Comme vous jouez avec l'état de la LED, je me demande dans quelle mesure vous n'avez pas des interférences entre vos boutons et vos LEDs...

    pouvez vous décrire le câblage?

    De manière générale la structure du code vous complique la vie parce que vous mélangez des actions avec des tests d'état. Il vaudrait mieux partir sur une architecture de machine à états et lors d'un évènement particulier (fin de course activé, bouton appuyé, timeout) vous avez des actions particulières lors de la détection (mise en route ou arrêt du moteur pour un certain nombre de pas par exemple). Tel qu'il est le code passe dans tous les if à chaque tour de loop et vu les interdépendances je ne suis pas sûr que ça fasse exactement ce que vous souhaitez.

  5. #5
    Membre éclairé Avatar de legrandse
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2010
    Messages
    354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 354
    Par défaut
    Citation Envoyé par Jay M Voir le message

    De manière générale la structure du code vous complique la vie parce que vous mélangez des actions avec des tests d'état. Il vaudrait mieux partir sur une architecture de machine à états et lors d'un évènement particulier (fin de course activé, bouton appuyé, timeout) vous avez des actions particulières lors de la détection (mise en route ou arrêt du moteur pour un certain nombre de pas par exemple). Tel qu'il est le code passe dans tous les if à chaque tour de loop et vu les interdépendance je ne suis pas sûr que ça fasse exactement ce que vous souhaitez.

    Merci pour les conseils.
    Oui c'est tout à fait mon style de programmation type "spaghetti" et je n'arrive pas à m'en défaire, même en PHP c'est pareil.

    Je n'arrive pas à découper le code en "fonctions" et l'ajout de "greffons de code" par ci par là n'arrange pas la lisibilité du code pour qqu'un d'autre que moi.

    Je joins mon câblage "basique" pour la compréhension.


  6. #6
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 921
    Par défaut
    Oui c'est tout à fait mon style de programmation type "spaghetti"


    Ma compréhension c'est que vous appuyez sur FWD et ça avance de 5000 pas au max, jusqu'à taper le end stop
    vous appuyez sur BWD et ça recule jusqu'à la position 0 (où vous tapez dans le end stop de départ)
    Si vous appuyez longtemps sur le bouton FWD ou BWD vous alternez le mode "manuel"

    j'aime bien utiliser la bibliothèque SimpleBouton car elle est efficace, Voici un exemple de code à base de machine à état. ATTENTION J'AI TAPE CELA ICI , CE N'EST ABSOLUMENT PAS TESTE...
    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
    // Define a stepper
    #include <AccelStepper.h>
    const byte pinDirection = 2;  //  Direction pin
    const byte pinSetp = 3;       //  Stepper pin
    AccelStepper stepper(AccelStepper::DRIVER, pinSetp, pinDirection);
     
    // define the buttons ==> wiring : pin---BP---GND
    #include <simpleBouton.h> // grab library here http://forum.arduino.cc/index.php?topic=375232.0
    simpleBouton boutonEndStopForward(8);   // end stop when going forward (pin---BP---GND)
    simpleBouton boutonEndStopBackward(9);  // end stop when going backward (pin---BP---GNDp)
    simpleBouton boutonBackward(11);        // momentary push button to go forward (pin---BP---GND)
    simpleBouton boutonForward(12);         // momentary push button to go forward (pin---BP---GND)
     
    // manual mode by default, can operate with buttons
    bool manualMode = true;
    const uint32_t shortPressDuration = 2000; // 2s long press will switch mode
    enum : byte {AT_START, GOING_FWD,  GOING_BWD, AT_END} currentState;
     
    void forward()
    {
      Serial.println(F("Going forward"));
      stepper.moveTo(5000);
      currentState = GOING_FWD;
    }
     
    void backward()
    {
      Serial.println(F("Going backward"));
      stepper.moveTo(0);
      currentState = GOING_BWD;
    }
     
    void stop()
    {
      Serial.println(F("Stopping"));
      stepper.stop();
    }
     
    void handleAction()
    {
      uint32_t dureeForward = boutonForward.dureeEnfonce();
      uint32_t dureeBackward = boutonBackward.dureeEnfonce();
     
      boutonEndStopForward.actualiser();
      boutonEndStopBackward.actualiser();
      boutonBackward.actualiser();
      boutonForward.actualiser();
     
      if (boutonForward.vientDEtreRelache() || boutonBackward.vientDEtreRelache()) {
        if ((dureeForward >= shortPressDuration) || (dureeBackward >= shortPressDuration)) {
          manualMode = !manualMode;
        }
      }
     
      if (manualMode) {
        switch (currentState) {
          case AT_START: // we are at start, can only move forward
            if (boutonForward.vientDEtreEnfonce()) forward();
            break;
     
          case GOING_FWD: // we are moving forward, we stop if we touch the end stop or if the motor has reached its destination
            if (boutonEndStopForward.estEnfonce() || (! stepper.isRunning())) {
              stop();
              currentState = AT_END;
            }
            break;
     
          case GOING_BWD: // we are moving backward, we stop if we touch the end stop or if the motor has reached its destination
            if (boutonEndStopBackward.estEnfonce() || (! stepper.isRunning())) {
              stop();
              stepper.setCurrentPosition(0); // we are at start define 0 (used for homing)
              currentState = AT_START;
            }
            break;
     
          case AT_END: // we are at end, can only move backward
            if (boutonBackward.vientDEtreEnfonce()) backward();
            break;
        }
      }
    }
     
    void setup() {
      pinMode(pinDirection, OUTPUT);
      pinMode(pinSetp, OUTPUT);
      Serial.begin(115200);
     
      stepper.setMaxSpeed(1000);
      stepper.setAcceleration(300);
     
      // homing to start position, end stop will stop us
      currentState = GOING_BWD;
      stepper.moveTo(-5000);
    }
     
    void loop() {
      handleAction();
      stepper.run(); // motor will move only if it has been told to
    }
    La fonction handleAction() regarde grace au switch/case dans quel état on est et ne traite que les événements susceptibles d'arriver dans cet état, donc c'est assez simple à lire.

    ==> Personnellement je trouve que c'est plus lisible que des tas de if imbriqués avec plein de conditions

  7. #7
    Membre éclairé Avatar de legrandse
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Décembre 2010
    Messages
    354
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Décembre 2010
    Messages : 354
    Par défaut
    Merci beaucoup pour l'exemple que je vais étudier de près.
    Effectivement le code est relativement clair à comprendre.

    Encore merci pour l'aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 08/06/2009, 17h05
  2. Réponses: 2
    Dernier message: 20/03/2007, 11h50
  3. Réponses: 4
    Dernier message: 19/03/2007, 12h03
  4. Question sur le fonctionnement interne au moteur PHP
    Par Leviathan_72 dans le forum Langage
    Réponses: 3
    Dernier message: 25/11/2005, 01h17
  5. Réponses: 15
    Dernier message: 23/05/2005, 16h08

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