
Cílem tohoto projektu je vytvořit systém pro vzdálené a přesné polohování servomotoru pomocí rotačního enkodéru (tzv. "digitální ruční kolečko"). Projekt demonstruje využití hardwarových přerušení (interrupts) Arduina a přímé řízení šířky impulsu v mikrosekundách pro dosažení maximální plynulosti pohybu.
Seznam použitého materiálu:
- Mikrokonrolér: Arduino Uno (nebo Nano/Mega)
- Vstupní prvek: Rotační enkodér (KY-040)
- Akční člen: Servomotor (SG90)
- Propojovací vodiče: Typ Male-to-Male / Male-to-Female
- Napájení: USB kabel nebo externí 5V
Schéma zapojení:
Komponenty jsou k Arduinu připojeny následovně:
|
Komponenta |
Pin na Arduinu |
Popis |
|
Enkodér CLK |
Pin 2 |
Signál A |
|
Enkodér DT |
Pin 3 |
Signál B |
|
Enkodér GND |
GND |
Společná zem |
|
Enkodér VCC |
5V |
Napájení logiky |
|
Servo Signal |
Pin 9 |
PWM řízení pohybu |
|
Servo VCC |
5V |
Napájení motoru |
|
Servo GND |
GND |
Společná zem |

Kód pro Arduino:
#include <Servo.h>
// --- DEFINICE PINŮ ---
const int encoderPinA = 2; // Pin s podporou přerušení (Interrupt)
const int encoderPinB = 3; // Pin s podporou přerušení (Interrupt)
const int servoPin = 9; // PWM pin pro servo
Servo mojeServo;
// --- NASTAVENÍ KALIBRACE ---
// Většina serv používá 544 us pro 0° a 2400 us pro 180°.
// Použití mikrosekund je mnohem přesnější než stupně 0-180.
const int minPuls = 544;
const int maxPuls = 2400;
// Standardní enkodér má 20 aretací (cvaknutí) na otáčku.
// Při 4x dekódování jedna plná otáčka = 80 "tiků".
// Tímto číslem měníte "převod" – jak moc se servo otočí na jednu otáčku enkodéru.
const int maxTiku = 80;
// 'volatile' říká procesoru, že se proměnná může změnit kdykoliv (v přerušení)
volatile long poziceEnkoderu = 0;
long posledniMapovanaPozice = -1;
void setup() {
// Připojení serva s definovaným rozsahem pulzů pro lepší přesnost
mojeServo.attach(servoPin, minPuls, maxPuls);
// pull-up rezistory udrží signál stabilní (HIGH), když enkodér nespíná
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
// Aktivace přerušení na OBOU pinech při jakékoliv ZMĚNĚ (CHANGE).
// Díky tomu zachytíme každý náběžnou i sestupnou hranu signálu.
attachInterrupt(digitalPinToInterrupt(encoderPinA), nactiEnkoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPinB), nactiEnkoder, CHANGE);
// Nastavení serva na střed při startu
mojeServo.writeMicroseconds(1500);
}
void loop() {
// 1. Omezíme hodnotu enkodéru na fyzický rozsah serva.
// Nechceme, aby se počítadlo točilo dál, když už je servo na dorazu.
poziceEnkoderu = constrain(poziceEnkoderu, 0, maxTiku);
// 2. Aktualizujeme servo pouze tehdy, pokud se enkodér pohnul.
// Neustálé posílání stejného příkazu může způsobit cukání (jitter).
if (poziceEnkoderu != posledniMapovanaPozice) {
// 3. Přepočet (mapování) tiků enkodéru na mikrosekundy.
// map(Hodnota, RozsahZ_Min, RozsahZ_Max, RozsahDo_Min, RozsahDo_Max)
int sirkaPulsu = map(poziceEnkoderu, 0, maxTiku, minPuls, maxPuls);
// 4. Poslání přímého časového signálu do servomotoru
mojeServo.writeMicroseconds(sirkaPulsu);
posledniMapovanaPozice = poziceEnkoderu;
}
}
/**
* LOGIKA ENKODÉRU (Kvadraturní dekódování)
* Tato funkce se spustí pokaždé, když pin 2 nebo 3 změní stav.
* Porovnává aktuální stavy s předchozími pro určení směru.
*/
void nactiEnkoder() {
static int minuleA = 0;
static int minuleB = 0;
int aktualniA = digitalRead(encoderPinA);
int aktualniB = digitalRead(encoderPinB);
if (aktualniA != minuleA || aktualniB != minuleB) {
// Logika XOR určuje směr otáčení (fázový posun)
if ((minuleA ^ aktualniB) & 1) {
poziceEnkoderu++;
} else {
poziceEnkoderu--;
}
}
minuleA = aktualniA;
minuleB = aktualniB;
}
Teorie a algoritmus:
Program využívá tři klíčové techniky pro zajištění vysoké kvality ovládání:
- 4x Kvadraturní dekódování: Namísto pouhého počítání "kliknutí" enkodéru systém sleduje každou elektrickou změnu na obou signálních pinech (náběžnou i sestupnou hranu). Tím se čtyřnásobně zvyšuje rozlišení ovládání.
- Hardwarová přerušení (Interrupts): Arduino okamžitě reaguje na pohyb enkodéru bez ohledu na to, co právě dělá v hlavní smyčce. Tím je zajištěno, že systém neztratí ani jeden krok enkodéru i při rychlém otáčení.
- Microsecond Control: Standardní příkazy pro servo pracují s rozlišením 0–180 stupňů. Tento projekt využívá přímé adresování časování pulsu v mikrosekundách (544 µs až 2400 µs), což poskytuje jemnost přes 1800 kroků na celém rozsahu pohybu.