Minggu, 28 Februari 2016

Membangkitkan PWM (Pulse Width Modulation) pada UC ATMega328

Microcontroller ATMega328 dapat dipergunakan untuk membentuk 3 jenis sinyal PWM, yaitu Fast PWM, Phase Correct PWM, dan Phase and Frequency Correct PWM. Ketiga Mode PWM tersebut diatur dengan menggunakan register TCCR1A (Timer Counter Control Register A 16 bit) dan TCCR1B (Timer Counter Control Register B 16 bit). Bit bit yang membentuk sinyal PWM adalah bit WGM10 dan WGM11 pada register TCCR1A dan bit WGM12 dan WGM13 pada register TCCR1B. Register TCCR1A dan Register TCCR1B diperlihatkan pada gambar 1. Jenis jenis PWM yang dapat dihasilkan dari kombinasi WGM (Waveform Generation Mode) diperlihatkan oleh gambar 2. Catatan penting bagi ketiga sinyal PWM tersebut adalah prinsip kerjanya sama, yaitu OC1x, OCR1A, TCNT1 dan Interrupt Flag. Perbedaan dari ketiga mode PWM tersebut pada timing diagram.
 


Gambar 1. Register TCCR1A dan Register TCCR1B untuk pembentukan PWM
Pada Fast PWM counter menghitung dari BOTTOM sampai TOP kemudian restart lagi dari BOTTOM. Pada mode non-inverting Compare Output, output compare (OC1x) atau OC1A (PortB1) diclearkan pada keadaan compare match terjadi antara TCNT1 dan OCR1A. Pin OC1A (PortB1) akan diset pada saat BOTTOM. Keadaan sebaliknya terjadi pada mode Inverting Compare Output, yaitu pin OC1A akan diset pada keadaan compare match terjadi antara TCNT1 dan OCR1A. Pin OC1A akan diclearkan pada saat BOTTOM.
Fast PWM jika dioperasikan pada mode 5, mode 6 dan mode 7 berdasarkan gambar 2, maka harga counter berturut turut akan mencapai 0x00FF, 0x01FF dan 0x03FF. Tetapi jika dioperasikan pada mode 14 dan mode 15 (berdasarkan gambar 2) maka isi counter akan mencapai maksimun pada ICR1 dan OCR1A masing masing untuk mode 14 dan mode 15. Counter akan diclearkan pada saat pulsa clock berikutnya. Timing diagram untuk fast PWM diperlihatkan pada gambar 3. Interrupt terjadi pada saat OCR1A atau ICR1A mencapai TOP atau dengan kata lain OCR1A atau ICR1A dapat didefinisikan untuk TOP dari counter. Interrupt Flag OC1A akan diset ketika Compare match terjadi.
Frekuensi sinyal PWM diformulakan dengan :

dengan N = prescaler yaitu 1, 8, 64, 256 atau 1024
Sinyal PWM dengan duty cycle 50% diperoleh dengan mengatur OC1A bersifat toggle. Hal ini dapat diperoleh dengan COM1A1/COM1B1 clear dan COM1A0/COM1B0 set.

Gambar 2. Kombinasi bit WGM10, WGM11, WGM12, WGM13 untuk membentuk Sinyal PWM

Timer/Counter Overflow Flag (TOV1) akan diset setiap kali counter mencapai Top. Sebagai tambahan OC1A atau ICF1 Flag diset pada siklus clock pewaktu yang sama sebagaimana halnya TOV1 menjadi set ketika OCR1A atau ICR1 digunakan untuk mendefinisikan TOP. Hal yang patut dicatat adalah proses updating ICR1 berbeda dengan proses updating OCR1A ketika digunakan untuk mendefinisikan TOP. Register OCR1A merupakan double buffer sehingga memungkinkan OCR1A I/O dapat ditulis/diganti setiap saat. Peng-Update-an dilakukan pada siklus clock timer yang sama sebagaimana TCNT1 diclearkan dan TOV1 flag diset. ICR1 merupakan single buffer sehingga tidak dapat di-Update setiap saat seperti OCR1A.
 
Gambar 3. Timing diagram pada Fast PWM. Garis horizontal pada TCNT1 menunjukkan
                  Compare Matches antara OCR1A dan TCNT1

Tabel 1. Compare output mode untuk mengontrol pin OC1A dan pin OC1B

Pada Phase Correct PWM berdasarkan pada gambar 2, maka mode operasi yang dijalankan adalah mode 1, mode 2, mode 3, mode 10 dan mode 11. Timing diagram diperlihatkan gambar 4. Pada gambar 4 ditunjukkan bahwa TOV1 flag terjadi setiap mencapai BOTTOM.
Frekuensi sinyal dari Phase Correct PWM dirumuskan dengan :
 
dengan N = prescaler 1, 8, 64, 256, 1024

 Gambar 4. Timing diagram pada Phase Correct PWM. Garis horizontal pada
                   TCNT1 menunjukkan Compare Matches antara OCR1A dan TCNT1

Frekuensi yang dibangkitkan dari Frekuensi dan Phase Correct PWM adalah :
 
dengan N adalah prescaler yaitu 1, 8, 64, 256, 1024.

Timing diagram diperlihatkan pada gambar 5.

Gambar 5. Timing diagram pada Frekuensi dan Phase Correct PWM. Garis horizontal           pada   
                  TCNT1 menunjukkan Compare Matches antara OCR1A dan TCNT1

Contoh program Fast PWM
// Program Membangkitkan pulsa PWM dengan mode Fast PWM
// Frekuensi Pulsa PWM 30 Hz
// Mempergunakan 16 bit counter, tidak mempergunakan interrupt
// Prescaler yang dipergunakan 256
// UC ATMega328, Frekuensi Kristal 16 MHz

# include <avr/io.h>

int main(void)
{
//Fast PWM mode 15 pada tabel 15.4 hal. 131
TCCR1A |= (1<<WGM10) | (1<<WGM11);
TCCR1B |= (1<<WGM12) | (1<<WGM13);
// PORTB1 atau OC1A sebagai non inverting PWM
// PORTB2 atau OC1B sebagai inverting PWM
// Berdasarkan tabel tabel 15.2 hal. 135
TCCR1B |= (1<<CS12); // Prescaler 256. Tabel 15.5 hal. 137
TCCR1A |= (1<<COM1A1); // OC1A non inverting
TCCR1B |= (1<<COM1B1) | (1<<COM1B0); //OC1B inverting
// Frekuensi Sinyal PWM pada pin OC1A dan OC1B adalah f = F_clk/(N*(1 + TOP))
// TOP dalam hal ini sama dengan OCR1A atau ICRA. Hal. 115 pada definitions
// Isi Register OCR1A = {16.000.000/(30 * 256)} – 1 = 2082
OCR1A = 2082;
OCR1B = 2082;
// Sinyal PWM inverting maupun non Inverting pada pin PB1 dan PB2
// Agar sinyal PWM muncul pada tersebut maka pin PB1 dan pin PB2 dijadikan output
DDRB |= (1<<DDB1) | (1<<DDB2);
while (1)
{
}
return(0);
}

Contoh program mempergunakan interrupt untuk membangkitkan pulsa PWM
// Program Membangkitkan pulsa PWM dengan menggunakan interrupt
// Frekuensi Pulsa PWM 10 Khz, Tampa mempergunakan Prescaler
// Mempergunakan 16 bit counter

// UC ATMega328, Frekuensi Kristal 16 MHz
include <avr/io.h>
include <avr/interrupt.h>

int main(void)
{
TCCR1B |= (1<<CS10);                         //no prescaler, Tabel 15.5, Hal. 137
TCCR1B |= (1<<WGM12);                      // Mode CTC atau Mode 4 pada Tabel 15.4 hal. 136
TIMSK1 |= (1<<OCIE1A)|(1<<OCIE1B);                  // Output Compare IRQ Hal.139
// Harga OCR1A adalah {16.000.000/(10.000*2*1)} – 1 = 800;
OCR1A = 800;
OCR1B = 400;                              // OCR1B diisi tampa hitungan
while (1)
{
}
return (0);
}

ISR(Timer1_CompA_vect)
{
// Routine/perintah untuk vector interrupt dari Output Compare A Match
}

ISR(Timer1_CompB_vect)
{
// Routine/perintah untuk vector interrupt dari Output Compare B Match
}

2 komentar: