DAFTAR PUSTAKA 1. Leonid Reznik, Fuzzy Controllers. Newnes, Victoria University of Technology, Melbourne, Australia 2. Ogata, Katsuhiko (1997), Modern Control Engineering, Third Edition, Prentice-Hall International, Inc. 3. Killian, Modern Control Technology, Component and Systems, 2nd edition, 4. J.S.R Jang, C.T.Sun, E.Mizutani (1997), Neuro Fuzzy and Soft Computing, Prentice-Hall International, Inc 5. Fuller Robert (1995), Neural Fuzzy System, Abo Akademi University 6. F. Martin McNeill, Ellen Thro, Ronald R. Yager (1994), Fuzzy Logic, A Practical Approach, Academic Press, Inc 7. Rashid, Muhammad, Power Electronics Handbook 8. Tim IE, Igit Purwahyudi, AN16, How 2 Use DT-51 PetraFuz 9. Atmel Corporation (2004), ATMega8535 Datasheet, http://www.atmel.com 10. STMicroelektronics (2000), L298N Datasheet http://www.st.com
76
LAMPIRAN
77
LAMPIRAN 1 Foto implementasi sistem kendali motor DC
Foto pengujian sistem kendali motor DC
78
LAMPIRAN 2 Diagram Alir Program Start
Inisialisasi: - Port - Timer 0 (Pencacah) - Timer 1 (PWM) - Timer 2 (Timer)
Baca: - SP (Seting Point) - PV (Kecepatan) E(n) = SP(n) - PV(n) CE(n) = E(n)-E(n-1) E(n-1) = E(n)
C(nf),E(nf) = Fuzzifikasi (E(n), CE(n) C(nf),E(nf) = Inferensi fuzzy (C(nf),E(nf) , rule) ∆PWM = Defuzzifikasi (E(nf), C(nf),E(nf))
PWM(n)
= PWM(n-1) + ∆PWM
PWM(n-1) = PWM (n)
n=n+1 Kirim ke PC via serial
79
LAMPIRAN 3 (a) Kode kendali open loop #include <mega8535.h> #include <stdio.h> #include
#define mode_ADC 0x20 int n; int e; int en_1; int ce; int pwm; int sp; int pwmn_1=100; int c_pwm; int pulsa; int pwm_speed; char i,j; float curr_ce_mem,curr_e_mem; int tampil; int hasil;
int e_member_funcs[5][3]={{-180,-80,-40}, {-80,-20, 0}, {-20, 0, 20}, { 0, 20, 80}, { 40, 80, 180} }; int ce_member_funcs[5][3]={{-180,-80,-40}, {-80,-20, 0}, {-20, 0, 20}, { 0, 20, 80}, { 40, 80, 180} }; int pwm_matrix[5][5]={{-155,-155,-155, -10, 0}, {-155, -10, -10, 0, 10}, {-155, -10, 0, 10, 155}, { -10, 0, 10, 10, 155}, { 0, 10, 155, 155, 155} }; // PROTOTIPE FUNGSI void tampilkan_pc(void); void baca_kecepatan(void); void hitung_fuzzy(void); void tampilkan_lcd(void); void baca_sp(void); void set_kecepatan_motor(void); unsigned char baca_adc(unsigned char); // PROGRAM UTAMA
80
void main (void) { //INISIALISASI ADC ADMUX=mode_ADC; ADCSRA=0x87; // INISIALISASI PORT DDRA=0x00; // PORT A SEBAGAI INPUT SETING POINT DDRB=0x00; // PORT B SEBAGAI INPUT ENKODER (T0) DDRD=0xFF; // PORT D SEBAGAI OUTPUT PWM // INISIALISASI USART, BAUDRATE 9600 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x47; //INISIALISASI TIMER 0 (UNTUK ENCODER) TCCR0=0x07; TCNT0=0x00; OCR0=0x00; // INISIALISASI TIMER 1 (UNTUK PWM) TCCR1A=0xA1; TCCR1B=0x0C; TCNT1=0x000; // SET ENABLE MOTOR PORTD.2=0; PORTD.3=1; // INISIALISASI TIMER 2 (UTK TIME SAMPLING 20 ms) TCCR2=0x07; TCNT2=0x28; // AKTIFKAN GLOBAL SETING UTK SEMUA TIMER TIMSK=0x40; #asm ("sei"); while(1); } interrupt [TIM2_OVF] void timer2_overflow(void) { baca_sp(); baca_kecepatan(); set_kecepatan_motor(); tampilkan_pc(); } void baca_sp(void) { sp=baca_adc(0); }
81
void set_kecepatan_motor(void) { OCR1A=sp; } void tampilkan_pc(void) { printf(" %3d",n); printf(" SP=%3d",sp); printf(" PV=%3d",pulsa); printf("\n\r"); }
unsigned char baca_adc(unsigned char pin_adc ) { ADMUX=pin_adc|mode_ADC; ADCSRA|=0x40; while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCH; } void baca_kecepatan(void) { pulsa=TCNT0; TCNT0=0; TCNT2=0x28; }
82
(b) Kode kendali fuzzy tanpa linierisasi #include <mega8535.h> #include <stdio.h> #include #define mode_ADC 0x20 int tampil_lcd; int n; int e; int en_1; int ce; int pwm; int sp; int pwmn_1=0; int c_pwm; int pulsa; int pwm_speed; char i,j; float curr_ce_mem,curr_e_mem; int hasil;
int e_member_funcs[5][3]={{-180,-80,-40}, {-80,-20, 0}, {-20, 0, 20}, { 0, 20, 80}, { 40, 80, 180} }; int ce_member_funcs[5][3]={{-180,-80,-40}, {-80,-20, 0}, {-20, 0, 20}, { 0, 20, 80}, { 40, 80, 180} }; int pwm_matrix[5][5]={{-255,-255,-255, -30, 0}, {-255, -30, -30, 0, 30}, {-255, -30, 0, 30, 255}, { -30, 0, 30, 30, 255}, { 0, 30, 255, 255, 255} }; // PROTOTIPE FUNGSI void tampilkan_pc(void); void hitung_fuzzy(void); void tampilkan_lcd(void); void baca_sp(void); void set_kecepatan_motor(void); unsigned char baca_adc(unsigned char); // PROGRAM UTAMA void main (void) {
83
// INISIALISASI ADC ADMUX=mode_ADC; ADCSRA=0x87; // INISIALISASI PORT DDRA=0x00; // PORT A SEBAGAI INPUT SETING POINT DDRB=0x00; // PORT B SEBAGAI INPUT ENKODER (T0) DDRD=0xFF; // PORT D SEBAGAI OUTPUT PWM // INISIALISASI USART, BAUDRATE 9600 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x47; //INISIALISASI TIMER 0 (UNTUK ENCODER) TCCR0=0x07; TCNT0=0x00; OCR0=0x00; // INISIALISASI TIMER 1 (UNTUK PWM) TCCR1A=0xA1; TCCR1B=0x0B; TCNT1=0x000; // SET ENABLE MOTOR PORTD.2=0; PORTD.3=1; // INISIALISASI TIMER 2 (UTK TIME SAMPLING 20 ms) TCCR2=0x07; // Ts=20ms. TCCR2=0x07, TCNT2=0x28 TCNT2=0x28; // Ts=10ms. TCCR2=0x07, TCNT2=0x94 // AKTIFKAN GLOBAL SETING UTK SEMUA TIMER TIMSK=0x40; #asm ("sei"); while(1); } interrupt [TIM2_OVF] void timer2_overflow(void) { baca_sp(); hitung_fuzzy(); set_kecepatan_motor(); tampilkan_pc(); } void baca_sp(void) { sp=baca_adc(0)/2; } void set_kecepatan_motor(void) { OCR1A=pwm; }
84
void tampilkan_pc(void) { printf(" %3d",n); // Jumlah pulsa printf(" SP=%3d",sp); // Jumlah pulsa printf(" PV=%3d",pulsa); // Jumlah pulsa printf(" PWM=%3d",OCR1A); // sp-pulsa printf("\n\r"); }
unsigned char baca_adc(unsigned char pin_adc ) { ADMUX=pin_adc|mode_ADC; ADCSRA|=0x40; while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCH; } void hitung_fuzzy(void) { char i,j; float curr_ce_mem,curr_e_mem; float e_membership[5]; float ce_membership[5]; float pwm_m[5][5]; float total_pwm; float total_e; float total_ce; pulsa=TCNT0; TCNT0=0; TCNT2=0x28; e=sp - pulsa; ce=e - en_1; en_1=e; // Menentukan nilai membership function E for(i=0; i< 5; i++) { if(e >= e_member_funcs[i][0] && e <= e_member_funcs[i][2]) { if(e < e_member_funcs[i][1]) { e_membership[i] = (float)(e - e_member_funcs[i][0]) / (e_member_funcs[i][1] e_member_funcs[i][0]); } else { e_membership[i] = (float)(e_member_funcs[i][2] e) / (e_member_funcs[i][2] - e_member_funcs[i][1]) ; } } else { e_membership[i] = 0.00; } }
85
for(i=0; i< 5; i++) { if(ce >= ce_member_funcs[i][0] && ce <= ce_member_funcs[i][2]) { if(ce < ce_member_funcs[i][1]) { ce_membership[i] = (float)(ce ce_member_funcs[i][0]) / (ce_member_funcs[i][1] ce_member_funcs[i][0]); //Naik } else { ce_membership[i] = (float)(ce_member_funcs[i][2] - ce) / (ce_member_funcs[i][2] - ce_member_funcs[i][1]) ; } } else { ce_membership[i] = 0.00; }
} total_e = 0.00; for(i=0; i<5; i++) { total_e = total_e + e_membership[i]; }
total_ce = 0.00; for(i=0; i<5; i++) { total_ce = total_ce + ce_membership[i]; }
for(i=0; i<5; i++) { e_membership[i] /= total_e; }
for(i=0; i<5; i++) { ce_membership[i] /= total_ce; }
for(i=0; i<5; i++) { curr_ce_mem = ce_membership[i]; for(j=0; j<5; j++) {
86
pwm_m[i][j] = pwm_matrix[i][j] * curr_ce_mem; } } total_pwm = 0.00; for(i=0; i<5; i++) { curr_e_mem = e_membership[i]; for(j=0; j<5; j++) { total_pwm += pwm_m[j][i] * curr_e_mem; } } pwm_speed = (short)total_pwm; pwm=pwm_speed + pwmn_1; // PEMBATASAN NILAI PWM 0-255 if(pwm > 255) pwm=255; if(pwm < 0) pwm=0; pwmn_1=pwm; n=n+1; }
87
(c) Kode kendali fuzzy dengan linierisasi #include <mega8535.h> #include <stdio.h> #include #define mode_ADC 0x20 //int batas; int n; int e; // Error ke n int en_1; // Error ke (n-1) int ce; // Selisih Error= E-En int pwm; int sp; int pwmn_1=100; int c_pwm; int pulsa; int pwm_speed; char i,j; float curr_ce_mem,curr_e_mem; int tampil; int hasil;
int e_member_funcs[5][3]={{-180,-80,-40}, {-80,-20, 0}, {-20, 0, 20}, { 0, 20, 80}, { 40, 80, 180} }; int ce_member_funcs[5][3]={{-180,-80,-40}, {-80,-20, 0}, {-20, 0, 20}, { 0, 20, 80}, { 40, 80, 180} }; int pwm_matrix[5][5]={{-155,-155,-155, -10, 0}, {-155, -10, -10, 0, 10}, {-155, -10, 0, 10, 155}, { -10, 0, 10, 10, 155}, { 0, 10, 155, 155, 155} }; // PROTOTIPE FUNGSI void tampilkan_pc(void); void hitung_fuzzy(void); void tampilkan_lcd(void); void baca_sp(void); void set_kecepatan_motor(void); unsigned char baca_adc(unsigned char); // PROGRAM UTAMA void main (void) {
88
//INISIALISASI ADC ADMUX=mode_ADC; referensi AREF, ADCSRA=0x87; MSB(bit9-bit2)
// Inisialisasi ADC tegangan // data hasil konversi 8 bit
// INISIALISASI PORT DDRA=0x00; // PORT A SEBAGAI INPUT SETING POINT DDRB=0x00; // PORT B SEBAGAI INPUT ENKODER (T0) DDRC=0xFF; // PORT C SEBAGAI OUTPUT LCD DDRD=0xFF; // PORT D SEBAGAI OUTPUT PWM // INISIALISASI USART, BAUDRATE 9600 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x47; //INISIALISASI TIMER 0 (UNTUK ENCODER) TCCR0=0x07; TCNT0=0x00; OCR0=0x00; // INISIALISASI TIMER 1 (UNTUK PWM) TCCR1A=0xA1; // output PWM high selama TCNT masih lebih kecil dari OCR, 0xA1= PWM 8 bit TCCR1B=0x0B; // Skalar 0x0D=1024, 0x0C=256, 0x0B=64, 0xA=8, 0x09=1 TCNT1=0x000; // setting inisial counter1=0 // SET ENABLE MOTOR PORTD.2=0; PORTD.3=1;
// INISIALISASI TIMER 2 (UTK TIME SAMPLING 20 ms) TCCR2=0x07; // Ts=20ms. TCCR2=0x07, TCNT2=0x28 TCNT2=0x28; // Ts=10ms. TCCR2=0x07, TCNT2=0x94 // AKTIFKAN GLOBAL SETING UTK SEMUA TIMER TIMSK=0x40; // Over Flow, T2=40, T0=0x01 #asm ("sei"); while(1);
// Global interupt // Ulangi terus menerus
} // PROGRAM YANG DIEKSEKUSI TIAP 20ms interrupt [TIM2_OVF] void timer2_overflow(void) { baca_sp(); hitung_fuzzy(); set_kecepatan_motor(); tampilkan_pc(); //tampilkan_lcd();
89
} void baca_sp(void) { sp=baca_adc(0)/2; } void set_kecepatan_motor(void) { OCR1A=pwm; } void tampilkan_pc(void) { printf(" %3d",n); printf(" SP=%3d",sp); printf(" PV=%3d",pulsa); printf(" PWM=%3d",OCR1A); printf("\n\r"); }
unsigned char baca_adc(unsigned char pin_adc ) { ADMUX=pin_adc|mode_ADC; ADCSRA|=0x40; while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCH; } void hitung_fuzzy(void) { char i,j; float curr_ce_mem,curr_e_mem; float e_membership[5]; float ce_membership[5]; float pwm_m[5][5]; float total_pwm; float total_e; float total_ce; pulsa=TCNT0; TCNT0=0; TCNT2=0x28; // Reset nilai awal counter 2 e=sp - pulsa; ce=e - en_1; en_1=e; // Menentukan nilai membership function E for(i=0; i< 5; i++) { if(e >= e_member_funcs[i][0] && e <= e_member_funcs[i][2]) { if(e < e_member_funcs[i][1]) // naik {
90
e_membership[i] = (float)(e e_member_funcs[i][0]) / (e_member_funcs[i][1] e_member_funcs[i][0]); //Naik } else // Turun { e_membership[i] = (float)(e_member_funcs[i][2] e) / (e_member_funcs[i][2] - e_member_funcs[i][1]) ; //Turun } } else { e_membership[i] = 0.00; }
} for(i=0; i< 5; i++) { if(ce >= ce_member_funcs[i][0] && ce <= ce_member_funcs[i][2]) { if(ce < ce_member_funcs[i][1]) // naik { ce_membership[i] = (float)(ce ce_member_funcs[i][0]) / (ce_member_funcs[i][1] ce_member_funcs[i][0]); //Naik } else // Turun { ce_membership[i] = (float)(ce_member_funcs[i][2] - ce) / (ce_member_funcs[i][2] - ce_member_funcs[i][1]) ; //Turun } } else { ce_membership[i] = 0.00; }
} //akhir loop E
total_e = 0.00; for(i=0; i<5; i++) { total_e = total_e + e_membership[i]; } total_ce = 0.00; for(i=0; i<5; i++)
91
{ total_ce = total_ce + ce_membership[i]; }
for(i=0; i<5; i++) { e_membership[i] /= total_e; }
for(i=0; i<5; i++) { ce_membership[i] /= total_ce; }
// Hitung PWM for(i=0; i<5; i++) { curr_ce_mem = ce_membership[i]; for(j=0; j<5; j++) { pwm_m[i][j] = pwm_matrix[i][j] * curr_ce_mem; } } total_pwm = 0.00; for(i=0; i<5; i++) { curr_e_mem = e_membership[i]; for(j=0; j<5; j++) { total_pwm += pwm_m[j][i] * curr_e_mem; } } pwm_speed = (short)total_pwm; pwm=pwm_speed + pwmn_1; // PEMBATASAN NILAI PWM 0-255 if(pwm > 255) pwm=255; if(pwm < 0) pwm=0; pwmn_1=pwm; n=n+1; }
92