====== Encodeur Rotatif avec Arduino UNO ====== J'ai besoin d'avoir une gestion d'un encodeur rotatif pour naviguer dans des menus ou avoir différentes actions sur un programme. L'interaction la plus simple est l'encodeur rotatif avec bouton poussoir qui va servir de validation. L'encodeur rotatif est composé de frotteurs mécanique, ce qui peut induire des faux-contacts. Si on ne prend pas de précautions, on va avoir, à cause des parasites induits par les faux-contacts, une grosse probabilité de pas supplémentaires dans la détection de rotation. On peut mettre des condensateurs pour intégrer les parasites. La solution que j'utilise est tout simplement une intégration logicielle, autant sur le codeur (**A** & **B**) que le bouton poussoir **C** qui peut lui aussi avoir des rebonds. Le programme ci-dessous utilise le TIMER_1 pour générer une fréquence de scrutation de 1kHz. la variable **_seconde** m'est utile mais pas pour l'encodeur et peut être supprimée. La led clignotante n'est pas utile non plus, ça permet juste de voir que la routine de scrutation fonctionne. Attention : le TIMER_1 utilisé ici l'est aussi par certaines librairies, dont servo.h. Faites donc vos recherches si vous avez des dysfonctionnement en les utilisant.\\ Le commun de l'encodeur et le bouton poussoir sont au GND.\\ #define LED LED_BUILTIN #define inA 2 // A ou B du codeur #define inB 3 // A ou B du codeur #define inC 4 // clic du codeur #define LBAS 3 #define LHAUT 6 #define LHH 9 #define APPUI_LONG 300 // nb de ms pour un appui long #define APPUI_TRES_LONG 2000 // nb de ms pour un appui très long volatile unsigned _ms=0; volatile unsigned _secondes=0; void setup(){ cli(); // ---- Init TIMER 1 RTC ---- TCNT1 = 65535-250; // Preset : 1ms@16Mhz TCCR1A = 0x00; TCCR1B |= (1 << CS11) | (1 << CS10); // prescaler timer1 à 64 TIMSK1 = (1 << TOIE1); // interruption sur overflow timer 1 sei(); pinMode(inA,INPUT_PULLUP); pinMode(inB,INPUT_PULLUP); pinMode(inC,INPUT_PULLUP); pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); } volatile int pos = 0; volatile byte clic = 0, clic_long=0, clic_tres_long=0; // --- Toutes les 1 ms --- ISR(TIMER1_OVF_vect){ static byte a=0, b=0; static byte int_sa=0, int_sb=0, int_sc=0; static byte _clic=0; static unsigned maintenu=0; byte voie_a, voie_b, voie_c; TCNT1 = 65535-250; if (++_ms == 1000) // 1 seconde écoulée { digitalWrite(LED,digitalRead(LED) ^ 1 ); _ms = 0; _secondes++; } voie_a = digitalRead(inA); voie_b = digitalRead(inB); voie_c = digitalRead(inC); //------------------------------------ if (voie_a==0){ // voie A est active if (int_sa != 0) // si integration en cours if (--int_sa <= LBAS) if (a!=0){ a=0; if (b==0) pos++; else pos--; } } else { // voie_a == 1 if (int_sa < LHH) // voie A passe inactive if (++int_sa >= LHAUT) // si integration en cours a=1; } // ------------------------------- if (voie_b==0) { if (int_sb!=0) if (--int_sb <= LBAS) b=0; } else { // voie_b == 1 if (int_sb < LHH) if (++int_sb >= LHAUT) b=1; } // traitement du clic if (voie_c==0) // bouton cliqué { if (int_sc != 0) if (--int_sc == 0) _clic=1; } else // bouton relâché { // voie_c == 1 if (int_sc < LHH) if (++int_sc > LHAUT) { if (_clic != 0) { _clic=0; if (maintenu < APPUI_LONG) clic = 1; else { if (maintenu < APPUI_TRES_LONG) clic_long = 1; } maintenu=0; } } } if (_clic != 0) if (++maintenu == APPUI_TRES_LONG) clic_tres_long = 1; } int pos_old = 0; void loop(void) { if (pos != pos_old) { Serial.println(pos); pos_old=pos; } if (clic != 0) { clic=0; Serial.println("clic !"); } if (clic_long != 0) { clic_long=0; Serial.println("clic long !"); } if (clic_tres_long != 0) { clic_tres_long=0; Serial.println("clic très long !"); } } Le programme va modifier 4 variables :\\ * **pos** qui donne la position de l'encodeur\\ * **clic** qui se met à 1 au moment du clic relâché court\\ * **clic_long** qui se met à 1 pour un clic relâché long (plus de 0,3s)\\ * **clic_tres_long** qui se met à 1 pour un clic très long (plus de 2s)\\ les variables clicxxxxxxxx doivent être remises à 0 par le programme qui les utilise.\\ la variable **pos** peut être elle aussi remise à 0.