L’encodeur rotatif est le remplaçant moderne du potentiomètre : on le tourne sans butée, d’un bout à l’autre, indéfiniment. Il ne renvoie pas une position mais un mouvement — chaque cran tourné produit des impulsions que l’Arduino compte pour savoir de combien, et dans quel sens, on a tourné.
Celui de cette page est un module prêt à brancher, référence KY-040 : un axe métallique cannelé, un bouton poussoir intégré quand on appuie sur l’axe, et cinq broches sérigraphiées sur la carte. C’est le composant des menus déroulants, des réglages de volume et de tous les appareils qui n’ont qu’un seul bouton pour tout faire.
Encodeur ou potentiomètre ?
Les deux se tournent avec les doigts, et c’est leur seule ressemblance.
- Le potentiomètre donne une position absolue. Sa piste s’use et crachote à la longue, et il ne peut pas faire plus d’un tour complet. L’Arduino lit une tension entre 0 et 5 V.
- L’encodeur donne une variation relative. Deux contacts internes s’ouvrent et se ferment en décalé pendant la rotation, et le programme compte les impulsions. Pas de piste qui s’use, rotation infinie, et une précision fixe : un cran reste un cran, quelle que soit la vitesse à laquelle on tourne.
La conséquence à retenir : l’encodeur ne dit jamais où il se trouve au démarrage. Il ne dit que « j’ai tourné de trois crans dans ce sens ». C’est au programme de choisir une valeur de départ, puis de l’incrémenter.
Caractéristiques techniques
| Modèle | Module KY-040 — encodeur rotatif incrémental avec bouton poussoir |
|---|---|
| Alimentation | 3,3 à 5 V continu |
| Signaux | Deux sorties en quadrature, CLK et DT |
| Bouton poussoir | Intégré à l’axe, sortie SW, normalement ouvert, relié à la masse à l’appui |
| Impulsions | Deux impulsions par cran, soit environ 30 crans par tour |
| Rotation | Infinie dans les deux sens, sans butée mécanique |
| Créneau de l’axe | Axe métallique de 6 mm à méplat, traversant, avec filetage et écrou de fixation sur la carte |
| Broches | 5 broches mâles au pas de 2,54 mm, sérigraphiées sur la carte |
Les cinq broches, une par une
Les libellés sont imprimés en blanc sur la carte, à côté de chaque broche. Comme sur toutes les cartes de ce type, l’ordre physique dépend du fabricant : lisez la sérigraphie plutôt que de vous fier à un dessin trouvé en ligne.
CLK | Le signal A de l’encodeur. C’est lui qui change le premier quand on tourne, et c’est donc lui qu’on surveille par interruption. |
|---|---|
DT | Le signal B, décalé d’un quart de tour par rapport à A. Comparé à CLK au moment du changement, il donne le sens de rotation. |
SW | Le bouton intégré à l’axe. Il est normalement ouvert et relie cette broche à la masse quand on appuie. |
+ | L’alimentation positive. À relier au 5 V de l’Arduino. |
GND | La masse. À relier au GND de l’Arduino. |
Un mot sur les résistances de tirage. Les contacts de l’encodeur ne font que fermer un circuit vers la masse : sans résistance de tirage, une broche laissée ouverte « flotte » et le programme lit n’importe quoi. Certaines cartes KY-040 embarquent déjà deux résistances pour CLK et DT, d’autres non. Le geste sûr, qui fonctionne dans tous les cas, consiste à activer les résistances internes de l’Arduino avec INPUT_PULLUP — y compris pour SW, qui n’en a jamais sur le module.
Le cran, le rebond et pourquoi il faut anticiper
Deux choses expliquent la quasi-totalité des encodeurs qui « sautent des valeurs » ou « vont dans le mauvais sens » :
- Il y a deux impulsions par cran. Un comptage brut divisé par deux donne le nombre de crans réels. Sans cette division, tourner d’un cran ajoute deux unités.
- Les contacts rebondissent. À chaque cran, le ressort mécanique fait plusieurs micro-rebonds électriques. Quelques millisecondes d’antiparasitage, ou un décodage par interruption, suffisent à obtenir une lecture propre.
Le décodage par interruption a un avantage décisif : il ne rate aucune impulsion, même si le programme est occupé ailleurs — pendant un affichage, une temporisation ou une communication. Sur un Arduino Uno, seules les broches D2 et D3 peuvent déclencher une interruption matérielle, d’où le câblage qui suit.
Mini-projet : un réglage de valeur au tour de molette
On tourne pour choisir une valeur de 0 à 100, on appuie sur l’axe pour revenir à zéro. Le résultat s’affiche dans le moniteur série — et se transposera tel quel sur un écran, un servomoteur ou une intensité de LED.
Ce qu’il faut
| Le réglage | Le module encodeur rotatif KY-040 — celui de cette page |
|---|---|
| Le cerveau | Uno R3 + câble USB |
| Le support | Plaque d’essai 400 points |
| Les liaisons | 10 × fil mâle-femelle |
Le câblage
Le module se pique directement dans la plaque d’essai : ses cinq broches mâles y entrent sans adaptateur.
Module CLK | → Arduino D2 — interruption matérielle |
|---|---|
Module DT | → Arduino D3 |
Module SW | → Arduino D4 |
Module + | → Arduino 5V |
Module GND | → Arduino GND |
Le programme
À copier dans l’IDE Arduino, puis à téléverser sur la carte :
/*
* Encodeur rotatif KY-040 - reglage d'une valeur de 0 a 100
* Carte : Arduino Uno R3
* Montage : encodeur CLK sur D2, DT sur D3, SW sur D4
*
* Composants, brochage et fiche complete : www.marocproduits.com
*/
const byte PIN_CLK = 2; // signal A : seule la broche 2 peut surveiller CLK
const byte PIN_DT = 3; // signal B : donne le sens de rotation
const byte PIN_SW = 4; // bouton poussoir integre a l'axe
volatile long impulsions = 0; // compteur brut, modifie par l'interruption
volatile byte dernierCLK = 0; // etat memoire de CLK
byte dernierSW = 1;
long affichee = 0;
// Appelee automatiquement a chaque changement de CLK.
void surRotation() {
byte etatCLK = digitalRead(PIN_CLK);
if (etatCLK != dernierCLK) {
dernierCLK = etatCLK;
// Au moment du changement, comparer DT a CLK donne le sens.
if (digitalRead(PIN_DT) != etatCLK) {
impulsions = impulsions + 1; // horaire
} else {
impulsions = impulsions - 1; // antihoraire
}
}
}
void setup() {
pinMode(PIN_CLK, INPUT_PULLUP);
pinMode(PIN_DT, INPUT_PULLUP);
pinMode(PIN_SW, INPUT_PULLUP);
dernierCLK = digitalRead(PIN_CLK);
attachInterrupt(digitalPinToInterrupt(PIN_CLK), surRotation, CHANGE);
Serial.begin(9600);
Serial.println("Tournez l'axe, appuyez pour remettre a zero.");
}
void loop() {
// Le bouton est actif au niveau bas : appui = etat 0.
byte etatSW = digitalRead(PIN_SW);
if (etatSW == 0 && dernierSW == 1) {
impulsions = 0;
}
dernierSW = etatSW;
// Deux impulsions par cran : on divise par deux.
long valeur = constrain(impulsions / 2, 0, 100);
if (valeur != affichee) {
affichee = valeur;
Serial.print("Valeur : ");
Serial.println(affichee);
}
// L'antiparasitage du bouton, sans bloquer le reste du programme.
delay(5);
}Comment ça marche
- L’interruption, branchée sur
CHANGE, appellesurRotation()à chaque changement deCLK, dans les deux sens. Aucune impulsion n’est perdue, même pendant une temporisation. - Le sens se déduit en comparant
DTàCLKà l’instant précis du changement : si les deux niveaux diffèrent, on tourne dans un sens ; s’ils sont identiques, dans l’autre. - La variable
impulsionsest déclaréevolatileparce qu’elle est modifiée hors duloop(). Sans ce mot-clé, le compilateur peut mettre la valeur en cache et afficher un compteur figé — c’est l’erreur classique de ce montage. constrain()borne la valeur entre 0 et 100. C’est l’équivalent logiciel de la butée mécanique que l’encodeur n’a pas.INPUT_PULLUPactive la résistance interne de l’Arduino sur les trois entrées : les signaux sont hauts au repos et tombent à 0 quand un contact se ferme.
Pour aller plus loin
- Un affichage en façade — envoyez la valeur sur un afficheur LCD 16×02 I2C : deux fils d’alimentation et deux fils de données, et le réglage devient visible sans ordinateur.
- Un vrai bouton d’axe — montez le bouton de potentiomètre sur l’axe cannelé : le geste devient immédiat, et l’appui ne glisse plus sous le doigt.
- Trois menus autour d’un seul composant — un état menu enchaîné par appui et une valeur modifiée par rotation suffisent à piloter plusieurs réglages avec ce seul module.
Questions fréquentes
La valeur saute ou recule quand je tourne doucement, pourquoi ?
C’est presque toujours la méthode de lecture. En interrogeant CLK dans le loop() avec un delay() trop long, on rate des impulsions ; et sans décodage, les rebonds comptent plusieurs crans pour un seul geste. Utilisez l’interruption comme ci-dessus, et gardez un delay() court dans la boucle principale.
Le sens est inversé chez moi
Rien n’est en cause : échangez simplement CLK et DT, dans le câblage ou dans le programme. Le sens dépend de la convention de comptage autant que du module.
Faut-il une résistance externe pour tirer les signaux au niveau haut ?
Non. Activez INPUT_PULLUP sur les trois broches : cela suffit, et c’est le seul réglage qui soit fiable quelle que soit la carte reçue.
Peut-on l’alimenter en 3,3 V, pour un ESP32 ou un ESP8266 ?
Oui, la carte accepte de 3,3 à 5 V. Alimentez-la avec la tension de votre microcontrôleur : les sorties suivent la tension d’alimentation, et restent donc compatibles avec ses entrées.
Le bouton a-t-il besoin d’antiparasitage ?
Oui, un contact mécanique appuie une fois mais produit plusieurs fronts électriques. Le delay(5) du loop() suffit pour un usage de réglage. Pour un bouton qui valide une action, préférez une détection de front complétée par un court délai d’attente, afin qu’un seul appui ne déclenche qu’une seule action.
Combien de crans fait un tour complet ?
Environ trente sur ce module, avec deux impulsions par cran. Le rapport exact n’a pas d’importance pour un réglage : c’est constrain() qui fixe la plage utile.
À combiner avec
Pour une commande qui doit connaître sa position réelle au démarrage, le potentiomètre 10 kΩ reste le bon choix, et il se combine très bien avec ce module sur le même montage. Si vous partez de zéro, la plaque d’essai 400 points accueille directement les cinq broches du module, et l’Uno R3 fournit les interruptions dont le décodage a besoin.








Avis
Il n’y a pas encore d’avis.