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



+ Répondre à la discussion
Page 2 sur 3 PremièrePremière 2 DernièreDernière
Affichage des résultats 16 à 30 sur 34

Utilisation d'un codeur incrémental

  1. invite13962411

    Date d'inscription
    janvier 2012
    Messages
    94

    Re : Utilisation d'un codeur incrémental

    Merci.

    C'est bien là ce qu'il m'avait semblé comprendre.

    Plus précisément : il doit bien y avoir une fréquence "limite" de l'Arduino non ?

    En fait, je me demande s'il existe un moyen de connaitre de manière relativement exacte le temps que met l'Arduino à faire telle ou telle opération.

    Car je ne sais pas encore si je vais pouvoir gérer les deux canaux du codeur sans ralentir l’exécution du reste du programme et tout en ne perdant aucune information... D'autant plus que pour la suite je vais utiliser un second codeur...

    -----

     


    • Publicité



  2. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    63 340

    Re : Utilisation d'un codeur incrémental

    Citation Envoyé par NeOtuX Voir le message
    Plus précisément : il doit bien y avoir une fréquence "limite" de l'Arduino non ?
    C'est a toi de la déterminer ! Tu fais le programme d'interruption (de préférence en assembleur) et tu calcules
    Car je ne sais pas encore si je vais pouvoir gérer les deux canaux du codeur sans ralentir l’exécution du reste du programme et tout en ne perdant aucune information... D'autant plus que pour la suite je vais utiliser un second codeur...
    Cela ne fait que doubler le temps d'exécution du programme d'interruption .
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  3. bokan

    Date d'inscription
    octobre 2013
    Messages
    106

    Re : Utilisation d'un codeur incrémental

    Si ça vous intéresse, il y a un algo encore plus performant.

    Les jumps et les tests c'est assez lourd à gérer pour un CPU (et oui !). En les évitant on gagne beaucoup (c'est surtout vrai pour les gros processeurs mais aussi pour les petits). Il y a même des fanatiques de la programation sans conditions http://www.antiifcampaign.com/.

    Donc une solution serait de pousser les états de AB actuels et passés dans une variable unique. Puis de créer un tableau de toutes les sommes à ajouter. On additionne souvent du vide, mais une addition est plus rapide qu'un simple test.

    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.
     */
    
    // quelques variables avec leur représentation binaires qu'on utilisera pas mais qui permettent de lister les différents états possibles
    #define B_0000  0 // 0  si a précédent =0, b précédent = 0, a actuel=0, b actuel=0 alors on ajoute 0
    #define B_0001  1 // +1 et
    #define B_0010  2 // -1 ainsi
    #define B_0011  3 // 0  de
    #define B_0100  4 // -1 suite
    #define B_0101  5 // 0  ...
    #define B_0110  6 // 0
    #define B_0111  7 // +1
    #define B_1000  8 // +1
    #define B_1001  9 // 0
    #define B_1010  10 // 0
    #define B_1011  11 // -1
    #define B_1100  12 // 0
    #define B_1101  13 // -1
    #define B_1110  14 // +1
    #define B_1111  15 // 0
    // les mêmes dans un tableau
    int motion= [0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,+1,0];
    
    unsigned rotation= 0; //variables globales je renomme rotation parceque var, ça me pique les yeux
     
    interrupt[14] void gray() // interruption sur compteur (toutes les 1,6ms)
    {
            static unsigned char var_ab=0;
            
            var_ab &&= B_0011  ; // ca ne garde que les deux petits bits qui correspondent à l'état précédent de a et b
            var_ab <<= 2;            // on les décale vers la gauche de deux bits pour libérer les bits  1 et 2
            var_ab = var_ab && ( SIG_A << 1 ) && SIG_B; // on y colle nos deux nouvelles valeurs 
            
            int rotation_temp = rotation + motion[var_ab];
            if(rotation_temp >= INC_MIN){
                   rotation = rotation_temp;
            }else if(rotation_temp <= INC_MAX){
                   rotation = rotation_temp;
            }
    }
    Je n'ai pas testé et il y a surement des erreurs, mais la logique est là.
    Le code est bien plus léger, il n'y a qu'un petit tableau de 16 octets en plus et il nous évite une foule de conditions.
    Dernière modification par bokan ; 27/10/2013 à 21h15.
     

  4. grosmatou75001

    Date d'inscription
    juin 2013
    Messages
    517

    Re : Utilisation d'un codeur incrémental

    Citation Envoyé par bokan Voir le message
    Les jumps et les tests c'est assez lourd à gérer pour un CPU (et oui !). En les évitant on gagne beaucoup (c'est surtout vrai pour les gros processeurs mais aussi pour les petits).
    Pour les gros genre Pentium j'y connais rien (y avait pas une histoire de pipeline de réorganisation de je ne sais plus quoi??), mais sur un AVR un test (CP, CPC, CPI, TST) c'est 1 cycle et un saut conditionnel (BR**) 2... D'accord, si on fait 10 tests ça s'accumule, mais alors on doit vraiment être dans un truc hyperserré au niveau temps si cela a une importance. Mais j'avoue qu'il est toujours intéressant de trouver mieux, même si le côté pratique est peut-être un peu... Bref. Si je trouve le temps dans les prochains jours je ferais bien passer les différents version par GCC et le simulateur, rien que pour comparer à une version assembleur pur (oui oui je sais, faut aimer...).

    Il y a même des fanatiques de la programation sans conditions http://www.antiifcampaign.com/.
    C'est quand même pas sérieux ce truc???

    Bon, il y a deux, trois trucs qui me sautent à l'oeil à première vue...

    Code:
            var_ab &&= B_0011  // &&=et LOGIQUE, il faut utiliser &
            var_ab <<= 2;
            var_ab = var_ab && ( SIG_A << 1 ) && SIG_B; //Même remarque, mais je pense qu'en fait il faut utiliser un OU et non un ET...
     

  5. bokan

    Date d'inscription
    octobre 2013
    Messages
    106

    Post Re : Utilisation d'un codeur incrémental

    grosmatou75001 :

    Effectivement les jumps sur pentium tuent les perfs c'est lié à la structure super scalaire du proc. Simplifions en disant qu'il y a 5 étapes pour faire une instruction (décoder l'instruction, rapatrier les données, executer l'instruction, remettre le résultat...http://en.wikipedia.org/wiki/Instruction_cycle), dans un proc normal ce sont les mêmes circuits qui sont utilisés à chaque étape il faut donc 5 tic (je ne sais plus le nom) par instruction, dans un pentium ils on scindé les circuits en 5 circuits dédiés à chaque étape (d'où le nom pentium) et à chaque tic chaqun fait son travail et passe au suivant un peu comme 5 travailleurs à la chaîne au lieu d'un. Ça fonctionne bien mais quand il y un jump ou quand une instruction dépends du résultat de la précédente, on doit attendre que le dernier travailleur aie fini pour pouvoir faire l'instruction suivante. Dans les procs hyperthreading, quand ce cas se présente, plutôt que d'attendre a rien faire, on execute une instruction d'un autre thread.

    Je suis tout à fait d'accord avec toi, les test et jumps ne sont pas catastrophiques surtout sur un AVR. Mais c'est quand même mieux de coder comme j'ai montré. Surtout que c'est le genre de code qu'on met dans une librairie et qu'on ne touche plus quand il marche. Alors autant l'optimiser à mort. Si tu compare mon code à de l'assembleur pur, tu aura très peu d'écart. Il se peut même que le code provenant de C soit plus rapide si le compilateur est bon (et le programmeur ASM pas parfait).

    C'est quand même pas sérieux ce truc???
    Si si, et dans le monde professionnel ça se comprends carrément. Y'as beaucoup de "programmeurs" qui ne connaissent que le if et qui vont te coller des enchaînements improbables. C'est illisible, impossible à maintenir.

    Bon, il y a deux, trois trucs qui me sautent à l'oeil à première vue...
    Honte suprême à moi qui joue les donneurs de leçon et confond un & et un &&, houps !
    Le code corrigé serait donc, avec une petite optimisation qui supprime un test quand il n'y a pas de mouvement :

    Code:
    int motionFromState= [0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,+1,0];
    
    unsigned rotation= 0; //variables globales
    
     interrupt[14] void gray() // interruption sur compteur (toutes les 1,6ms)
    { 
           static unsigned char currentState=0;   
           
           currentState &= 3 ; // 3= 00000011 en binaire ca ne garde que les deux petits bits qui correspondent à l'état précédent de a et b    
           currentState <<= 2; // on les décale vers la gauche de deux bits pour libérer les bits  1 et 2
           currentState |= ( SIG_A << 1 ) | SIG_B; // on y colle nos deux nouvelles valeurs
    
           int motion = motionFromState[currentState];
    
           if(motion){ // si c'est différent de 0
                   var rotationTemp = rotation + rotationTemp;
    
                   if((rotationTemp >= INC_MIN) && (rotationTemp<= INC_MAX)){
                         rotation = rotationTemp;
                  }
           }
    }
    
    Notez qu'il n'y aucun problème à déclarer plein de variables très locales (motion et rotationTemp). Le compilateur ne va même pas leur donner d'espace mémoire correspondant, juste leur attribuer un registre pendant quelques cycles.
    Dernière modification par bokan ; 28/10/2013 à 10h35.
     


    • Publicité



  6. grosmatou75001

    Date d'inscription
    juin 2013
    Messages
    517

    Re : Utilisation d'un codeur incrémental

    Merci pour le petit cours sur les Pentium, intéressant! Pour les comparaisons ASM je verrai si j'ai le temps...
     

  7. bokan

    Date d'inscription
    octobre 2013
    Messages
    106

    Re : Utilisation d'un codeur incrémental

    Code:
    int motionFromState= [0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,+1,0];
    
    unsigned rotation= 0; //variables globales
    
     interrupt[14] void gray() // interruption sur compteur (toutes les 1,6ms)
    { 
           static unsigned char currentState=0;   
           
           currentState &= 3 ; // 3= 00000011 en binaire ca ne garde que les deux petits bits qui correspondent à l'état précédent de a et b    
           currentState <<= 2; // on les décale vers la gauche de deux bits pour libérer les bits  1 et 2
           currentState |= ( SIG_A << 1 ) | SIG_B; // on y colle nos deux nouvelles valeurs
    
           int motion = motionFromState[currentState];
    
           if(motion==0) return; // si c'est 0 on a fini
    
           var rotationTemp = rotation + rotationTemp;
    
           if((rotationTemp < INC_MIN) || (rotationTemp> INC_MAX)) return; // valeur hors limite, on a fini
    
           rotation = rotationTemp;
           
    }
    Juste pour le fun parce que je viens de relire mon code. Il vaut mieux coder comme ceci, sans imbriquer les if quand ce n'est pas utile. bien qu'un bon compilateur générera exactement le même code.
     

  8. extremgear

    Date d'inscription
    mai 2013
    Messages
    156

    Re : Utilisation d'un codeur incrémental

    Bonjour,

    Lorsque l'on veut interfacer un codeur optique fonctionnant en 24V avec un pic 5v , existe il une meilleure solution que les ponts diviseurs ?
    merci.

    A vrai dire je ne vois pas les problèmes qui peuvent se poser avec cette solution.
    Dernière modification par extremgear ; 03/07/2014 à 20h36.
     

  9. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    63 340

    Re : Utilisation d'un codeur incrémental

    C'est une bonne solution .
    Les sorties sont en 24V ou en collecteurs ouverts ? Référence et lien WEB sur ce codeur ?
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  10. extremgear

    Date d'inscription
    mai 2013
    Messages
    156

    Re : Utilisation d'un codeur incrémental

    Merci pour la réponse hyper rapide !

    Les sorties peuvent être entre 10 et 30 V , selon comment est alimenté le codeur .
    Je compte alimenter en 24V .
    lien :
    http://files.pepperl-fuchs.com/selec...151794_fra.pdf
     

  11. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    63 340

    Re : Utilisation d'un codeur incrémental

    C'est quoi la référence complète de ton codeur ?
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  12. extremgear

    Date d'inscription
    mai 2013
    Messages
    156

    Re : Utilisation d'un codeur incrémental

    RVI58N 032YYA31N Y0200

    Je précise que je suis bien certain d'avoir le modèle en 10-30V , j'ai déjà fait des tests à l'oscillo + montage , à l'époque je l'avais utilisé avec un optocoupleur ( pourquoi ? allez dont savoir !)
    je vais faire un schéma de l'utilisation que je compte en faire .
    ce codeur sera destiné à l'asservissement d'un motoréducteur pour un projet perso .
    Dernière modification par extremgear ; 03/07/2014 à 21h42.
     

  13. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    63 340

    Re : Utilisation d'un codeur incrémental

    Ca correspond pas trop .... à l'oscilloscope tu as quoi sur A et /A ?
    Bonjour et au revoir .... a remettre en début et en fin de réponse
     

  14. extremgear

    Date d'inscription
    mai 2013
    Messages
    156

    Re : Utilisation d'un codeur incrémental

    arf je viens de trouver la bonne doc :
    http://files.pepperl-fuchs.com/selec...253654_fra.pdf

    je ne dispose que des sortie A B 0.
     

  15. DAUDET78

    Date d'inscription
    septembre 2006
    Localisation
    Ile de France
    Âge
    74
    Messages
    63 340

    Re : Utilisation d'un codeur incrémental

    C'est mieux ..... donc, pont diviseur .
    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, 14h30
  2. Codeur Incrémental
    Par petitnul12 dans le forum Électronique
    Réponses: 16
    Dernier message: 27/10/2010, 21h21
  3. Codeur incrémental - 16f628
    Par Gilgari dans le forum Électronique
    Réponses: 0
    Dernier message: 12/10/2010, 08h39
  4. Codeur incrémental?
    Par méta_flo dans le forum Électronique
    Réponses: 1
    Dernier message: 20/04/2007, 21h51
  5. Codeur Incremental
    Par 1953 dans le forum Électronique
    Réponses: 4
    Dernier message: 26/02/2006, 13h55