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 :

Commande PWM moteur CC, lecture encodeur


Sujet :

Arduino

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut Commande PWM moteur CC, lecture encodeur
    Bonjour,

    Je débute en Arduino, et j'essaie d'identifier expérimentalement un moto-réducteur CC muni d'un encodeur.
    La manip de base consiste à imposer une tension d'alimentation et de recueillir les informations du codeur pour tracer la vitesse en fonction du temps.
    On en déduit le gain statique et la constante de temps, en assimilant le moteur à un premier ordre.

    Moteur CC 6V, réducteur au 1/53, codeur 2 voies à 6 ticks par tour chaque.
    Je considère que je ne loupe aucun tick, vu que je ne fais rien dans la loop, mais je fais des trucs dans la gestion de l'interruption
    je calcule et affiche la vitesse de l'arbre réducteur en tr/min sur la voie série
    Programme ci-dessous :

    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
     
    // Faire tourner le moteur à une vitesse constante
    // Récupérer chaque changement d'état grace à une interruption sur l'une des 2 voies
    // Calculer la vitesse du réducteur en tr/min et l'afficher sur la liaison série
     
    const int _MOTEUR =  9;                 // Digital pin pour commande moteur
    unsigned long temps;                       // variable de temps en microsecondes, car avec micros() direct, ça marche pas !!
    unsigned long tempsinit;                   // instant initial
    float vitesse ;
     
    /* Routine d'initialisation */
    void setup() {
        pinMode(_MOTEUR, OUTPUT);   // Configuration de la broche en sortie
        analogWrite(_MOTEUR, 255);   // Commande PWM de 0 à 255 Max (de 0 à 100% de la "tension d'alimentation")
        delay(5000);                // Pause de 5 sec pour laisser le temps au moteur de s'arréter si celui-ci est en marche
     
        attachInterrupt(0, compteur, CHANGE);    // Interruption sur tick de la codeuse (interruption 0 = pin2 arduino mega)
        Serial.begin(230400) ;
        tempsinit = micros();
    }
     
    /* Fonction principale */
    void loop(){
    }
     
    /* Interruption sur tick de la codeuse */
    void compteur(){
        temps = micros();
        vitesse = (1000000/float(temps-tempsinit))*60/6/53 ;
        Serial.println(vitesse);
        tempsinit=temps;    
    }
    Pb : quand je change la valeur du PWM (typiquement : 127 au lieu de 255)
    la vitesse ne change pas en proportion.
    Qu'est-ce que je loupe ?

    Par avance, merci de votre aide

  2. #2
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonsoir Horus68
    Citation Envoyé par Horus68 Voir le message
    ....mais je fais des trucs dans la gestion de l'interruption....
    Pour le principe, pas de print dans un traitement d'interrupt.

    Citation Envoyé par Horus68 Voir le message
    Pb : quand je change la valeur du PWM (typiquement : 127 au lieu de 255)
    la vitesse ne change pas en proportion.
    Qu'est-ce que je loupe ?
    Tu ne loupes rien, PWM n'est pas un asservissement en vitesse, le rapport doit même être assez aléatoire.

    Cordialement¨
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  3. #3
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    Je n'ai pas encore utiliser les interruptions alors j'ai regardé attachInterrupt() dans lequel il est dit ceci :

    Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs, only one can run at a time, other interrupts will be executed after the current one finishes in an order that depends on the priority they have. millis() relies on interrupts to count, so it will never increment inside an ISR. Since delay() requires interrupts to work, it will not work if called inside an ISR. micros() works initially but will start behaving erratically after 1-2 ms. delayMicroseconds() does not use any counter, so it will work as normal.
    Apparemment au delà de 1-2 ms la fonction micros() ne fonctionne pas correctement... Alors peut-être que ça joue dans ton cas ?

    EDIT : Ah je crois que cela ne joue pas dans ton cas finalement...

  4. #4
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Comment est alimenté le moteur? Décrivez le montage.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par jpbbricole Voir le message
    Bonsoir Horus68
    Pour le principe, pas de print dans un traitement d'interrupt.

    Tu ne loupes rien, PWM n'est pas un asservissement en vitesse, le rapport doit même être assez aléatoire.

    Cordialement¨
    jpbbricole
    Merci pour cette réponse.

    Ah!, pas de print :
    Par quoi puis-je le remplacer, alors, si je veux récupérer une information de vitesse pour l'exploiter a posteriori ?
    J'avais pensé à stocker les valeurs dans un tableau, mais j'ai échoué lamentablement ...

    PWM n'est pas un asservissement en vitesse, mais en régime permanent, la tension moyenne vue par le moteur est bien proportionnelle au rapport cyclique, donc la vitesse en RP devrait être presque proportionnelle à la commande PWM. Là, on en est très très loin :
    255 -> 154 tr/min ; 127 -> 128 tr/min ; 64 -> 84 tr/min.

    Cordialement

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Jay M Voir le message
    Comment est alimenté le moteur? Décrivez le montage.
    J'utilise un kit de chez Digilent et une carte Arduino Uno
    Alimentation stabilisée de 6V, 2A ;
    Un pont en H PmodHB5, relié à l'alim, pour la puissance, au moteur et codeur via cable dédié (connecteur JST)
    et à la carte arduino via 6 fils : Vcc 3.3V, GND, codeur B, codeur A, Enable, Direction

    arduino :
    codeur B sur voie 3, codeur A sur voie 2, enable sur voie 9, dir sur voie 5

    Cordialement

  7. #7
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonjour Horus68
    Tu peux afficher la variable vitesse en dehors du traitement de l'interruption en ajoutant volatile avant le float de la déclaration de la variable.

    Pour ce qui est de la vitesse par rapport au cycle PWM, je doute qu'il y ait un rapport direct, trop de paramètres entrent en ligne de compte. Mais je ne suis pas spécialiste de la chose.

    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  8. #8
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut La même chose avec un motorshield
    Suite aux réponses précédentes, je me suis demandé si le problème ne venait pas du matériel.
    Jusqu'à présent, je ne m'étais même pas posé la question...

    J'ai changé de carte arduino, je l'ai associée à un motorshield
    J'ai fait les branchements sur la voie B (alimentation moteur)

    Le programme est identique au précédent, aux spécificités du motorshield (Brake, notamment)
    ...

    Les résultats sont les mêmes. Le PWM ne semble pas délivrer une tension proportionnelle au rapport cyclique.
    Je me base sur une comparaison simple : l'alimentation en direct, avec PWM=255, en 3, 4.5 et 6V donne
    respectivement : 78, 114, 154, soit 50.6%, 74% et 100%

    Donc là, la vitesse en RP est presque proportionnelle à la tension d'alimentation.
    Ce qui n'est pas le cas quand je commande avec un PWM différent de 255

    Par avance, merci pour des avis qui pourraient expliquer ce comportement
    Cordialement
    Horus68

  9. #9
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut Autre programme avec le PmodHB5
    Pour éviter de faire un Serial.print dans la routine de gestion d'interruption,
    j'ai essayé de remplir un tableau avec les valeurs, pour le faire lire seulement après.
    J'ai réussi grâce aux conseils avisés de jpbbricole : le "volatile" est la clef

    Le comportement ne semble pas très différent. Mais, avec les données remontées, on peut noter une forte différence de temps de réponse,
    alors que théoriquement, ça ne dois pas être le cas...

    Le programme :
    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
    // Faire tourner le moteur à une vitesse constante, sauf démarrage
    // Récupérer chaque changement d'état grace à une interruption chaque voie du codeur
    // Calculer la vitesse du réducteur en tr/min et la stocker dans un tableau
    // Transmettre a posteriori via la voie série
     
    const int nbTicks = 96;
    const int _MOTEUR =  9;                 // Digital pin pour commande moteur
    unsigned int tick_codeuse = 0;          // Compteur de tick de la codeuse
    unsigned long Old_tick_codeuse = 0;     // Ancienne valeur de tick de la codeuse
    unsigned long Millis_tick_codeuse = 0;    // Ancien instant de tick de la codeuse
    unsigned long temps;                       // variable de temps en microsecondes, car avec micros() direct, ça marche pas !!
    unsigned long temps_ant;                   // instant antérieur
    unsigned long timeinit;                    // instant initial
    volatile float vitesse;
    volatile float periode;
    volatile float vitesses[nbTicks][2];
    volatile bool vide = true ;
    volatile int i = 0 ;
     
    /* Routine d'initialisation */
    void setup() {
        pinMode(_MOTEUR, OUTPUT);   // Configuration de la broche en sortie
        analogWrite(_MOTEUR, 127);   // Commande PWM de 0 à 255 Max (de 0 à 100% de la "tension d'alimentation")
        attachInterrupt(0, compteur, CHANGE);    // Interruption sur tick de la codeuse (interruption 0 = pin2 arduino uno) 
        attachInterrupt(1, compteur, CHANGE);    // Interruption sur tick de la codeuse (interruption 1 = pin3 arduino uno)
        Serial.begin(230400) ;
        Serial.flush();
        delay(5000);                // Pause de 5 sec pour laisser le temps au Serial de s'initialiser
        timeinit = micros();
        temps_ant = timeinit ;
    }
     
    /* Fonction principale */
    void loop(){
      while (vide){
      }
      if (not vide){
        Serial.println("Tableau des vitesses");
        for (int j=0 ; j<nbTicks ; j++){
          Serial.print(vitesses[j][0]); Serial.print(", ");Serial.println(vitesses[j][1]);
        vide = true ;
        }
      }
    }
     
    /* Interruption sur tick de la codeuse */
    void compteur(){
    //    Old_tick_codeuse = tick_codeuse ;   // mémorise l'ancien instant
        tick_codeuse++;  // On incrémente le nombre de tick de la codeuse
        temps = micros();
    //    periode = float(temps-temps_ant)/1000;
        if (i<nbTicks){
          vitesse = 1000000.0/float(temps-temps_ant)*60/12/53 ;
          vitesses[i][0]= (temps-timeinit) ; vitesses[i][1]= vitesse ;
          temps_ant=temps;
    //      Serial.print("i= "); Serial.print(i); Serial.print(", ");
    //      Serial.println(vitesse);
          i++ ;
        }
        else {
        analogWrite(_MOTEUR, 0);
        vide = false;
    //    Serial.println(vitesse);
    //    Serial.print(" , ");
    //    Serial.println(tick_codeuse);
        }
    }

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1

  11. #11
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonjour Horus68
    Citation Envoyé par Horus68 Voir le message
    Le PWM ne semble pas délivrer une tension proportionnelle au rapport cyclique.
    Je me base sur une comparaison simple : l'alimentation en direct, avec PWM=255, en 3, 4.5 et 6V donne
    respectivement : 78, 114, 154, soit 50.6%, 74% et 100%
    Cette comparaison n'est pas valable. Le PWM ne fournit pas de tension, mais un rapport cyclique, il faudrait avoir un convertisseur PWM > tension.
    En fait, en alimentant ton moteur en "direct", tu l'alimente avec une tension carrée dont le rapport cyclique est réglé par la valeur du PWM. Je te laisses imaginer tout les critères qui font qu'il ne peut pas y avoir de rapport entre PWM et vitesse du moteur

    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  12. #12
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Pour une charge de type moteur, piloter le enable du pont en H en PWM revient bien à contrôler la puissance moyenne perçue par le moteur (du fait de son inertie et de la fréquence du PWM assez rapide). Il devrait donc y avoir une certaine continuité / linéarité si les conditions de fonctionnement du moteur sont stables sur toute la rotation.

    Votre lecture de l’encodeur est peut être à affiner, vous balancez les 2 interruptions sur la même fonction. Il serait intéressant de voir réellement ce que vous recevez et quand (encodeur quadratique?).

    Au lieu de traiter l’encodeur à la main vous pourriez essayer de prendre cette encoder library et lire la valeur du compteur toutes les secondes dans la loop pour calculer la vitesse

  13. #13
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut
    Bonjour Jay M

    Citation Envoyé par Jay M Voir le message
    Votre lecture de l’encodeur est peut être à affiner, vous balancez les 2 interruptions sur la même fonction. Il serait intéressant de voir réellement ce que vous recevez et quand (encodeur quadratique?).

    Au lieu de traiter l’encodeur à la main vous pourriez essayer de prendre cette encoder library et lire la valeur du compteur toutes les secondes dans la loop pour calculer la vitesse
    Merci pour le lien, je vais essayer ça.
    Le codeur est bien un encodeur quadratique, avec les deux voies déphasées, permettant de récupérer l'état de A au changement d'état de B pour en déduire le sens de rotation, mais ce n'est pas mon propos pour le moment.
    Utiliser les 2 voies avec interruption sur chaque front me permet juste d'augmenter la résolution de la lecture.
    En observant les intervalles de temps entre les différents fronts, on voit une cyclicité (de 12), la répartition des pôles (?) ne semblant pas très régulière

    L'un des obstacles est le temps d'exécution de tout ça :
    L'objectif est d'obtenir le maximum de points de mesure pour qualifier le transitoire et en déduire un temps de réponse à 5%.
    L'ordre de grandeur est de 20ms, pour être un minimum précis, il serait bon d'avoir une dizaine de mesures dans cet intervalle.
    La période théorique entre 2 ticks est de 600 microsecondes à pleine vitesse.

    Cordialement
    Horus68

  14. #14
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Citation Envoyé par Horus68 Voir le message

    Utiliser les 2 voies avec interruption sur chaque front me permet juste d'augmenter la résolution de la lecture.
    ...
    L'un des obstacles est le temps d'exécution de tout ça :
    L'objectif est d'obtenir le maximum de points de mesure pour qualifier le transitoire et en déduire un temps de réponse à 5%.
    L'ordre de grandeur est de 20ms, pour être un minimum précis, il serait bon d'avoir une dizaine de mesures dans cet intervalle.
    La période théorique entre 2 ticks est de 600 microsecondes à pleine vitesse.
    Que veux-tu dire par "entre 2 ticks" ? Est-ce le temps entre deux fronts montants (ou descendants) d'une des deux voies (= période du signal d'une des deux voies)? Ou le temps entre chaque front consécutif (montant et descendant) d'une des deux voies ? Ou le temps entre chaque front consécutif (montant et descendant) des deux voies ? Le troisième cas est quatre fois plus précis que le premier mais du coup la période entre 2 ticks est plus courte...

    600 µs cela semble faisable de détecter chaque "tick" même sans interruption sachant qu'il me semble qu'on peut aller plus vite en lisant directement les ports, en plus on peut lire les deux voies d'un coup si on les connecte aux pins d'un même port...

  15. #15
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut
    Bonjour Beginner,

    L'ambition est d'utiliser chaque changement d'état sur les 2 voies, d'où l'utilisation d'une seule fonction de gestion d'interruption, appelée sur CHANGE
    Donc pour être le plus précis possible. La contrepartie étant la cadence élevée...

    Citation Envoyé par Beginner. Voir le message
    600 µs cela semble faisable de détecter chaque "tick" même sans interruption sachant qu'il me semble qu'on peut aller plus vite en lisant directement les ports, en plus on peut lire les deux voies d'un coup si on les connecte aux pins d'un même port...
    Ah, ça, je ne connais pas, mais ça me parait scabreux : si je branche mes deux sorties codeur sur la même entrée, je crée une fonction OU, donc à 1 si l'un ou l'autre ou les deux signaux sont à 1, et l'ensemble ne redescend à 0 que lorsque les 2 voies sont à 0. Du coup, je crains la perte de précision.
    Pour ne mobiliser qu'une entrée, je pense qu'il me faudrait un système intermédiaire, de type détecteur de front, et encore, je ne suis pas sur que ça soit compatible.

    Par contre, ton idée de lire directement les ports m'intéresse, peux-tu m'en dire plus ? Un lien ?

    Cordialement
    Horus68

  16. #16
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut
    Bonjour Jay M,

    Citation Envoyé par Jay M Voir le message
    Au lieu de traiter l’encodeur à la main vous pourriez essayer de prendre cette encoder library et lire la valeur du compteur toutes les secondes dans la loop pour calculer la vitesse
    J'ai donc essayé la bibliothèque "Encoder"
    J'ai légèrement modifié le code du "Basic example" pour faire tourner mon moteur et récupérer les changements d'état des 2 codeurs
    (broches 2 et 3) de l'arduino
    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
    /* Encoder Library - Basic Example
     * http://www.pjrc.com/teensy/td_libs_Encoder.html
     *
     * This example code is in the public domain.
     */
     
    #include <Encoder.h>
     
    // Change these two numbers to the pins connected to your encoder.
    //   Best Performance: both pins have interrupt capability
    //   Good Performance: only the first pin has interrupt capability
    //   Low Performance:  neither pin has interrupt capability
    Encoder myEnc(2, 3);
    //   avoid using pins with LEDs attached
    const int _MOTEUR =  9;                 // Digital pin pour commande moteur
    long newtime ;
    long oldtime ;
     
    void setup() {
      pinMode(_MOTEUR, OUTPUT);   // Configuration de la broche en sortie
      analogWrite(_MOTEUR, 255);   // Commande PWM de 0 à 255 Max (de 0 à 100% de la "tension d'alimentation")
      Serial.begin(230400);
      Serial.println("Basic Encoder Test:");
      long Oldtime = micros();
    }
     
    long oldPosition  = -999;
     
    void loop() {
      long newPosition = myEnc.read();
      if (newPosition != oldPosition) {
        newtime = micros();
        Serial.println(newtime-oldtime); 
    /*    Serial.print(", ");
        Serial.println(newPosition-oldPosition);*/
        oldPosition = newPosition ;
        oldtime = newtime;
      }
    }
    Hélas, le comportement reste le même.
    La PWM semble perturbée par la gestion des interruptions (!!??),
    la vitesse mesurée à travers le comptage des fronts étant toujours en accord avec un comptage manuel du nb de tours par min
    (comptage visuel du nb de tours + chronomètre... fastidieux...)

    Cordialement
    Horus68

  17. #17
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    attention à la portée des variables et aux majuscules/minuscules

    essayez avec ce code en branchant le moteur sur la pin 6 et dites moi ce qu'affiche la console série réglée à 1 million de bauds
    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
    #include <Encoder.h>
    Encoder encodeur(2, 3);          //   avoid using pins with LEDs attached
    const byte enablePin =  6;    // attention changement  Digital pin pour commande moteur  
    unsigned long newTime ;
    unsigned long oldTime ;
    
    long newPosition;
    long oldPosition = -999;
    
    void setup() {
      pinMode(enablePin, OUTPUT);   // Configuration de la broche en sortie
      analogWrite(enablePin, 128);   // Commande PWM de 0 à 255 Max (de 0 à 100% de la "tension d'alimentation")
      Serial.begin(1000000); // attention changement 
      Serial.println("Basic Encoder Test:");
      encodeur.write(0);
    }
    
    void loop() {
      newPosition = encodeur.read();
      if (newPosition != oldPosition) {
        newTime = micros();
        Serial.print(newTime - oldTime);
        Serial.write('\t');
        Serial.println(newPosition);
        oldPosition = newPosition ;
        oldTime = newTime;
      }
    }

  18. #18
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut
    Bonsoir Jay M,

    Citation Envoyé par Jay M Voir le message
    attention à la portée des variables et aux majuscules/minuscules

    essayez avec ce code en branchant le moteur sur la pin 6 et dites moi ce qu'affiche la console série réglée à 1 million de bauds
    Alors, pas de million de bauds dans ma version d'ide Arduino (la 1.8.1)
    A 250 000, ça donne une incrémentation stricte de la position, une période 850 microsec, à la louche (PWM à 128)
    Un aperçu du moniteur Série :

    824 -5067
    896 -5068
    704 -5069
    940 -5070
    804 -5071
    788 -5072
    844 -5073
    880 -5074
    732 -5075
    848 -5076
    856 -5077
    772 -5078

    Avec un PWM à 255 : 650 microsec à la louche
    576 -8783
    660 -8784
    668 -8785
    604 -8786
    644 -8787
    704 -8788
    556 -8789
    744 -8790
    632 -8791
    624 -8792
    668 -8793
    700 -8794
    580 -8795
    672 -8796


    Cordialement
    Horus68

  19. #19
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    Citation Envoyé par Horus68 Voir le message
    L'ambition est d'utiliser chaque changement d'état sur les 2 voies, d'où l'utilisation d'une seule fonction de gestion d'interruption, appelée sur CHANGE
    Donc pour être le plus précis possible. La contrepartie étant la cadence élevée...
    Ok j'ai aussi regardé le code que tu as posté et j'en déduis que tu es dans le cas trois : "Ou le temps entre chaque front consécutif (montant et descendant) des deux voies ? Le troisième cas est quatre fois plus précis que le premier mais du coup la période entre 2 ticks est plus courte..."


    Citation Envoyé par Horus68 Voir le message
    Ah, ça, je ne connais pas, mais ça me parait scabreux : si je branche mes deux sorties codeur sur la même entrée, je crée une fonction OU, donc à 1 si l'un ou l'autre ou les deux signaux sont à 1, et l'ensemble ne redescend à 0 que lorsque les 2 voies sont à 0. Du coup, je crains la perte de précision.
    Ah ben oui ça cela poserait problème c'est clair... En fait ce n'est pas ce que je voulais dire par "..en plus on peut lire les deux voies d'un coup si on les connecte aux pins d'un même port...".

    Il ne faut évidement pas connecter les deux voies à la même entrée. Je parle bien de deux entrées (pins) différentes mais appartenant au même port.

    Regarde ce lien : Port Registers

    En effet, comme il est dit, la carte Arduino possède trois ports :

    • B (digital pin 8 to 13)
    • C (analog input pins)
    • D (digital pins 0 to 7)
    Par exemple le PORTB correspond aux pins 8 à 13 (6 pins) ---> Et on peut lire l'état de ces 6 pins d'un seul coup (en même temps) et c'est très rapide en plus ! Il n'y a qu'un seul registre à lire...

    Ensuite petite astuce si tu choisis les pins 8 et 9 alors tu obtiendras directement un nombre (2 bits) dont la valeur pourra être 0,1,2 ou 3 (en binaire : 00,01,10,11) ---> cela servira à savoir dans quel sens tourne le moteur assez facilement et rapidement.

    Citation Envoyé par Horus68 Voir le message
    Pour ne mobiliser qu'une entrée, je pense qu'il me faudrait un système intermédiaire, de type détecteur de front, et encore, je ne suis pas sur que ça soit compatible.
    Oui on peut faire ça avec des circuits logiques (bascules)... Mais franchement cela ne vaut pas le coup, la carte Arduino est suffisamment rapide ce serait dommage d'utiliser d'autres CI pour ça et c'est moins marrant...

    Citation Envoyé par Horus68 Voir le message
    Par contre, ton idée de lire directement les ports m'intéresse, peux-tu m'en dire plus ? Un lien ?
    J'en ai donné un ci-dessus et en voilà un autre : Putting it all together: common problems solved. On peut trouver d'autres exemples...

    EDIT : un autre lien : https://www.teachmemicro.com/arduino-pins-manipulation et encore un autre avec comparaison à l’oscilloscope : https://www.best-microcontroller-pro...italwrite.html


    Enfin le code proposé par Jay M semble bien fonctionné et ce rapidement en plus... C'est vrai qu'il faut faire attention à la transmission série qui peut prendre du temps.. Alors si tu ne peux pas choisir 1 000 000 de bauds alors on peut toujours stoker n mesures dans un tableau et les afficher à la fin...

    Mais tes tests ont l'air correctes donc ça va apparemment...

  20. #20
    Nouveau Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 25
    Points : 1
    Points
    1
    Par défaut Ports A, B et C
    Bonjour Beginner,

    Merci beaucoup pour ces explications.
    Effectivement, j'ai confondu port et entrée, erreur de débutant ...

    ça a l'air super.
    Je m'informe plus avant, je teste et je vous dis ce que ça donne.

    Cordialement
    Horus68

Discussions similaires

  1. Programme Arduino de commande de moteur+encodeur.
    Par loquet38 dans le forum Arduino
    Réponses: 7
    Dernier message: 15/03/2018, 20h20
  2. Commander un moteur (virtuellement)
    Par soft001 dans le forum LabVIEW
    Réponses: 0
    Dernier message: 12/04/2012, 10h06
  3. Commander un Moteur Electrique via une Interface Web
    Par felops dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 05/03/2008, 14h00
  4. Installation d'un module en ligne de commande sur moteur 9i
    Par Arakil dans le forum Installation
    Réponses: 0
    Dernier message: 10/09/2007, 12h47
  5. Commander plusieurs moteurs par un seul port USB
    Par wolfjeremy dans le forum Windows
    Réponses: 6
    Dernier message: 11/06/2006, 14h52

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