[Résolu] Probleme de vitesse de comptage d'un encodeur

Bonjour,

Je suis débutant en arduino (mais pas en programmation). Je suis en train de tester un systeme qui me permettrait d'indiquer les coordonnées d'un astre visé avec un télescope. Dans ce but j'ai mis en place un Arduino Mega 2560 que j'avais sous la main et j'ai réussi à récupérer 2 encodeurs rotatif de la marque Sick qui ont 10000 pas par tour, soit un resolution d'environ 2 Arcminute par impulsion

Voici les encodeurs: DFS60B-S1PK10000 | Codeurs | SICK

Le but est donc de me donner l'angle horizontale (Azimut) et l'angle vertical (Altitude). J'ai donc Ecrit un bout de code classique pour des encodeurs avec gestion des impulsions par interruption. Ça ne marche pas trop mal si je tourne très doucement mais dès que j'accélère, je perd vraiment beaucoup d'impulsion (jusqu'à 50% si je tourne très vite).

Quelle est la cause de ce phénomène: Encodeurs trop précis et/ Arduino trop lent? ou un problème de code (que je joins ci dessous)? Y-a-t-il une solution pour régler ce soucis ou tout au moins le réduire de façon conséquente. Pour ceux qui connaissent, le télescope est un Dobson, donc tourner à la main.

// CONSTANTES
#define ENC_AZIM_A 2	                                      // Port signal A encodeur Azimut
#define ENC_AZIM_B 22                                       // Port signal B encodeur Azimut
#define NB_IMP_ENC 10000.0                                  // Nb impulsions par tour encodeur
#define ENC_ALTI_A 3                                        // Port signal A encodeur Altitude
#define ENC_ALTI_B 23                                       // Port signal B encodeur Altitudeaison
#define SEC_PAR_TR 360.0*60*60                              // Nbre d'Arseconde par tour
#define INC_SEC SEC_PAR_TR/NB_IMP_ENC                       // Angle en Arcseconde par pas de l'encodeur

// VARIABLES GLOBALES
volatile long ComptImpAzim;                          // Compteur d'impulsions en Azimut
volatile long ComptImpAlti;                          // Compteur d'impulsions en Altitude
unsigned long AncienMillis;                          // Pour tempo non bloquante

// PROTO FONCTIONS
char *arcsec2str( double arcsec);                    
void Move_Azim();
void Move_Alti();


// Récupération des mouvements de l'azimut
void Move_Azim()
{
	if (digitalRead(ENC_AZIM_B))
		ComptImpAzim--;
    if (ComptImpAzim < 0) ComptImpAzim += NB_IMP_ENC;
	else
		ComptImpAzim++;
   if (ComptImpAzim >= NB_IMP_ENC) ComptImpAzim -= NB_IMP_ENC;
}

// Récupération des mouvements de l'altitude
void Move_Alti()
{
  if (digitalRead(ENC_ALTI_B))
    ComptImpAlti--;
    if (ComptImpAlti < 0) ComptImpAlti += NB_IMP_ENC;
  else
    ComptImpAlti++;
   if (ComptImpAlti >= NB_IMP_ENC) ComptImpAlti -= NB_IMP_ENC;
}

// Transforme l'angle en arcsec vers une chaine [+ddd° mm' ss.ss"]
char *arcsec2str(double arsec )
{
	int degre;
	int minute;
	double seconde;
	static char rep[20];
  char secch[5];
	char minch[2];
	
	degre = int(arsec/3600);
	minute = int((arsec - (degre*3600)) /60);
	seconde = (arsec - (degre*3600) - (minute*60));

  dtostrf(seconde, 5, 2, secch);
  dtostrf(minute, 2, 0, minch);
  // 
	sprintf(rep,"%4d° %s' %s""",degre, minch, secch);

	return rep;
}


void setup()
{
	// Pin A et B encodeur Az en entrée
	pinMode(ENC_AZIM_A, INPUT);
	pinMode(ENC_AZIM_B, INPUT);
 // Pin A et B encodeur AltC en entrée
  pinMode(ENC_ALTI_A, INPUT);
  pinMode(ENC_ALTI_B, INPUT);
	// Pull up 
	digitalWrite(ENC_AZIM_A, HIGH);
	digitalWrite(ENC_AZIM_B, HIGH); 
	digitalWrite(ENC_ALTI_A, HIGH);
  digitalWrite(ENC_ALTI_B, HIGH);

  // Init port série 0 pour moniteur
	Serial.begin (9600);

  // Init à 0 des compteurs d'impulsions
  ComptImpAzim = 0;
  ComptImpAlti = 0;
  
  // Detection des mouvements d'encodeurs par interruption sur front descendant sur signal A
	attachInterrupt(digitalPinToInterrupt(ENC_AZIM_A), Move_Azim, FALLING);
	attachInterrupt(digitalPinToInterrupt(ENC_ALTI_A), Move_Alti, FALLING);

}



void loop()
{
  float Ang_Azim;
  float Ang_Alti;
 
  AncienMillis = millis();

  // Affichage des angles toutes les 500ms sans blocage
  if ( (millis() - AncienMillis) > 500) {
    // Angle d'azimut
    Ang_Azim = ComptImpAzim*INC_SEC;
    Serial.print("Azim: ");
	  Serial.print(arcsec2str(Ang_Azim));
  
    // Angle d'azimut
    Ang_Alti = ComptImpAlti*INC_SEC;
    Serial.print(" - Alt: ");
    Serial.print(arcsec2str(Ang_Alti));

    AncienMillis = millis();
  }
  
/*
    * AUTRES TRAITEMENTS ET CALCUL FAIT ICI
    * Avec des tempo non bloquantes (millis())
    * 
    *
 */  
   
	
}

Je vous remercie d'avance de l'aide que vous voudrez bien m'apporter.

Anthony.

Quand on s'inscrit sur un forum on commence par :

  • prendre connaissance de ses règles
  • le parcourir avant de poser une question.

Pour les règles c'est pourtant très simple : en tête de forum il y a un message épinglé intitulé : "Règles du forum francophone", c'est pourtant clair qu'il faut le lire en premier. Il y a aussi un autre message intitulé "Faire un nouveau message avec les balises" : c'est tout aussi clair.

Dans l'état actuel tu as posté dans un sous forum spécialisé pour y déposer des cours, même si tu n'avais pas compris le titre la lecture préalable d'un ou deux sujets t'aurait fait comprendre que ce n'était pas l'endroit pour poser des questions.

La règle est simpple :

  • aucune réponse a ta question tant que tu n'aura pas demandé à faire déplacer le sujet --> utilise le lien "Report to moderator"
  • si tu ne demande rien ta question sera supprimée par le moderateur qui a autre chose à faire que de passer son temps à faire le ménage.

Sujet déplacé...

Anthony59:
...Ça ne marche pas trop mal si je tourne très doucement mais dès que j'accélère, je perd vraiment beaucoup d'impulsion (jusqu'à 50% si je tourne très vite).

Quelle est la cause de ce phénomène: Encodeurs trop précis et/ Arduino trop lent? ou un problème de code (que je joins ci dessous)? Y-a-t-il une solution pour régler ce soucis ou tout au moins le réduire de façon conséquente. Pour ceux qui connaissent, le télescope est un Dobson, donc tourner à la main.

Bonjour
Je te conseille d'utiliser cette lib encoder de pjrc
elle offre beaucoup de souplesse et d'adaptabilité

Bonjour,

Si tu mets

 AncienMillis = millis();

juste avant le test

 if ( (millis() - AncienMillis) > 500) {

Tu es sur de ne jamais passer dans le test. Supprimes cette affectation.

Bonjour et merci pour vos réponse.

Je vais essayé la "Encoder.h" ce soir pour voir les amélioration qu'elle apporte.

kamill:
Si tu mets

 AncienMillis = millis();

juste avant le test

 if ( (millis() - AncienMillis) > 500) {

Tu es sur de ne jamais passer dans le test. Supprimes cette affectation.

Oui, il s'agit d'un oubli: j'ai supprimé une partie du code qui n'avait rien à voir avec mon souci pour des raisons de lisibilité sur le forum. En fait j'utilise les tempos sans delay() pour toutes les autres fonctions avec des tempo allant de 1s à plusieurs secondes selon l'importance du traitement à faire ( 1s pour la récupération de l'heure systeme, 5min pour la température,...etc ). J'espérer en faisant cela, libérer du temps pour les encodeurs .

Bonsoir,

Suite à vos conseils, j'ai essayé la library encodeur que vous m'avez conseillé. Je ne recevais que des valeurs vraiment bizarre. Après plusieurs essais j'ai décidé de créer ma librairie (surtout à des fins didactitielles, vu ce qu'il y a déjà sur le marché). Je rappelle que j'ai des notions de programmations, mais pas de classes ni de C++.

J'ai quelque chose de simple mais .... Ca ne marche pas. Le problème des interruptions dans des classes est (si j'ai bien compris tout ce que j'ai lu) STATIC mais l'interet est bien de différencier les 2 encodeurs. Donc d'y perd mon latin (et même mon C++) et je sollicites donc votre aide.

Pour mon sketch, j'ai cela:

#include <simpleMinuteur.h>
#include "DSC_Encoder.h"

#define TMR_ENC 500		// Durée du Timer de lecture des positions

// Déclaration des pins de l'arduino utilisées
#define AZpinA 2		
#define ALTpinA 3
#define AZpinB 22
#define ALTpinB 23

// Création du Timer pour la lecture des encodeurs
simpleMinuteur TMREncodeur(TMR_ENC); 

// création des 2 encodeurs
encodeur EncAzim(AZpinA, AZpinB);
encodeur EncAlti(ALTpinA, ALTpinB);

// Variables pour stocker les positions lues des encodeurs
long PosAZ, PosALT;

// Initialisations
void setup()
{
	Serial.begin(115200);
	
}

// Boucle principales
void loop(){
	// Si Timee encodeur écoulé
	if (TMREncodeur.estTermine()){
		// Lectures des positions des 2 encodeurs
		PosAZ = EncAzim.read();
		PosALT = EncAlti.read();
		// Affichage des positions sur moniteur série
		Serial.print("Azimut: ");
		Serial.print(PosAZ);
		Serial.print(" - Altitude: ");
		Serial.print(PosALT);
		// Redémarre le timer encodeur
		TMREncodeur.redemarrer();
	}

}

ensuite mon entete (.h) donne ceci:

#ifndef DSC_ENCODER_H

#define DSC_ENCODER_H
#include <arduino.h> 


class encodeur 
{
	
	public :

		// Constructeur
		encodeur(int pin1, int pinB);  	// Création d'un encodeur sur les pin spécifiées
		long read();					// Lecture de la postition d'un encodeur
		void write(long p);				// Force la position d'un encodeur
		void RAZ();						// Remise à 0 de la position de l'encodeur
		
		


    private:
    	
		int _pA, _pB;					// N° de pin en interne
    	volatile long position;			// Position courante de l'encodeur
    	static void FctInt();			// Fonction privée STATIC qui lance la procédure ISR
    	void encodeur_ISR();			// Traitement à faire lors d'une interruption (Incrémente Décrémente la position)
    	
};


#endif

et finalement le code proprement dit de la lib:

#include <arduino.h>
#include "DSC_encoder.h"




encodeur::encodeur(int pinA, int pinB) {

		_pA = pinA;														// Récupération des pin
		_pB = pinB;
		pinMode(_pA, INPUT);											// Pin A en entrée
		digitalWrite(_pA, HIGH);										// Pull Up
		pinMode(_pB, INPUT);											// Pin B en entrée 
		digitalWrite(_pB, HIGH);										// Pull Up
		position = 0;													// Initialisation de la position à 0
		attachInterrupt( digitalPinToInterrupt(_pA), FctInt, CHANGE );  // Déclenche la fonction FctInt à changement de la pin A
}


// Renvoie la position de l'encodeur en nombre de pas
long encodeur::read(){
	long Valrtn;
	noInterrupts();			// Bloque les interruptions
	Valrtn = position;		// Recupère la position
	interrupts();			// ReAutorise les interruptions
	return Valrtn;			// Renvoie la valeur lue
}

// Force la position de l'encodeur en nombre de pas
void encodeur::write(long p){
	noInterrupts();			// Bloque les interruptions
	position = p;			// Modifie la valeur de la position arduinovec la valeur passée en parametre
	interrupts();			// ReAutorise les interruptions
}

// Remet la position de l'encodeur à 0 
void encodeur::RAZ(){
	write(0);				// Met à 0 la position courante
}


// Lancement de la fonction ISR sur l'interruption
void FctInt(){
	encodeur_ISR();	// Lance la fonction ISR 
}


// Traitement à reception de l'interruption
void encodeur::encodeur_ISR(){
	int etatB, etatA;

	// Récupère les états des 2 pins
	etatA = digitalRead(_pA);
	etatB = digitalRead(_pB);

	// Si les pins sont dans le même état
	if (etatA == etatB )
	{	
		noInterrupts();		// Bloque les interruptions
		position++;			// Incrémente la position
		interrupts();		// re Autorise les interruptions
	}
	else // Si les états sont différents
	{
		noInterrupts();		// Bloque les interruptions
		position--;			// Décrémente la position
		interrupts();		// re Autorise les interruptions
	}




}

J'ai bien noté, en parcourant certains articles, que la fonction d'interruption devait etre static . Mais l'interet étant bien évidemment pas que les 2 encodeurs soient complètement indépendant, j'ai créer comme conseillé une fonction static privée qui appelle la fonction public qui réalise le traitement à proprement parlé.
Ceci dit le compilateur me renvoie ce message alors que la fonction est bien déclaré:

[Build] F:/Users/Anthony/Documents/Arduino/DSCOO...
[Step 1] Check Toolchain.
[Step 2] Find all source files.
[Step 3] Start building.
[3.3%] Compiling DSCOO.ino.cpp...
[6.7%] Compiling DSC_encoder.cpp...
F:/Users/Anthony/Documents/Arduino/DSCOO/DSC_encoder.cpp: In function 'void FctInt()':
F:/Users/Anthony/Documents/Arduino/DSCOO/DSC_encoder.cpp:44:15: error: 'encodeur_ISR' was not declared in this scope
  encodeur_ISR(); // Lance la fonction ISR 
               ^
[Build] Error occurred.

Merci d'avance pour le temps que vous pourrez me consacrer.

Bonjour,

C'est bien d'écrire une class générique pour gérer un encodeur au lieu d'écrire plusieurs fois la même chose.

Pour ce qui est de ton problème:
encodeur_ISR() est un membre non static d'une classe donc il doit être appelé en précisant l'instance à laquelle il appartient.

Pour cela il faut

  • creer une fonction par interruption
    par exemple FctInt0() et FctInt1()

  • dans le constructeur mémoriser l'adresse de l'instance suivant l'interruption utilisée dans des variables statiques
    par exemple dans adEncodeur0 et adEncodeur1

  • toujours dans le constructeur faire un attachInterrupt soit avec FctInt0 soit avec FctInt1 en fonction du numéro de l'interruption

  • dans les fonctions interruptions, appeler la fonction encodeur_ISR() avec la bonne instance
    pour l'interruption 0:
    void encodeur::FctInt0() {
    adEncodeur0->encodeur_ISR(); // Lance la fonction ISR
    }

Merci pour tes explications Kamill.
J'ai donc modifié le code selon tes conseils. J'ai créé un tableau d'adresses d'encodeurs avec un nombre maxi d'encodeurs. A chaque construction j'incrémente l'indice de l'encodeur et stocke l'adresse de l'instance dans le tableau.
J'ai cependant une erreur de compil dans la fonction fctint() qui execute AdrEnc[indice]->Encodeur_ISR() (Lance la fonction Encodeur_ISR de l'instance en cours, si j'ai bien compris). En effet, il m'indique que l'indice est non déclaré alors qu'il fait bien parti des propriété de la classe.
J'ai du raté quelque chose, mais je ne vois franchement pas quoi.

Voici mon code:

l'entete .h

#ifndef DSC_ENCODER_H

#define DSC_ENCODER_H
#include <arduino.h> 
#define MAX_ENCODEUR 4 // Nombre Maxi d'encodeur 



class encodeur 
{
 
 public :

 // Constructeur
 encodeur(int pin1, int pinB);   // Création d'un encodeur sur les pin spécifiées
 long read(); // Lecture de la postition d'un encodeur
 void write(long p); // Force la position d'un encodeur
 void RAZ(); // Remise à 0 de la position de l'encodeur



    private:
     
 int _pA, _pB; // N° de pin en interne
     volatile long position; // Position courante de l'encodeur
     static void FctInt(); // Fonction privée STATIC qui lance la procédure ISR
     void encodeur_ISR(); // Traitement à faire lors d'une interruption (Incrémente Décrémente la position)
     static int NbEnc; // Nombre d'encodeurs ( = Nbre d'instance de la classe)
   int IndEnc; // Indice de l'encodeur
   
};


#endif

et le cpp de la classe

#include <arduino.h>
#include "DSC_encoder.h"


encodeur *AdrEnc[MAX_ENCODEUR]; // Tableau des adresses de chaque instance de classe des encodeurs


encodeur::encodeur(int pinA, int pinB) {

 // La construction ne se fait que si le nombre max d'encodeurs n'est pas atteint
 if (NbEnc < MAX_ENCODEUR){
 IndEnc = NbEnc; // Indice de l'instance courante
 NbEnc++; // Nombre d'encodeurs
 AdrEnc[IndEnc] = this; // Adresse de l'instance courante
 _pA = pinA; // Récupération des pins
 _pB = pinB;
 pinMode(_pA, INPUT); // Pin A en entrée
 digitalWrite(_pA, HIGH); // Pull Up
 pinMode(_pB, INPUT); // Pin B en entrée 
 digitalWrite(_pB, HIGH); // Pull Up
 position = 0; // Initialisation de la position à 0
 attachInterrupt( digitalPinToInterrupt(_pA), FctInt, CHANGE );  // Déclenche la fonction FctInt à changement de la pin A
 }
}


// Renvoie la position de l'encodeur en nombre de pas
long encodeur::read(){
 long Valrtn;
 noInterrupts(); // Bloque les interruptions
 Valrtn = position; // Recupère la position
 interrupts(); // ReAutorise les interruptions
 return Valrtn; // Renvoie la valeur lue
}

// Force la position de l'encodeur en nombre de pas
void encodeur::write(long p){
 noInterrupts(); // Bloque les interruptions
 position = p; // Modifie la valeur de la position arduinovec la valeur passée en parametre
 interrupts(); // ReAutorise les interruptions
}

// Remet la position de l'encodeur à 0 
void encodeur::RAZ(){
 write(0); // Met à 0 la position courante
}


// Lancement de la fonction ISR sur l'interruption
void FctInt(){
 AdrEnc[IndEnc]->encodeur_ISR(); // Lance la fonction ISR  de l'instance courante
}


// Traitement à reception de l'interruption
void encodeur::encodeur_ISR(){
 int etatB, etatA;

 // Récupère les états des 2 pins
 etatA = digitalRead(_pA);
 etatB = digitalRead(_pB);

 // Si les pins sont dans le même état
 if (etatA == etatB )
 { 
 noInterrupts(); // Bloque les interruptions
 position++; // Incrémente la position
 interrupts(); // re Autorise les interruptions
 }
 else // Si les états sont différents
 {
 noInterrupts(); // Bloque les interruptions
 position--; // Décrémente la position
 interrupts(); // re Autorise les interruptions
 }




}

résultat de la compil:

[Build] F:/Users/Anthony/Documents/Arduino/DSCOO...
[Step 1] Check Toolchain.
[Step 2] Find all source files.
[Step 3] Start building.
[3.3%] Compiling DSCOO.ino.cpp...
[6.7%] Compiling DSC_encoder.cpp...
F:/Users/Anthony/Documents/Arduino/DSCOO/DSC_encoder.cpp: In function 'void FctInt()':
F:/Users/Anthony/Documents/Arduino/DSCOO/DSC_encoder.cpp:51:9: error: 'IndEnc' was not declared in this scope
  AdrEnc[IndEnc]->encodeur_ISR(); // Lance la fonction ISR  de l'instance courante
         ^
[Build] Error occurred.

Il faut que tu déclares que FctInt() appartient à la class encodeur
void encodeur::FctInt(){

Mais à mon avis ça ne va pas marcher car quand tu entres dans la fonction statique tu ne peux accéder à un membre non statique IndEnc

Sais-tu combien ta carte peut traiter au maximum d'interruptions par seconde avec un attachinterrupt() ?

Sachant que comme tu es parti, il te faudra donc 2 attachinterrupt() par encodeur (Phase A et Phase B) pour connaître sa position, et que tu auras 2 encodeurs (un pour l'horizontale, un autre pour la verticale).

kamill:
Il faut que tu déclares que FctInt() appartient à la class encodeur
void encodeur::FctInt(){

J'ai corrigé cet oubli, mais effectivement ca ne change rien.

ard_newbie:
Sais-tu combien ta carte peut traiter au maximum d'interruptions par seconde avec un attachinterrupt() ?

Sachant que comme tu es parti, il te faudra donc 2 attachinterrupt() par encodeur (Phase A et Phase B) pour connaître sa position, et que tu auras 2 encodeurs (un pour l'horizontale, un autre pour la verticale).

Avec une version du programme sans classe, j'ai estimé les temps d'execution. La fonction ISR proprement dite prend 20µs, le temps entre 2 interruptions est de 100µs si je tourne l'encodeur à la main à une vitesse raisonnable (mais tout de même plus rapide qu'en condition réelle).

J'utilise une carte arduino Mega 2560 (j'avais oublié de le préciser). Si je ne me trompe pas il y a 6 pin sur lesquelles on peut connecter des interruptions externes (Mais je n'utilise que celles des pins 2 et 3 car les autres sont sur les RX0/TX0 et les pins de l'I2C qui seront utilisée par d'autres péripheriques). Par contre il me semble qu'1 seule interruption par encodeur suffit: Je déclenche l'interruption sur tous les fronts (montant et descendant) du signal A.

Sur front Montant de A (donc A passe à 1): si B = 1 => +1 (A=B)
Sur front Montant de A (donc A passe à 1): si B = 0 => -1 (A<>B)
Sur front descendant de A (donc A passe à 0): si B = 1 => +1 (A<>B)
Sur front descendant de A (donc A passe à 0): si B = 0 => -1 (A=B)
Ce fonctionnement permet d'ailleurs de multiplier le nombre de pas physique de l'encodeur par 2 et donc d'obtenir un meilleur résolution.

Oui une seule interruption suffit.
Mais en utilisant deux interruptions tu peux multiplier la résolution encore par 2.

C'est vrai Kamill mais je ne suis pas sur qu'un Mega 2560 arrive à suivre vu qu'il aura quand même d'autres choses à faire en paralelle. Un Due aurait peut etre pu mais son défaut (enfin pour cette application) est que ses pin sont limité à 3.3V. Mes encodeurs sont alimentés en 5V mini et ressortent donc du 5V sur les signaux A et B.
Et puis les 20000 impulsions par tour me donne une résolution d'environ 1 Arcminutes ce qui est relativement correcte pour l'utilisation prévue.Il faut rester raisonnable et savoir ne pas être trop gourmand. C'est mon 1er projet Arduino.

Pour une précision maximum, je suppose que c'est le cas ici, il faut enregistrer par interruptions les fronts montants ainsi que descendants de Phase A et Phase B, faute de quoi il y a une imprécision lors d'un changement de direction.

Par ailleurs, certains encodeurs fournissent aussi un Index (c'est le cas des tiens il me semble) qui permet de remettre à zéro le compteur de position en envoyant un pulse à chaque tour complet. Ce pulse d' Index peut aussi être capté sur une autre interruption.

Certains fabricants d'encodeurs étiquettent leurs produits avec un nombre de CPR (Cycles par révolution) et l'appellent PPR (Pulses par révolution), alors que PPR = 4*CPR sur un encodeur quadratique car chaque "cycle" produit 2 fronts sur Phase A et 2 autres sur Phase B.

En conséquence, un produit labellisé par exemple 600 PPR peut éventuellement générer en réalité 2400 pulses par révolution. Le nombre affiché de PPR est donc à tester au départ, ou voir la doc si c'est précisé. Ça change beaucoup la donne puisqu'on doit multiplier par 4 le nombre d'interruptions, et on arrive vite, pour des vitesses de rotation conséquentes, à des centaines de milliers de pulses par seconde à enregistrer sans en perdre au passage….donc hors de portée d'un microcontrôleur à 16 MHz.

Pour passer du 5V au 3.3V, un simple diviseur de tension avec 2 résistances fera l'affaire (ou un décaleur de niveau loqique, mais pas absolument nécessaire ici).

Pour info, la carte DUE possède 2 décodeurs quadratiques hardwares. Pour les sketches d'exemples, voir ici (reply #84 et #87).

Anthony59:
C'est vrai Kamill mais je ne suis pas sur qu'un Mega 2560 arrive à suivre vu qu'il aura quand même d'autres choses à faire en paralelle. Un Due aurait peut etre pu mais son défaut (enfin pour cette application) est que ses pin sont limité à 3.3V. Mes encodeurs sont alimentés en 5V mini et ressortent donc du 5V sur les signaux A et B.
Et puis les 20000 impulsions par tour me donne une résolution d'environ 1 Arcminutes ce qui est relativement correcte pour l'utilisation prévue.Il faut rester raisonnable et savoir ne pas être trop gourmand. C'est mon 1er projet Arduino.

Je ne dis pas qu'il faut utiliser deux interruptions mais qu'on peut le faire.
Je suis d'accord avec toi, mieux vaut une interruption qui fonctionne bien que deux qui risquent de plomber le système.

ard_newbie:
Pour info, la carte DUE possède 2 décodeurs quadratiques hardwares. Pour les sketches d'exemples, voir ici (reply #84 et #87).

Je ne connaissais pas ce détail. C'est effectivement très intéressant pour ce projet. Par contre le code a l'air assez ardu (en tout cas pour mes maigres compétences actuelles). Je vais essayé d'éplucher les docs et posts et tout ce que je trouve à ce sujet.

Merci de cette info.

Bonsoir à tous et merci de l'attention que vous avez porté à mon problème et de l'aide que vous m'avez apporté.

Mon problème de vitesse d'encodage est résolu. J'ai désinstallé l'IDE Arduino et je l'ai réinstallé avec le strict minimum des librairie dont j'avais besoin. J'ai refait un essai avec la librairie encoder de JPRC et ca fonctionne. J'ai même fait l'essai en connectant les 2 encodeurs sur 4 pins interruptibles. Ca va super vite et avec 40000 pas par tour, ce qui me fait une résolution de 30 Arcsecondes. Je perds un port série mais j'essaierai de m'en arranger. J'ai pour l'instant l'écran et le RTC qui tournent sur les pins séries. Il ne reste donc que le RX/TX0 que je garde pour le moniteur série. Si j'ai d'autres modules à rajouter je m'orienterai vers de l'I2C.

Je pense qu'à force d'essayer pleins de librairies différentes, j'ai mis un tel bazar que l'IDE s'est perdu lui même.

Je pense donc m'orienter vers cette librairie encoder qui d'après ce que j'ai pu lire reste la meilleure.

Bonne soirée

Anthony59:
...
Je pense donc m'orienter vers cette librairie encoder qui d'après ce que j'ai pu lire reste la meilleure.

Bonsoir
Je ne sais pas si c'est la meilleure, mais perso même dans des applications à hautes vitesses (relatives) , je n'ai pas reussi à la "mettre à genoux" dans l'environnement arduino de base.