Un joystick Arduino ouvre la porte à des projets interactifs précis : manette de jeu DIY, robot piloté au pouce, interface de contrôle pour caméra ou menu. Pourtant, beaucoup de makers se retrouvent vite coincés devant des valeurs analogiques instables, un axe qui « sature » ou un bouton qui réagit mal.
En partant de joysticks analogiques classiques et du Modulino Joystick Arduino ABX00135, allons pas à pas vers un code complet, fiable et calibré pour lire les axes X et Y, filtrer les mesures et exploiter chaque mouvement avec exactitude.
| Élément clé | Description | Pourquoi c’est important |
|---|---|---|
| Axe X | Sortie analogique variant généralement entre 0 et 1023 selon l’inclinaison. | Permet de détecter les mouvements horizontaux du joystick. |
| Axe Y | Même principe que l’axe X, mais pour les déplacements verticaux. | Indispensable pour obtenir une interaction complète à deux dimensions. |
| Tension de repos | Environ 512 sur une lecture analogique Arduino. | Permet de calibrer et filtrer le joystick pour éviter les dérives. |
| Bruit de lecture | Petites variations de 2 à 10 points qui nécessitent un filtrage logiciel. | Améliore la précision et la stabilité des valeurs reçues. |
| Bibliothèques utiles | Exemples : Filters.h, ResponsiveAnalogRead. | Simplifient la gestion des axes et le lissage des valeurs. |
Principe de fonctionnement d’un joystick analogique avec Arduino
Un joystick analogique pour Arduino repose sur deux potentiomètres linéaires montés à 90°. Un axe mesure le mouvement horizontal (X), l’autre le mouvement vertical (Y). Lorsque le manche est au repos, les deux potentiomètres se trouvent au milieu de leur course. Le microcontrôleur lit alors une valeur analogique proche du centre de l’ADC.
En déplaçant le joystick, la tension sur chaque axe varie entre un minimum et un maximum. Reliés aux broches analogiques d’une carte Arduino, ces signaux deviennent des valeurs numériques grâce au convertisseur analogique-numérique (ADC) intégré. La précision de lecture dépend directement de la résolution de cet ADC.
Un joystick analogique standard KY-023 propose deux sorties analogiques (X et Y) et un bouton poussoir digital. Chaque axe s’appuie sur un potentiomètre de 10 kΩ, adapté aux entrées analogiques des cartes Arduino classiques. À l’inverse, un joystick plus évolué comme le Modulino Joystick Arduino ABX00135 intègre déjà un microcontrôleur STM32 avec un ADC 12 bits et communique via I2C.
« Un joystick analogique bien lu par le microcontrôleur transforme un simple mouvement du pouce en commande précise et répétable »

Résolution ADC : 10 bits, 12 bits, 16 bits
La résolution de l’ADC conditionne le nombre de niveaux disponibles entre la tension minimale et maximale. Une résolution plus fine améliore la précision des mesures et facilite la gestion de zones mortes et de seuils.
| Résolution ADC | Plage de valeurs | Valeur centre théorique | Usage typique |
|---|---|---|---|
| 10 bits | 0 à 1023 | 512 | Arduino Uno, Nano, KY-023 |
| 12 bits | 0 à 4095 | 2048 | STM32, Modulino ABX00135 |
| 16 bits (module externe) | 0 à 65535 | 32768 | Lecture de précision via I2C (KY-053) |
Pour un joystick standard directement branché sur une carte Arduino Uno, la résolution est de 10 bits. Avec un module comme le Modulino ABX00135, le microcontrôleur STM32 interne exploite un ADC 12 bits. Pour des besoins avancés, un module ADC 16 bits KY-053 accessible via I2C élargit encore la finesse de mesure.
Matériel : panorama des joysticks pour Arduino
Avant d’aborder le code, un tour d’horizon des matériels les plus courants clarifie les approches possibles : lecture analogique directe, communication I2C, ou simple détection de directions digitales.
Joystick analogique standard KY-023
Le joystick KY-023 représente un choix répandu pour les projets Arduino. Il offre deux axes analogiques et un bouton poussoir intégré, avec une alimentation compatible 3,3 V à 5 V.
- Type : joystick 2 axes analogiques + bouton digital
- Tension d’alimentation : 3,3–5 V
- Sorties : X analogique, Y analogique, bouton numérique
- Potentiomètres : 2 × 10 kΩ
- Résolution typique : lecture sur ADC 10 bits (0–1023)
- Dimensions : largeur env. 35 mm, hauteur 30 mm
La plage de valeurs typique d’un joystick KY-023 sur une entrée 10 bits se situe autour de :
- Min : 0
- Centre : 512
- Max : 1023
Dans la pratique, le centre réel varie légèrement selon la qualité des potentiomètres et le montage mécanique. Un calibrage logiciel assure une interprétation cohérente de ces écarts.
Pour vos premiers tests avec le KY-023, reliez le joystick à un simple sketch de lecture série et notez les valeurs min, max et centre obtenues sur chaque axe. Ces valeurs guideront ensuite vos seuils et votre zone morte.

Modulino Joystick Arduino ABX00135
Le Modulino Joystick Arduino ABX00135 adopte une approche modulaire. Il intègre un microcontrôleur STM32C011F4 qui numérise les axes du joystick modèle FJN10K-S1B10KD0N en ADC 12 bits, puis expose les données via I2C ou UART, avec support du port de debug SWD.
- Microcontrôleur : STM32C011F4
- Joystick : FJN10K-S1B10KD0N
- Mouvements : environ 60° sur X, 60° sur Y
- Alimentation : 3,3 V (consommation env. 3,4 mA)
- Résolution ADC : 12 bits (0–4095)
- Valeurs typiques : X_min 0, X_max 4095, X_centre 2048 (idem pour Y)
- Communication : I2C (adresse 0x2C), UART optionnel, SWD
- Bouton poussoir : booléen intégré
- Connectique : Qwiic + headers 1×4 espacés de 22,86 mm
- Dimensions : largeur 25,36 mm, poids 4,4 g
- SKU : ABX00135
Grâce à son approche I2C, le Modulino soulage l’ADC interne de la carte Arduino. L’application récupère directement des valeurs déjà numérisées, ce qui simplifie les projets multi-capteurs où les entrées analogiques viennent à manquer.
Autres joysticks utiles selon les usages
D’autres références complètent ce paysage, chacune avec un usage ciblé.
- Adafruit Mini Joystick analogique : petit joystick 10 kΩ, tolérance 10 %, angles d’environ 25° sur X et Y, durée de vie annoncée à 500 000 cycles. Idéal pour des interfaces compactes.
- Joystick 5 directions COM5WS : plutôt orienté navigation de menus. Il génère des sorties digitales pour plusieurs directions (jusqu’à 7 lignes), avec un état actif bas et un état de repos haut. Dimensions env. 47 × 26 × 11 mm pour un poids d’environ 5 g.
Les joysticks purement digitaux comme le COM5WS ne se lisent pas via les entrées analogiques, mais par de simples entrées numériques. Ils restent intéressants pour créer des commandes de navigation ou des sélecteurs dans une interface utilisateur Arduino.

Branchement d’un joystick analogique classique sur Arduino
Pour un KY-023 ou tout joystick 2 axes analogiques similaire, le câblage reste direct : chaque axe sur une entrée analogique, le bouton sur une entrée digitale, et une alimentation stable.
Schéma de connexions typique (KY-023)
Sur une carte Arduino Uno ou Nano :
- VCC du joystick → 5 V (ou 3,3 V selon le modèle et la carte)
- GND du joystick → GND de l’Arduino
- Sortie X → A0
- Sortie Y → A1
- Bouton SW → D2 (par exemple), avec résistance de pull-up interne activée
Si le joystick supporte 3,3–5 V, un branchement direct sur 5 V reste en cohérence avec l’ADC de l’Arduino Uno. Sur une carte type Arduino Due (logique 3,3 V), un raccordement à 3,3 V protège les entrées.
Un joystick alimenté en 5 V relié à une carte basée sur un microcontrôleur strictement 3,3 V (certains STM32, ESP32 sans tolérance 5 V sur les entrées) nécessite une adaptation de niveau. Sans cela, les entrées analogiques subissent une surtension.
Lecture brute des axes analogiques : code minimal
Une fois le câblage validé, un premier sketch consiste à lire régulièrement les axes X et Y, puis à afficher les valeurs dans le moniteur série. Cette étape sert de base au calibrage et au débogage.
Code Arduino de base pour lire X et Y (ADC 10 bits)
const int pinJoyX = A0;
const int pinJoyY = A1;
const int pinButton = 2;
void setup() {
Serial.begin(9600);
pinMode(pinJoyX, INPUT);
pinMode(pinJoyY, INPUT);
pinMode(pinButton, INPUT_PULLUP); // bouton actif à l'état bas
}
void loop() {
int x = analogRead(pinJoyX); // 0 à 1023
int y = analogRead(pinJoyY); // 0 à 1023
bool buttonPressed = (digitalRead(pinButton) == LOW);
Serial.print("X=");
Serial.print(x);
Serial.print("\tY=");
Serial.print(y);
Serial.print("\tBTN=");
Serial.println(buttonPressed ? "1" : "0");
delay(50);
}
Ce code affiche les valeurs brutes non filtrées. En déplaçant doucement le joystick dans chaque direction, les extrêmes et le centre réel se révèlent. Ces mesures servent ensuite de références pour le traitement logiciel.
Comprendre les valeurs analogiques et les seuils de direction
La lecture brute n’exprime pas directement une direction. Pour interpréter le mouvement (gauche, droite, haut, bas, neutre), l’usage de seuils s’impose. Les valeurs analogiques typiques pour un ADC 10 bits suivent un schéma assez régulier.
Plage de valeurs typiques et centre théorique
Sur un Arduino en 10 bits, une représentation classique de joystick atteint les valeurs ci-dessous :
| Résolution | Min | Centre | Max |
|---|---|---|---|
| 10 bits | 0 | 512 | 1023 |
| 12 bits | 0 | 2048 | 4095 |
Pour identifier rapidement la direction, des seuils simples suffisent en 10 bits :
- Droite : X > 700
- Gauche : X < 400
- Haut : Y > 700
- Bas : Y < 400
Ces règles laissent naturellement une zone neutre autour du centre. Le joystick reste ainsi considéré comme « au repos » tant que les valeurs se trouvent entre 400 et 700.
Exemple de code pour convertir les valeurs en directions
int x = analogRead(pinJoyX);
int y = analogRead(pinJoyY);
String dirX = "NEUTRE";
String dirY = "NEUTRE";
if (x > 700) {
dirX = "DROITE";
} else if (x < 400) {
dirX = "GAUCHE";
}
if (y > 700) {
dirY = "HAUT";
} else if (y < 400) {
dirY = "BAS";
}
Serial.print("Direction X: ");
Serial.print(dirX);
Serial.print("\tDirection Y: ");
Serial.println(dirY);
La logique reste similaire pour une résolution 12 bits. Seuls les seuils évoluent (par exemple autour de 2800/1300 au lieu de 700/400).
Calibrage avancé du joystick et gestion de la zone morte
Les retours d’expérience montrent parfois une plage de lecture très restreinte. Une mesure rapportée affiche par exemple une valeur minimale vers 511 et une valeur maximale vers 560, soit à peine 49 valeurs de différence. Un tel comportement rend la commande peu exploitable sans post-traitement.
Analyse d’un cas de lecture limitée
Une plage de mesure réduite entre 511 et 560 révèle un problème de calibrage ou de montage :
- Potentiomètre du joystick utilisé seulement sur une petite partie de sa course.
- Tension de référence non adaptée ou atténuée.
- Câblage incorrect reliant les bornes du potentiomètre.
- Code qui lit une valeur déjà filtrée ou mise à l’échelle.
« Une plage de 49 valeurs sur un ADC 10 bits ne reflète pas les capacités réelles d’un joystick analogique correctement câblé »
Lorsque le matériel reste inchangé, un recalibrage logiciel maximise tout de même la plage utile. L’idée consiste à mesurer le minimum et le maximum réellement atteints, puis à étirer cette plage sur 0–1023 (ou 0–4095).
Calibrage automatique sur quelques secondes
Un approche consiste à demander à l’utilisateur de déplacer le joystick dans toutes les directions pendant quelques secondes. Le code enregistre les valeurs min et max de chaque axe, puis en déduit un facteur d’échelle.
int xMin = 1023;
int xMax = 0;
int yMin = 1023;
int yMax = 0;
void calibrateJoystick(unsigned long durationMs) {
unsigned long start = millis();
while (millis() - start < durationMs) {
int x = analogRead(pinJoyX);
int y = analogRead(pinJoyY);
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
delay(5);
}
}
int scaleValue(int value, int inMin, int inMax, int outMin, int outMax) {
if (value < inMin) value = inMin;
if (value > inMax) value = inMax;
long num = (long)(value - inMin) * (outMax - outMin);
long den = (inMax - inMin);
if (den == 0) return (outMin + outMax) / 2;
return outMin + (int)(num / den);
}
Après calibrage, chaque lecture passe par une mise à l’échelle :
int xRaw = analogRead(pinJoyX);
int yRaw = analogRead(pinJoyY);
int xCal = scaleValue(xRaw, xMin, xMax, 0, 1023);
int yCal = scaleValue(yRaw, yMin, yMax, 0, 1023);
Pour un projet abouti, stockez les valeurs xMin, xMax, yMin, yMax dans l’EEPROM de la carte Arduino après calibrage. La calibration reste alors valable même après un redémarrage, sans nouvelle manipulation de l’utilisateur.
Gestion de la zone morte (dead zone)
Un joystick réel n’est jamais parfaitement stable au centre. De légères variations apparaissent même au repos, parfois accentuées par le bruit électrique. Une zone morte autour du centre évite les mouvements parasites.
Avec un centre théorique à 512 en 10 bits, une zone morte de ±50 valeurs rend les commandes plus nettes :
const int deadZone = 50;
int x = analogRead(pinJoyX);
int y = analogRead(pinJoyY);
int xOffset = x - 512;
int yOffset = y - 512;
if (abs(xOffset) < deadZone) xOffset = 0;
if (abs(yOffset) < deadZone) yOffset = 0;
En combinant calibrage et zone morte, la lecture devient plus fluide : les mouvements faibles proches du centre ne déclenchent plus de commandes involontaires.
Filtrage et stabilisation des valeurs analogiques
Pour des applications exigeant une commande stable (robot, pan-tilt de caméra, manette virtuelle), la lecture brute se révèle parfois trop bruyante. Quelques techniques de filtrage numérique améliorent significativement la stabilité.
Moyenne glissante (moving average)
La moyenne glissante consiste à lisser le signal en calculant la moyenne d’un ensemble des dernières mesures. Cette méthode réduit les variations rapides mais ajoute un léger délai de réaction.
const int N = 8;
int bufferX[N];
int bufferY[N];
int indexBuf = 0;
void initBuffers() {
for (int i = 0; i < N; i++) {
bufferX[i] = 512;
bufferY[i] = 512;
}
}
int movingAverage(int *buffer) {
long sum = 0;
for (int i = 0; i < N; i++) {
sum += buffer[i];
}
return (int)(sum / N);
}
void loop() {
int xRaw = analogRead(pinJoyX);
int yRaw = analogRead(pinJoyY);
bufferX[indexBuf] = xRaw;
bufferY[indexBuf] = yRaw;
indexBuf = (indexBuf + 1) % N;
int xSmooth = movingAverage(bufferX);
int ySmooth = movingAverage(bufferY);
Serial.print("X smooth: ");
Serial.print(xSmooth);
Serial.print("\tY smooth: ");
Serial.println(ySmooth);
delay(10);
}
En ajustant la taille N, l’équilibre entre réactivité et stabilité se règle facilement.
Filtre passe-bas exponentiel (EMA)
Un filtre exponentiel calcule une nouvelle valeur lissée en combinant la mesure actuelle et la valeur filtrée précédente. Ce filtre tient sur quelques lignes et réagit bien aux grandes variations tout en éliminant les petites oscillations.
float alpha = 0.2; // 0 < alpha <= 1
float xFiltered = 512;
float yFiltered = 512;
void loop() {
int xRaw = analogRead(pinJoyX);
int yRaw = analogRead(pinJoyY);
xFiltered = alpha * xRaw + (1.0 - alpha) * xFiltered;
yFiltered = alpha * yRaw + (1.0 - alpha) * yFiltered;
Serial.print("X filt: ");
Serial.print((int)xFiltered);
Serial.print("\tY filt: ");
Serial.println((int)yFiltered);
delay(10);
}
Une valeur alpha proche de 1 rend le joystick très réactif mais peu filtré. Une valeur plus faible augmente le lissage.
Lecture d’un joystick en 12 bits : cas du Modulino ABX00135
Avec le Modulino Joystick Arduino ABX00135, le microcontrôleur STM32 interne gère directement les entrées analogiques. Le projet Arduino n’a plus à configurer son propre ADC pour les axes. L’échange de données passe par le bus I2C, sur l’adresse 0x2C.
Structure typique des valeurs en 12 bits
Les caractéristiques fournies pour le Modulino Joystick indiquent :
- X_min : 0
- X_max : 4095
- X_centre : 2048
- Y_min : 0
- Y_max : 4095
- Y_centre : 2048
Chaque valeur tient sur 12 bits. La communication I2C transporte généralement ces valeurs sur deux octets par axe. La documentation du Modulino précise le format exact, mais sur Arduino, la logique d’interprétation reste la même : conversion de la plage 0–4095 en valeurs utiles, ajout d’une zone morte autour de 2048, puis mapping vers -100 à +100 ou -1.0 à +1.0.
Exemple de lecture I2C (esquisse de code)
Un exemple générique de lecture I2C d’un module à adresse 0x2C :
#include <Wire.h>
const byte JOYSTICK_ADDR = 0x2C;
void setup() {
Wire.begin();
Serial.begin(115200);
}
bool readJoystick12bit(uint16_t &x, uint16_t &y, bool &button) {
Wire.beginTransmission(JOYSTICK_ADDR);
// Selon le protocole du Modulino, un registre de départ peut être requis.
// Wire.write(0x00); // Exemple de registre
byte status = Wire.endTransmission(false); // redémarrage sans stop
if (status != 0) {
return false;
}
// Nombre d'octets à adapter selon le protocole (ex : 5 ou 6 octets)
uint8_t bytesToRead = 5; // exemple : 2B X, 2B Y, 1B bouton
Wire.requestFrom((int)JOYSTICK_ADDR, (int)bytesToRead);
if (Wire.available() < bytesToRead) {
return false;
}
uint8_t xL = Wire.read();
uint8_t xH = Wire.read();
uint8_t yL = Wire.read();
uint8_t yH = Wire.read();
uint8_t b = Wire.read();
x = ((uint16_t)xH << 8) | xL;
y = ((uint16_t)yH << 8) | yL;
button = (b != 0);
return true;
}
void loop() {
uint16_t x, y;
bool button;
if (readJoystick12bit(x, y, button)) {
Serial.print("X="); Serial.print(x);
Serial.print("\tY="); Serial.print(y);
Serial.print("\tBTN="); Serial.println(button ? "1" : "0");
} else {
Serial.println("Erreur lecture joystick");
}
delay(20);
}
Une fois les valeurs 12 bits récupérées, le traitement logiciel suit les mêmes étapes que pour un joystick analogique direct : calibrage, mappage, zone morte, filtrage.
Le format exact des registres, l’ordre des octets et la manière de lire le bouton poussoir restent décrits dans la documentation spécifique du Modulino ABX00135. L’architecture du code ci-dessus reste toutefois prête à intégrer ces détails.
Améliorer la précision avec un module ADC 16 bits (KY-053)
Pour un projet nécessitant une haute précision, un module ADC externe 16 bits comme le KY-053 apporte un gain notable. Le joystick se raccorde alors au module, et l’Arduino lit les valeurs converties via I2C.
Intérêt d’un ADC 16 bits pour un joystick
En 16 bits, la plage de valeurs atteint 0–65535. Chaque mouvement du joystick se décompose en une grande quantité de niveaux distincts. Ce niveau de finesse s’avère utile dans certains contextes :
- Contrôle fin d’un bras robotisé.
- Interface de pilotage d’un curseur avec micro-ajustements.
- Application de mesure ou d’instrumentation interactive.
Un joystick analogique standard reste limité par la linéarité de son potentiomètre et par sa mécanique. L’ADC 16 bits n’augmente pas la qualité du potentiomètre lui-même, mais il exploite pleinement toute variation, même faible.
Comparatif des options de lecture
| Solution | Résolution effective | Complexité | Usage conseillé |
|---|---|---|---|
| ADC interne Arduino (KY-023 direct) | 10 bits (0–1023) | Faible | Projets standards, jeux simples, robots basiques |
| Modulino Joystick ABX00135 (ADC STM32) | 12 bits (0–4095) | Moyenne (I2C) | Projets modulaires, gestion multi-capteurs, précision accrue |
| Module KY-053 ADC 16 bits | 16 bits (0–65535) | Plus élevée (I2C avancé) | Applications nécessitant une grande finesse de contrôle |
Pour un premier projet de joystick Arduino, l’ADC interne suffit largement. Un ADC 16 bits KY-053 s’adresse surtout aux projets aboutis où la résolution 10 ou 12 bits limite réellement l’expérience utilisateur.
Exploiter le joystick dans des projets Arduino concrets
Une fois la lecture maîtrisée, le joystick anime de nombreux projets ludiques ou pratiques. En associant les axes X et Y à des sorties PWM, à des moteurs ou à des servomoteurs, l’expérience utilisateur prend forme.
Contrôler un servo sur deux axes
Le mapping des valeurs analogiques vers l’angle d’un servomoteur constitue un exemple récurrent : X contrôle la rotation horizontale, Y la rotation verticale.
#include <Servo.h>
const int pinJoyX = A0;
const int pinJoyY = A1;
const int pinServoX = 9;
const int pinServoY = 10;
Servo servoX;
Servo servoY;
void setup() {
servoX.attach(pinServoX);
servoY.attach(pinServoY);
}
void loop() {
int x = analogRead(pinJoyX); // 0-1023
int y = analogRead(pinJoyY);
int angleX = map(x, 0, 1023, 0, 180);
int angleY = map(y, 0, 1023, 0, 180);
servoX.write(angleX);
servoY.write(angleY);
delay(15);
}
En combinant ce type de code avec un calibrage et un filtrage, un pan-tilt de caméra ou une tourelle laser se contrôle de manière fluide.
Manette de jeu Arduino et interaction avancée
Un joystick analogique se prête bien à la création d’une manette maison. En combinant axes X/Y, bouton poussoir et quelques boutons supplémentaires, la carte Arduino devient une interface de commande pour des jeux ou des simulations.
Pour approfondir cette approche, un tutoriel dédié à la création de manette de jeu Arduino apporte des pistes détaillées sur les boutons, le protocole de communication avec un PC, ou l’intégration dans un simulateur.
Intégrer le joystick dans un apprentissage progressif Arduino
La maîtrise d’un joystick analogique s’inscrit dans un chemin d’apprentissage Arduino plus large. Comprendre la lecture analogique, le mappage, le filtrage et la gestion d’événements offre une base solide pour d’autres capteurs.
Revenir aux fondamentaux de la lecture analogique
Avant de pousser le joystick dans ses retranchements, un retour sur les notions de tension, d’ADC, de résolution et de références de tension donne des repères clairs. Des exercices avec un simple potentiomètre isolé préparent efficacement aux subtilités du joystick.
ArduinoPiloter un relais 230 V avec Arduino en sécurité : 5 erreurs à éviterUn guide dédié au potentiomètre Arduino détaille ces notions : branchement, lecture, filtrage, mapping. Un joystick n’en reste finalement qu’une déclinaison à deux axes, avec une mécanique plus sophistiquée.
Joysticks et projets complets pour débutants
Pour un lecteur qui débute sur Arduino, le joystick offre un terrain de jeu riche. Associer la lecture analogique à un retour visuel (LEDs, écran LCD, OLED) ou à un mouvement (servomoteur, robot) accélère la compréhension de la boucle capteur → traitement → action.
Une liste de projets progressifs sur le thème Arduino, présentée dans la page projet Arduino débutant, guide pas à pas vers des réalisations concrètes où le joystick devient tour à tour manette, curseur ou contrôleur de vitesse.
Un joystick analogique reste un composant mécanique soumis à l’usure. Les potentiomètres possèdent une durée de vie en nombre de cycles (par exemple 500 000 pour le mini joystick Adafruit). Pour un projet professionnel ou soumis à de fréquentes sollicitations, ce paramètre influence le choix du modèle et le dimensionnement du système.






