Arduino Mega 2560 broches dinterruption et mappage de ports avec encodeur rotatif

Jessaie dutiliser la manipulation de port dans les interruptions pour lire un encodeur rotatif. Jai trouvé du code pour un Uno, donc lappel de port pour les broches 2 et 3 est différent. Je pense que sur le Mega, ce sont respectivement PORTH3 et PORTH4. Mon code ne fonctionne pas. Est-ce que mes ports sont erronés? Jai essayé de lire ceci et je ne comprends pas complètement la partie Bxxxxxxxx. Je pense que cest peut-être ce qui est incorrect. Voici une partie de mon code avec lune des interruptions.

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2 static int pinB = 3; // Our second hardware interrupt pin is digital pin 3 volatile byte aFlag = 0; // let us know when we"re expecting a rising edge on pinA to signal that the encoder has arrived at a detent volatile byte bFlag = 0; // let us know when we"re expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set) volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255 volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor) volatile byte reading = 0; void setup () { pinMode(pinA, INPUT); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases) pinMode(pinB, INPUT); attachInterrupt(0, PinA, RISING); // set an interrupt on PinA, //looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below) attachInterrupt(1, PinB, RISING); // set an interrupt on PinB, //looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below) } void PinA() { //CCW cli(); //stop interrupts happening before we read pin values reading = PORTH & 0xC; // read all eight pin values then strip away all but pinA and pinB"s values if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin"s rising edge encoderPos --; //decrement the encoder"s position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00000100) bFlag = 1; //signal that we"re expecting pinB to signal the transition to detent from free rotation sei(); //restart interrupts } 

Commentaires

  • Avez-vous déjà réussi à faire fonctionner cela? Jai également voulu utiliser un Arduino Mega pour suivre la position angulaire dun encodeur Omron avec 3 interruptions. Une des interruptions pour que lindex soit réinitialisé à 0 à chaque fois il effectue une révolution. Je veux lutiliser pour suivre un mât rotatif pour la radiogoniométrie. Il y a des morceaux de code mais rien de complet. Le vôtre est-il complet? [email protected]

Réponse

Re « Les broches 2 et 3 sont différentes. Je pense que sur le Mega ce sont respectivement PORTH3 et PORTH4 », cest vrai que les broches numériques Arduino 2 et 3 appartiennent à des ports différents sur les cartes Uno et Mega2560.

Les Mega2560 « ont six broches INTx, contre deux sur les Uno ». Sur le Mega, INT0 … INT3 sont PD0 … PD3 et INT4, INT5 sont PE4, PE5. Sur lUno, INT0, INT1 sont PD2, PD3. Remarque, dans une réponse à Les interruptions externes peuvent-elles être OU « d ensemble sur le » 328 (Uno)? Je montre quelques routines qui afficheront les masques appropriés pour broches sur différents Arduinos. Voir les sections «Utilisation dautres broches pour les PCI» et «Sketch générant un framework ISR».


Voici quelques problèmes avec le code indiqué dans la question:

  1. aFlag est initialisé à zéro et nest jamais mis à une valeur différente de zéro dans le code affiché. Ainsi, la première condition if dans PinA() nest jamais remplie.

  2. PinA() est un gestionnaire dinterruptions, connecté aux interruptions par vos appels attachInterrupt(). Étant donné que le matériel désactive les interruptions avant dentrer dans un gestionnaire dinterruptions, il nest pas nécessaire que le gestionnaire dinterruptions désactive les interruptions. Autrement dit, supprimez cli() dans PinA(). De même, supprimez le sei() à la fin de PinA() car le matériel restaure létat dinterruption lorsquune instruction RETI sexécute.

  3. Lenvironnement logiciel Arduino définit des constantes comme B00001100 avec des valeurs binaires qui correspondent au nom. Autrement dit, dans lenvironnement logiciel Arduino, la constante B00001100 a la valeur 0B00001100. À mon avis, cest « une fonctionnalité stupide et inutile; je suggère que dans votre code vous utilisez la notation C standard comme 0B00001100 lorsque vous souhaitez utiliser des valeurs constantes binaires.

  4. Je considère lécriture de encoderPos -- au lieu de encoderPos-- comme une perversion et suggère de supprimer cet espace inutile.

  5. Comme vous n’avez pas montré le gestionnaire d’interruptions PinB(), je ne sais pas comment vous alliez gérer le encoderPos++. A en juger par le code affiché, vous utilisez une méthode qui ne gère pas correctement les erreurs de rebond et intermittentes. Je suggère dutiliser des interruptions de changement de broche et une méthode de machine détat, comme illustré dans les réponses à:
    Lecture à partir dun encodeur rotatif KY-040 avec Digispark
    Comment lire RPS pour une rotation rapide avec la méthode de changement détat dans Arduino?
    Lire les canaux du récepteur RC en utilisant Interrupt au lieu de PulseIn
    Les interruptions externes peuvent-elles être OU « d ensemble sur le » 328 (Uno)?

Réponse

Sur le méga, vous « auriez lu les épingles avec PIN.

Ainsi, votre code dans PinA deviendrait:

 reading = PINE & 0b00110000; if(reading == 0b00110000 && aFlag) { encoderPos --; bFlag = 0; aFlag = 0; } else if (reading == 0b00010000) bFlag = 1;  

I trouvé une excellente discussion sur le masquage requis ici: https://forum.arduino.cc/index.php?topic=561741.0

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *