Bonjour, cliquez-ici pour vous inscrire et participer au forum.
  • Login:



+ Répondre à la discussion
Page 1 sur 3 12 DernièreDernière
Affichage des résultats 1 à 15 sur 34

Utilisation d'un codeur incrémental

  1. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    62 725

    Utilisation d'un codeur incrémental

    Cette question revient de temps en temps, alors, j'ai rassemblé dans ce tuto un certain nombre de réponse aux questions qui ont été posées. Le codeur incrémental existe sous deux formes, rotatif ou linéaire. La mécanique est différente, le traitement électrique est le même.

    What is it?
    Un codeur incrémental génère 3 signaux :
    • Un signal A
    • Un signal B
    • Un signal Top Zéro

    Les niveaux électriques sont :
    • Haute tension (24V par exemple)
    • TTL (0/5V)
    • RS422 Dans ce cas, on a les signaux A et /A , B et /B , Z et /Z il faut passer par un récepteur de ligne RS422 (avec sa résistance d'adaptation)
    • Un simple contact sec et il faut une PullUp (ces codeurs, qui remplacent des potentiomètres, ne donnent pas de Top Zéro)

    Principe de fonctionnement
    Dans la suite, on oubliera la gestion du TopZéro qui ne sert qu'a recaler le compteur électronique en synchronisme avec la position zéro du codeur.

    Les signaux A et B sont décalés en quadrature (on dit aussi à 90° ou en Grecque) et chaque période de A (et donc de B) indique que le codeur a fait un pas sachant que le nombre de pas par tour peut aller de 32 à 8096 suivant le prix du codeur.
    Pour détecter le sens de rotation, Il faut regarder si les transitions positives de A sont avant ou après les transitions positives de B . Par contre, si on est un peu futé, on peut augmenter la résolution apparente par quatre en utilisant toutes les transitions.
    Pour le moment, tout ça c'est de la théorie ... En effet les signaux A et B sont entachés par des rebonds au moment des transitions. Ces rebonds proviennent :
    • Du contact électrique si celui-ci est fait par deux lamelles de cuivre
    • De l'hésitation en rotation du codeur quand il y a des vibrations

    La réalisation de la fonction de décodage avec des bascules et des circuits RC est vouée à l'échec et donne des montages qui tombent en marche . La seule solution valable est la méthode par échantillonnage. On regarde la valeur du signal et on la compare avec la valeur lue précédemment .

    Pour qu'aucune transition utile ne soit perdue, il faut au moins un échantillon du signal pendant une période " stable ", donc une fréquence d'échantillonnage d'au moins 4 fois la fréquence maximum de sortie du codeur.
    Par exemple :
    • Codeur de 1024 pas qui tourne à 1000 tour/minute
    • Fout= 1024*1000/60=17067 Hertz
    • Féchantillonnage > 17067*4=68267 Hertz

    Algorithme
    Cela consiste à faire une machine d'état (en soft ou en Hard). En fonction des deux entrées lues et des deux entrées mémorisées, il y a 16 états ( dont 4 impossibles, on ne peut pas lire 01 et avoir en mémoire 10 par exemple). Et pour chaque état, une action à faire : compter, décompter ou ne rien faire

    Code:
    Etat précédent de AB =00 Etat lu de AB=01 Compte=+1
    Etat précédent de AB =00 Etat lu de AB=00 Compte=0
    Etat précédent de AB =00 Etat lu de AB=10 Compte=-1
    
    Etat précédent de AB =01 Etat lu de AB=11 Compte=+1
    Etat précédent de AB =01 Etat lu de AB=01 Compte=0
    Etat précédent de AB =01 Etat lu de AB=00 Compte=-1
    
    Etat précédent de AB =11 Etat lu de AB=10 Compte=+1
    Etat précédent de AB =11 Etat lu de AB=11 Compte=0
    Etat précédent de AB =11 Etat lu de AB=01 Compte=-1
    
    Etat précédent de AB =10 Etat lu de AB=00 Compte=+1
    Etat précédent de AB =10 Etat lu de AB=10 Compte=0
    Etat précédent de AB =10 Etat lu de AB=11 Compte=-1
    Réalisation
    Il y a trois choix de technologie pour résoudre ce problème :
    • Circuit spécialisé genre HCTL2000
    • Circuit PAL genre GAL16V8
    • Microcalculateur (si le Timer et le programme en interruption peut tourner assez vite)
    NB : Certains automates programmables ont cette fonction dans leurs modules I/O

    Simulation
    Le bon fonctionnement de l'algorithme est montré sur cette simulation qui utilise des bascules et des portes (l'équivalent d'un GAL16V8)

    Programme pour microcalculateur
    Notre ami Canaillou2k5 a utilisé cette algorithme pour programmer un PIC . Le but est d'utiliser un bouton rotatif codeur pour faire évoluer une variable entre 0 et 100

    Code:
    unsigned char var_a=0, var_b=0, var=0; //variables globales
     
    void stockage() //stockage des anciennes valeurs
    {
        var_a=PIND.2;
        var_b=PIND.3;
    }
       
    void var_plus()           //fonction incrémenter
    {
        if(var<100)var++; //on incrément si on est en dessous de la valeur maxi. 
        stockage();            //stockage des anciennes valeurs
    }
    void var_moins()       //fonction décrémenter
    {
        if(var>0)var--;      //on décrément si on est au dessus de la valeur mini.
        stockage();           //stockage des anciennes valeurs
    }
        
    interrupt[14] void gray() // interruption sur compteur (toutes les 1,6ms)
    {
    
            if(var_a==0 && var_b==0)
            { 
            
                if(PIND.2==0 && PIND.3==1)var_plus();           //fonction incrémenter
                else if(PIND.2==1 && PIND.3==0)var_moins(); //fonction décrémenter
            }   
            else if(var_a==0 && var_b==1)
            {
                if(PIND.2==1 && PIND.3==1)var_plus();
                else if(PIND.2==0 && PIND.3==0)var_moins();
            } 
            else if(var_a==1 && var_b==1)
            {
                if(PIND.2==1 && PIND.3==0)var_plus();
                else if(PIND.2==0 && PIND.3==1)var_moins();
            }
            else if(var_a==1 && var_b==0)
            {
                if(PIND.2==0 && PIND.3==0)var_plus();
                else if(PIND.2==1 && PIND.3==1)var_moins();      
            }
    
    }
    Comme je suis nul en programmation, j'hésite à donner un avis mais je pense que l'exécution serait plus rapide (mais le programme plus long en place mémoire) si on n'utilisait pas des procédures mais des macros

    -----

    Images attachées
    Dernière modification par gienas ; 08/08/2011 à 15h42. Motif: Mise en page
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     


    • Publicité



  2. Jack

    Date d'inscription
    avril 2003
    Localisation
    Metz
    Messages
    15 957

    Re : Utilisation d'un codeur incrémental

    en utilisant des macro comme proposé par DAUDET78, et sans remettre l'algo en jeu, on peut obtenir quelque chose de plus générique pour de dernier.
    Seule la syntaxe de l'appel de la fonction d'interruption est non standard et devra être retouchée.
    Code:
    #define SIG_A PIND.2
    #define SIG_B PIND.3
    #define INC_MAX 100
    #define INC_MIN 0
    /* Les lignes précédentes sont à ajuster 
       en fonction du codeur et du µcontroleur.
       On peut par exemple les placer dans un fichier .h à part.
     */
    #define STOCKAGE \
        var_a=SIG_A; \
        var_b=SIG_B;
        
    #define INCREMENTER \
        if (var<INC_MAX) var++;\
        STOCKAGE        
        
    #define DECREMENTER \
        if (var>INC_MIN) var--;\
        STOCKAGE            
       
    unsigned var=0; //variables globales
     
    interrupt[14] void gray() // interruption sur compteur (toutes les 1,6ms)
    {
            static unsigned char var_a=0, var_b=0;
            if(var_a==0 && var_b==0)
            {   
                if(SIG_A==0 && SIG_B==1) INCREMENTER 
                else if(SIG_A==1 && SIG_B==0) DECREMENTER
            }   
            else if(var_a==0 && var_b==1)
            {
                if(SIG_A==1 && SIG_B==1) INCREMENTER
                else if(SIG_A==0 && SIG_B==0) DECREMENTER
            } 
            else if(var_a==1 && var_b==1)
            {
                if(SIG_A==1 && SIG_B==0) INCREMENTER
                else if(SIG_A==0 && SIG_B==1) DECREMENTER
            }
            else if(var_a==1 && var_b==0)
            {
                if(SIG_A==0 && SIG_B==0) INCREMENTER
                else if(SIG_A==1 && SIG_B==1) DECREMENTER      
            }
    }
     

  3. Jack

    Date d'inscription
    avril 2003
    Localisation
    Metz
    Messages
    15 957

    Re : Utilisation d'un codeur incrémental

    une autre implémentation qui diminue le nombre de tests:
    Code:
    #define SIG_A PIND.2
    #define SIG_B PIND.3
    #define INC_MAX 100
    #define INC_MIN 0
    /* Les lignes précédentes sont à ajuster 
       en fonction du codeur et du µcontroleur.
       On peut par exemple les placer dans un fichier .h à part.
     */
    #define INCREMENTER \
        if (var<INC_MAX) var++;\
        var_ab=(SIG_A<<1)+SIG_B;
        
    #define DECREMENTER \
        if (var>INC_MIN) var--;\
        var_ab=(SIG_A<<1)+SIG_B;
       
    unsigned var=0; //variables globales
     
    interrupt[14] void gray() // interruption sur compteur (toutes les 1,6ms)
    {
            static unsigned char var_ab=0;
            switch (var_ab){
                case 0:if(SIG_A==0 && SIG_B==1) INCREMENTER 
                       else if(SIG_A==1 && SIG_B==0) DECREMENTER
                       break;
                case 1:if(SIG_A==1 && SIG_B==1) INCREMENTER
                       else if(SIG_A==0 && SIG_B==0) DECREMENTER
                       break;
                case 2:if(SIG_A==1 && SIG_B==0) INCREMENTER
                       else if(SIG_A==0 && SIG_B==1) DECREMENTER
                       break;
                case 3:if(SIG_A==0 && SIG_B==0) INCREMENTER
                       else if(SIG_A==1 && SIG_B==1) DECREMENTER      
            }
    }
     

  4. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    62 725

    Re : Utilisation d'un codeur incrémental

    Oui, cela me semble plus performant, au moins en vitesse d’exécution !
    Maintenant, il reste deux questions :
    1/ Quelqu'un est il volontaire pour évaluer pour un µC Français moyen le temps d’exécution de ce programme en C ?
    2/ Quelqu'un est il volontaire pour écrire en assembleur ce programme pour un µC Français moyen et aussi d'évaluer le temps d’exécution de ce programme ?

    PS 1 : J'ai deux Carambars à donner en remerciement !
    PS 2: Le nombre d'instructions machine à exécuter dans le pire cas serait aussi une bonne indication .
    Dernière modification par DAUDET78 ; 08/08/2011 à 14h58.
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  5. Canaillou2k5

    Date d'inscription
    octobre 2007
    Âge
    26
    Messages
    356

    Re : Utilisation d'un codeur incrémental

    Mon microprocesseur est un ATMEL.

    Avec le logiciel AVR studio je vais pouvoir faire des mesures de temps d'execution avec les différent programmes (si j'arrive à me souvenir car j'ai fait ça une fois il y à 1 ans...) en C mais aussi en assembleur, mais un assembleur crée par le compilateur C si je me souvient bien, donc du coup je ne sait pas si ça va changer quelque chose, c'est normalement moins rapide que de l'asm écrit à la main...
     


    • Publicité



  6. Mazen21

    Date d'inscription
    décembre 2010
    Localisation
    Tunisie
    Messages
    62

    Re : Utilisation d'un codeur incrémental

    Bonjour,
    Est ce que vous pouvez me dire que représente les valeur INC_MAX et INC_MIN et pourquoi la valeur "var" n'est jamais mis à 0?
    merci,
     

  7. Jack

    Date d'inscription
    avril 2003
    Localisation
    Metz
    Messages
    15 957

    Re : Utilisation d'un codeur incrémental

    Est ce que vous pouvez me dire que représente les valeur INC_MAX et INC_MIN
    Es-tu bien sur d'avoir bien lu ce qui précède? Je rappelle un point du problème initial:
    Le but est d'utiliser un bouton rotatif codeur pour faire évoluer une variable entre 0 et 100
    et on peut lire plus loin:
    Code:
    #define INC_MAX 100 
    #define INC_MIN 0
    je te laisse conclure.

    pourquoi la valeur "var" n'est jamais mis à 0?
    Même constatation: tu n'as pas lu ce qui précède:
    Code:
    unsigned var=0; //variables globales
    Bonne lecture.
     

  8. Mazen21

    Date d'inscription
    décembre 2010
    Localisation
    Tunisie
    Messages
    62

    Re : Utilisation d'un codeur incrémental

    Oui vous avez raison je n'ai pas bien lu le problème.
    En fait je veux implémenter cette solution sur 2 encodeurs incrémentaux pour mesurer la vitesse et la position de mon robot.
     

  9. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    62 725

    Re : Utilisation d'un codeur incrémental

    Dans le programme d'interruption, tu écris deux fois le programme (avec des déclarations de variable différente évidemment)
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  10. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    62 725

    Re : Utilisation d'un codeur incrémental

    Une autre solution donnée par Microchip
    Citation Envoyé par RISC Voir le message
    Il ne faut SURTOUT PAS toucher à GIE dans l'interruption...
    L'acceptation d'une interruption entraine la désactivation automatique des interruptions (GIE=0) heureusement ...
    De même à la fin de l'interruption, la sortie provoque automatiquement la réautorisation des interruptions (GIE=1).
    Le programmeur doit simplement remettre à 0 le flag de l'interruption qui a été activé.

    Pour ce qui est de ton encodeur, cela dépend de la vitesse...si elle est importante, ton micro va passer son temps en interruptions...
    Cette note d'application (AN718) montre une méthode qui consomme peu de ressources micro, mais nécessite des bascules externes.
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  11. joey57

    Date d'inscription
    août 2005
    Âge
    29
    Messages
    669

    Re : Utilisation d'un codeur incrémental

    Salut,

    Ca me rappel un de mes sujets il y'a quelques mois sur cette fonction.
    J'avais donc réalisé un programme qui gère mon codeur mais sans utiliser de timer.

    Je voulais utiliser le timer pour mesurer le temps entre des "contacts" et ensuite évaluer la rapidité d'incrémentation ou de décrémentation.
    Je m’explique :

    Je suis à 10 (de 000 à 999)
    Je souhaite aller à 20, OK je tourne doucement, je fais +1 ou -1.
    Maintenant je souhaite aller à 600, je tourne rapidement le codeur, donc au lieu de faire +1 ou -1, pourquoi pas faire +10 ou-10 ?

    Et ce en fonction du temps mis pour faire quelques contacts(en faisant une moyenne).

    Sinon, très utile comme sujet
     

  12. invite13962411

    Date d'inscription
    janvier 2012
    Messages
    94

    Re : Utilisation d'un codeur incrémental

    Salut !

    Joli déterrage que je fais là...

    Je me penche actuellement sur l'exploitation de l'un de ces codeurs et j'utilise pour cela un Arduino.

    Auriez-vous une idée de la vitesse à laquelle l'Arduino est capable d'effectuer une mesure de front montant avec la fonction interrupt ? J'ai peur de "sauter" des stries en déplaçant le codeur trop vite...
     

  13. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    62 725

    Re : Utilisation d'un codeur incrémental

    Citation Envoyé par NeOtuX Voir le message
    Auriez-vous une idée de la vitesse à laquelle l'Arduino est capable d'effectuer une mesure de front montant avec la fonction interrupt ? J'ai peur de "sauter" des stries en déplaçant le codeur trop vite...
    La méthode que j'utilise est différente .... c'est une machine d'état avec un Timer ....J'ai déjà donné la réponse ....
    Citation Envoyé par DAUDET78 Voir le message
    Pour qu'aucune transition utile ne soit perdue, il faut au moins un échantillon du signal pendant une période " stable ", donc une fréquence d'échantillonnage d'au moins 4 fois la fréquence maximum de sortie du codeur.
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  14. invite13962411

    Date d'inscription
    janvier 2012
    Messages
    94

    Re : Utilisation d'un codeur incrémental

    Très juste !

    Comment puis-je connaitre/déterminer la fréquence d’échantillonnage ?
     

  15. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    62 725

    Re : Utilisation d'un codeur incrémental

    C'est toi qui la fixe !
    - Il faut une fréquence suffisamment haute pour ne pas perdre de "pas"
    - Il faut une fréquence suffisamment basse pour ne pas surcharger ton µC par le travail en interruption du Timer ( qui est relativement court). A toi de faire cette évaluation .....
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     


    • Publicité







Sur le même thème :





 

Discussions similaires

  1. Codeur incrémental
    Par le fondateur du cosmos dans le forum Électronique
    Réponses: 9
    Dernier message: 16/12/2011, 13h30
  2. Codeur Incrémental
    Par petitnul12 dans le forum Électronique
    Réponses: 16
    Dernier message: 27/10/2010, 20h21
  3. Codeur incrémental - 16f628
    Par Gilgari dans le forum Électronique
    Réponses: 0
    Dernier message: 12/10/2010, 07h39
  4. Codeur incrémental?
    Par méta_flo dans le forum Électronique
    Réponses: 1
    Dernier message: 20/04/2007, 20h51
  5. Codeur Incremental
    Par 1953 dans le forum Électronique
    Réponses: 4
    Dernier message: 26/02/2006, 12h55