Silnik krokowy sterowany modułem ULN2003 to jedno z najprostszych i najpopularniejszych rozwiązań w projektach robotycznych opartych na Arduino. Ten sterownik umożliwia precyzyjną kontrolę 4-fazowych silników unipolarnych, takich jak popularny model 28BYJ-48, pozwalając na łatwe zarządzanie kierunkiem obrotów, prędkością i liczbą kroków.

To praktyczne połączenie zapewnia tani start, dużą kontrolę nad ruchem oraz minimalne ryzyko błędów na etapie prototypowania.

W tym rozbudowanym artykule omówimy wszystko, co potrzebne do uruchomienia takiego układu: od zasad działania, przez podłączenie, po przykładowy kod i zaawansowane aplikacje w robotyce. Idealne dla początkujących entuzjastów elektroniki i budowniczych robotów.

Czym jest silnik krokowy i dlaczego ULN2003?

Silniki krokowe różnią się od zwykłych silników DC tym, że obracają się w dyskretnych „krokach”, co zapewnia wyjątkową precyzję pozycjonowania bez dodatkowych enkoderów. Popularny model 28BYJ-48 to silnik unipolarny 4-fazowy, zasilany napięciem 5V, z wbudowaną przekładnią redukującą prędkość i zwiększającą moment obrotowy.

ULN2003 (oraz jego wersje modułowe V2/V3) to układ z siedmioma tranzystorami Darlingtona pełniący rolę elektronicznych przełączników. Umożliwia sterowanie uzwojeniami silnika za pomocą sygnałów logicznych z Arduino (HIGH/LOW na pinach IN1–IN4). Nie nadaje się do silników bipolarnych (brak mostka H), ale idealnie sprawdza się w silnikach unipolarnych.

Poniżej znajdziesz kluczowe cechy, które warto znać przed montażem:

  • zasilanie 5V – z Arduino lub zasilacza zewnętrznego;
  • kompatybilność – silniki 4-fazowe, m.in. 28BYJ-48 (złącze XH/biała wtyczka);
  • kontrola ruchu – kierunek obrotów i prędkość poprzez sekwencję impulsów;
  • wydajność prądowa – do kilkuset mA na kanał, wystarczająca dla małych silników.

Dzięki ULN2003 nie podłączasz silnika bezpośrednio do Arduino, co chroni piny mikrokontrolera przed przeciążeniem i uszkodzeniem.

Schemat podłączenia – krok po kroku

Podłączenie jest proste i nie wymaga lutowania. Użyjemy standardowego Arduino Uno lub innej zgodnej płytki. Przy kilku silnikach stosuj zewnętrzny zasilacz 5V o odpowiedniej wydajności prądowej.

Podstawowy schemat połączeń

Poniższa tabela pokazuje mapowanie pinów Arduino na wejścia modułu ULN2003 oraz opis złącza silnika:

Element sterownika ULN2003 Pin Arduino Uwagi
+ (VCC) 5V Zasilanie modułu i silnika
(GND) GND Wspólna masa
IN1 Pin 8 Sterowanie fazą 1
IN2 Pin 9 Sterowanie fazą 2
IN3 Pin 10 Sterowanie fazą 3
IN4 Pin 11 Sterowanie fazą 4
Wtyczka silnika (biała) Gniazdo na module 5 przewodów: czerwony = +5V (wspólny), niebieski/różowy/żółty/pomarańczowy = fazy

Wskazówki montażu

Wykonaj kolejno poniższe kroki, aby uniknąć błędów połączeń:

  1. Wepnij wtyczkę silnika 28BYJ-48 bezpośrednio do gniazda na module ULN2003.
  2. Podłącz + modułu do 5V Arduino oraz GND do GND – dla jednego silnika zwykle wystarczy zasilanie z USB.
  3. Uwaga na zasilanie – przy dwóch i więcej silnikach lub większym obciążeniu użyj zewnętrznego zasilacza 5V, by uniknąć spadków napięcia i resetów Arduino.
  4. Dla Arduino Uno: użyj pinów 8–11 jak w tabeli. Dla ESP32: np. IN1→GPIO16, IN2→GPIO17, IN3→GPIO25, IN4→GPIO26. Dla Wemos D1 mini (ESP8266): np. IN1→D5, IN2→D6, IN3→D7, IN4→D8.

Jeśli silnik kręci się w przeciwnym kierunku niż oczekiwany, zamień kolejność sygnałów na wejściach IN1–IN4 lub użyj wartości ujemnych w poleceniu kroku.

Sterowanie w praktyce – kod Arduino

Użyjemy biblioteki Stepper.h dostępnej domyślnie w Arduino IDE. Typowa liczba kroków na obrót dla 28BYJ-48 to 2048–4096 (zależnie od sekwencji kroków i biblioteki), dlatego warto wykonać kalibrację w projekcie.

Prosty kod – obrót o 90° i 180°

Poniższy szkic demonstruje podstawy sterowania z biblioteką Stepper:

#include <Stepper.h>

const int krokiNaObrot = 2048; // Dla 28BYJ-48 (często 2048 lub 4096 — skalibruj w praktyce)
Stepper myStepper(krokiNaObrot, 8, 10, 9, 11); // Kolejność pinów dla ULN2003: IN1, IN3, IN2, IN4

void setup() {
myStepper.setSpeed(15); // Prędkość w obr/min (5–20 RPM)
}

void loop() {
myStepper.step(512); // ~90° zgodnie z ruchem wskazówek zegara
delay(1000);
myStepper.step(-1024); // ~180° przeciwnie do ruchu wskazówek zegara
delay(1000);
}

Jak to działa?

  • Stepper(steps, pin1, pin2, pin3, pin4) – tworzy obiekt z liczbą kroków/obrót i przypisaniem pinów,
  • setSpeed(RPM) – ustawia prędkość w obr/min; większa wartość to szybszy obrót, ale mniejszy moment,
  • step(liczbaKroków) – dodatnia wartość = obrót w prawo, ujemna = w lewo,
  • do testów zacznij od 15 RPM i wartości 512/1024 kroków dla 90°/180°.

Zaawansowany kod – sekwencja półkroków z „rampą”

Jeśli chcesz pełną kontrolę nad sekwencją i przyspieszeniem, użyj półkroków oraz prostej rampy czasowej:

const uint8_t piny[4] = {8, 9, 10, 11}; // IN1..IN4

// Sekwencja półkroków (8 stanów) dla 28BYJ-48
const uint8_t SEQ[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}
};

void setStep(uint8_t s) {
for (uint8_t k = 0; k < 4; k++) digitalWrite(piny[k], SEQ[s][k] ? HIGH : LOW);
}

void setup() {
for (uint8_t i = 0; i < 4; i++) pinMode(piny[i], OUTPUT);
}

void loop() {
// Ramp-up (przyspieszenie) i ramp-down (hamowanie) dla ~90°
uint16_t krokow = 512; // docelowa liczba półkroków (~90°)
uint8_t minDelay = 3; // minimalne opóźnienie między półkrokami (ms)
uint8_t maxDelay = 12; // startowe opóźnienie (ms)
int8_t dir = +1; // +1 w prawo, -1 w lewo

// Przyspieszenie
for (uint8_t d = maxDelay; d >= minDelay; d--) {
for (uint8_t s = 0; s < 8; s++) {
setStep(s);
delay(d);
}
}

// Ruch ze stałą prędkością
uint16_t pozostalo = krokow - 2 * 8; // odejmij kroki wykorzystane na rampy
for (uint16_t i = 0; i < pozostalo; i++) {
for (uint8_t s = 0; s < 8; s++) {
setStep(dir > 0 ? s : (7 - s));
delay(minDelay);
}
}

// Hamowanie
for (uint8_t d = minDelay; d <= maxDelay; d++) {
for (uint8_t s = 0; s < 8; s++) {
setStep(dir > 0 ? s : (7 - s));
delay(d);
}
}

delay(1000);
}

Półkroki dają płynniejszy ruch i większy moment trzymający, kosztem nieco mniejszej prędkości maksymalnej.

Zastosowania w robotyce i elektronice

ULN2003 + 28BYJ-48 to podstawa wielu praktycznych projektów. Oto najczęstsze scenariusze użycia:

  • roboty mobilne – napęd i precyzyjne skręty lekkich platform;
  • manipulatory – ramiona i chwytaki do sortowania małych przedmiotów;
  • automatyka domowa – sterowanie żaluzjami, zamkami, wskaźnikami i pokrętłami;
  • prototypy – głowice kamer PT, mini mechanizmy XY, edukacyjne drukarki w małej skali.

Wielosilnikowe układy

Przy większej liczbie napędów użyj Arduino Mega (więcej pinów) lub ekspanderów I/O. Warto skorzystać z biblioteki AccelStepper, aby uzyskać rampy przyspieszenia i lepszą kontrolę ruchu.

Problemy i rozwiązania

Poniższe wskazówki pomogą szybko zdiagnozować najczęstsze trudności:

  • drgania lub gubienie kroków – zmniejsz prędkość, zastosuj półkroki, podnieś napięcie zasilania do stabilnych 5V;
  • silnik nie rusza – sprawdź kolejność pinów IN1–IN4, błędna sekwencja odwraca kierunek lub blokuje ruch;
  • przegrzewanie – zapewnij odpowiednią wentylację modułu, rozważ radiator lub zewnętrzny zasilacz o większej wydajności.

Porównanie sterowników

Jeżeli rozważasz inne sterowniki, ta tabela ułatwi szybką decyzję:

Sterownik Zasilanie Typ silnika Prędkość Cena
ULN2003 5V Unipolarny Niska ~4 zł
A4988 8–35V Bipolarny Wysoka ~10 zł
DRV8825 8–45V Bipolarny Bardzo wysoka ~15 zł

ULN2003 wygrywa prostotą i kosztami w projektach edukacyjnych oraz prototypach z małymi silnikami.

Podsumowujące wskazówki dla zaawansowanych

Na dalszym etapie rozwoju projektu rozważ poniższe usprawnienia:

  • kalibracja kroków – zmierz liczbę kroków/obrót dla konkretnego egzemplarza (często 2048–4096) i wpisz do stałej w kodzie;
  • środowiska wizualne – eksperymentuj z XOD lub Node-RED do szybkiego prototypowania logiki;
  • Raspberry Pi – steruj przez GPIO podobnie jak z Arduino (pamiętaj o osobnym zasilaniu 5V dla silnika).

Duet Arduino + ULN2003 + 28BYJ-48 to szybka droga do precyzyjnej mechaniki – od pierwszego szkicu do działającego prototypu.