12 Jan 2017

3
Komentar

AVR PWM dengan Timer0

Bismillaahirrahmaanirrahiim.

Di post kali ini saya akan mencoba menjelaskan secara singkat mengenai PWM atau Pulse Width Modulation dan implementasinya pada mikrokontroler AVR.

Mengenal PWM

PWM adalah cara "mengakali" sinyal digital yang terdiri dari sinyal LOW dan HIGH atau umumnya tegangan 0V dan 5V, menjadi tegangan analog antara 0~5V. Dengan PWM, kita dapat membuat berbagai macam aplikasi yang membutuhkan variasi tegangan analog. Mulai dari dimmer  atau pengatur kecerahan sebuah lampu atau LED, mengatur kecepatan motor, mengatur posisi servo, dan lain sebagainya.

Tutorial PWM Atmega8 Atmega16
Gambar 1. Ilustrasi Sinyal PWM

Pulse Width Modulation atau PWM adalah pengaturan lebar pulsa dalam suatu frekuensi yang konstan. Semakin besar lebar pulsa atau Pulse Width-nya maka tegangan yang dihasilkan semakin mendekati tegangan maksimum, dan juga sebaliknya. Tegangan seakan-akan bervariasi berdasarkan Pulse Width-nya.

Kemudian faktor  lainnya yang perlu diketahui adalah Duty Cycle. Yaitu persentase lebar pulsa HIGH dalam 1 periode. Misal terdapat sinyal PWM dengan periode 10 detik dengan Duty Cycle 25%, artinya sinyal HIGH hanya menyala selama 2.5 detik dari 10 detik.

Nilai Duty Cycle dapat dicari dengan menggunakan rumus berikut :
Duty Cycle = (T_ON / (T_ON + T_OFF)) x 100%

Gambar 2. Sinyal PWM dengan duty cycle 50%

Mengenal Timer

Setelah memahami konsep dasar Pulse Width Modulation, maka tahap selanjutnya adalah bagaimana cara mengimplementasikannya menggunakan mikrokontroler AVR. Seperti yang kita ketahui bahwa PWM berkaitan dengan frekuensi, dengan kata lain: waktu. Maka untuk itu kita dapat memanfaatkan fitur Timer pada AVR.

Timer adalah fitur internal mikrokontroler ATmega yang dapat digunakan untuk aplikasi yang membutuhkan timing. Dengan timer kita bisa mengeksekusi program atau memanggil fungsi pada tiap waktu tertentu.

Selain itu, juga terdapat fitur output compare (OC) dimana hasil pengolahan timer bisa digunakan untuk mengaktifkan sinyal output. Pin output untuk Timer ditandai pada gambar 3.

Gambar 3. Pin OC pada ATmega16

Register Timer0 pada AVR

Dari referensi datasheet ATmega16 [link] di bagian 8-bit Timer/Counter0 with PWM di halaman 83, kita dapat menemukan tabel berikut :

Gambar 4. Tabel Register Timer0

Register tersebut yang akan digunakan dalam mengaktifkan fitur PWM pada Timer0. Kemudian di halaman selanjutnya, terdapat tabel untuk mengaktifkan pin OC0 sebagai output sinyal PWM.

Gambar 5. Alokasi register COM00 dan COM01 untuk Fast PWM Mode

Berikutnya register TCNT0. Register ini digunakan untuk menyimpan counter waktu dari Timer0, dan akan otomatis menghitung apabila register timer diaktifkan. Kemudian Register OCR0 atau Output Compare Register 0, register ini digunakan sebagai pembanding nilai dari TCNT0.

Gambar 6. TCNT0 dan OCR0

Menggunakan Timer0 Untuk PWM

Defaultnya, counter TCNT0 selalu dimulai dari 0. Karena registernya adalah 8-bit. Maka hitungan akan berakhir di nilai 255. Saat itu terjadi counter akan kembali bernilai 0, menghitung lagi hingga bernilai 255 dan seterusnya.

Pada mode normal (non-inverting, lihat gambar 5), nilai TCNT0 akan dibandingkan dengan nilai OCR0. Saat nilai TCNT0 lebih kecil daripada OCR0 maka output dari OC0 adalah aktif HIGH. Sebaliknya, pada saat nilai TCNT0 lebih besar daripada OCR0, maka output OC0 menjadi aktif LOW (Jika menggunakan mode Clear on compare match non-inverting). Berikut ini adalah ilustrasi dari sinyal PWM yang di-generate dengan membandingkan counter TCNT0 dengan nilai OCR0:

Gambar 7. Output Compare

Nilai state dari OC0 ini yang menjadi output PWM. Maka dengan mengatur nilai OCR0, lebar pulsa atau Duty Cycle dari PWM dapat ditentukan. Pada ATmega16, OC0 berada pada pin PB3.

Gambar 8. Output OC0

Mengatur Frekuensi PWM
Perlu dipahami, clock pada timer pada AVR bersumber dari system clock. System Clock adalah sumber clock dari xtall yang digunakan. Karena itu kita juga perlu mengenal prescale, yaitu pembagi system clock untuk digunakan pada Timer

Misalnya kita menggunakan system clock 16MHZ, maka jika kita bagi dengan prescale=64 hasilnya adalah 250KHz. Prescale ini yang menentukan berapa frekuensi PWM di Timer0.

Gambar 9. Tabel Prescale

Program AVR
Berikut ini contoh implementasi program sederhana dari PWM dengan Timer0, dengan Fast-PWM Mode, no-prescale:
#include <stdlib.h>
#include <avr/io.h>

int main()
{
    TCCR0 |= (1<<WGM00) | (1<<WGM01); //Fast PWM Mode
    TCCR0 |= (1<<COM01); //Low jika TCNT0 >= OCR0
    TCCR0 |= (1<<CS00); //No-Prescale
  DDRB |= (1<<PB3); //Set PB3 sebagai Output

  while(1)
   {
     for(int i = 0; i<255; i++)
    {
      OCR0 = i;
      _delay_ms(10);
    }
    }
}

Dari program diatas, nilai pembanding OCR0 bertambah setiap 10ms. Maka nilai Duty Cycle akan bertambah. Jadi jika kita menggunakan LED sebagai output PB3, LED akan menyala redup hingga terang secara perlahan, berulang lagi dan seterusnya. Penutup
Sekian penjelasan mengenai penggunaan PWM Timer0 pada AVR ATmega. Semoga bisa bermanfaat! Salam.

<z/>

Ada 3 tanggapan | Berikan komentarmu!

  1. PWM dapat kita manfaatkan untuk merekaya output mikrokontroler seolah-olah menjadi analog sehingga kita dapat mengatur kecepatan motor DC

    BalasHapus
    Balasan
    1. Benar sekali Mas Aldrin, terimakasih atas informasi tambahannya

      Hapus
  2. sangat membantu, thanks ilmu nya mas

    BalasHapus