Kendali Motor Servo Menggunakan PWM dari Timer

motor servo adalah sebuah aktuator yang bergerak dalam poros yang mempunyai spesifikasi untuk control posisi sudut yang presisi. Banyak jenis motor servo. Ada yang dikontrol secara serial ataupun dengan PWM. Kali ini kita akan mencoba megatur posisi dari sebuah motor servo dengan menggunakan PWM yang dibangkitkan dari timer1. PWM harus diatur agar memenuhi standar sinyal input untuk motor servo sehingga motor servo dapat bergerak sesuai dengan perintah yang kita kirimkan lewat PWM.

Review motor servo.       servo_1 servo_2

Nilai input PWM pada setiap servo terkadang berbeda sesuai merek. Misalnya saja Servo Futaba tipe Futaba S3003 – Standard Servo.

0.388ms = 0 degree.

1.264ms = 90 degrees. (neutral position)

2.14ms = 180 degrees.

Akan tetapi kita coba dengan setting pada proteus seperti berikut.

servo_3

Mari kita mulai.Buat sebuah folder untuk project yang akan kita buat. Semua file project akan disimpan di folder ini. Buat folder dengan nama motor servo.

Pertama buat new project, lalu masukan chip ATMega8535, ambil dari library.

servo_4

servo_5

masukan juga komponen motor servo

servo_6

Lalu rangkai seperti gambar sirkuit di bawah ini.

servo_7

Untuk komponen VCC dan Ground bisa di drag dari Terminals mode.

servo_8

Sekarang kita beralih ke codevisionAVR. Buat new project. Klik File, lalu New.

servo_9

Kemudian pilih Project, lalu klik OK.

servo_10

Jika muncul pertanyaan seperti di bawah ini. Klik Yes.

servo_11

Setelah itu kita lakukan pengaturan untuk project yang akan kita buat. Pertama setting chip yang akan digunakan. Kita gunakan ATmega8535 dan nilai clock yaitu 16 MHz. (dalam pemrograman, tanda titik berarti koma, untuk memisahkan bilangan decimal. Missal 3,7 maka diketik 3.7 dan begitu pula jika kita memasukan nilai clock 11,059200MHz maka diketik 11.059200 MHz.

Lalu kita lakukan setting pada bagian Timer1. Kita akan gunakan Timer1 ini untuk membangkitkan sinyal PWM yang digunakan untuk mengontrol motor servo. Lakukan setting di bawah ini.

servo_12

kita akan menggunakan mode

// Timer/Counter 1 initialization

// Clock source: System Clock

// Clock value: 250.000 kHz

// Mode: Fast 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

Dari informasi diatas kita dapati bahwa counter akan berjalan dalam interval waktu T=1/250kHz yaitu 4us, dan akan menggunaka mode Fast PWM. Dengan nilai TOP counter yaitu ICR1 1387 atau 4999. Hal ini dikarenakan kita membutuhkan sinya PWM dengan lebar perioda 20ms atau frekuensi 50Hz untuk mengendalikan servo. Berikut perhitungannya.

servo_13

servo_14

Sedangkan nilai lebar pulsa high dari PWM atau lebar dutty cycle positif akan ditentukan oleh register OCR1.

servo_15

Dutty cycle: perbandingan lebar perioda HIGH dengan lebar perioda gelombang.

perhitungan OCR1 untuk menghasilkan lebar pulsa dari 1ms – 2ms (sesuai settingan servo di simulasi proteus) adalah.

OCR1A= (((sudut + 90)/90)*1000)/4;

Dimana nilai 1ms – 2ms tersebut akan menghasilkan nilai sudut dari -900 sampai 900. Perhitungan di atas didapat berdasarkan bahwa couter berjalan dalam interval 250kHz atau 4us  sehingga untuk menghasilkan gelombang 1ms – 2ms adalah.

Atau jika kita menggunakan MS-Exel untuk mendapat persamaannya maka setelah membuat table dari data sumbu x untuk sudut x={-90,90} dan y untuk OCR1A={250,500} maka kita bisa mendapatkan persamaan linier dengan cara klik kanan pada garis yang ada di table dan klik Add Trendline.

servo_16

Lalu setting seperti berikut.

servo_17

Maka akan muncul persamaan.

servo_18

y = 1.388x + 375

dan kita ganti nilai x dan y sehingga menjadi.

OCR1A = (unsigned int)((1.388*(float)sudut) + 375);

Sekarang kita masukan ke program.

 /*****************************************************
Chip type           : ATmega8535
Program type        : Application
Clock frequency     : 16.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 128
*****************************************************/

#include <mega8535.h>
#include <delay.h>

// Declare your global variables here
void set_servo(int sudut)
{
        OCR1A= (((sudut + 90)/90)*1000)/4; 
        //OCR1A = (unsigned int)((1.388*(float)sudut) + 375);
}

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=0 State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x20;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 250.000 kHz
// Mode: Fast 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=0x1B;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x13;
ICR1L=0x87;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

while (1)
      {
      // Place your code here
      set_servo(-90); //set servo ke -90 derajat
      delay_ms(1000); //tahan posisi servo selama 1000ms

      set_servo(90);  //set servo ke 90 derajat
      delay_ms(1000); //tahan posisi servo selama 1000ms
      };
}

Lalu klik Make the project.

servo_19

servo_20

Klik OK, maka akan ter-generate file .hex. File inilah yang akan diupload ke dalam mikrokontroler.

Seperti biasa jangan lupa lakukan pengaturan di chip ATMEGA8535.

servo_21

Klik pada ikon folder Program File. Browse file .hex yang sudah kita generate tadi di codevisionAVR.

servo_22

Atur CKSEL Fuses menjadi Ext. Clock dan Clock Frequency dengan nilai clock 16MHz yang sudah kita atur juga pada codevisionAVR.

Klik OK.

Setelah proses setting selesai, maka langsung saja klik Play.

servo_23

Untuk melihat sinyal yang mengatur motor servo bisa kita tambahkan osiloskop pada rangkaian proteus yang sudah kita buat.

servo_24

Kita capture di jalur input servo.

servo_25

Maka bisa dilihat sinyal PWM-nya.

servo_26

33 Responses to Kendali Motor Servo Menggunakan PWM dari Timer

  1. joan says:

    gan, pils post juga cara kendali servo via uart dgn ngirim data posisi sudut maka servo akan bergerak sesuai posisi yg d input ?

    trimakasih (y)

  2. Prayogo says:

    gan,, rumus 64 (1+TOP) itu maksudnya apa?dapet darimana ya ?

  3. azaz says:

    gan gimana kalo ada 3 servo yang di kendalikan? ada tutorialnya ato website referensi
    trimakasih

  4. irvan says:

    gan ane masih newbee mau tanya
    apa itu cuma bisa lewat port oc1a aja ya?

    • wangready says:

      iya gan, setau ane atmega8535 cuma bisa port tsb, klo port timer yg lain gk cukup buat counter nya…kecuali bikin PWM manual…
      gk tau tp kalo atmega versi lain….

  5. minona says:

    untuk mencari OCR1A
    = (((sudut + 90)/90)*1000)/4

    misal dipakai sudut -90
    (-90 + 90)=0
    0/90*1000/4=0

    kok hasil nya 0 gan ?

  6. roy says:

    gan aku mau buat pintu otomatis pake servo ,,,,gimana supaya mutar 180 drajat gan ???

    • wangready says:

      buat pintu beneran mah harus pake servo gede gan, mending pake pneumatic….
      bukannya servo biasa jg bisa 180 derajat gan, tinggal kasih pwm aja…

  7. Cahyono Hadi says:

    pak, kalo ngontrol motor servo dengan serial itu gmn caranya?

    • wangready says:

      int derajat;
      while(1)
      {
      scanf(“servo=%d”,&derajat);
      servo(derajat);
      }
      jadi tinggal kirim aja lewat serial servo=nilai derajat nya, fungsi servonya ada di atas gan

  8. gan,kalo mau bikin sudutnya 30,60, sama 90 gimana ya?

  9. ian says:

    gan, kalau ngontrol sudut servo dengan pwm melalui interupt gimana caranya??

  10. 082320911955 says:

    gan bagaimana caranya kalau kita ingin menggerakkan 45 derajat kiri dan kanan ??

  11. 082320911955 says:

    sudah saya coba dan simulasikan di proteus gan , saya ubah nilainya di set_sevo -45 dan 45 tapi tetap aja gan di +90 dan -90, apa ada yg harus diubah di timer1nya atau di programnya saja gan,minta solusinya gan???

  12. arfai says:

    gan itu kenapa harus T=1/250KHz = 4?

  13. Nikko says:

    Itu kalau mau menggerakan dari 90 ke 0 ke -90 itu gmana gan?

    • wangready says:

      tinggal panggil aja fungsinya gan….
      set_servo(90); //set servo ke 90 derajat
      delay_ms(1000); //tahan posisi servo selama 1000ms
      set_servo(0); //set servo ke 0 derajat
      delay_ms(1000); //tahan posisi servo selama 1000ms
      set_servo(-90); //set servo ke -90 derajat
      delay_ms(1000); //tahan posisi servo selama 1000ms

  14. yudhie bacho says:

    saya udah buat seperti yang di atas,,, servonya ada bunyi sedikit,, tapi gak muter,, apa suplai powernya yang kurang ya gan,,,mohon dijawab,,, buat skripsi soalnya

  15. Teguh Bima says:

    bro kok punyaku ga bisa di set sudut ya misal di set sudut 30 tetep masuk sudut 90
    gimana ya?

  16. Numpang nanya saya, pake atmega2560 saya ikutin program diatas lalu coba compile muncul error OCR1A undefined symbol, solusinya gimana ya ? apa saya harus gunain OCR1AH ato OCR1AL untuk deklarasi rumus tersebut?

    • wangready says:

      kok error ya, kalo saya pake CVAVR versi 1.xx bisa sih gan… hmmm mungkin bisa coba pake ini:
      void set_servo(int sudut)
      {
      int ConvertOCR = (((sudut + 90)/90)*1000)/4;
      OCR1AL = convertOCR & 255;
      OCR1AH = convertOCR & ‭65280‬;
      }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s