Untuk dapat mengontrol motor servo kita perlu memberikan pulsa high dan pulsa low dengan lebar tertentu. Frekuensi yang diperlukan adalah 50 Hz. Pulsa ini dapat dihasilkan dengan port I/O biasa pada mikrokontroler. Namun terkadang dengan cara ini pergerakan servo menjadi kurang akurat. Oleh karena itu digunakan metode Pulse Width Modulation (PWM). Dengan metode PWM dapat dihasilkan gerakan servo yang cukup akurat dengan resolusi yang kita sesuaikan dengan keinginan kita

Berikut ini adalah salah satu contoh pulsa yang dihasilkan untuk menggerakan servo dengan sudut 0o,90o, dan 180o

Pulsa ini dapat dihasilkan dari pin OCR pada mikrokontroler. Perlu pengaturan register timer pada mikrokontroler agar dapat dihasilkan pulsa dengan lebar yang sesuai kita inginkan. Hal yang sangat penting adalah pengaturan frekuensi dan lebar pulsa on dan pulsa off. Oleh karena itu perlu dihitung berapa konstanta-konstanta timer yang di atur pada mikrokontroler.

Dua parameter utama yang diperlukan untuk mencari konstanta-konstanta timer adalah nilai clock mikrokontroler dan nilai clock timer (ditentukan dari prescaler). Dari kedua parameter itu kita dapat merancang lebar pulsa high dan pulsa low dengan frekuensi tertentu yang sesuai untuk menggerakan motor servo, seperti pulsa pada gambar di atas.

Sebagai contoh kita menggunakan clock eksternal 11.059200 MHz. Untuk pembangkitan PWM kita menggunakan Timer1. Alasan menggunakan Timer1 karena timer ini dapat menampung data sebesar 16 bit sehingga dapat dihasilkan resolusi yang cukup besar untuk menggerakan servo. Maksud resolusi ini adalah besarnya nilai sudut step dari servo, semakin besar resolusi maka step gerakan servo semakin halus, dan sebaliknya jika resolusinya kecil maka gerakan servo akan terlihat patah-patah.

Mode PWM yang digunakan adalah Phase Correct PWM top=ICR1 dengan prescaler 8 sehingga nilai clock timer adalah 1382.4 KHz. Dengan demikian kenaikan counter pada timer dapat dihitung dari periodenya yaitu 1/1382.4 KHz = 7.2338x10-7 s atau sekitar 72.34 mikrosekon.

Periode PWM yang kita ingin hasilkan adalah 20 ms, karena kita menggunakan mode Phase Correct PWM maka periodenya adalah dua kalinya dari kenaikan counter timer, sehingga nilai counter timer adalah 10 ms. Nilai top dari timer bergantung dari ICR1 dimana nilainya dihitung dari pembagian total waktu yang kita inginkan dengan periode timer yaitu 10 ms / 7.2338x10-7 = 13823.99. Nilai inilah yang perlu dimasukan ke register ICR1. Karena register adalah tipe data integer maka perlu dibulatkan menjadi 13824. Dalam bilangan hexadimal menjadi 0x3600.

Berikut adalah pengaturan timer dengan menggunakan CodeWizardAVR. Untuk keluaran PWM dihasilkan hanya pada Out A yaitu port OCR1A dengan Non-Inv agar pulsa yang dihasilkan tidak dilakukan pembalikan.

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1382.400 kHz
// Mode: Ph. correct PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x82;
TCCR1B=0x12;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x36;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

Hal yang perlu diperhatikan juga adalah port pada OCR1A perlu dijadikan sebagai output.

Untuk mengatur sudut putaran servo kita perlu menghitung rentang nilai OCR1A yang perlu diberikan ke motor servo agar dapat bergerak dari sudut 0o hingga 180o. Sama seperti cara sebelumnya untuk menghitung nilai top dari counter timer, maka nilai OCR1A diperoleh dari pembagian pulse on yang diperlukan dengan periode timer. Untuk sudut 0o diperlukan pulsa on dengan lebar 1 ms. Dengan membaginya dengan dua karena mode Phase Correct PWM maka menjadi 0.5 ms. Sehingga 0.5 ms / 7.2338x10-7 s = 691.19 atau dalam integer 691.

Sedangkan untuk sudut 180o, pulsa yang perlu diberikan adalah 2 ms. Diperoleh nilai integer untuk OCR1A adalah 1 ms / 7.2338x10-7 s = 1382.39 atau 1382.

Dari sinilah kita dapat membuat fungsi untuk menggerakan motor servo dengan parameter sudut yang kita inginkan. Berikut adalah fungsinya,

void servoA(int degree)
{
 int x = 1037 - (int)degree*346.0/90.0;

 OCR1A = x;
}

Dengan cara yang sama dengan di atas dapat dihitung konstanta-konstanta timer yang diperlukan dengan konfigurasi nilai clock dan prescaler timer yang ada. Semakin besar perbedaan nilai integer OCR1a untuk sudut 0o dan sudut 180o maka resolusi timer makin kecil dan membuat gerakan servo menjadi lebih halus.

Berikut ini adalah simulasi kontrol motor servo menggunakan ISIS Proteus (download simulasi dan program disini)

Untuk meyakinkan bahwa pulsa yang dihasilkan sudah sesuai maka kita dapat mengeceknya dengan menggunakan osiloskop.

Semoga Bermanfaat.

Didedikasikan untuk TRUI (Tim Robotika UI) AppNotes