Brancher un 28BYJ-48 sur Arduino semble simple. Pourtant, entre le câblage du driver ULN2003, les pas, le sens de rotation et le couple disponible, beaucoup de projets finissent avec un moteur qui vibre… ou ne tourne pas du tout.
En maîtrisant la logique de commande, la structure du code et quelques réglages précis, ce petit moteur pas à pas devient une solution fiable pour créer des mouvements lents, précis et répétables dans des projets très variés. La suite du guide détaille chaque étape, du branchement au code complet optimisé.
| Élément clé | Synthèse rapide |
| Matériel utilisé | Arduino + moteur pas à pas 28BYJ-48 avec driver ULN2003 |
| Principe | Pilotage du moteur via des séquences d’activation des bobines pour avancer pas par pas |
| Code fourni | Programme complet pour contrôler rotation, vitesse et direction ✔️ |
| Utilité | Idéal pour projets robotique, précision de mouvement et tests d’axes 🎛️ |
Présentation du moteur pas à pas 28BYJ-48 et de son driver ULN2003
Le moteur 28BYJ-48 s’impose comme une référence dans les projets Arduino nécessitant un mouvement angulaire contrôlé. Il s’agit d’un moteur pas à pas unipolaire 4 phases, généralement livré avec une carte driver ULN2003. Ce duo forme un ensemble économique, robuste et simple à intégrer pour l’automatisation, la robotique légère ou la domotique.
ArduinoArduino et domotique : automatiser sa maison pour pas cherCe moteur fonctionne en basse tension, principalement 5 V DC dans la version la plus répandue, avec une variante en 12 V utilisable dans des environnements plus exigeants. Son architecture interne repose sur un train d’engrenages avec un rapport de réduction d’environ 1/64, ce qui augmente la résolution angulaire au niveau de l’arbre de sortie et améliore le couple utile.

Caractéristiques techniques détaillées du 28BYJ-48
Comprendre la fiche technique du 28BYJ-48 permet d’écrire un code Arduino plus précis et d’éviter les erreurs de dimensionnement. Voici les données clés les plus utiles lors du développement :
| Paramètre | Valeur typique | Utilité pour le code Arduino |
|---|---|---|
| Tension nominale | 5 V DC (version courante), 12 V disponible | Détermine l’alimentation et la compatibilité avec la carte Arduino |
| Type | Moteur pas à pas unipolaire 4 phases | Conditionne la séquence de pas utilisée dans le code |
| Résistance DC | Environ 50 Ω / 21 Ω / 70 Ω (12 V) / 200 Ω ±7% à 25°C | Permet d’estimer le courant et la dissipation thermique |
| Intensité nominale | ≈ 25 mA par phase | Aide à dimensionner l’alimentation externe et à éviter les surcharges |
| Angle de pas interne | 5,625° en pas complet | Utile pour calculer le nombre de pas théoriques par tour |
| Nombre de pas (avec réduction) | 64 pas internes × 64 ≈ 4096 pas par tour | Base de tout calcul d’angle ou de position |
| Couple de traction | > 34,3 mN·m à 120 Hz | Oriente le choix d’application (charge, inertie, frottements) |
| Niveau sonore | ≈ 40 dB | Indique un fonctionnement relativement discret |
| Dimensions | Diamètre moteur 27–28 mm, arbre 5 mm, longueur 8–12 mm | Facilite la conception mécanique des supports et engrenages |
Les valeurs de résistance DC et de couple apparaissent souvent sous-estimées par les débutants. Le couple disponible reste modéré, le 28BYJ-48 appartient clairement à la catégorie des petits actionneurs de précision, pas à celle des moteurs de forte puissance.
Le rôle du driver ULN2003 dans la commande du 28BYJ-48
Le 28BYJ-48 ne se branche jamais directement sur les broches de sortie d’une carte Arduino. Les sorties de l’Arduino ne supportent ni le courant ni la tension de commutation nécessaires à la commutation des quatre phases. Le driver ULN2003 sert d’interface de puissance entre la logique 5 V de l’Arduino et les bobinages du moteur.
La carte ULN2003 comporte un réseau de transistors Darlington, des diodes de roue libre pour absorber les surtensions inductives et un bornier pour l’alimentation externe du moteur. Les broches IN1 à IN4 reçoivent les signaux de commande depuis Arduino, tandis que les sorties OUT1 à OUT4 attaquent directement les phases du moteur.
« L’utilisation d’un ULN2003 entre Arduino et le 28BYJ-48 offre une marge de sécurité électrique qui limite les risques de dommages sur la carte, même lors de tests répétés ou de séquences rapides. »
Cette séparation claire entre logique et puissance simplifie considérablement le développement. L’Arduino ne fait que générer une séquence binaire sur 4 broches, le driver se charge du reste.
Câblage Arduino + 28BYJ-48 + ULN2003 : schéma et bonnes pratiques
La fiabilité du montage repose sur un câblage propre et cohérent. Un schéma logique reste toujours le même, seule la répartition des broches Arduino peut varier selon le projet.

Schéma de câblage typique
La configuration la plus courante utilise une alimentation 5 V commune pour l’Arduino et le moteur, avec une attention particulière portée aux masses. Le principe de câblage se résume en quelques connexions clés :
- Alimentation moteur : +5 V sur le bornier VCC de la carte ULN2003.
- Masse commune : GND de l’Arduino relié au GND de l’alimentation moteur et au GND de l’ULN2003.
- Signaux de commande : IN1→IN4 de l’ULN2003 reliés à quatre broches numériques Arduino (par exemple 8, 9, 10, 11).
- Moteur : le connecteur 5 broches du 28BYJ-48 enfiché sur la prise dédiée de la carte ULN2003.
Une fois cette base mise en place, la séquence de pas envoyée par le code Arduino pilotera chaque phase via l’ULN2003. L’ordre des broches IN1–IN4 a une incidence directe sur le sens de rotation. Un simple croisement dans le câblage peut inverser la direction.
Brochage Arduino recommandé
Pour garder un code lisible et facilement extensible, il reste pratique de regrouper les quatre broches de commande sur des pins numériques consécutives. Un exemple fréquent :
- IN1 ULN2003 → Arduino D8
- IN2 ULN2003 → Arduino D9
- IN3 ULN2003 → Arduino D10
- IN4 ULN2003 → Arduino D11
Ces broches ne nécessitent pas de PWM. Un simple contrôle en HIGH/LOW suffit, ce qui laisse libres d’autres sorties PWM pour des servos, des LED ou des contrôleurs de vitesse dans des projets plus avancés. Cette approche se marie d’ailleurs très bien avec des projets complexes comme ceux décrits dans /projet-arduino-avance/.

Principe de fonctionnement d’un moteur pas à pas unipolaire
Le 28BYJ-48 convertit des signaux électriques discrets en un mouvement angulaire segmenté. Chaque impulsion sur une phase du moteur correspond à un décalage angulaire défini. L’enchaînement de plusieurs pas forme une rotation continue et plus ou moins fluide selon la séquence adoptée.
Contrairement aux moteurs DC classiques, la vitesse, l’angle et la position se contrôlent en compteur de pas. La précision du mouvement dépend directement du nombre de pas envoyés et du modèle de séquence utilisé (pas complet ou demi-pas).
Pas complet, demi-pas et fluidité de rotation
Deux modes de pilotage dominent pour le 28BYJ-48 : le pas complet et le demi-pas. Chacun présente ses propres caractéristiques en termes de couple et de régularité.
| Mode | Principe | Avantages | Inconvénients |
|---|---|---|---|
| Pas complet | Activation successive de deux bobinages simultanément | Couple plus élevé, séquence simple à coder | Résolution angulaire plus faible, rotation moins fluide |
| Demi-pas | Alternance d’un puis deux bobinages actifs | Meilleure résolution, mouvement plus régulier | Couple légèrement variable selon le pas |
Avec son angle de pas interne de 5,625° et son train d’engrenages au rapport d’environ 1/64, le 28BYJ-48 atteint 4096 demi-pas pour un tour complet de l’arbre de sortie. Cette valeur sert de base à tous les calculs d’angle.
Code Arduino minimal pour piloter le 28BYJ-48 en demi-pas
Un premier code fonctionnel permet de valider le câblage et la logique de commande. L’exemple ci-dessous utilise une séquence en demi-pas pour tirer parti de la meilleure résolution du 28BYJ-48.
Définition des broches et séquence de pas
On commence par déclarer les broches connectées au driver ULN2003, puis la matrice représentant la séquence de demi-pas. Chaque ligne de cette matrice correspond à un état des quatre bobines.
// Broches de commande vers ULN2003
const int IN1 = 8;
const int IN2 = 9;
const int IN3 = 10;
const int IN4 = 11;
// Nombre total de demi-pas par tour complet de l'arbre
const int STEPS_PER_REV = 4096; // valeur couramment admise pour le 28BYJ-48
// Séquence de demi-pas (4 bobines, 8 états)
int halfStepSequence[8][4] = {
{1, 0, 0, 0},
{1, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1},
{1, 0, 0, 1}
};
La constante STEPS_PER_REV fournit une référence directe pour programmer des angles spécifiques ou des positions absolues. Ce choix évite de réécrire tout le programme en cas d’ajustement lié à une variante de moteur.
Fonctions de base : setup, pas vers l’avant, pas vers l’arrière
Ensuite, on implémente les fonctions essentielles pour commander le moteur sur un nombre de pas donné, dans un sens ou dans l’autre. Le principe : parcourir la séquence de demi-pas dans un ordre ou dans l’autre.
int stepDelay = 3; // délai en ms entre deux demi-pas (ajuste la vitesse)
int currentStepIndex = 0; // position actuelle dans la séquence de 0 à 7
void setup() {
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
}
void setStep(int s1, int s2, int s3, int s4) {
digitalWrite(IN1, s1);
digitalWrite(IN2, s2);
digitalWrite(IN3, s3);
digitalWrite(IN4, s4);
}
void stepForward(int steps) {
for (int i = 0; i < steps; i++) {
currentStepIndex++;
if (currentStepIndex > 7) currentStepIndex = 0;
setStep(
halfStepSequence[currentStepIndex][0],
halfStepSequence[currentStepIndex][1],
halfStepSequence[currentStepIndex][2],
halfStepSequence[currentStepIndex][3]
);
delay(stepDelay);
}
}
void stepBackward(int steps) {
for (int i = 0; i < steps; i++) {
currentStepIndex--;
if (currentStepIndex < 0) currentStepIndex = 7;
setStep(
halfStepSequence[currentStepIndex][0],
halfStepSequence[currentStepIndex][1],
halfStepSequence[currentStepIndex][2],
halfStepSequence[currentStepIndex][3]
);
delay(stepDelay);
}
}
Ces deux fonctions stepForward() et stepBackward() constituent le cœur du pilotage. Toute la logique avancée (positionnement précis, mouvements conditionnels, synchronisation avec des capteurs) s’appuie sur elles.
Exemple de boucle loop pour tester la rotation
Pour vérifier le système, la boucle loop() alterne une rotation dans un sens puis dans l’autre. Ce test suffit pour valider le sens de rotation, le câblage et la vitesse choisie.
void loop() {
// Un tour complet dans un sens
stepForward(STEPS_PER_REV);
delay(1000);
// Un tour complet dans l'autre sens
stepBackward(STEPS_PER_REV);
delay(1000);
}
Une LED d’état intégrée sur certaines cartes ULN2003 aide à visualiser la séquence d’activation des bobines. Les LED doivent s’allumer dans un ordre régulier, sans clignotements aléatoires.
Version avec la bibliothèque Arduino Stepper et alternatives
Pour simplifier le code, la bibliothèque Stepper intégrée à l’IDE Arduino offre une abstraction pratique. Elle gère automatiquement la séquence de pas et propose des fonctions simples du type step() et setSpeed(). Une autre approche consiste à utiliser la bibliothèque AccelStepper pour des profils d’accélération plus élaborés.
Utilisation de la bibliothèque Stepper avec le 28BYJ-48
Voici un exemple fonctionnel utilisant la bibliothèque standard Stepper. Ce code reste adapté pour un contrôle basique du 28BYJ-48 sans gestion fine de l’accélération.
#include <Stepper.h>
const int STEPS_PER_REV = 4096; // demi-pas approximatif pour un tour
// Broches reliées à IN1, IN2, IN3, IN4 de l'ULN2003
const int IN1 = 8;
const int IN2 = 9;
const int IN3 = 10;
const int IN4 = 11;
Stepper myStepper(STEPS_PER_REV, IN1, IN3, IN2, IN4);
void setup() {
// Vitesse en tours par minute
myStepper.setSpeed(10); // ajuste selon le couple et la charge
}
void loop() {
// Un tour dans un sens
myStepper.step(STEPS_PER_REV);
delay(1000);
// Un tour dans l'autre sens
myStepper.step(-STEPS_PER_REV);
delay(1000);
}
L’ordre des broches passé au constructeur Stepper influe directement sur le sens de rotation. En cas de rotation inversée par rapport aux besoins de l’application, il suffit souvent d’échanger la position de deux broches dans la déclaration.
Quand utiliser une bibliothèque plus évoluée
La bibliothèque AccelStepper gère :
- des rampes d’accélération et de décélération progressives,
- le contrôle de plusieurs moteurs de manière simultanée,
- la configuration de limites de vitesse et d’accélération.
Elle devient pertinente dès qu’un projet dépasse la simple rotation périodique. Par exemple, dans un système de déplacement linéaire synchronisé avec des capteurs ou un bras robotisé multi-axes, la gestion fluide des changements de vitesse limite les pertes de pas et les à-coups mécaniques.
Conversion d’angle en pas et positionnement précis
Pour exploiter réellement le potentiel du 28BYJ-48, le code doit intégrer une conversion systématique entre angle de rotation et nombre de pas. Cette étape rend le projet beaucoup plus intuitif à paramétrer, surtout lorsque plusieurs positions doivent être mémorisées.
Formules de conversion angle ↔ pas
Avec la valeur de référence STEPS_PER_REV = 4096, les conversions restent directes :
- Pas vers degrés :
angle_deg = (steps * 360.0) / STEPS_PER_REV - Degrés vers pas :
steps = (angle_deg * STEPS_PER_REV) / 360.0
En intégrant ces calculs dans des fonctions dédiées, le code devient plus lisible et moins sujet aux erreurs.
long angleToSteps(float angleDeg) {
return (long)((angleDeg * STEPS_PER_REV) / 360.0);
}
float stepsToAngle(long steps) {
return (steps * 360.0) / (float)STEPS_PER_REV;
}
Avec ces deux fonctions, le pilotage se fait en degrés dans le reste du programme, tandis que l’exécution interne reste basée sur les pas du moteur.
Exemple : aller à une position angulaire précise
Pour gérer un positionnement absolu, le code maintient un compteur global de pas et calcule l’écart avec la position cible en degrés. Ce principe convient parfaitement pour des applications comme un volet orientable ou un indexeur simple.
long currentPositionSteps = 0; // position actuelle en pas
void goToAngle(float targetAngleDeg) {
long targetSteps = angleToSteps(targetAngleDeg);
long delta = targetSteps - currentPositionSteps;
if (delta > 0) {
stepForward(delta);
} else if (delta < 0) {
stepBackward(-delta);
}
currentPositionSteps = targetSteps;
}
Cette logique suppose que le moteur ne saute pas de pas sous la charge. Pour un système soumis à des efforts variables, un capteur de référence (fin de course, optique, magnétique) apporte une correction périodique de la position réelle.
Gestion de la vitesse, du couple et de la chauffe
Trois paramètres influencent directement le comportement du 28BYJ-48 sur Arduino : la vitesse de rotation, le couple utile et la température des bobinages. Le code doit intégrer ces éléments pour préserver la durée de vie du moteur et garantir un mouvement régulier.
Réglage de la vitesse via le délai entre pas
Dans l’exemple de base, la variable stepDelay contrôle la vitesse :
int stepDelay = 3; // ms
Un délai plus court augmente la vitesse de rotation, mais réduit le couple disponible et augmente le risque de pertes de pas si la charge mécanique oppose une résistance importante. Un délai trop long rend le mouvement lent et haché.
Un calibrage simple consiste à :
- partir d’une valeur prudente (par exemple 5–10 ms),
- réduire progressivement pour atteindre un compromis entre vitesse et couple,
- tester en condition réelle avec la charge finale.
Couple disponible et charge admissible
Le 28BYJ-48 affiche un couple de traction supérieur à 34,3 mN·m à 120 Hz. Ce niveau convient pour actionner de petits mécanismes : volets légers, curseurs, indicateurs, mini-robots, systèmes de verrouillage. En revanche, pour des charges lourdes ou des vitesses élevées, un moteur pas à pas de type NEMA reste plus adapté.
La nature unipolaire du moteur et sa tension de fonctionnement limitent les efforts mécaniques admissibles. En cas de surdimensionnement de la charge, le moteur risque de :
- vibrer sans tourner,
- s’arrêter brutalement sur certains segments de rotation,
- chauffer de manière excessive.
Gestion de la chauffe et durée d’activation des bobines
La documentation technique mentionne une hausse de température inférieure à 40 K à 120 Hz. Dans un projet Arduino statique, la fréquence de pas reste souvent bien inférieure, mais un maintien prolongé sous tension garde les bobines excitées, ce qui génère de la chaleur inutile.
ArduinoPiloter un relais 230 V avec Arduino en sécurité : 5 erreurs à éviterPour limiter la température :
- désactiver les bobines quand le moteur reste immobile sur une longue période,
- réduire légèrement le courant (dans le cas d’une alimentation ajustable),
- prévoir une ventilation légère ou un support dissipant si le moteur tourne longtemps.
void releaseMotor() {
setStep(0, 0, 0, 0); // coupe l'alimentation des bobines
}
Cette fonction libère le rotor, ce qui supprime le couple de maintien. Selon l’application, la mécanique doit compenser cette absence de maintien par un verrouillage mécanique ou par la gravité.
Applications concrètes et intégration dans des projets Arduino
Le couple modéré, la précision de positionnement et le bruit contenu du 28BYJ-48 en font un composant intéressant pour une large palette de projets. Le robotique léger, la domotique et l’affichage mécanique bénéficient particulièrement de cette combinaison.
Exemples de projets adaptés au 28BYJ-48
Quelques catégories d’applications tirent pleinement parti du couple et de la résolution du 28BYJ-48 :
- Positionnement angulaire : antennes directionnelles, panneaux indicateurs, cadrans mécaniques.
- Automatisation légère : ouverture de trappes, volets, petites portes, vannes miniatures.
- Robotique éducative : plateaux tournants, bases rotatives, modules de visée.
- Instrumentation : réglage fin de potentiomètres multi-tours, ajustement optique.
Ces scénarios entrent en résonance avec les tendances du marché des moteurs pas à pas. Les segments robotique et équipement médical ou de laboratoire exploitent de plus en plus des solutions miniatures pour obtenir des mouvements contrôlés avec une consommation modérée.
« En 2024, le marché mondial des moteurs pas à pas s’élève à plus d’un milliard de dollars US, avec une croissance annuelle régulière tirée par l’Asie-Pacifique, la robotique industrielle et l’automatisation de précision. »
Les grandes familles de moteurs pas à pas (hybrides, à aimant permanent, à réluctance variable) cohabitent sur le marché. Le 28BYJ-48 appartient à la catégorie des moteurs à aimant permanent, très utilisés pour les petits mécanismes automatisés et les systèmes embarqués.
Intégrer le 28BYJ-48 dans un projet Arduino avancé
Une fois maîtrisé le contrôle basique, le 28BYJ-48 se combine sans difficulté avec d’autres modules : capteurs de fin de course, boutons, interfaces I2C, sorties série. Des scénarios avancés incluent par exemple :
- un système de poursuite solaire couplant un capteur de luminosité et un 28BYJ-48,
- un distributeur de composants ou d’objets avec indexation précise par pas,
- un mécanisme de mise au point ou de zoom pour une caméra légère.
Pour approfondir les intégrations complexes, un détour par /projet-arduino-avance/ offre une base solide en matière de structuration de code, de gestion d’interruptions et d’organisation modulaire des fonctions.
Optimiser la fiabilité et la répétabilité des mouvements
Pour des rotations répétées jour après jour, la fiabilité passe par une combinaison d’ajustements logiciels et de précautions mécaniques. Un calibrage méthodique limite les pertes de pas, les dérives de position et l’usure prématurée.
Étalonnage et retour à une position de référence
Un capteur de référence (fin de course, interrupteur, capteur optique) définit une position zéro reproductible. Au démarrage du système, le code effectue une séquence simple :
- rotation dans un sens jusqu’à l’activation du capteur,
- réinitialisation du compteur de pas à zéro,
- déplacement vers la position de départ souhaitée.
Cette stratégie compense progressivement les glissements de pas cumulatifs. Elle convient bien aux mécaniques soumises à des variations de charge ou à des frottements variables.
Gestion logicielle des limites mécaniques
Un mouvement de rotation mécanique se trouve souvent borné par des butées physiques. Pour éviter les chocs répétés, le code peut imposer des limites logicielles en nombre de pas. Par exemple :
long minPositionSteps = 0;
long maxPositionSteps = angleToSteps(270.0); // rotation limitée à 270°
void goToSafeAngle(float targetAngleDeg) {
long targetSteps = angleToSteps(targetAngleDeg);
if (targetSteps < minPositionSteps) {
targetSteps = minPositionSteps;
}
if (targetSteps > maxPositionSteps) {
targetSteps = maxPositionSteps;
}
long delta = targetSteps - currentPositionSteps;
if (delta > 0) {
stepForward(delta);
} else if (delta < 0) {
stepBackward(-delta);
}
currentPositionSteps = targetSteps;
}
Cette protection logicielle préserve la mécanique d’efforts superflus et limite les risques de décalage du train d’engrenages interne du 28BYJ-48.
Aller plus loin : variantes, alternatives et ressources complémentaires
Le 28BYJ-48 existe en version 5 V et en version 12 V. Le principe de pilotage reste identique, seule la tension d’alimentation change. La version 12 V trouve sa place dans des environnements plus bruyants électriquement ou alimentés en 12 V natif (systèmes automobiles, certains équipements industriels).
Pour des besoins de couple plus élevés ou de vitesses supérieures, un moteur pas à pas bipolaire de type NEMA, piloté par un driver dédié (A4988, DRV8825, etc.), offre une solution complémentaire. Le code Arduino reste basé sur l’envoi de pas, mais la gestion électrique se fait différemment.
Les projets détaillés sur /arduino-stepper-moteur-pas-a-pas/ et /arduino-28byj-48-code/ fournissent d’autres exemples de séquences de pas, de configurations de broches et de stratégies de contrôle adaptées à ce moteur. En combinant ces ressources avec les éléments présentés ici, un développeur Arduino dispose d’une base solide pour piloter un 28BYJ-48 de manière fiable et précise dans des contextes très variés.





