[RESOLU](enfin presque! XD)Galère avec encodeur incrémentale

Bonjour à toutes et à tous,

dans le cadre de mon projet, un générateur de fonction par DDS9850,
j' ai un encodeur incrémentale qui est lu toute les 2mS par une interruption du Timer2,
ce dernier sert (à terme) à modifier les valeurs suivantes:
-wForme ( carré ou sinusoïdal )
-Pas ( soit pour l' incrémentation des valeurs soit pour le balayage de fréquence ).
-min ( valeur de départ du balayage ).
-max ( valeur d' arrivé du balayage ).
-freq ( pour sélectionner une fréquence fixe " précise au Hertz ).
-xxx ( peut être pour des gammes de balayage ).

Voici un extrait du code:

#define ENC1DOWN  21					// Encodeur 1 down
#define ENC1UP    211				        	    // Encodeur 1 up

// Tableau pour faciliter l' ajout d' encodeur supplémentaire
	int pinA[] = {3};							// Pins A des encodeurs
	int pinB[] = {2};							// Pins B des encodeurs
	int lcounter[] = {0};						// valeurs précédentes des encodeurs	
	volatile int lastEncoded[] = {0};		    // Dernieres valeur lue encodeurs
	volatile int counter[] = {0};		    	// Valeur courante des encodeurs
	int bcounter[] = {0};				    	// valeurs encodeurs divisees par 4	
	byte valencodeurs;                      // numero encodeur et sens

int WForm =  0;
	int mWForm = 1;
	long pas   = 10;
	long min   =  1;
	unsigned long max   =  5000000;
	unsigned long freq  =  1000;	// le générateur commence à 1kHz

//	Variable du rotacteur
	const int rotac = A0;	// Lecture façon analog.read
	int rotacVal = 0;
	byte param = 0;		// Après comparaison, le paramètre param sera envoyé au switch de l' encodeurParamètre


void setup() {
setEncodeurs();
}
		void setEncodeurs    (void){
				/*-------------------------------------
			// Initialisation des pin des encodeurs
			// Mode input
			// Resistance pull-up activee
			//-------------------------------------*/
			byte i;

			for(i=0;i<1;i++) {					// Ajuster le nombre de tours par rapport au nombre d' encodeurs
				pinMode(pinA[i], INPUT_PULLUP);
				pinMode(pinB[i], INPUT_PULLUP);
			}
			// Configuration du timer 2
			/*----------------------------------------	
			// Pour la lecture des encodeurs
			// Execution de la routine d'interruption
			// toutes les 2ms (par overflow)
			//----------------------------------------*/
			TIMSK2 &= ~(1<<TOIE2);
			// Timer 2 en mode normal
			TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
			TCCR2B &= ~(1<<WGM22);
			// Horloge interne
			ASSR &= ~(1<<AS2);
			// Mode overflow
			TIMSK2 &= ~(1<<OCIE2A);
			// Prescaler a 256
			TCCR2B |= (1<<CS22)  | (1<<CS21) ; // Set bits
			TCCR2B &= ~(1<<CS20);              // Clear bit
			// Sauvegarde de la valeur pou reloader dans l'ISR
			tcnt2 = 131;
			// Chargement et mise en route du timer
			TCNT2 = tcnt2;
			TIMSK2 |= (1<<TOIE2);
		}
	ISR(TIMER2_OVF_vect) {
		// TIMER 2 pour lecture des entrées
	/*
		Création d'un compteur pour créer une interruption qui lance une fonction de la lecture
		 des broches de l' encodeur
	*/
		/*----------------------------------------
		// Routine executee tous les 2ms
		// par overflow sur le compteur du timer 2
		//----------------------------------------*/
	int MSB;
	int LSB;
	int encoded;
	int sum;
	byte i;
	TCNT2 = tcnt2;      // Reload du timer
	// Lecture des 4 encodeurs
	for (i=0;i<1;i++) {
	MSB = digitalRead(pinA[i]); // MSB = most significant bit
	LSB = digitalRead(pinB[i]); // LSB = least significant bit
	encoded = (MSB << 1) |LSB; // conversion
	sum  = (lastEncoded[i] << 2) | encoded; // Ajout a la valeur precedent
	// Test si on avance
	if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
	counter[i]++;
	// Test si on recule
	if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
	counter[i]--;
	lastEncoded[i] = encoded;   // On memorise la valeur pour la prochaine fois
	bcounter[i]=counter[i]>>1;  // Compteur utilisateur divise par 4
	}

	}
		byte readEncodeurs   (void){
			/*--------------------------------------------
			// Routine principale de lecture des encodeurs
			//--------------------------------------------*/
		byte i,val;
		val=0;
			// Lire les 4 encodeurs
			for (i=0;i<1;i++) {
			// si la valeur a variee pour un des encodeurs
				if (lcounter[i]!=bcounter[i]) {
				// Si UP valeur de 11 a 14
					if (bcounter[i]>lcounter[i])
					val=i+211;
					// Si down valeur de 1 a 4
					else
					val=i+21;
					lcounter[i]=bcounter[i];
					Serial.println(val,DEC);
					Serial.println(lcounter[i],DEC);
				return val;
				}
			}

		return 0;	
		}
		void readRoctact     (void){
			/*
			//	Une sorte de Macro de définition de variable 
			//	qui servira de paramètre pour savoir quel valeur (param) l' encodeur augmentera ou diminuera
			*/
			rotacVal=analogRead(rotac);
			if (rotacVal>=9 && rotacVal<=12){
				param = 0;				// Parametre 0 Form
			}
			if (rotacVal>=32 && rotacVal<=38){
				param = 1;				// parametre 1 Pas
			}
			if (rotacVal>=90 && rotacVal<=100){
				param = 2;				// parametre 2 min
			}
			if (rotacVal >=180 && rotacVal <=200){
				param = 3;				// parametre 3 max
			}
			if (rotacVal >=270 && rotacVal <=290){
				param = 4;				// parametre 4 freq
			}	
			if (rotacVal >=370 && rotacVal <=390){
				param = 5;				// parametre 5 
			}
		
	
		}
//-------Gestion des valeurs de bases
		void PARAM (void){
			switch(param){
				case 0:						// Form
				FORM(valencodeurs);Serial.println(valencodeurs,DEC);break;
				case 1:
				PAS();break;
				case 2:
				MIN();break;
				case 3:
				MAX();break;
				case 4:break;
				FREQ();
				//case 5:
			}
		}
			void FORM(byte valencodeurs ){
			// Ici on sélectionne la forme d' onde, on bascule le relais, et on affiche la forme	
				Serial.println("on rentre dans FORM");
				//if (mWForm =! WForm){	// condition d' entrée
				//	Serial.println("on rentre dans le if de FORM");
					switch (valencodeurs)
					{
						case 0:
						Serial.println("on rentre dans case 0 FORM ");delay(500);break;
						case ENC1UP:
						Serial.println("on rentre dans FORM case ENC1UP");delay(500);
							if (WForm = 0){WForm = 1;Serial.println("on rentre dans if FORM ENC1UP");delay(500);}
								else {WForm = 0;Serial.println("on rentre dans else FORM ENC1UP");delay(500);}delay(500);
							//mWForm = WForm;	
						break;
						
						case ENC1DOWN:
							if (WForm = 1){WForm = 0;Serial.println("on rentre dans FORM case ENC1DOWN");delay(500);}
								else {WForm=1;Serial.println("on rentre dans FORM else ENC1DOWN");delay(500);}
						//	mWForm = WForm;
						break;						
					}
					lcd.setCursor(6,0);lcd.print("     ");lcd.setCursor(6,0);//delay(500);
					if (WForm = 0){digitalWrite(WFormBascule,LOW);lcd.print("Carre");}//delay(500);
					if (WForm = 1){digitalWrite(WFormBascule,HIGH);lcd.print("Sinus");}//delay(500);
				//mWForm = WForm;
				//}				

void loop(){
readRoctact();  readEncodeurs();
valencodeurs=readEncodeurs();     // On recupère la variable byte val de la fonction readEncodeurs
	PARAM();lcd.setCursor(16,0);	lcd.print(WForm,DEC);
	ENVOI_FREQ(freq);     // on envoie le mot de 32 bits au DDS 9850
}

Le souci est que dans le switch de la fonction FORM, valencodeur est toujours à zéro, alors que dans la fonction PARAM, valencodeur correspond bien au mouvement de l' encodeur, ENC1UP ou ENC1DOWN.

Ce code est tiré du code du SIDaster de chez cfpradio

Si quelqu' un veut bien m' aiguiller... Merci.

dans ton code de la loop :

valencodeurs = readEncodeurs();

c'est donc parce que la fonction readEncodeurs() te retourne 0.

dans ton code de readencodeur:

for (i = 0; i < 1; i++)

il y a un problème pour scruter les 4 encodeurs

Merci dfgh,

quelle rapidité :smiley: Je n' avait peut-être pas précisé, il n' y a qu' un encodeur.

En effet, bizarrement il m' a fallu augmenter d' un tour la boucle, maintenant, la valeur de la fonction sort bien vers la loop, mais seulement la valeur ENC1DOWN...

Bon je devrais pouvoir trouver ça...

Merci dfgh. 8)

En supprimant les delay, ENC1UP apparait dans le moniteur, cependant, la valeur ENC1DOWN revient sans que j' ai tourné l' encodeur dans l' autre sens... :o

weetoz:
En supprimant les delay, ENC1UP apparait dans le moniteur, cependant, la valeur ENC1DOWN revient sans que j' ai tourné l' encodeur dans l' autre sens... :o

bonsoir
à tu verifié déjà le bon fonctionnement de ton encodeur ?
pour de l'encodeur A/B j'utilise la lib de PJRC , elle est tres versatile

Bonsoir Artouste,

pour l' encodeur, pas de souci, ça incrémente et décrémente sans aucun souci, je penche plus pour la partie readEncodeur.
Je pense que j' ai un souci soit dans l' ISR, soit dans la fonction readEncoder.

Cependant, je vais essayer cette librairie à nouveau, ça avait été assez dur pour moi lorsque je l' avais essayé l' année dernière, mais ça date un peu, peut-être qu' avec les quelques p'tits progrès...

Merci L' Artouste! :wink:

J' ai donc testé la lib prjc avec l' exemple "basic", et il apparait des irrégularités dans l' incrémentation et la décrémentation.

Je n' ai pas ce problème en utilisant une interruption interne pour une scrutation dans le code que j' adapte pour le DDS9850.
...

weetoz:
J' ai donc testé la lib prjc avec l' exemple "basic", et il apparait des irrégularités dans l' incrémentation et la décrémentation.

donc utilisation des pins 5 et 6 pour ton encodeur ?

refait le test (et modif de l'exemple "basic" avec ton encodeur sur pin 2 et 3 si uno )
c'est quoi ton arduino ?

perso , je l'ai bien torturée cette lib et je n'en suis pas venu à bout (evidemment en restant dans du raisonnable)
en utilisation encodeur/moteur , donc bien au delà des vitesses concernant les encodeurs en entrée IHM

Un duemilanove, j' avais bien fait la modification des broches:

Encoder myEnc(2, 3);

J' admets volontiers que c' est un encodeur de récupération d' un appareil bas de gamme ( chaine HIFI chinoise à pas chère ) et qu'il a été beaucoup plus difficile de le faire fonctionner.

J' avais essayé par interruption externe avec différentes valeurs de capacité, rien n' y faisaient, toujours des rebonds et donc des interruptions intempestives.

La méthode de polling est la plus concluante pour l' instant, avec des capa de 100nF.

C' était dans la condition d' entrée dans le premier if ici:

byte readEncodeurs   (void){
			/*--------------------------------------------
			// Routine principale de lecture des encodeurs
			//--------------------------------------------*/
		byte i,val;
		val=0;
			// Lire les 4 encodeurs
			for (i=0;i<2;i++) {
			 // si la valeur a variee pour un des encodeurs
				if (lcounter[i]!=counter[i]) {

En fait c' était la valeur de l' incrémentation divisé par 4 "bcounter[]" qui était comparé à la valeur courante de l' encodeur ce qui entrainait systématiquement le else ici:

	else{
						Serial.println("else");
					val=i+21; Serial.println(val,DEC);
					}

Maintenant, il reste plus qu' à trouver le moyen de remettre val à zéro... ( en la déclarant en variable globale, ça devrait faire l' affaire).

Je remercie chaleureusement les intervenants de ce post pour m' avoir aidé! ( dfg et Artouste ).

Suite et fin de l' histoire.

J' ai déclaré val en variable globale, puis modifié les conditions d' incrémentation et décrémentation dans la fonction readEncodeurs:

		byte readEncodeurs   (void){
			/*--------------------------------------------
			// Routine principale de lecture des encodeurs
			//--------------------------------------------*/
		byte i;
			// Lire les 4 encodeurs
			for (i=0;i<2;i++) {
			 // si la valeur a variee pour un des encodeurs
				if (lcounter[i]!=counter[i]) {
				// Si UP valeur de 31 a 34
				 Serial.println("Premier if");
					if (lcounter[i]<counter[i]){
						Serial.println("deuxieme if");
						val=i+31;// Serial.println(val,DEC);
					}
					// Si down valeur de 21 a 24
					//else{
					if (lcounter[i]>counter[i]){	
						Serial.println("troisieme if");
					val=i+21; //Serial.println(val,DEC);
					}
				}			// fin du if (lcounter[i]!=counter[i])
				lcounter[i]=counter[i];
				Serial.println(val,DEC);
				//Serial.println(bcounter[i],DEC);
					delay(2000);
				return val;
			}				// fin de la boucle for (i=0;i<2;i++)
		return 0;	
		}

Ainsi il suffit de remettre à zero "val" une fois qu' une des valeurs des paramètres est été incrémenté | décrémenté, ce qui assure que le premier pas ne sot pas d'ignoré.

cool