====== Servomootor ======
//Vajalikud teadmised:
[HW] [[et:hardware:homelab:digi]], [HW] [[et:hardware:homelab:combo]],
[AVR] [[et:avr:timers]], [AVR] [[et:avr:adc]],
[LIB] [[et:software:homelab:library:module:motor]], [LIB] [[et:software:homelab:library:adc]]//
===== Teooria =====
[{{ :examples:motor:servo:motor_servomotor.jpg?220|RC servomootor}}]
[{{ :examples:motor:servo:motor_servo_signal_position.png?220|Servomootori PWM signaali laiuse ja võllil oleva hoova asendi vaheline seos}}]
RC (inglise keeles //radio-controlled//, lühend RC) servomootor on mudelismis ja robootikas laialt levinud täiturmehhanism, mis koosneb väikesest alalisvoolumootorist, hammasreduktorist ja juhtloogikast. Servomootori rootor liigub üldjuhul mingisse kindlasse asendisse ja üritab siis seda asendit püsivalt hoida. Rootori asend sõltub servomootorile etteantavast juhtsignaalist. Sõltuvalt mootori tüübist võib maksimaalne pöördenurk olla erinev. Harvem esineb pideva pöörlemisega servomootoreid. Sellisel juhul määrab juhtsignaal mitte rootori asendi, vaid pöörlemiskiiruse. Levinud on ka servomootori nn. häkkimine, mille käigus asendit määrav servomootor tehakse ümber pidevalt pöörlevaks. Sisuliselt tähendab see, et asendist tagasisidet andev potentsiomeeter asendatakse kahe fikseeritud takistiga ja eemaldatakse hammasrattalt täispööret takistav mehaaniline takistus. Servomootori üks oluline tunnus on tema hea kaalu ja võimsuse suhe.
Servomootori juhtsignaaliks on spetsiifiline pulsilaiusmodulatsiooni (PWM) signaal, kus pulsi laius määrab ära rootori asendi. Signaali perioodiks on 20 ms (sagedus 50 Hz) ja kõrge poolperioodi laiuseks 1-2 ms. 1 ms tähistab rootori üht äärmist asendit ja 2 ms teist rootori äärmist asendit. 1,5 ms tähistab rootori keskasendit.
Traditsiooniline RC servomootor kannab ka analoog-servomootori nime. Põhjus on selles, et viimasel kümnendil tekkisid ka nii-öelda digitaalsed servomootorid. Nende kahe vahe seisneb selles, et analoog-servomootoris juhitakse mootorit sellesama 50 Hz PWM sisendsignaaliga, digitaal-servomootoris juhib mootorit aga eraldi mikrokontroller palju kõrgema sagedusega. Sisendsignaal on digitaalsel servomootoril küll sama, kuid kõrgem mootori moduleerimissagedus võimaldab täpsemat ja kiiremat asendi määramist.
===== Praktika =====
Kodulabori Kombomoodulil on kaks või neli pistikut RC servomootorite ühendamiseks. Pistikute PWM signaali otsad on ühendatud mikrokontrolleri viikudega, millel on taimeri funktsioon. Taimer on võimeline raudvaraliselt tekitama PWM signaali ja seetõttu on mootorite juhtimine programmis väga lihtne. Keerulisem on ainult taimeri seadistamine.
Taimer tuleb seadistada PWM signaali tekitamise režiimi, kus taimeri maksimaalne väärtus on määratud ICR registriga. Taimeri taktijaguri ja programmis muudetava maksimaalse väärtusega saab täpselt ära määrata servomootori juhtimiseks vajaliku PWM signaali sageduse. Taimeri võrdlusregistriga saab määrata kummagi PWM signaali kõrge poolperioodi pikkuse. Taimeritel on nimelt spetsiaalsed võrdlusüksused, mis jälgivad loenduri väärtust ja kui see saab samaks võrdlusregistri väärtusega, siis muudavad võrdlusüksuse väljundi väärtust. Järgnevalt on toodud servomootoreid juhtiva Kodulabori teegi programmikood, mis universaalsuse eesmärgil kasutab makrofunktsioonidega määratud taimeri parameetreid. Näiteks kasutatakse perioodi leidmiseks //F_CPU// konstanti, mis tähistab mikrokontrolleri taktsagedust. Makrodega ei pea taimeri parameetreid erinevate taktsageduste jaoks ise välja arvutama ja kompilaator teisendab makrodega tehted niikuinii konstantideks, nii et programmimälu ei suurene ja ei võta ka rohkem täitmisaega. Järgnev teeginäide on Kodulabor II (ATmega2561) kohta.
// Taimeri väärtus PWM täisperioodi (20 ms) saavutamiseks
// F_CPU on mikrokontrolleri taktsagedus, mis jagatakse 8-ga ja 50 Hz
#define PWM_PERIOD (F_CPU / 8 / 50)
// PWM servo keskasend (1,5 ms / 20 ms)
// Keskasend saadakse täisperioodist 15/200 võtmisega
#define PWM_MIDDLE_POS (PWM_PERIOD * 15 / 200)
// Kordamistegur, et protsentidest (-100 % kuni 100 %) vajalik periood saada
// +1 liidetakse selleks, et poolperiood kindlasti ulatuks 1 ja 2 ms
// piiridesse või siis natuke üle
#define PWM_RATIO (PWM_PERIOD / 20 / 2 / 100 + 1)
// Viikude seadistamine
static pin servo_pins[2] =
{
PIN(B, 5), PIN(B, 6)
};
// Määratud servomootori algseadistamine
void servomotor_init(unsigned char index)
{
// PWM signaali viigu väljundiks määramine
pin_setup_output(servo_pins[index]);
// Taimer 1 seadistamine
// Taktijagur 8
// Kiire PWM režiim kus TOP = ICR
// OUTA ja OUTB võrdusel madalaks
timer1_init_fast_pwm(
TIMER1_PRESCALE_8,
TIMER1_FAST_PWM_TOP_ICR,
TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH,
TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH,
TIMER1_FAST_PWM_OUTPUT_DISABLE);
// Perioodi määramine maksimaalse väärtuse kaudu
timer1_set_input_capture_value(PWM_PERIOD);
}
// Servomootori positsiooni määramine
// Positsiooni parameeter on -100 kuni 100 %
void servomotor_position(unsigned char index, signed short position)
{
switch (index)
{
case 0:
timer1_set_compare_match_unitA_value(
PWM_MIDDLE_POS + position * PWM_RATIO);
break;
case 1:
timer1_set_compare_match_unitB_value(
PWM_MIDDLE_POS + position * PWM_RATIO);
break;
}
}
Näiteprogramm kasutab kirjeldatud Kodulabori teegi funktsioone. Programmi alguses pannakse esimese servomootori PWM signaali genereeriv taimer tööle //servomotor_init// funktsiooniga. Servomootori asendi väärtus saadakse analoog-digitaalmuunduri kanalist, kuhu on ühendatud potentsiomeeter. Et servomootori juhtimiseks vajalikku -100 kuni 100 vahemikku saavutada, lahutatakse ADC väärtusest pool maksimumi (ehk 512) ja jagatakse viiega. Tulemuseks on küll ±102, kuid pisike ebatäpsus ei loe, sest servomootorid ise ka erinevad PWM signaali ja pöördenurga suhtelt. Täpseks liigutuseks tuleb rakendustes PWM poolperioodi laius siiski katse- ja eksitusmeetodil määrata. Ka raadiojuhitavate mudelite pultidel on täpseks seadistuseks vastavad võimalused (inglise keeles //trim//). Programmi käivitades muutub vastavalt potentsiomeetri asendile ka servomootori võlli asend.
// Kodulabori mootorite mooduli servomootori näidisprogramm
#include
#include
// Põhiprogramm
int main(void)
{
short position;
// ADC seadistamine
adc_init(ADC_REF_AVCC, ADC_PRESCALE_8);
// Mootori seadistamine
servomotor_init(1);
// Lõputu tsükkel
while (1)
{
// Potentsiomeetrist positsiooni lugemine ja servomootori
// piirkonda teisendamine
// Kodulabor II puhul tuleb lugeda vastavat ADC kanalit ning kasutada
// järgmist valemit:
// position = ((short)adc_get_value(3) - (short)512) / (short)5;
position = ((short)adc_get_value(15) / 10) - 102 ;
// Servomootori positsiooni määramine
servomotor_position(1, position);
}
}