Question

J'ai du mal à faire fonctionner correctement un encodeur rotatif avec les microcontrôleurs AVR.L'encodeur est un mécanique Encodeur ALPES, et j'utilise Atmega168.

Clarification

J'ai essayé d'utiliser une interruption externe pour écouter les broches, mais il semble que ce soit trop lent.Lorsque la broche A passe au niveau haut, la procédure d'interruption démarre puis vérifie si la broche B est au niveau haut.L’idée est que si la broche B est haute au moment où la broche A est devenue haute, alors elle tourne dans le sens inverse des aiguilles d’une montre.Si la broche B est basse, elle tourne dans le sens des aiguilles d’une montre.Mais il semble que l'AVR prenne trop de temps pour vérifier la broche B, elle est donc toujours lue comme étant haute.

J'ai également essayé de créer un programme qui bloque simplement jusqu'à ce que la broche B ou la broche A change.Mais il se peut qu'il y ait trop de bruit lorsque l'on tourne l'encodeur, car cela ne fonctionne pas non plus.Ma dernière tentative était d'avoir une minuterie qui stocke les 8 dernières valeurs dans un tampon et vérifie si elle passe de bas en haut.Cela n'a pas fonctionné non plus.

J'ai essayé de définir la portée de l'encodeur, et il semble utiliser entre 2 et 4 ms entre le premier changement de broche et l'autre changement de broche.

Était-ce utile?

La solution

J'ai une page Web sur encodeurs rotatifs et comment les utiliser, qui pourrait vous être utile.

Malheureusement, sans plus d'informations, je ne peux pas résoudre votre problème particulier.

Quelles broches du microcontrôleur sont connectées à l'encodeur et quel est le code que vous utilisez actuellement pour décoder les impulsions ?

Ok, vous êtes confronté à quelques problèmes différents, le premier problème est qu'il s'agit d'un encodeur mécanique, vous devez donc gérer le bruit des commutateurs (rebond, bavardage).Le Fiche de données indique que cela peut prendre jusqu'à 3 mS pour que les pièces cessent de rebondir et de créer de fausses sorties.

Vous devez créer une routine anti-rebond.Le plus simple est de vérifier en permanence si A monte haut.Si c'est le cas, démarrez un minuteur et vérifiez-le à nouveau dans 3 ms.S'il est toujours élevé, alors vous pouvez vérifier B - s'il n'est pas élevé, vous ignorez l'impulsion parasite et continuez à chercher A élevé.Lorsque vous cochez B, vous le regardez, démarrez une minuterie de 3 ms, puis regardez à nouveau B.Si c'était la même chose les deux fois, alors vous pouvez utiliser cette valeur - si elle change dans les 3 ms, vous devez le refaire (lisez B, attendez 3 ms, puis relisez-le et voyez si cela correspond).

L'Atmega est suffisamment rapide pour que vous n'ayez pas à vous soucier de la lenteur de ces vérifications, à moins que vous n'utilisiez également une vitesse d'horloge lente.

Une fois que vous avez traité le bruit mécanique, vous souhaitez alors examiner une routine de code gris appropriée - l'algorithme que vous suivez ne fonctionnera pas à moins que vous ne décrémentiez également si A est élevé lorsque B devient faible.Généralement, les gens stockent la dernière valeur des deux entrées, puis la comparent à la nouvelle valeur des deux entrées et utilisent une petite fonction pour incrémenter ou décrémenter en fonction de cela.(Consultez la rubrique "lecture haute résolution" sur le site Web que j'ai mentionné ci-dessus pour le tableau).Je combine les deux lectures en un nombre de quatre bits et j'utilise un tableau simple pour me dire si j'incrémente ou décrémente le compteur, mais il existe des solutions encore plus avancées et optimisées pour la taille, la vitesse ou la facilité de maintenance du code.

Autres conseils

L'ajout d'un filtre passe-bas analogique améliore considérablement le signal.Avec le filtre passe-bas, le code sur l'AVR était vraiment simple.

       _________
        |         |
        | Encoder |
        |_________|
          |  |  |
          |  |  |
     100n |  O  | 100n  
 GND O-||-+ GND +-||-O GND
          |     | 
          \     /
      3K3 /     \ 3K3
          \     /
          |     |    
VCC O-/\/-+     +-\/\-O VCC
     15K  |     |  15K
          |     |
          O     O
          A     B

Ah, les merveilles de l'art ASCII :p

Voici le programme sur l'AVR.Connectez A et B à l'entrée PORTB sur l'avr :

#include <avr/io.h>

#define PIN_A (PINB&1)
#define PIN_B ((PINB>>1)&1)

int main(void){
    uint8_t st0 = 0;
    uint8_t st1 = 0;
    uint8_t dir = 0;
    uint8_t temp = 0;
    uint8_t counter = 0;
    DDRD = 0xFF;
    DDRB = 0;
    while(1){   
    if(dir == 0){
        if(PIN_A & (!PIN_B)){
            dir = 2;
        }else if(PIN_B & (!PIN_A)){
            dir = 4;
        }else{
            dir = 0;
        }
    }else if(dir == 2){
        if(PIN_A & (!PIN_B)){
            dir = 2;
        }else if((!PIN_A) & (!PIN_B)){
            counter--;
            dir = 0;
        }else{
            dir = 0;
        }
    }else if(dir == 4){
        if(PIN_B & (!PIN_A)){
            dir = 4;
        }else if((!PIN_A) & (!PIN_B)){
            counter++;
            dir = 0;
        }else{
            dir = 0;
        }
    }else if(PIN_B & PIN_A){
        dir = 0;
    }
        PORTD = ~counter;
    }
    return 0;
}

Ce code fonctionne sauf si vous faites tourner l'encodeur très rapidement.Il se peut alors qu'il manque un pas ou deux, mais ce n'est pas important, car la personne qui utilise l'encodeur ne saura pas de combien de pas elle l'a tourné.

La vitesse ne devrait pas être un problème.La plupart des commutateurs mécaniques nécessitent des routines anti-rebond.Si vous souhaitez faire cela avec des interruptions, désactivez l'interruption lorsqu'elle se déclenche, démarrez une minuterie qui la réactivera après quelques ms.Gardez votre programme sans sondage > :)

Avec quoi as-tu des problèmes exactement ?Je suppose que vous avez pu accrocher les broches de l'encodeur à votre PIC conformément aux spécifications techniques liées sur la page Farnell que vous avez donnée, le problème est-il donc lié à la lecture des données ?Vous ne recevez aucune donnée de l'encodeur ?Vous ne savez pas comment interpréter les données que vous récupérez ?

/* into 0 service rutine */
if(CHB)
{
  if(flagB)
   Count++;
  FlagB=0;
}
else
{
  if(FlagB)
   count--:
  FlagB=0:
}

/* into 1 service rutine */
FlagB=1;

/* make this give to you a windows time of 1/4 of T of the encoder resolution
   that is in angle term: 360/ (4*resolution)
 */
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top