ebSkola

2.4 Servo motors

Stundas uzdevums: Izprast Servo motora darbības principu, pievienot to mikrokontrolierim un uzrakstīt programmu, kas ļauj fiziski kontrolēt motora leņķi, izmantojot potenciometra kloķi.

Datorika 7. klase (D.7.1.1., D.7.4.2., D.7.6.1.)

70 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~15 min) - pieslēdz servo motora trīs vadus · 2. uzdevums (~20 min) - liec motoram griezties pa trim leņķiem · 3. uzdevums (~25 min) - vadi motora leņķi ar potenciometru. Papildu uzdevumu sāc tikai tad, ja pārējie trīs ir gatavi.

Pirms sāc: atver tinkercad.com un jaunu Circuit projektu - noderēs arī 2.3 stundas potenciometra slēgums, jo to izmantosi 3. uzdevumā.

Teorija: Kas ir Servo motors un kā ar to "sarunāties"?

Atšķirībā no parastajiem motoriem (kā ventilatoriem), kas griežas uz riņķi nepārtraukti, Servo motors ir īpašs – tam var pateikt precīzu leņķi (parasti no 0° līdz 180°), un tas turēs šo pozīciju. Tas ir ideāli piemērots robotu rokām, stūres mehānismiem un durvju slēdzenēm.

  • Trīs vadi: Servo motoram ir 3 vadi. Sarkanais iet uz 5V (strāva), brūnais/melnais iet uz GND (mīnuss), bet dzeltenais/oranžais ir "Signāla" vads, kas jāsavieno ar Arduino pinu.
  • C++ Bibliotēkas: Lai pašiem nebūtu jāraksta sarežģīts matemātiskais kods motora vadībai, programmētāji izmanto gatavas "bibliotēkas". Koda pašā sākumā jāieraksta #include <Servo.h>.
  • Objekta izveide: Tāpat kā mainīgajam, mums jādod motoram vārds, ierakstot Servo mansMotors;.
  • Map() funkcija: Mūsu potenciometrs dod datus no 0 līdz 1023, bet motors saprot tikai leņķus no 0 līdz 180. Lai šos skaitļus automātiski proporcionāli pārveidotu, C++ valodā ir maģiskā komanda map(vērtība, no_min, no_max, uz_min, uz_max).

Praktiskie uzdevumi

1. uzdevums -

Pieslēdz servo motora trīs vadus

Beigās tavs servo motors būs pareizi savienots ar strāvu un 9. portu.

  1. Izveido jaunu Tinkercad projektu ar Arduino un maketo plati.
  2. Savieno 5V ar sarkano (+) līniju un GND ar melno (-) līniju.
  3. Ievelc darba laukumā komponenti "Micro Servo".
  4. Savieno motora vadu "Ground" ar melno (-) līniju.
  5. Savieno vadu "Power" ar sarkano (+) līniju.
  6. Savieno vadu "Signal" ar Arduino 9. portu un iekrāso to oranžu.

Gatavs, kad: no motora iet tieši trīs vadi un signāla vads beidzas 9. portā.

2. uzdevums -

Liec motoram griezties pa trim leņķiem

Beigās motora ass pati staigās starp 0, 90 un 180 grādiem.

  1. Ieraksti koda pašā augšā rindu #include <Servo.h>.
  2. Ieraksti zem tās rindu Servo mansMotors;.
  3. Ieraksti funkcijā setup() rindu mansMotors.attach(9);.
  4. Ieraksti funkcijā loop() rindas mansMotors.write(0); un delay(1000);.
  5. Pievieno tādu pašu pāri leņķim 90 un vēl vienu leņķim 180.
  6. Palaid simulāciju un vēro motora asi.

Gatavs, kad: motors bez apstājas atkārto trīs pozīcijas, katrā pastāvot vienu sekundi.

3. uzdevums -

Vadi motora leņķi ar potenciometru

Beigās motora ass sekos tavai rokai, kad griezīsi kloķi.

  1. Pievieno potenciometru: malējās kājas pie 5V un GND, vidējo pie A0.
  2. Izdzēs no loop() iepriekšējā uzdevuma rindas.
  3. Ieraksti rindu int klokis = analogRead(A0);.
  4. Pievieno rindu int lenkis = map(klokis, 0, 1023, 0, 180);.
  5. Pievieno rindas mansMotors.write(lenkis); un delay(15);.
  6. Palaid simulāciju un lēnām pagriez kloķi.
  7. Pieraksti vienu secinājumu: ko dara funkcija map().

Gatavs, kad: kloķa galos motors stāv 0 un 180 grādos un pa vidu seko kloķim bez raustīšanās.

Papildu uzdevums - Motora vadība ar divām pogām

Ja pamatdarbs ir gatavs, nomaini kloķi pret divām pogām, kas griež asi pa soļiem.

  1. Pievieno divas pogas ar INPUT_PULLUP pie portiem 2 un 3.
  2. Ieraksti virs setup() rindu int pozicija = 90;.
  3. Uzraksti nosacījumu: ja nospiesta 2. poga, pozicija = pozicija - 10;.
  4. Uzraksti otru nosacījumu: ja nospiesta 3. poga, pozicija = pozicija + 10;.
  5. Pievieno abos zaros delay(100);, lai leņķis nelec pārāk ātri.
  6. Pievieno cikla beigās mansMotors.write(pozicija);.

Gatavs, kad: katrs pogas piespiediens pagriež asi tieši par vienu soli, nevis aizgriež to līdz galam.

Biežākās kļūdas (un kā tās labot):

  • Kods uzrāda kļūdu pie vārda "Servo": Tu aizmirsi koda augšā ierakstīt #include <Servo.h> vai uzrakstīji "servo" ar mazo burtu. C++ atšķir lielos un mazos burtus!
  • Motors simulācijā "dreb" vai raustās: Tu aizmirsi loop() beigās pievienot delay(15);. Ja komandas nāk tūkstošiem reižu sekundē, motors nespēj tikt līdzi un sāk vibrēt.
  • Map funkcija nestrādā pareizi: Pārbaudi mainīgo nosaukumus un to, vai tiešām lieto map(). Ja motoram sūti potenciometra vērtību (0-1023) tiešā veidā, tas saprot tikai 0-180 un apstāsies galā.
  • Kods nekompilējas, un kļūda rāda uz mainīgā vārdu: Mainīgo nosaukumos nedrīkst lietot garumzīmes un mīkstinājuma zīmes. Raksti klokis, nevis kloķis, un lenkis, nevis leņķis.

Koda piemērs (map() no 0-1023 uz 0-180 - grūtākā daļa)

// Grūtākā vieta: potenciometrs dod 0..1023, bet servo saprot tikai 0..180.
// Bez map() motors jau pie ceturtdaļas kloķa aizgriežas līdz galam un apstājas.
//   map(vērtība, no_min, no_max, uz_min, uz_max)
//   map(512, 0, 1023, 0, 180)  ->  90 grādi (tieši pa vidu)

#include <Servo.h> // Pievieno Servo bibliotēku

Servo mansMotors;   // Izveido motora objektu
int potPin = A0;    // Potenciometra ports

void setup() {
  // Pievieno motoru 9. portam
  mansMotors.attach(9); 
}

void loop() {
  // 1. Nolasa potenciometra stāvokli (0 līdz 1023)
  int klokaStavoklis = analogRead(potPin);
  
  // 2. Pārveido šos datus leņķu skalā (0 līdz 180)
  int motoraLenkis = map(klokaStavoklis, 0, 1023, 0, 180);
  
  // 3. Pasaka motoram fiziski pagriezties uz šo leņķi
  mansMotors.write(motoraLenkis);
  
  // 4. Pagaida, lai motors pabeidz kustību
  delay(15); 
}
        
Griežot kloķi, motora ass proporcionāli seko tavai kustībai visā 0-180 grādu diapazonā. Ja izņem map() rindu, ass aizgriežas līdz galam jau pie neliela kloķa pagrieziena un tālāk nekustas.