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.
Gambar 1. Ilustrasi Sinyal PWM |
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 |
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 |
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);
}
}
}
#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/>
PWM dapat kita manfaatkan untuk merekaya output mikrokontroler seolah-olah menjadi analog sehingga kita dapat mengatur kecepatan motor DC
BalasHapusBenar sekali Mas Aldrin, terimakasih atas informasi tambahannya
Hapussangat membantu, thanks ilmu nya mas
BalasHapus