12. PWM Pada AVR ATMEGA 16/32/8535
12. PWM Pada AVR ATMEGA 16/32/8535

Operasi PWM

Salah satu fitur yang dimiliki AVR ATmega32/16/8535 adalah adanya PWM (Pulse Width Modulation) yang berfungsi untuk menghasilkan pulsa-pulsa yang dapat diatur lebarnya berdasarkan penggunaan timer/counter yang sudah ada. Pulsa PWM merupakan salah satu cara yang baik dan mudah dalam mengatur kecepatan motor DC, mengatur pemicuan dan penyalaan lampu strobo atau LED misalnya.

PWM menghasilkan amplitudo konstan tetapi lebar pulsanya atau duty cycle berubah-ubah. Duty cycle adalah persentasi waktu pulsa high terhadap periode pulsa.

Dalam mendesain pembangkit sinyal PWM prinsipnya adalah pada timer/counter yang telah dibahas sebelumnya. Pemilihan timer mode PWM diatur melalui bit WGM01 dan bit WGM00 pada register TCCR0.

Keluaran sinyal PWM pada Timer/Counter0 diambil dari pin OC0. Ketika nilai TCNT0 sama dengan nilai OCR0, maka keluaran pin OC0 akan berlogika 0 atau 1 tergantung pada pemilihan mode PWM. Pemilihan mode ini dapat dilakukan baik mode normal atau mode inverted PWM. Pemilihan mode ini diatur melalui bit COM01 dan bit COM00 pada register TOCR0.


Fast PWM Timer/Counter 0

Pada Fast PWM, counter melakukan pencacahan serupa yang dilakukan pada mode normal. Setelah timer mulai diaktifkan maka akan mulai terjadi pencacahan. Pencacahan menaik hingga mencapai batas 0xFF. Ketika terjadi roll over dari 0xFF ke 0x00 maka TOV0 flag akan diset HIGH. 

Fast PWM dalam Timer/Counter0 digunakan untuk mengendalikan waktu ton dan toff melalui isi register pembanding OCR0  yang akan berakibat kepada nilai duty cycle yang dihasilkan. Pin keluaran yang digunakan untuk PWM timer/counter0 adalah pin PB3 (OC0). Dalam mode Fast PWM, karakteristik cacahan register pencacah TCNT0 mencacah dari BOTTOM (0x00) hingga mencacah naik mencapai MAX (0xFF) kemudian mulai dari BOTTOM lagi dan demikian seterusnya. Cacahan ini dinamakan single slope yang mencacah satu arah saja.

Pada mode PWM non-inverting, output pada pin OC0 (PB3) di-clear pada saat compare match (TCNT0=OCR0) dan di-set pada saat BOTTOM (TCNT0=0x00). Pada mode PWM inverting, output pada pin OC0 (PB3) di-set pada saat compare match (TCNT0==OCR0) dan di-clear pada saat BOTTOM (TCNTO=0x00).

Perbedaan Fast PWM non-inverting dan inverting yang dapat dilihat adalah bentuk pulsanya, di mana PWM non-inverting yang dikendalikan adalah lama ton nya melalui isi register OCR0 sedangkan PWM inverting yang dikendalikan adalah lama toff-nya melalui isi register OCR0.

Besarnya frekuensi yang muncul pada pin OC0 (PB3) untuk Fast PWM dihitung menggunakan persamaan 8.1 berikut:

fOCnPWM = fclk_I/O / (N X 256)  ........ (8.1)

fclk_I/O --> frekuensi clock chip yang digunakan,

N --> prescaler sumber clock yang digunakan (1, 8, 64, 256, 1024).

Ketika Timer/Counter0 sedang beroperasi, kita dapat mengubah isi register OCR0 namun efeknya satu siklus pulsa PWM akan tidak simetris.

Untuk menghitung duty cycle Fast PWM0 dengan mode non-inverting digunakan persamaan 8.2 berikut:

DC(F_PWM0)non-inv = [(1+OCR0)/256] x 100% ...... (8.2)

Dengan cara yang serupa maka duty cycle Fast PWM0 dengan mode inverting digunakan persamaan 8.3:

DC(F_PWM0)inv = [(255 – OCR0)/256] x 100% ......... (8.3)

Pada Gambar kita dapat melihat reaksi pembangkit gelombang jika terjadi compare match ketika timer dalam mode Fast PWM.

.

Contoh 1

Hitunglah nilai OCR0 untuk membangkitkan gelombang dengan duty cycle 75%

SOLUSI:

DC(F_PWM0)non-inv = [(1+OCR0)/256] x 100%
75% = [(1 + OCR0)/256] x 100% --> 1 + OCR0 = 192

OCR0 = 191 (0xBF)

.

Contoh 2

Tentukanlah nilai TCCR0 untuk menginisialisasi . Timer0 mode Fast PWM0, pembangkit gelombang PWM0 non-inverting, dan tanpa prescaler.

SOLUSI:

Dengan merujuk pada Gambar , maka diperoleh sbb:

WGM01:00 = 11 = mode Fast PWM0,        CS02:00 = 001 = tanpa prescaler

COM01:00 = 10 = PWM0 non-inverting

Jadi nilai register TCCR0 = 0x69

.

.

Contoh 3

Buatlah sebuah program Fast PWM0 Timer0  yang membangkitkan gelombang dengan frekuensi 31,25 kHz dan duty cycle 75% non-inverting. Gunakan kristal 8 MHz.

SOLUSI:

fOC0PWM = fclk_I/O / (N X 256)

31250Hz = 8000000Hz/(N X 256) --> N = 1.

Karena diperoleh N=1,   berarti tanpa prescaler

Program:

.

#include <avr/io.h>

int main ()
{
	DDRB |= (1<<3);//inisialisasi PB3 sebagai output
	OCR0 = 191;//nilai 191 berasal dari contoh 1 (duty cycle 75%)
	TCCR0 = 0x69;//nilai 0x69 berasal dari contoh 2

	while (1)//mode Fast PWM, tanpa prescaler dan non-inverting
	return 0;
}

Hasil Pada Oscilloscope:

.

Video Demo:

.

.

Contoh 4

Buatlah sebuah program Fast PWM Timer0 yang membangkitkan gelombang dengan frekuensi 3,90625 kHz dan duty cycle 37,5% non-inverting. Gunakan kristal 8 MHz.

SOLUSI:

fOC0PWM = fclk_I/O /(N x 256)

3906,25Hz = 8000000Hz/(N X 256) --> N = 8 (berarti prescaler = 8)

DC(F_PWM0)non-inv = [(1+OCR0)/256 x 100%

37,5% = [(1 + OCR0)/256] x 100%→ 1 + OCR0 = 96 →

OCR0 = 95

Dengan merujuk pada Gambar, maka diperoleh sbb:

WGM01:00 = 11 = mode Fast PWM0  CS02:00 = 010 = prescaler 8

COM01:00 = 10 = PWM0 non-inverting

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRB |= (1<<3);//inisialisasi PB3 sebagai output
	OCR0 = 95;//nilai OCR0 (duty cycl 37,5%)

	TCCR0 = 0x6A;//nilai 0x6A berasal dari contoh 8.2

	while (1)//mode Fast PWM, dengan prescaler 8 dan non-inverting
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.

.

Contoh 5

Ulangi Contoh 4 di atas tapi dengan mode inverting.

SOLUSI:

fOC0PWM = fclk_I/O /(N x 256)

3906,25Hz = 8000000Hz/(N X 256) --> N = 8 (berarti prescaler = 8)

DC(F_PWM0)inv = [(255 – OCR0)/256] x 100%

37,5% = [(255 – OCR0)/256] x 100% à 255 – OCR0 = 96 →

OCR0 = 159

Dengan merujuk pada Gambar, maka diperoleh sbb:

WGM01:00 = 11 = mode Fast PWM0  CS02:00 = 010 = prescaler 8

COM01:00 = 11 = PWM0 inverting

.

Program:

.

#include <avr/io.h>
int main()
{
	DDRB |= (1<<3);//inisialisasi PB3 sebagai output
	OCR0 = 159;//nilai OCR0 = 159 (duty cycle 37,5%)

	TCCR0 = 0x7A;//mode Fast PWM, dengan prescaler 8 dan inverting
	while (1)

	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.


Phase Correct PWM Timer/Counter 0

Pada kondisi COM01 =  '1' dan COM00 = '0', maka pin OC0 clear pada Compare Match ketika mencacah naik dan pin OC0 set pada Compare Match ketika mencacah turun. Gelombang ini disebut non-inverting PWM. Sebaliknya jika COM01 = '1' dan COM00 = '1', maka pin OC0 set pada Compare Match ketika mencacah naik dan pin OC0 clear pada Compare Match ketika mencacah turun. Gelombang ini disebut inverting PWM.

Besarnya frekuensi phase correct PWM Timer/Counter0 dihitung dengan menggunakan persamaan 8.4.

fOCnPCPWM0 = fclk_I/O / (N x 510)............. (8.4)

 fclk_I/O --> adalah frekuensi clock chip yang digunakan,

N --> prescaler sumber clock yang digunakan (1, 8, 64, 256, 1024).

Ketika Timer/Counter0 sedang beroperasi, kita dapat mengubah isi register OCR0 namun efeknya satu siklus pulsa PWM akan tidak simetris. Untuk menghitung duty cycle Phase Correct PWM non-inverting digunakan persamaan 8.5 berikut:

DC(PC_PWM0)non-inv = (OCR0/255) x 100% ............. (8.5)

Dengan cara yang serupa maka duty cycle Phase Correct PWM0 dengan mode inverting digunakan persamaan 8.6 berikut:

DC(PC_PWM0)inv = [(255-OCR0)/255] x 100% ......... (8.6)

Pada Gambar di bawah kita dapat melihat reaksi pembangkit gelombang jika terjadi compare match ketika timer dalam mode Phase Correct PWM.

.

.

Contoh 6

Tentukanlah nilai TCCR0 untuk menginisialisasi Timer0 mode Phase Correct PWM0, pembangkit gelombang PWM0 non-inverting, dan tanpa prescaler. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 15,686 kHz dan duty cycle 75%. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

fOC0PCPWM = fclk_I/O / (N x 510)

15686 =  8000000 / (N x 510) --> N = 1 (tanpa prescaler).

DC(PC_PWM0) non-inv = (OCR0/255) x 100%

75% = (OCR0 / 255) x 100% → OCR0 = 191

Dengan merujuk pada Gambar , maka diperoleh sbb:

WGM01:00 = 01 = mode Phase Correct PWM0

CS02:00 = 001 = tanpa prescaler

COM01:COM00 = 10 = non-inverting

Jadi nilai register TCCR0 = 0x61.

.

Program:

.

#include <avr/io.h>
int main()
{
	DDRB |= (1<<3);//inisialisasi PB3 (OC0) sebagai output
	OCR0 = 191;//nilai OCR0 (duty cycle 75%)
	TCCR0 = 0x61;//Phase Correct PWM, non-inverting, tanpa prescaler
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.

Contoh 7

Tentukanlah nilai TCCR0 untuk menginisialisasi Timer0 mode Phase Correct PWM, pembangkit gelombang PWM inverting, dan dengan prescaler. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 61 Hz dan duty cycle 87,5%. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

fOC0PCPWM = fclk_I/O / (N x 510)

61 =  8000000 / (N x 510) --> N = 256 (prescaler 256).

DC(PC_PWM0) inv = (255 - OCR0 / 255) x 100%

87,5% = ((255 - OCR0) / 255) x 100% → OCR0 = 32

Dengan merujuk pada Gambar , maka diperoleh sbb:

WGM01:00 = 01 = mode Phase Correct PWM0

CS02:00 = 100 = prescaler 256

COM01:COM00 = 11 = PWM0 inverting

Jadi nilai register TCCR0 = 0x74.

.

Program:

.

#include <avr/io.h>
int main()
{
	DDRB |= (1<<3);//inisialisasi PB3 (OC0) sebagai output
	OCR0 = 32;//nilai OCR0 (duty cycle 87,5%)
	TCCR0 = 0x74;//Phase Correct PWM, inverting, prescaler 256
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.


Fast PWM Timer/Counter 1

Terdapat lima macam mode Fast PWM pada Timer1 yaitu: mode 5, 6, 7, 14, dan 15. Pada mode 5, 6, dan 7 nilai puncaknya berturut-turt adalah 0xFF, 0x1FF, dan 0x3FF; sedangkan pada mode 14 dan 15 nilai puncaknya berturut-turut berada pada register ICR1 dan OCR1A (lihat Gambar (a) sampai (f)).

Pada mode 5, 6 dan 7 yang mempunyai nilai puncak tetap, TOV1 flag akan di-set jika timer dalam keadaan roll over (lihat Gambar (b), (c), dan (d)).

Mode 14 mempunyai nilai puncak yang dinyatakan oleh ICR1. Status dari ICF1 flag akan di-set jika timer dalam keadaan roll over (lihat Gambar (e)).

Mode 15 mempunyai nilai puncak yang dinyatakan oleh OCR1A. Status dari OCF1A flag akan di-set jika timer dalam keadaan roll over (lihat Gambar (f)).

Fast PWM dalam Timer/Counter1 digunakan untuk mengendalikan waktu t on dan off melalui isi register pembanding OCR1A atau OCR1B yang berakibat kepada nilai duty cycle yang dihasilkan.

Pin keluaran yang digunakan untuk PWM timer/counter1 adalah pin OC1A (PD5) atau OC1B (PD4). Dalam mode Fast PWM, karakteristik cacahan register pencacah TCNT1 mencacah dari BOTTOM (0x0000) hingga mencacah naik mencapai TOP (nilai maksimal yang ditentukan berdasarkan resolusi yang dikehendaki, misalnya resolusinya 10-bit maka nilai TOP=0x01FF) kemudian mulai dari BOTTOM lagi dan demikian seterusnya, Cacahan ini dinamakan single slope yang mencacah satu arah saja.

Pada mode non-inverting, kanal keluaran PWM pin OC1x di-clear pada saat compare match (TCNT1=OCRx) dan di-set ketika BOTTOM (TCNT1=0x0000).

Pada mode inverting, kanal keluaran PWM pin OC1x di-set pada saat compare match (TCNT1=OCRx) dan di-clear ketika BOTTOM (TCNT1=0x0000).

PWM non-inverting yang dikendalikan adalah lama t on nya melalui isi register OCR1x sedangkan PWM inverting yang dikendalikan adalah lama t off nya melalui isi register OCR1x.

Besarnya frekuensi Fast PWM Timer/Counter1 dihitung menggunakan persamaan 8.7.

fOCnxPWM1 = fclk_I/O / N.(TOP + 1) ............(8.7)

fclk_I/O --> frekuensi clock chip yang digunakan,

N --> prescaler sumber clock yang digunakan (1, 8, 64, 256, 1024).

Untuk menghitung duty cycle Fast PWM1 non-inverting digunakan persamaan 8.8 berikut:

DC(F_PWM1)non-inverting = [(OCR1x +  1)/(TOP+1)] x 100% ....... (8.8)

Untuk menghitung duty cycle Fast PWM1 inverting digunakan persamaan 8.9 berikut:

DC(F_PWM1)inverting = [(TOP - OCR1x)/(TOP+1)] x 100% ....... (8.9)

.

Pada Gambar di bawah kita dapat lihat bagaimana pembangkit gelombang ketika terjadi compare match pada saat timer dalam mode Fast PWM.

Ketika COM1A1:0 = 00 maka pin OC1A bekerja sebagai port I/O. Ketika COM1A1:0 = 10, maka pembangkit gelombang men-clear pin OC1A kapanpun compare match terjadi, dan akan set ketika berada pada nilai puncak. Mode ini disebut Fast PWM non-inverting (lihat Gambar di bawah). Dari Gambar ini kita dapat melihat semakin besar nilai OCR1A maka nilai duty cycle juga semakin besar.

Ketika COM1A1:0 = 11, maka pembangkit gelombang men-set pin OC1A kapanpun compare match terjadi, dan akan clear ketika berada pada nilai puncak. Mode ini disebut Fast PWM inverting. Dari Gambar ini kita dapat melihat semakin besar nilai OCR1A maka nilai duty cycle semakin kecil.

Hal yang sama juga terjadi pada register OCR1B dan bit COM1B1:0

.

Contoh 8

Hitunglah nilai untuk register OCR1A untuk membangkitkan gelombang Fast PWM1 dengan duty cycle 75% untuk setiap mode berikut:

(a) Mode 5 non-inverting

(b) Mode 6 non-inverting

(c) Mode 7 non-inverting

(d) Mode 5 inverting

(e) Mode 7 inverting

SOLUSI:

(a) Pada mode 5: TOP = 0xFF = 255

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_ PWM)non-inverting = [(OCR1x +1)/(TOP+1)] x 100%

-->75% = [(OCR1x +1)/(255+1)] x 100%

→ OCR1A = 191

(b) Pada mode 6: TOP = 0x1FF = 511

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8) :

DC(F_PWM1)non-inverting = [(OCR1x +1)/(TOP+1)] x 100%

-->75% = [(OCR1x +1)/(511+1)] x 100%

→ OCR1A = 383


(c) Pada mode 7: TOP = 0x3FF = 1023

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_PWM1)non-inverting = [(OCR1x +1)/(TOP+1)] x 100%

→ 75% = [(OCR1x +1)/(1023+1)] x 100%

→ OCR1A = 767

(d) Pada mode 5: TOP = 0xFF = 255

Untuk menghitung duty cycle mode inverting digunakan persamaan (8.9):

DC(F_PWM1)inverting = [(TOP - OCR1x)/(TOP+1)] x 100%

→ 75% = [(255 - OCR1x)/(255+1)] x 100%

→ OCR1A = 63

 (e) Pada mode 7: TOP = 0x3FF = 1023

Untuk menghitung duty cycle mode inverting digunakan persamaan (8.9):

DC(F_PWM1)inverting = [(TOP - OCR1x)/(TOP+1)] x 100%

→ 75% = [(1023 - OCR1x)/(1023+1)] x 100%

 → OCR1A = 255

.

Contoh 9

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Timer1 mode Fast PWM1, pembangkit gelombang PWM1 non-inverting mode 5. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 31,250 KHz dan duty cycle 75%. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

Untuk menghitung nilai prescaler digunakan persamaa (8.7):

Pada mode 5: TOP = 0xFF 255

fOCnxPWM1 = fclk_I/O / [N x (TOP + 1)]

31250 = 8000000 / [(N * (255+1)] → N = 1 (tanpa prescaler).

 → Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_PWM1)non-inverting = [(OCR1x +1)/(TOP+1)] x 100%

 75% = [(OCR1x +1)/(255+1)] x 100%

→ OCR1A = 191

--> Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 0101 = Fast PWM1 mode 5  

CS12:10 = 001 = tanpa prescaler COM1A0:1A0 = 10 = PWM1 non-inverting

Jadi nilai register TCCR1A = 0x81 dan TCCR1B = 0x09

.

Program:

.

/*
 * 6 contoh 9 slide.c
 *
 * Created: 20/12/2022 9:05:28
 * Author : DELL
 */ 

#include <avr/io.h>


int main(void)
{
	DDRD |= (1<<5); //inisialisasi PORT PD5 sebagai output
	OCR1AH = 0;
	OCR1AL = 191; //nilai OCRIAH (duty cycle 75%)
	TCCR1A = 0x81; //Fast PWM1 mode 5, non-inverting, tanpa prescaler
	TCCR1B = 0x09; //(terdapat pada TCCR1A dan TCCR1B)
	
    /* Replace with your application code */
    while (1) 
    return 0;
}

.

Hasil Pada Oscilloscope:

Video Demo:

.

.

Contoh 10

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Timer1 mode Fast PWM1, pembangkit gelombang PWM1 non-inverting mode 6. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 1,953 KHz dan duty cycle 60%. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

→ Untuk menghitung nilai prescaler digunakan persamaa (8.7):

Pada mode 6: TOP = 0x1FF = 511

fOCnxPWM1 = fclk_I/O/ [N * (TOP + 1)]

1953 = 8000000 / [(N (511+1)] → N = 8 (berarti prescaler 8).

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_PWM 1) non-inverting = [(OCR1x +1)/(TOP+1)] x 100%

→ 60% = [(OCR1x +1)/(511+1)] x 100%

--> OCR1A = 306

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 0110 = Fast PWM1 mode 6  

CS12:10 = 010 = prescaler 8

COM1A1:1A0 = 10 = PWM1non-inverting

Jadi nilai register TCCR1A = 0x82 dan TCCR1B = 0x0A

.

Program:

.

#include <avr/io.h>

int main ()
{
	DDRD |= (1<<5); //inisialisasi PORT PD5 sebagai output
	OCR1AH = 306 >> 8; //nilai OCRIAH (duty cycle 60%)
	OCR1AL = 306; //nilai OCR1AL (duty. cycle 60%)
	TCCR1A = 0x82; //Fast PWM1 mode 6, non-inverting, prescaler
	TCCR1B = 0x0A; //(terdapat pada TCCR1A dan TCCR1B)
	while (1)
	return 0;
}

Hasil Pada Oscilloscope:

.

Video Demo:

.

.

Contoh 11

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Timer1 mode Fast PWM1, pembangkit gelombang PWM1 non-inverting mode 7. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 7,8125 KHz dan duty cycle 75%. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

→ Untuk menghitung nilai prescaler digunakan persamaa (8.7):

Pada mode 7:  TOP = 0x3FF = 1023

fOCnxPWM1 = fclk_I/O / [N * (TOP + 1)]

7812,5 = 8000000 / [(N X (1023+1)] + N = 1 (tanpa prescaler).

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_PWM 1) non-inverting = [(OCR1x +1)/(TOP+1)] x 100%

75% = [(OCR1x +1)/(1023+1)] x 100%

→ OCR1A = 767

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 0111 = Fast PWM1 mode 7  

CS12:10 = 001 = tanpa prescaler

COM1A1:1A0 = 10 = PWM1non-inverting

Jadi nilai register TCCR1A = 0x83 dan TCCR1B = 0x09

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRD |= (1<<5); //inisialisasi PORT PD5 sebagai output
	OCR1AH = 767>>8; //nilai OCR1AH (duty cycle 75%)
	OCR1AL = 767; //nilai OCRIAL (duty cycle 75%)
	TCCR1A = 0x83; //Fast PWM1 mode 7, non-inverting, tanpa prescaler
	TCCR1B = 0x09; //(terdapat pada TCCR1A dan TCCR1B)
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.

.

Contoh 12

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Timer1 mode Fast PWM1, pembangkit gelombang PWM1 inverting mode 6. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 1,953 KHz dan duty cycle 60%. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

→ Untuk menghitung nilai prescaler digunakan persamaa (8.7):

Pada mode 7:  TOP = 0x1FF = 511

fOCnxPWM1 = fclk_I/O / [N * (TOP + 1)]

1953 = 8000000 / [(N x (511+1)] → N = 8 (berarti prescaler 8).

Untuk menghitung duty cycle mode inverting digunakan persamaan (8.9):

DC(F_PWM 1) inverting = [(TOP - OCR1x)/(TOP+1)] x 100%

→ 60% = [(511 - OCR1x)/(511+1)] x 100%

→ OCR1A = 204

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 0110 = Fast PWM1 mode 6  

CS12:10 = 010 = prescaler 8

COM1A1:1A0 = 11 = PWM1 inverting

Jadi nilai register TCCR1A = 0xC2 dan TCCR1B = 0x0A

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRD |= (1<<5); //inisialisasi PORT PD5 sebagai output
	OCR1AH = 204>>8; //nilai OCR1AH (duty cycle 60%)
	OCR1AL = 204; //nilai OCRIAL (duty cycle 60%)
	TCCR1A = 0xC2; //Fast PWM1 mode 6, inverting, prescaler 8
	TCCR1B = 0x0A; //(terdapat pada TCCR1A dan TCCR1B)
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.

.

Karena nilai puncak (TOP) untuk mode 5, 6 dan 7 bersifat tetap, maka berdasarkan persamaan fOCnxPWM1 = fclk_I/O / [N x (TOP + 1) ] berarti nilai frekuensi gelombang yang dapat diperoleh hanya tergantung pada nilai prescaler N. Sehingga tidak semua frekuensi yang kita inginkan dapat diakomodasi oleh mode 5, 6, dan 7 (frekuensi ini dapat diperoleh dari Tabel di bawah).

Jika kita menginginkan frekuensi gelombang lebih banyak pilihannya, maka dapat digunakan mode 14 atau mode 15 di mana nilai puncaknya ditetapkan pada ICR1 dan register OCR1A. Jadi kita dapat mengubah nilai frekuensi dengan cara mengisi nilai tertentu ke dalam ICR1 dan OCR1A.

.

Contoh 13

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Timer1 mode Fast PWM1, pembangkit gelombang PWM1 non-inverting mode 14. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 80 KHz dan duty cycle 20%. Anggap kristal yang digunakan 8MHz.

SOLUSI:

→ Untuk menghitung nilai prescaler digunakan persamaa (8.7):

Pada mode 7:  TOP = ICR1

fOCnxPWM1 = fclk_I/O / [N * (TOP + 1)]

80000 = 8000000 / [(N x (TOP+1)] → N x (TOP+1) = 100

jika diambil N = 1 maka diperoleh TOP = 99 = ICR1.

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_PWM 1) non-inverting = [(OCR1x + 1)/(TOP+1)] x 100%

--> 20% = [(OCR1x + 1)/(99+1)] x 100%   (dengan OCR1x = OCR1A)

--> OCR1A = 19

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 1110 = Fast PWM1 mode 14  

CS12:10 = 001 = prescaler 1

COM1A1:1A0 = 10 = PWM1non-inverting

Jadi nilai register TCCR1A = 0x82 dan TCCR1B = 0x19

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRD |= (1<<5); //inisialisasi PORT PD5 sebagai output
	ICR1H = 0x00;
	ICR1L = 99;
	OCR1AH = 0; //nilai OCR1AH (duty cycle 20%)
	OCR1AL = 19; //nilai OCR1AL (duty cycle 20%)
	TCCR1A = 0x82; //Fast PWM1 mode 14, non-inverting, tanpa prescaler
	TCCR1B = 0x19; //(terdapat pada TCCR1A dan TCCR1B)
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.

Jika kita menggunakan mode 15 sebagai pengganti mode 14, maka OCR1A di-buffer dan isi dari buffer akan di-load ke dalam OCR1A jika timer mencapai nilai puncak. Pada mode 15 kita hanya dapat menggunakan pembangkit gelombang OC1B sedangkan pembangkit gelombang OC1A tidak bisa karena register OCR1A digunakan untuk penetapan nilai puncak.

.

Contoh 14

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Timer1 mode Fast PWM1, pembangkit gelombang PWM1 non-inverting mode 15. Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 64 KHz dan duty cycle 20%. Anggap kristal yang digunakan 8MHz.

SOLUSI:

→ Untuk menghitung nilai prescaler digunakan persamaa (8.7):

Pada mode 7:  TOP = OCR1A

fOCnxPWM1 = fclk_I/O / [N * (TOP + 1)]

64000 = 8000000 / [(N x (TOP+1)] → N x (TOP+1) = 125 jika diambil N = 1 maka diperoleh TOP = 124 = OCR1A.

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.8):

DC(F_PWM 1) non-inverting = [(OCR1x + 1)/(TOP+1)] x 100%

→ 20% = [(OCR1x + 1)/(124+1)] x 100%  (dengan OCR1x = OCR1B)

→ OCR1B = 24

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 1111 = Fast PWM1 mode 15

CS12:10 = 001 = prescaler 1

COM1B1:1B0 = 10 = PWM1 non-inverting

Jadi nilai register TCCR1A = 0x23 dan TCCR1B = 0x19

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRD |= (1<<4); //inisialisasi PORT PD4 sebagai output
	OCR1AH = 0x00;
	OCR1AL = 124;
	OCR1BH = 0; //nilai OCR1AH (duty cycle 20%)
	OCR1BL = 24; //nilai OCR1AL (duty cycle 20%)
	TCCR1A = 0x23; //Fast PWM1 mode 15, non-inverting, tanpa prescaler
	TCCR1B = 0x19; //(terdapat pada TCCR1A dan TCCR1B)
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.


Phase Correct PWM Timer/Counter 1

Timer mencacah naik hingga mencapai nilai puncak, kemudian mencacah turun hingga mencapai nol. Flag TOV1 akan set jika timer kembali ke nol. Ada lima mode phase correct PWM1 yaitu mode 1, 2, 3, 10 dan 11.

Pada mode non-inverting, kanal keluaran PWM pin OC1x di-clear pada saat compare match (TCNT1=OCRx) dalam keadaan counting up dan di-set pada saat compare match dalam keadaan counting down.

Pada mode inverting, kanal keluaran PWM pin OC1x di-set pada saat compare match (TCNT1==OCRx) dalam keadaan counting up dan di-clear pada saat compare match dalam keadaan counting down.

Besarnya frekuensi phase correct PWM timer/counter1 dihitung menggunakan persamaan 8.10.

fOCnxPCPWM = fclk_I/O / 2.N.TOP .......(8.10)

Untuk menghitung duty cycle Phase Correct PWM1 mode non-inverting digunakan persamaan 8.11:

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100% ...... (8.11) :

Sedangkan untuk menghitung duty cycle Phase Correct PWM1 mode inverting digunakan persamaan 8.12:

DC(PC_PWM1)inverting = [(TOP - OCR1x)/TOP] x 100%..... (8.12)

TOP = nilai maksimum counter (TCNT1), TOP mempunyai 3 buah nilai untuk ketiga mode tersebut yaitu 8 bit (FF), 9 bit (1FF) dan 10 bit (3FF).

Pada Gambar diberikan nilai puncak untuk phase correct PWM1 mode 1, 2 dan 3 yaitu berturut-turut 0xFF, 0x1FF, dan 0x3FF.

Untuk mode 10 nilai puncaknya ditetapkan pada register ICR1, sedangkan untuk mode 11 pada register OCR1A. Reaksi pembangkit gelombang ketika compare match terjadi pada mode Phase Correct PWM1 dapat dilihat pada Gambar.

Pada saat COM1A1:00 = 00 maka pin OC1A berfungsi sebagai port I/O. Jika COM1A1:00= 10, maka pembangkit gelombang akan men-clear pin OC1A pada compare match ketika terjadi pencacahan naik, dan akan men-set pin OC1A pada compare match ketika terjadi pencacahan turun. Mode inilah yang disebut non-inverting. Pada Gambar dapat kita lihat untuk mode non-inverting bahwa duty cycle akan bertambah jika nilai OCR1A bertambah.

Pada saat COM1A1:00 = 11, maka pembangkit gelombang akan men-set pin OC1A pada compare match ketika terjadi pencacahan naik, dan akan men-clear pin OC1A pada compare match ketika terjadi pencacahan turun. Ini disebut mode inverting.

Pada Gambar dapat kita lihat untuk mode inverting bahwa duty cycle akan berkurang jika nilai OCR1A bertambah.

Hal yang sama terjadi pada register OCR1B dan bit COM1B1:10.

.

.

Contoh 15

Hitunglah nilai untuk register OCR1B untuk membangkitkan gelombang Phase Correct PWM1 dengan duty cycle 75% untuk setiap mode berikut:

a) Mode 1 non-inverting

b) Mode 2 non-inverting

c) Mode 1 inverting

d) Mode 2 inverting

e) Mode 3 inverting

SOLUSI:

(a) Pada mode 1: TOP = OxFF = 255

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.11):

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100%

→ 75% (OCR1x/255) x 100%

→ OCR1B = 191

(b) Pada mode 2: TOP = 0x1FF = 511

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.11):

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100%

--> 75% = (OCR1x/511) x 100%

--> OCR1B = 383

(c) Pada mode 1: TOP = 0xFF = 255

Untuk menghitung duty cycle mode inverting digunakan persamaan (8.12):

DC(PC_PWM1)inverting = [(TOP - OCR1x)/TOP] x 100%

→ 75% = [(255 - OCR1x)/255] x 100%

--> OCR1B = 64

(d) Pada mode 2: TOP = 0x1FF = 511

Untuk menghitung duty cycle mode inverting digunakan persamaan (8.12):

DC(PC_PWM1)inverting = [(TOP - OCR1x)/TOP] x 100%

→ 75% =  [(511- OCR1x)/ 511] x 100%

-->OCR1B = 128

(e) Pada mode 3: TOP = 0x3FF = 1023

Untuk menghitung duty cycle mode inverting digunakan persamaan (8.12)

DC(PC_PWM1)inverting = [(TOP - OCR1x)/TOP] x 100%

→ 75% = [(1023- OCR1x)/1023] x 100%

→ OCR1B = 255

.

.

Contoh 16

Tentukanlah nilai TCCR1A dan TCCR1B untuk menginisialisasi Phase Correct PWM, pembangkit gelombang PWM1 non-inverting mode 1 (nilai TOP=0xFF). Kemudian buatlah program yang membangkitkan gelombang tersebut yang frekuensinya 15,686KHz dan duty cycle 75%. Anggap kristal yang digunakan 8 MHZ.

SOLUSI:

Untuk menghitung nilai prescaler digunakan persamaan (8.10):

Pada mode 1: TOP = 255

fOCnxPCPWM = fclk_I/O / (2 x N x TOP)

15686 = 8000000 / (2 x N x 255) à N = 1

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.11):

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100%

--> 75% = [(OCR1x +1)/(255+1)] x 100%

→ OCR1B = 191

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 0001 = Phase Correct PWM1 mode 1

CS12:10 = 001 = prescaler 1

COM1A1:1A0 = 10 = PWM1non-inverting

Jadi nilai register TCCR1A = 0x81 dan TCCR1B = 0x01

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRD |= (1<<5); //inisialisasi PORT PD5 (OC1A) sebagai output
	OCR1AH = 0x00;
	OCR1AL = 191;
	TCCR1A = 0x81; //Phase Correct PWM1l mode 1, non-inverting, N=1
	TCCR1B = 0x01; //(terdapat pada TCCRIA dan TCCR1B)
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

Video Demo:

.

Karena nilai puncak (TOP) untuk mode 1, 2 dan 3 bersifat tetap, maka berdasarkan persamaan fOCnxPWM1 = fclk_I/O / (2 N x TOP) berarti nilai frekuensi gelombang yang dapat diperoleh hanya tergantung pada nilai prescaler N. Sehingga tidak semua frekuensi yang kita inginkan dapat diakomodasi oleh mode 1, 2, dan 3 (frekuensi ini dapat diperoleh dari Tabel).

Jika kita menginginkan frekuensi gelombang lebih banyak pilihannya, maka dapat digunakan mode 10 atau mode 11 di mana nilai puncaknya ditetapkan pada ICR1 dan register OCR1A. Jadi kita dapat mengubah nilai frekuensi dengan cara mengisi nilai tertentu ke dalam ICR1 dan OCR1A.

Contoh 17

Hitunglah nilai untuk register OCR1B untuk membangkitkan gelombang  Correct PWM1 untuk setiap mode berikut:

a) Mode 10 non-inverting, ICR1 = 250, duty cycle 30%

b) Mode 10 non-inverting, ICR1 = 250, duty cycle 60%

c) Mode 11 inverting, OCR1A = 50, duty cycle 30%

SOLUSI:

(a) Pada mode 10: TOP = ICR1 = 250

Untuk menghitung duty cycle mode non-inverting digunakan persamaan (8.11):

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100%

--> 30% = (OCR1x/(250) x 100%

→ OCR1B = 75

(b) Pada mode 10: TOP = ICR1 = 250

Untuk menghitung duty cycle mode NON-INVERTING digunakan persamaan (8.11):

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100%

--> 60% = (OCR1x/(250) x 100%

→ OCR1B = 150

(c) Pada mode 11: TOP = OCR1A = 50

Untuk menghitung duty cycle mode INVERTING digunakan persamaan (8.12):

DC(PC_PWM1) inverting = [(TOP - OCR1x)/TOP] x 100%

--> 30% = [(50 - OCR1x)/50] x 100%

→ OCR1B = 35

.

.

Contoh 18

Buatlah program dengan menggunakan Phase Correct PWM1 mode 10 untuk membangkitkan gelombang 62,5Hz dengan duty cycle 30% dan 60% berturut-turut pada pin OC1A dan OC1B. Gunakan prescaler 256. Anggap kristal yang digunakan 8 MHz.

SOLUSI:

→ Untuk menghitung nilai prescaler digunakan persamaan (8.10):

Pada mode 10: fOCnxPCPWM = fclk_I/O / (2 x N x TOP)

untuk N = 256:

→ 62,5 = 8000000 / (2 x 256 x TOP) → TOP = 250

Untuk menghitung duty cycle mode NON-INVERTING digunakan persamaan (7.11):

DC (PC_PWM1) non-inverting = (OCR1x/TOP) x 100%

→ 30% = (OCR1x/(250) x 100%

→ OCR1A = 75 (PORT PD5)

DC(PC_PWM1)non-inverting = (OCR1x/TOP) x 100%

--> 60% = (OCR1x/250) x 100%

--> OCR1B = 150 (PORT PD4)

Dengan merujuk pada TCCR1A dan TCCR1B, maka diperoleh sbb:

WGM13:10 = 1010 = Phase Correct PWM1 mode 10,  

CS12:10 = 100 → N=256

COM1A1:1A0 = 10 = PWM1non-inverting

COM1B1:1B0 = 10 = PWM1non-inverting

Jadi nilai register TCCR1A = 0xA2 dan TCCR1B = 0x14

.

Program:

.

#include <avr/io.h>
int main ()
{
	DDRD = DDRD | (1<<5) | (1<<4); //inisialisasi PORTD PD5 dan PD4 sebagai output
	OCR1AH = 0x00;
	OCR1AL = 75;
	OCR1BH = 0x00;
	OCR1BL = 150;
	ICR1H = 0x00;
	ICR1L = 250;
	TCCR1A = 0xA2; //Phase Correct PWMl mode 10, non-inverting, N=256
	TCCR1B = 0x14; //(terdapat pada TCCR1A dan TCCR1B)
	while (1)
	return 0;
}

.

Hasil Pada Oscilloscope:

.

.

Video Demo:

.

.

.

Contoh 19:

Program di bawah ini digunakan untuk mengendalikan kecepatan motor DC (OC 0) dengan potensiometer yang dihubungkan dengan kaki ADC 0 disertai dengan switch PB. 1 yang digunakan untuk membalik arah putaran motor DC yang terletak pada PB.2.

#define F_CPU 8000000UL			/* Define CPU Frequency 8MHz */
#include <avr/io.h>			/* Include AVR std. library file */
#include <avr/interrupt.h>
#include <stdio.h>			/* Include std. library file */
#include <util/delay.h>			/* Include Delay header file */

volatile uint8_t Direction = 0;

void ADC_Init()				/* ADC Initialization function */
{
	DDRA = 0x00;			/* Make ADC port as input */
	ADCSRA = 0x87;			/* Enable ADC, with freq/128 */
	ADMUX = 0x40;			/* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)		/* ADC Read function */
{
	ADMUX = 0x40 | (channel & 0x07);/* set input channel to read */
	ADCSRA |= (1<<ADSC);		/* Start ADC conversion */
	while (!(ADCSRA & (1<<ADIF)));	/* Wait until end of conversion */
	ADCSRA |= (1<<ADIF);		/* Clear interrupt flag */
	_delay_ms(1);			/* Wait a little bit */
	return ADCW;			/* Return ADC word */
}



int main(void)
{
	DDRB |= (1<<PB3);		/* Make OC0 pin as Output */ // PWM
	DDRB |= (1<<PB2);   /// DIR
	PORTB |= (1<<PB1);   /// SW7
	
	ADC_Init();			/* Initialize ADC */
	TCNT0 = 0;			/* Set timer0 count zero */
	TCCR0 = (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00)|(1<<CS01);/* Set Fast PWM with Fosc/64 Timer0 clock */
	while(1)
	{
		if (bit_is_clear(PINB, 1))	/* Rotate DC motor Clockwise */
			PORTB |= (1<<PB2);
		else			/* Else rotate DC motor Anticlockwise */
			PORTB &= ~(1<<PB2);
		
		
		OCR0 = (ADC_Read(0)/4);	/* Read ADC and map it into 0-255 to write in OCR0 register */
	}
	return 0;
}

.

.

Video Demo:

.

Contoh 20: (Merupakan lanjutan dari contoh 19 tetapi disertai dengan LCD 16x2 4 bit)

Program di bawah ini digunakan untuk mengendalikan kecepatan motor DC (OC 0) dengan potensiometer yang dihubungkan dengan kaki ADC 0 disertai dengan switch PB. 1 yang digunakan untuk membalik arah putaran motor DC yang terletak pada PB.2.

.

#define F_CPU 8000000UL			/* Define CPU Frequency 8MHz */
#include <avr/io.h>			/* Include AVR std. library file */
#include <avr/interrupt.h>
#include <stdio.h>			/* Include std. library file */
#include <util/delay.h>			/* Include Delay header file */
#include "lcd.h"

volatile uint8_t Direction = 0;

void ADC_Init()				/* ADC Initialization function */
{
	DDRA = 0x00;			/* Make ADC port as input */
	ADCSRA = 0x87;			/* Enable ADC, with freq/128 */
	ADMUX = 0x40;			/* Vref: Avcc, ADC channel: 0 */
}

int ADC_Read(char channel)		/* ADC Read function */
{
	ADMUX = 0x40 | (channel & 0x07);/* set input channel to read */
	ADCSRA |= (1<<ADSC);		/* Start ADC conversion */
	while (!(ADCSRA & (1<<ADIF)));	/* Wait until end of conversion */
	ADCSRA |= (1<<ADIF);		/* Clear interrupt flag */
	_delay_ms(1);			/* Wait a little bit */
	return ADCW;			/* Return ADC word */
}



int main(void)
{
	//Initialize LCD module
	LCDInit(LS_BLINK|LS_ULINE);

	//Clear the screen
	LCDClear();

	
	DDRB |= (1<<PB3);		/* Make OC0 pin as Output */
	DDRB |= (1<<PB2);
	PORTB |= (1<<PB1);
	
	ADC_Init();			/* Initialize ADC */
	TCNT0 = 0;			/* Set timer0 count zero */
	TCCR0 = (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00)|(1<<CS01);/* Set Fast PWM with Fosc/64 Timer0 clock */
	while(1)
	{
		if (bit_is_clear(PINB, 1))	/* Rotate DC motor Clockwise */
		PORTB |= (1<<PB2);
		else			/* Else rotate DC motor Anticlockwise */
		PORTB &= ~(1<<PB2);
		
		
		OCR0 = (ADC_Read(0)/4);	/* Read ADC and map it into 0-255 to write in OCR0 register */
		//Simple string printing
		LCDWriteString("MOTOR SPEED POT.");

		//A string on line 2
		LCDWriteStringXY(0,1,"PWM:");
		LCDWriteIntXY(5,1,OCR0,3);
		_delay_ms(250);
		LCDClear();
	}
	return 0;
}

//https://www.electronicwings.com/avr-atmega/dc-motor-interfacing-with-atmega-1632

.

Contoh 21:

Berikut ini contoh kendali kecepatan motor DC menggunakan metode PID sederhana.

.

#define F_CPU 8000000UL			/* Define CPU Frequency 8MHz */
#include <avr/io.h>			/* Include AVR std. library file */
#include <avr/interrupt.h>
#include <stdio.h>			/* Include std. library file */
#include <util/delay.h>			/* Include Delay header file */
#include "lcd.h"

volatile uint8_t Direction = 0;
unsigned int hapusLCD, encoder;
int enc_target = 3, error, Kp = 35, Kd = 5, P, error_dif, error_prev;
//maksimal enc_target = 10 , pwm nya otomatis 255 tergantung Kp dan Kd nya

/*Interrupt Service Routine for INT0*/
ISR(INT0_vect)
{
	encoder++;
	
}


//Timer 0 overflow interrupt service routing
ISR(TIMER0_OVF_vect)
{
	// PID
	error = enc_target - encoder;
	error_dif = error - error_prev;
	error_prev = error;

	P = (Kp*error) + (Kd*error_dif);

	if(P<0)
	{
		P*=(-1);
	}
	if(P>255)P=255;

	OCR0 = (unsigned char)P;
	
	hapusLCD++;
	
	if (hapusLCD == 100)
	{
		LCDClear();
		
	}
	else if (hapusLCD == 101)
	{
		LCDWriteStringXY(0,0,"Enc. Target:");
		LCDWriteIntXY(13,0,enc_target,2);

		//A string on line 2
		LCDWriteStringXY(0,1,"PWM:");
		LCDWriteIntXY(5,1,OCR0,3);
		hapusLCD = 0;
	}
	
	encoder = 0;
}


int main(void)
{
	//Initialize LCD module
	LCDInit(LS_BLINK|LS_ULINE);

	//Clear the screen
	LCDClear();

	PORTD |= (1<<PD2);  //UTK INT0 
	GICR = 1<<INT0;		/* Enable INT0*/
	MCUCR = 1<<ISC01 | 1<<ISC00;  /* Trigger INT0 on rising edge */
	
	//Unmask Timer 0 overflow interrupt
	TIMSK= 0x01;
	
	sei();			/* Enable Global Interrupt */
	
	DDRB |= (1<<PB3);		/* Make OC0 pin as Output */
	DDRB |= (1<<PB2);
	PORTB |= (1<<PB1);
	
	TCNT0 = 0;			/* Set timer0 count zero */
	TCCR0 = (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00)|(1<<CS01);/* Set Fast PWM with Fosc/64 Timer0 clock */
	while(1)
	{
		if (bit_is_clear(PINB, 1))	/* Rotate DC motor Clockwise */
		PORTB |= (1<<PB2);
		else			/* Else rotate DC motor Anticlockwise */
		PORTB &= ~(1<<PB2);
		
		
	}
	return 0;
}

//https://wangready.wordpress.com/2012/03/03/kontrol-posisi-motor-dc-mengunakan-rotary-encoder-berbasis-mikrokontroler-avr/

.


Berikut ini Link semua Program di atas:

https://drive.google.com/file/d/1vXkm_CGgN8ZgQ0bzqlmW2uEktvGquQ-k/view?usp=sharing

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *