Servo motor
Kako servo motor SG90 zna svoj kut: impuls svakih 20 ms, tri žice, zasebno napajanje, biblioteka Servo na Arduinu i koliko mu treba da se okrene.

Što je servo motor?
Običan motor se vrti dok ima struje. Servo motor se okrene na kut koji mu zadamo i ondje ostane. Program mu kaže okreni se na 90°, a servo se okrene i drži taj položaj, čak i kad ga nešto gura. Najčešći servo motori okreću se od 0° do 180°, pola kruga.
Servo motore nalaziš u modelima aviona i brodova, gdje pomiču kormila, u robotskim rukama i u igračkama koje mašu. U našem fliperu servo motor podiže stupić između palica da spasi kuglicu.

Na radionicama koristimo mali servo SG90. Težak je oko 9 grama, a ima tri žice:
- smeđa je GND (minus),
- crvena je napajanje od oko 5 V (plus),
- narančasta je signal, koji servu kaže na koji se kut treba okrenuti.
Neki servo motori imaju žice drukčijih boja: crnu za GND, crvenu za plus i bijelu ili žutu za signal.
Na osovinu se nataknu poluge (engleski horn) raznih oblika.
Što je u servo motoru?

- Motor: mali i brz, ali slab.
- Zupčanici smanjuju brzinu i povećavaju silu. Motor se okrene mnogo puta dok se osovina okrene jednom.
- Osovina izlazi iz kućišta. Na nju stavljamo polugu.
- Potenciometar je spojen s osovinom i okreće se s njom, pa njegov otpor kaže na kojem je kutu osovina.
- Sklop uspoređuje kut koji traži program s kutom koji pokazuje potenciometar. Ako se razlikuju, okreće motor dok ne budu jednaki. Ako netko pomakne polugu, sklop to primijeti i vrati je.
To je kao kad posegneš za čašom: oči stalno javljaju koliko je ruka daleko, pa ruka uspori kad se približi i stane točno na čaši.
Ne okreći servo motor rukom
Zupčanici usporavaju motor mnogo puta, pa se motor okrene mnogo puta dok se poluga okrene jednom. Kad polugu okrećeš rukom, cijeli niz zupčanika vrtiš unatrag, a mali motor na kraju niza mora se vrtjeti mnogo brže od poluge. Za to treba velika sila, a nju nose sitni zubi plastičnih zupčanika. Zub pukne ili se odlomi, a servo motor poslije preskače, zapinje ili se više ne okreće.
Ako je servo motor uključen, još je gore: sklop primijeti da je poluga pomaknuta i svom snagom je gura natrag. Ti i motor tada se borite, a motor troši najveću struju i grije se. Polugu zato namještaj programom. Ako je ipak moraš pomaknuti rukom, na primjer da nataknuš polugu, najprije isključi napajanje, a zatim je okreći polako i bez sile.
Kako servo zna koji kut želimo?
Narančasta žica svakih 20 milisekundi dobije kratki impuls: napon skoči na 5 V i vrati se na 0 V. Kut ovisi o tome koliko impuls traje:

- impuls od 1 ms znači 0°,
- impuls od 1,5 ms znači 90°,
- impuls od 2 ms znači 180°.
Dulji impuls znači veći kut. Točne granice malo se razlikuju od servo motora do servo motora, ali sredina je gotovo uvijek 1,5 ms.
Pozicijski i kontinuirani servo motor
Servo motori dolaze u dvije vrste:
- Pozicijski servo motor (engleski positional) okreće se na zadani kut i ondje stane, najčešće negdje od 0° do 180°. Takav je SG90, a o njemu govori ostatak ove stranice. Impuls mu kaže gdje da stane.
- Kontinuirani servo motor (engleski continuous rotation), na primjer FS90R, vrti se u krug, kao običan motor. Impuls mu kaže na koju stranu i koliko brzo da se vrti: oko 1,5 ms znači stani, 1 ms punom brzinom na jednu stranu, a 2 ms punom brzinom na drugu. Impulsi između daju sporije okretanje.
Kontinuirani servo motor nema potenciometra koji bi pratio osovinu, a nema ni graničnika koji zaustavlja osovinu na kraju puta. Zato ne zna na kojem je kutu i ne može stati na zadanom kutu, ali se može vrtjeti bez kraja. Izvana obje vrste izgledaju gotovo isto, pa vrstu provjeri na naljepnici ili u opisu proizvoda.
Pozicijski servo motor pomiče polugu, kormilo ili stupić u fliperu. Kontinuirani pokreće kotače malog robota, kojem tada ne treba poseban modul za upravljanje motorima.
Gdje ga koristimo?
- Na micro:bit radionici servo motor spajamo na robota Maqueen. U MakeCodeu ga okreće blok servo write pin, iz kategorije Pins.
- Na Arduino radionici servo motori SG90 dio su flipera: podižu stupić, a mogu pomicati i druge mehanizme.
Servo motor na Arduino radionici
Od ovog mjesta stranica je za Arduino radionicu.
Napajanje
Dok se SG90 okreće, troši nekoliko stotina mA, a kad krene ili zapne, i do 0,7 A. To je mnogo više nego što smije dati pin, a i više nego što bez problema daje USB. Kad servo krene, napon na Arduinu padne i Arduino se može sam resetirati. Zato servo motor ima svoje napajanje:

- Signal ide s pina D9, a struju servo uzima iz zasebnog izvora od 5 V, na primjer adaptera.
- Kondenzator od 470 µF uz servo motor daje struju u trenutku kad servo krene, pa napon ne padne. U fliperu, s tri servo motora, stavljamo 1000 µF.
- GND izvora i GND Arduina moraju biti spojeni. Servo mjeri impuls prema svom GND-u, pa bez zajedničke mase ne zna kad impuls počinje (zabluda 8).
Biblioteka Servo
Impulse ne moramo slati sami. To radi biblioteka Servo, koja dolazi s Arduino IDE-om:
// C++
#include <Servo.h> // biblioteka Servo, dolazi s Arduino IDE-om
Servo servo; // naš servo motor
const int pinServa = 9; // narančasta žica
void setup() {
servo.attach(pinServa); // od sada D9 svakih 20 ms šalje impuls
}
void loop() {
servo.write(0); // brzo na 0°
delay(1000);
servo.write(90); // brzo na 90°
delay(1000);
servo.write(180); // brzo na 180°
delay(1000);
for (int kut = 180; kut >= 0; kut--) {
servo.write(kut); // polako natrag, stupanj po stupanj
delay(15);
}
delay(1000);
}
Što je novo u programu?
Servo servo;– Stvara objekt za jedan servo motor. Za dva servo motora napravili bismo dva objekta s različitim imenima.servo.attach(pinServa);– Od tog trenutka biblioteka sama, u pozadini, šalje impulse na D9, dok program radi nešto drugo.servo.write(90);– Zadaje kut u stupnjevima, od 0 do 180. Biblioteka ga pretvori u trajanje impulsa: 0° je 544 µs, a 180° je 2400 µs. To je malo šire od 1 do 2 ms, da bi i servo motori sa širim granicama dosegli kraj.- Polagano okretanje dobivamo tako da kut mijenjamo za jedan stupanj i malo pričekamo. Cijeli put od 180° do 0° tada traje 181 · 15 ms ≈ 2,7 s.
Na Unu biblioteka Servo koristi brojač vremena Timer1, pa dok je spojen ijedan servo motor, analogWrite() ne radi na pinovima 9 i 10. Zato servo motori i palice u fliperu nisu na istom Unu. Uno može upravljati s najviše 12 servo motora.
Koji pinovi Una znaju PWM?
Arduino Uno ima PWM na šest pinova: D3, D5, D6, D9, D10 i D11. Na pločici su označeni valovitom crtom (~). Svaki par tih pinova pokreće jedan brojač vremena, pa naredba ili biblioteka koja zauzme brojač zauzme i njegova dva pina:
| Pinovi | Brojač | PWM | Tko ga još koristi |
|---|---|---|---|
| D5 i D6 | Timer0 | oko 980 Hz | millis() i delay(), a PWM i dalje radi |
| D9 i D10 | Timer1 | oko 490 Hz | biblioteka Servo |
| D3 i D11 | Timer2 | oko 490 Hz | tone() i biblioteka IRremote |
Servo motoru PWM pin ne treba: biblioteka Servo šalje impulse na bilo koji digitalni pin. Signal servo motora nije isto što i PWM iz analogWrite(). analogWrite() pin pali i gasi oko 490 puta u sekundi, a servo motor očekuje jedan impuls svakih 20 ms, 50 u sekundi. Sve pinove Una opisuje stranica Raspored pinova.
Koliko se dugo okreće?
servo.write() ne čeka da se servo okrene. Program odmah ide dalje, a servo se još okreće. Graf pokazuje izračun za SG90, koji se na 4,8 V okrene za 60° u 0,1 s:

servo.write() u programu treba delay() ili provjera s millis(), prije nego što računamo da je poluga stigla.Kad servo zuji
Ako servo na kraju puta zuji i grije se, poluga ili mehanizam ne daju mu da stigne do zadanog kuta. Sklop tada stalno gura motor, a motor troši najveću struju. Kut tada smanji, na primjer na 10° do 170°, ili granice impulsa zadaj sam: servo.attach(pinServa, 1000, 2000); šalje 1000 µs za 0° i 2000 µs za 180°.
Kontinuirani servo motor u programu
Kontinuiranim servo motorom upravljamo istom bibliotekom Servo, ali servo.write() sada ne zadaje kut, nego brzinu: servo.write(90) ga zaustavi, servo.write(0) vrti ga punom brzinom na jednu stranu, a servo.write(180) na drugu. Vrijednosti između, na primjer 70 ili 110, daju sporije okretanje. Ako se servo kod 90 i dalje polako vrti, probaj 88 ili 92: točka u kojoj stoji malo se razlikuje od servo motora do servo motora.
Polagan pokret: servo motor bez trzaja
servo.write() pošalje servo motoru novi kut, a servo motor do njega jurne punom brzinom. Nagli pokret i naglo zaustavljanje udaraju zupčanike u servo motoru i mehanizam koji on pomiče: polugu, stupić ili zglob robotske ruke. Što je mehanizam teži, udarac je jači. Zato veliki pokret ne zadajemo odjednom, nego servo motor polako vodimo do cilja, malim koracima:
// C++
#include <Servo.h>
Servo servo;
const int pinServa = 9;
const int POCETNI_KUT = 90; // gdje servo stoji kad se program pokrene
const unsigned long KORAK_MS = 15; // svakih 15 ms jedan stupanj: 60° u 0,9 s
int kutServa = POCETNI_KUT; // kut koji je servo zadnji put dobio
int ciljServa = POCETNI_KUT; // kut do kojeg servo polako ide
unsigned long zadnjiKorakServa = 0; // kada se servo zadnji put pomaknuo
unsigned long zadnjaPromjena = 0; // kada smo zadnji put promijenili cilj
void setup() {
servo.write(POCETNI_KUT); // prvi impuls već nosi početni kut, a ne 90°
servo.attach(pinServa);
}
void loop() {
// primjer: svake 4 sekunde novi cilj, naizmjence 160° i 20°
if (millis() - zadnjaPromjena >= 4000) {
zadnjaPromjena = millis();
if (ciljServa == 160) {
ciljServa = 20;
} else {
ciljServa = 160;
}
}
pomakniPremaCilju(servo, kutServa, ciljServa, zadnjiKorakServa, KORAK_MS);
}
// Pomakne servo za jedan stupanj prema cilju, ako je od zadnjeg koraka prošlo korakMs.
// Parametri s & su reference: funkcija mijenja baš one varijable s kojima je pozvana.
void pomakniPremaCilju(Servo &s, int &kut, int cilj, unsigned long &zadnjiKorak, unsigned long korakMs) {
if (kut == cilj) {
return; // već smo na cilju
}
if (millis() - zadnjiKorak < korakMs) {
return; // još nije vrijeme za sljedeći korak
}
zadnjiKorak = millis();
if (cilj > kut) {
kut = kut + 1;
} else {
kut = kut - 1;
}
s.write(kut);
}
Što je novo u programu?
kutServa,ciljServaizadnjiKorakServa– Program pamti kut koji je servo motor zadnji put dobio, kut do kojeg treba stići i kada je napravljen zadnji korak. Ostatak programa mijenja samociljServa.pomakniPremaCilju(servo, kutServa, ciljServa, zadnjiKorakServa, KORAK_MS);– Funkcija sve što treba dobiva kao parametre i ne dira nijednu globalnu varijablu. Zato je možeš koristiti za više servo motora. Za drugi servo motor, na primjerruka, napraviš njegove varijable i pozoveš istu funkciju:pomakniPremaCilju(ruka, kutRuke, ciljRuke, zadnjiKorakRuke, KORAK_MS);. Oba se tada miču istodobno, svaki prema svom cilju.int &kut– Znak&kaže da je parametar referenca. Funkcija ne dobiva kopiju vrijednosti, nego mijenja baš varijablu s kojom je pozvana: kad povećakut, poveća sekutServa. Isto vrijedi zazadnjiKoraki za servo motorServo &s.ciljikorakMsfunkcija samo čita, pa ih dobiva kao obične parametre, bez&.millis() - zadnjiKorak < korakMs– Korak se napravi tek kad prođe 15 ms od prošlog, kao smirivanje u lekciji o tipkalima. Program pritom ne čeka, paloop()u međuvremenu može čitati tipke i senzore. Polagano okretanje sdelay()iz programa iznad zaustavilo bi sve ostalo dok se servo motor ne okrene.KORAK_MS– Određuje brzinu: s 15 ms servo motor prijeđe 60° u 0,9 s, šest puta sporije nego punom brzinom (0,1 s za 60°). S 30 ms ide upola sporije.servo.write(POCETNI_KUT);prijeservo.attach()– Program ne zna gdje je poluga kad se Arduino uključi. Biblioteka bi bez toga prvim impulsom poslala 90°, pa bi servo motor jurnuo onamo. Ovako prvi impuls nosi početni kut. Na početni kut servo motor i dalje skoči, ali samo ako ga je netko pomaknuo dok je bio isključen.
U pravom programu cilj ne mijenja sat, nego događaj: pritisak tipke, poruka drugog Arduina ili očitanje senzora. Za još mekši pokret korak može biti veći dok je servo motor daleko od cilja, a manji kad mu se približi.
Što smo naučili?
- Servo motor se okrene na zadani kut i drži ga. U njemu su motor, zupčanici, potenciometar i sklop koji ih uspoređuje.
- SG90 ima tri žice: smeđu (GND), crvenu (5 V) i narančastu (signal).
- Kut određuje trajanje impulsa koji dolazi svakih 20 ms: oko 1 ms za 0°, 1,5 ms za 90° i 2 ms za 180°.
- Servo motor ima svoje napajanje od 5 V, sa zajedničkim GND-om i kondenzatorom.
servo.write()ne čeka da se servo okrene. Na Unu biblioteka Servo isključi PWM na pinovima 9 i 10.- Veliki pokret zadajemo malim koracima prema cilju, s
millis(), da ne udaramo zupčanike i mehanizam. - Pozicijski servo motor stane na zadanom kutu. Kontinuirani nema potenciometra, pa se vrti u krug, a impuls mu zadaje smjer i brzinu.
Mali kviz
1. Po čemu se servo motor razlikuje od običnog motora?
2. Kako servo zna na kojem je kutu?
3. Koliko traje impuls za 90° i koliko često dolazi?
4. Kad servo krene, Arduino se resetira. Što je najvjerojatnije krivo?
5. Program zove servo.write(180) i odmah zatim čita senzor na poluzi. Zašto senzor još ne javlja da je poluga stigla?
servo.write() ne čeka. SG90 treba oko 0,37 s da se okrene od 0° do 180°, pa programu treba delay() ili provjera s millis().6. Na Unu je servo motor na D9, a LED-icu na D10 želiš prigušiti s analogWrite(). Zašto ne radi?
7. Po čemu se kontinuirani servo motor razlikuje od pozicijskog?