Anda di halaman 1dari 30

Mata Kuliah Teknik Kendali Adaptif

Berlianne Shanaza Andriany (I0717012)


Projek UAS : Perancangan Pengontrolan Kecepatan Motor Encoder dengan Fuzzy PID
Pengontrolan motor encoder dengan fuzzy-PID ini bertujuan untuk meningkatan
efisiensi dan penghematan energi motor. Input variable dari fuzzy adalah eror dan daya. Pada
perancangan Pengontrolan Kecepatan dengan metode Fuzzy-PID ini, saya menggunakan
Proteus Professional V.8.10, PLX DAQ, Arduino IDE, MATLAB, dan com0com. Com0com
pada perancangan ini digunakan sebagai virtual port untuk menghubungkan PLX DAQ
dengan compim proteus.
Langkah – Langkah dalam perancangan ini adalah sebagai berikut :
1. Menginstall Software yang dibutuhkan (com0com).
2. Menginstall Library Arduino ke Proteus.
3. Membuat rangkaian Open Loop Pengontrolan Kecepatan Motor Encoder.
4. Membuat dan meng-compile program Kontrol Kecepatan di Arduino IDE dan meng-
copy file HEX nya lalu dimasukkan ke Proteus.
5. Mengkoneksikan port yang sesuai dengan com0com. Pada perancangan ini port yang
digunakan untuk PLX adalah com 8. Men-connect PLX.
6. Mengkoneksikan port pada COMPIM yang sesuai dengan com0com. Pada
perancangan ini port yang dipakai pada COMPIM adalah com 7. Arduino juga
disetting agar baudratenya sesuai dengan PLX.
7. Menjalankan proteus, lalu hasil input dan output simulasi dapat terbaca di Ms.Excel.
Input berupa nilai hasil pembacaan tegangan dan output berupa pembacaan nilai
kecepatan.
8. Membuka Matlab, menjalankan ‘system identification’. Lalu, Mengimport data hasil
pembacaan sensor.

9. Dari data yang telah di-import diubah kedalam bentuk state space. Lalu meng-klik
‘show in LTI viewer’ untuk melihat hasil transfer function.
10. Membuat blok diagram Simulink untuk close loop PID dan memasukkan nilai transfer
function sesuai hasil system identification.
11. Men-tunning PID dengan Autotuning, mencatat hasil Kp, Ki, dan Kd nya.
12. Membuat Program close loop PID dan memasukkan nilai Kp, Ki, dan Kd hasil
autotuning.
13. Memasukkan program ke rangkaian, dan melihat hasil pembacaan.
14. Mengganti nilai Kp, Ki, dan Kd agar didapatkan respon yang lebih baik.
15. Membuat Rule Fuzzy pada Matlab dengan tool fuzzy.
16. Membuat Program Arduino Fuzzy-PID dari parameter-parameter yang telah
didapatkan diatas.

1. Skematik Rangkaian

Penjelasan rangkaian :
Pada perancangan ini, terdapat 3 sensor yang digunakan, yaitu sensor kecepatan,
sensor tegangan, dan sensor arus (ACS712). Pada rangkaian pembacaan kecepatan
dilakukan dengan menghubungkan koneksi pin pada rotary encoder ke pin yang ada
pada Arduino. R2 dan R3 merupakan Voltage divider untuk pembacaan nilai
tegangan. C1 dan R1 digunakan sebagai stabilizer agar pembacaan nilai arus lebih
mudah dilakukan. Compim adalah virtual port yang digunakan untuk komunikasi
virtual hasil pembacaan sensor Arduino. LM298 adalah motor driver yang berfungsi
untuk menggerakkan motor, dan Potensiometer digunakan untuk mengatur kecepatan
secara manual.

2. Coding
1. Coding Open Loop Arduino
Terlampir
2. Coding Close Loop Arduino dengan PID
Terlampir

3. Analisa Hasil
Hasil Pembacaan Simulasi Open Loop dengan PLX DAQ
Time (Sec.) Kecepatan (RPM) Tegangan (volt)
1 64 11.42
2 151 11.5
3 168 11.53
4 172 11.53
5 172 11.53
6 172 11.53
7 172 11.53
8 172 11.53
9 172 11.53
10 172 11.53
11 172 11.53
11 172 11.53
13 172 11.53
14 172 11.53
15 172 11.53
16 172 11.53
17 172 11.53
18 172 11.53
19 172 11.53
19 172 11.53
21 172 11.53
22 172 11.53
23 172 11.53
24 172 11.53
25 172 11.53
26 172 11.53
27 172 11.53
27 172 11.53
29 172 11.53
30 172 11.53
31 172 11.53
32 172 11.53
33 172 11.53
34 172 11.53
35 172 11.53
35 172 11.53
37 172 11.53
38 172 11.53
39 172 11.53
40 172 11.53
41 172 11.53
42 172 11.53
43 172 11.53
43 172 11.53
45 172 11.53
46 172 11.53
47 172 11.53
48 172 11.53
49 172 11.53
50 172 11.53
51 172 11.53
52 172 11.53
53 172 11.53
53 172 11.53
55 172 11.53
56 172 11.53
57 172 11.53
58 172 11.53
59 172 11.53
60 172 11.53
61 172 11.53
62 172 11.53
63 172 11.53
64 172 11.53
65 172 11.53
66 172 11.53
67 172 11.53
68 172 11.53
69 172 11.53
70 172 11.53
70 172 11.53
72 172 11.53
73 172 11.53
74 172 11.53
75 172 11.53
76 172 11.53
77 172 11.53
78 172 11.53
79 172 11.53
80 172 11.53
80 172 11.53
82 172 11.53
83 172 11.53
83 172 11.53
85 172 11.53
86 172 11.53
87 172 11.53
88 172 11.53
89 172 11.53
90 172 11.53
90 172 11.53
92 172 11.53
93 172 11.53
94 172 11.53
95 172 11.53
96 172 11.53
97 172 11.53
97 172 11.53
99 172 11.53
100 172 11.53

Data yang dianalisis diambil dari data pengukuran 1-100. Sistem stabil ketika tegangan berada
pada nilai 11.53 V. Pada saat tegangan stabil pada 12.26 V, nilai kecepatan stabil pada nilai
172 RPM. Didapatkan hasil identifikasi sistem berupa grafik hubungan kecepatan dengan
tegangan dengan pengambilan 100 data hasil pembacaan.
Gambar Grafik Hubungan Kecepatan dengan Tegangan pada Rangkaian Open Loop

Setelah mengimport data nilai kecepatan dan tegangan di systemidentification. Didapatkan


hasil mydata yang akan diubah ke dalam transfer function model. Disini sudah ditetapkan
untuk menggunakan 2 poles dan 0 zeros.

Hasil Step Response Continuous Transfer function


Hasil Continuous Transfer function
1.347
Tf= 2
s −0.8149 s+ 0.1012

Hasil Step Response Diskrit Transfer function

Hasil Diskrit Transfer function

10.53 z 2
Tf=
z 2−0.2079 z +0. 0 007859

Men-Tuning PID
Untuk mencari nilai Kp, Ki, dan Kd dibuat Blok Diagram close loop Simulink dan
memasukkan nilai hasil diskrit transfer function ke sistem.
Blok PID Simulink

Dari hasil Autotunning yang didapatkan dari matlab, didapatkan hasil Kp = 0.001055, Ki =
0.00211, dan Kd = 0.

Setelah itu membuat program Close Loop PID Arduino dengan memasukkan nilai Kp, Ki,
dan Kd hasil autotunning. Didapatkan hasil pembacaan sebagai berikut :
Time Kecepatan Tegangan
(Sec.) (RPM) (volt)
1 13 0.29
2 6 0.12
3 3 0
4 1 0
5 0 0
6 0 0
7 0 0
8 0 0
9 0 0
10 0 0
11 0 0
12 0 0
13 0 0
14 0 0
15 0 0
16 0 0
17 0 0
18 0 0
19 0 0
20 0 0
21 0 0
22 0 0
23 0 0
24 0 0
25 0 0
26 0 0
27 0 0
28 0 0
29 0 0
30 0 0
31 0 0
32 0 0
33 0 0
34 0 0
35 0 0
36 0 0
37 0 0
38 0 0
39 0 0
40 0 0
41 0 0
42 0 0
43 0 0
44 0 0
45 0 0
46 0 0
47 0 0
48 0 0
49 0 0
50 0 0
Grafik Respon sistem dengan Autotuning PID

Hasil Pembacaan kecepatan dan tegangan turun lalu bernilai 0. Oleh karena itu disini nilai
Kp, Ki, dan Kd diubah agar mendapatkan hasil respon yang lebih baik. Hasil PID Ki =
0.3, Kp = 0.386, Kd = 0.042. Berikut hasil pembacaan respon sistem ketika nilai Kp, Ki,
dan Kd dirubah. Didapatkan hasil kecepatan yang stabil pada 172 rpm dengan tegangan
stabil pada detik ke-8 dengan 11.53 Volt.

Time (Sec.) Kecepatan (RPM) Tegangan (volt)


1 13 0.43
2 7 0.45
3 7 0.65
4 10 0.94
5 16 11.01
6 125 11.48
7 163 11.52
8 171 11.53
9 172 11.53
10 172 11.53
11 172 11.53
12 172 11.53
13 172 11.53
14 172 11.53
15 172 11.53
16 172 11.53
17 172 11.53
18 172 11.53
19 172 11.53
20 172 11.53
21 172 11.53
22 172 11.53
23 172 11.53
24 172 11.53
25 172 11.53
26 172 11.53
27 172 11.53
28 172 11.53
29 172 11.53
30 172 11.53
31 172 11.53
32 172 11.53
33 172 11.53
34 172 11.53
35 172 11.53
36 172 11.53
37 172 11.53
38 172 11.53
39 172 11.53
40 172 11.53
41 172 11.53
42 172 11.53
43 172 11.53
44 172 11.53
45 172 11.53
46 172 11.53
47 172 11.53
48 172 11.53
49 172 11.53
50 172 11.53
51 172 11.53
52 172 11.53
53 172 11.53
54 172 11.53
55 172 11.53
56 172 11.53
57 172 11.53
58 172 11.53
59 172 11.53
60 172 11.53
61 172 11.53
62 172 11.53
63 172 11.53
64 172 11.53
65 172 11.53
66 172 11.53
67 172 11.53
68 172 11.53
69 172 11.53
70 172 11.53
71 172 11.53
72 172 11.53
73 172 11.53
74 172 11.53
75 172 11.53
76 172 11.53
77 172 11.53
78 172 11.53
79 172 11.53
80 172 11.53
81 172 11.53
82 172 11.53
83 172 11.53
84 172 11.53
85 172 11.53
86 172 11.53
87 172 11.53
88 172 11.53
89 172 11.53
90 172 11.53
91 172 11.53
92 172 11.53
93 172 11.53
94 172 11.53
95 172 11.53
96 172 11.53
97 172 11.53
98 172 11.53
99 172 11.53
100 172 11.53

Grafik Step Respon dengan PID Ki = 0.3, Kp = 0.386, Kd = 0.042

Perancangan Fuzzy Logic-PID Control


1. Fuzzifikasi
Pada fuzzifikasi, kita memasukkan parameter input dan output. Disini input berupa
nilai eror dan tegangan, sedangkan output berupa nilai KpAutotuning dan
KpFineTunning. Masing-masing input dan output diset memiliki 3 membership
function.
Membership fuction untuk input eror diatur sebagai berikut :
Membership Function Error Range
N (Negatif) [-720 -360 0]
ZE (Zero Error) [ -360 0 360]
P (Positif) [0 360 720]

Membership fuction untuk input tegangan diatur sebagai berikut :


Membership Function Error Range
MN (Minimal) [0 5 10]
S (Sedang) [5 10 15]
MX (Maximal) [10 15 20]

Membership fuction untuk output KpAutoTuning diatur sebagai berikut :


Membership Function Error Range
K (Kecil) [0.14 0.19 0.24]
Sd (Sedang) [0.19 0.24 0.29]
B (Besar) [0.24 0.29 0.34]
Membership fuction untuk output KpFineTunning diatur sebagai berikut :
Membership Function Error Range
K (Kecil) [0.2 0.25 0.3]
AV (Average) [0.25 0.3 0.35]
B (Besar) [0.3 0.35 0.4]

2. Rule Base

Error
N ZE P
Daya
MN K Sd B
AV K Sd B
MX K Sd S

Dari rule base diatas, diubah menjadi code program Arduino. Lalu dijalankan
Kembali dan melakukan pembacaan data menggunakan PLX DAQ.

Didapatkan hasil pembacaan data seperti berikut, dimana sepertinya program dan
setting masih eror sehingga hasil respon grafiknya menurun.
Time (Sec.) Kecepatan (RPM) Tegangan (volt)
1 13 0.29
2 6 0.12
3 3 0
4 1 0
5 0 0
6 0 0
7 0 0
8 0 0
9 0 0
10 0 0

Lampiran
1. Program Open Loop Arduino
unsigned long int milli_time;
const int nbaca = 10;
int baca[nbaca];
int bacaindex = 0;
int total = 0;
int rerata = 0;

//Millis2
unsigned long pm = 0;
const long per = 1000;

const byte pin_a = 2; //for encoder pulse A


const byte pin_b = 3; //for encoder pulse B
const byte pin_fwd = 10; //for H-bridge: run motor forward
const byte pin_bwd = 11; //for H-bridge: run motor backward
const byte pin_pwm = 6; //for H-bridge: motor speed
int encoder = 0;
int m_direction = 0; //sebagai penanda apakah motor bergerak atau tidak
int sv_speed = 255; //this value is 0~255
double pv_speed = 0; //Hasil pembacaan encoder disimpan pada variabel encoder
int timer1_counter; //for timer
//==========================================================
float input_volt = 0;
float temp = 0;
float r1 = 6800; //r1 value
float r2 = 4700; //r2 value
double mVperAmp = 0.135;
double RawValue = 0;
double ACSoffset = 2.5;
double Voltage = 0;
double Amps = 0;

void setup()
{
pinMode(pin_a, INPUT_PULLUP);
pinMode(pin_b, INPUT_PULLUP);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(pin_fwd, OUTPUT);
pinMode(pin_bwd, OUTPUT);
pinMode(pin_pwm, OUTPUT);
//==========================================================

attachInterrupt(digitalPinToInterrupt(pin_a), detect_a, RISING);


// start serial port at 9600 bps:
Serial.begin(9600);

//Tabel daq
Serial.println("CLEARDATA"); //This string is defined as a
// commmand for the Excel VBA
// to clear all the rows and columns
Serial.println("LABEL,Computer Time,Time (Sec.),Kecepatan (RPM),Tegangan
(volt),Arus (Ampere), Daya (watt)");
//LABEL command creates label for
// columns in the first row with bold font

//--------------------------timer setup
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
timer1_counter = 34286; // preload timer 65536-16MHz/256/2Hz
TCNT1 = timer1_counter; // preload timer
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//--------------------------timer setup
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
}

void loop()
{
int sv_speed = analogRead(A2) / 4;
int analogvalue = analogRead(A0);
temp = (analogvalue * 5) / 1023.0;
input_volt = (temp / (r2 / (r1 + r2)));
if (input_volt < 0.09)
{
input_volt = 0.0;
}
RawValue = analogRead(A1);
Voltage = (RawValue * 5) / 1023;
Amps = (Voltage - ACSoffset) / mVperAmp;
if (Amps < 0.09)
{
Amps = 0.0;
}
total = total - baca[bacaindex];
baca[bacaindex] = pv_speed;
total = total + baca[bacaindex];
bacaindex = bacaindex + 1;
if (bacaindex >= nbaca)
{
bacaindex = 0;
}
rerata = total / nbaca;
milli_time = millis(); // untuk set waktu sampling
float daya = Amps * input_volt;
digitalWrite(pin_fwd, 0); //run motor backward
digitalWrite(pin_bwd, 1); //run motor backward
analogWrite(pin_pwm, sv_speed); //set motor speed
unsigned long cM = millis(); // store the current time
//code daq----------------
if (cM - pm >= per)
{ // check if 1000ms passed
pm = cM;
Serial.print("DATA,TIME,"); // computer time
Serial.print(milli_time / 1000); // menampilkan waktu sampling
Serial.print(",");
Serial.print(rerata); //menampilkan rerata kecepatan
Serial.print(",");
Serial.print(input_volt); // menampilkan tegangan
Serial.print(",");
Serial.print(Amps);
Serial.print(",");
Serial.println(daya);
}
}

void detect_a()
{
encoder++;
m_direction = digitalRead(pin_b);
}

ISR(TIMER1_OVF_vect) // interrupt service routine - tick every 0.5sec


{
TCNT1 = timer1_counter; // set timer
pv_speed = 60 * (encoder / 200.0) / 0.5;
encoder = 0;
}

2. Program PID Close Loop


//moving average=================================================
unsigned long int milli_time;
const int nbaca = 10; //pembacaan tiap 15 nilai akan dirata-rata
int baca[nbaca];
int bacaindex = 0;
int total = 0;
int rerata = 0;

//Millis2
unsigned long pm = 0;
const long per = 1000;

//untuk koneksi motor============================================


const byte pin_a = 2; //for encoder pulse A
const byte pin_b = 3; //for encoder pulse B
const byte pin_fwd = 10; //for H-bridge: run motor forward
const byte pin_bwd = 11; //for H-bridge: run motor backward
const byte pin_pwm = 6; //for H-bridge: motor speed
int encoder = 0;
int m_direction = 0;
double pv_speed = 0;
double set_speed = 200; //untuk set kecepatan motor
//untuk
PID======================================================
double e_speed = 0; //error of speed = set_speed - pv_speed
double e_speed_pre = 0; //last error of speed
double e_speed_sum = 0; //sum error of speed
double pwm_pulse = 0; //this value is 0~255
double kp = 0.386;
double ki = 0.3;
double kd = 0.042;
int timer1_counter; //for timer
int i = 0;

//Voltage divider================================================
float input_volt = 0;
float temp = 0;
float r1 = 6800; //r1 value
float r2 = 4700; //r2 value
float daya;

//ACS712======================================================
===
double mVperAmp = 0.1175; //untuk kalibrasi, bisa diganti
double RawValue = 0;
double ACSoffset = 2.5; //dari datasheet acs712
double Voltage = 0;
double Amps = 0;
//============================================================
===

void setup() {
pinMode(pin_a, INPUT_PULLUP);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(pin_fwd, OUTPUT);
pinMode(pin_bwd, OUTPUT);
pinMode(pin_pwm, OUTPUT);
//===========================================================
==

attachInterrupt(digitalPinToInterrupt(pin_a), detect_a, RISING);


// start serial port at 9600 bps:
Serial.begin(9600);

//Tabel daq
Serial.println("CLEARDATA"); //This string is defined as a
// commmand for the Excel VBA
// to clear all the rows and columns
Serial.println("LABEL,Computer Time,Time (Sec.),Kecepatan (RPM),Tegangan
(volt),Arus(Ampere),Daya(watt)");
//LABEL command creates label for
// columns in the first row with bold font

//--------------------------timer setup
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
timer1_counter = 34286; // preload timer 65536-16MHz/256/2Hz

TCNT1 = timer1_counter; // preload timer


TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//--------------------------timer setup

while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
}
}

void loop()
{
//Voltage divider================================================
int analogvalue = analogRead(A0);
temp = (analogvalue * 5) / 1023.0; // konversi ADC
input_volt = (temp / (r2 / (r1 + r2))); // dari rumus pembagi tegangan
if (input_volt < 0.09)
{ //pembatasan pembacaan sensor menghindari minus
input_volt = 0.0;
}

//ACS712=====================================================
====
RawValue = analogRead(A1);
Voltage = (RawValue * 5) / 1023; //konversi ADC
Amps = (Voltage - ACSoffset) / mVperAmp;
if (Amps < 0.09)//pembatasan pembacaan sensor menghindari minus
{
Amps = 0.0;
}

//Running average untuk kecepatan================================


total = total - baca[bacaindex];
baca[bacaindex] = pv_speed;
total = total + baca[bacaindex];
bacaindex = bacaindex + 1;
if (bacaindex >= nbaca)
{
bacaindex = 0;
}
rerata = total / nbaca;
daya = Amps * input_volt; //untuk daya

//PLX DAQ
=======================================================
milli_time = millis(); // untuk set waktu sampling
unsigned long cM = millis(); // store the current time
if (cM - pm >= per)
{ // check if 1000ms passed
pm = cM;
Serial.print("DATA,TIME,");// computer time
Serial.print(milli_time / 1000); // menampilkan waktu sampling
Serial.print(",");
Serial.print(rerata);//menampilkan rerata kecepatan
Serial.print(",");
Serial.print(input_volt);// menampilkan tegangan
Serial.print(",");
Serial.print(Amps);//menampilkan arus
Serial.print(",");
Serial.println(daya);//menampilkan daya
}
}

//Mendeteksi pulse encoder=======================================


void detect_a()
{
encoder++;
}

//Interrupt service routine======================================


ISR(TIMER1_OVF_vect)
{
TCNT1 = timer1_counter; // set timer

//Pembacaan
RPM====================================================
pv_speed = 60 * (encoder / 200.0) / 0.5; // dari rumus RPM=60detik*(pulsa/PPR
motor)/waktu cuplik
encoder = 0;
int sv_speed = analogRead(A2) / 4; //pembacaan potensio
digitalWrite(pin_fwd, 0); //run motor backward
digitalWrite(pin_bwd, 1); //run motor backward
// e_speed = sv_speed - pv_speed; //set kecepatan, enabled jika mau pake
potensiometer
e_speed = set_speed - pv_speed; //set kecepatan, enabled jika mau pake setpoint
pwm_pulse = kp * (e_speed + e_speed_sum * ki + (e_speed - e_speed_pre) *
kd); //Program PID ideal
e_speed_pre = e_speed; //menyimpan nominal eror sebelumnya
e_speed_sum += e_speed; //penjumlahan eror
if (e_speed_sum > 4000) e_speed_sum = 4000; //batas atas kumulatif error
if (e_speed_sum < -4000) e_speed_sum = -4000; // batas bawah kumulatif error
if (pwm_pulse < 255 & pwm_pulse > 0)
{
analogWrite(pin_pwm, pwm_pulse); //set kecepatan motor
}
else
{
if (pwm_pulse > 255)
{ //pembatasan nilai pwm
analogWrite(pin_pwm, 255);
}
else
{
analogWrite(pin_pwm, 0);
}
}
}

3. Program Close-Loop Fuzzy PID


//moving average=================================================
unsigned long int milli_time;
const int nbaca = 10; //pembacaan tiap 15 nilai akan dirata-rata
int baca[nbaca];
int bacaindex = 0;
int total = 0;
int rerata = 0;

//Millis2
unsigned long pm = 0;
const long per = 1000;

//untuk koneksi motor============================================


const byte pin_a = 2; //for encoder pulse A
const byte pin_fwd = 10; //for H-bridge: run motor forward
const byte pin_bwd = 11; //for H-bridge: run motor backward
const byte pin_pwm = 6; //for H-bridge: motor speed
int encoder = 0;
int m_direction = 0;
double pv_speed = 0;
double set_speed = 200; //untuk set kecepatan motor

//Inisiasi Daya
float daya;

//Untuk Fuzzy
#define on 1
#define off 0
float N, ZE, P;
float MN, S, MX;
float K, Sd, B;
float hasilK, hasilSd, hasilB;
float CogK, CogSd, CogB;
float CogxK, CogxSd, CogxB;
float Totalkom, Totalpen, Cog;

//untuk PID======================================================
double e_speed = 0; //error of speed = set_speed - pv_speed
double e_speed_pre = 0; //last error of speed
double e_speed_sum = 0; //sum error of speed
double pwm_pulse = 0; //this value is 0~255
//PID Fine Tuning
double kp = 0.3;
double ki = 0.386;
double kd = 0.042;
//PID Hasil Autotuning
//double kp = 0.000876437310672245;
//double ki = 4;
//double kd = 0;
int timer1_counter; //for timer
int i = 0;

//Voltage divider================================================
float input_volt = 0;
float temp = 0;
float r1 = 6800; //r1 value
float r2 = 4700; //r2 value

//ACS712========================================================
=
double mVperAmp = 0.15; //untuk kalibrasi, bisa diganti
double RawValue = 0;
double ACSoffset = 2.5; //dari datasheet acs712
double Voltage = 0;
double Amps = 0;
//===============================================================
void setup()
{
pinMode(pin_a, INPUT_PULLUP);
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(pin_fwd, OUTPUT);
pinMode(pin_bwd, OUTPUT);
pinMode(pin_pwm, OUTPUT);
//=============================================================

attachInterrupt(digitalPinToInterrupt(pin_a), detect_a, RISING);


//Start serial port at 9600 bps:
Serial.begin(9600);

//Tabel daq
Serial.println("CLEARDATA"); //This string is defined as a
// commmand for the Excel VBA
// to clear all the rows and columns
Serial.println("LABEL,Computer Time,Time (Sec.),Kecepatan (RPM),Tegangan
(volt),Arus (Ampere), Daya (watt)");
//LABEL command creates label for
// columns in the first row with bold font

//--------------------------timer setup
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
timer1_counter = 34286; // preload timer 65536-16MHz/256/2Hz
TCNT1 = timer1_counter; // preload timer
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//--------------------------timer setup

while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
}
}

void loop()
{
//Voltage divider================================================
int analogvalue = analogRead(A0);
temp = (analogvalue * 5) / 1023.0; // konversi ADC
input_volt = temp / (r2 / (r1 + r2)); // dari rumus pembagi tegangan
if (input_volt < 0.09)
{ //pembatasan pembacaan sensor menghindari minus
input_volt = 0.0;
}

//ACS712========================================================
=
RawValue = analogRead(A1);
Voltage = (RawValue * 5) / 1023; //konversi ADC
Amps = (Voltage - ACSoffset) / mVperAmp;
if (Amps < 0.09)//pembatasan pembacaan sensor menghindari minus
{
Amps = 0.0;
}

//Running average untuk kecepatan================================


total = total - baca[bacaindex];
baca[bacaindex] = pv_speed;
total = total + baca[bacaindex];
bacaindex = bacaindex + 1;
if (bacaindex >= nbaca)
{
bacaindex = 0;
}
rerata = total / nbaca;
daya = Amps * input_volt; //untuk daya

//======================
// fuzzyfikasi eror
//======================
if (e_speed == -360) {
N = 1, ZE = 0, P = 0;
}
else if ((e_speed > -360) && (e_speed < 0)) {
N = 0, ZE = ((e_speed + 360) / 360), P = 0;
}
else if (e_speed == 0) {
N = 0, ZE = 1, P = 0;
}
else if ((e_speed > 0) && (e_speed < 360)) {
N = 0, ZE = (1 - ((e_speed - 0) / 360)), P = 0;
}
else if (e_speed == 360) {
N = 0, ZE = 0, P = 1;
}

//======================
// fuzzyfikasi daya
//======================
if (daya == 0) {
MN = 0, S = 0, MX = 0;
}
else if ((daya > 0) && (daya < 5.0)) {
MN = ((daya - 0) / 5.0), S = 0, MX = 0;
}
else if (daya == 5.0) {
MN = 1, S = 0, MX = 0;
}
else if ((daya > 5.0 ) && (daya < 10.0)) {
MN = (1 - ((daya - 5.0) / 5.0)), S = ((daya - 5.0) / 5.0), MX = 0;
}
else if (daya == 10.0) {
MN = 0, S = 1, MX = 0;
}
else if ((daya > 10.0) && (daya < 15.0)) {
MN = 0;
S = (1 - ((daya - 10.0) / 5.0)), MX = (daya - 10.0) / 5.0;
}
else if (daya == 15.0) {
MN = 0, S = 0, MX = 1;
}
else if ((daya > 15.0) && (daya < 20.0)) {
MN = 0, S = 0, MX = (1 - ((daya - 15.0) / 5.0));
}
else if (daya == 20.0) {
MN = 0, S = 0, MX = 0;
}

//===================================|
// fuzzy rule |
//===================================|
//error N daya MN==============================================
if ((e_speed == -360 ) && (daya == 5.0)) {
if (N < MN) {
K = N; //Kp
}
else if (N > MN) {
K = MN; //Kp
}
else if (N == MN) {
K = MN; //Kp
}
hasilK = K;
hasilSd = 0;
hasilB = 0;
}

//error N daya S ===========================================


else if ((e_speed == -360 ) && (daya == 10.0)) {
if (N < S) {
K = N; //Kp
}
else if (N > S) {
K = S; //Kp
}
else if (N == S) {
K = S; //Kp
}
hasilK = K;
hasilSd = 0;
hasilB = 0;
}

//error N daya MX=================================================


else if ((e_speed == -360 ) && (daya == 15.0)) { //1AB
if (N < MX) {
K = N; //Kp
}
else if (N > MX) {
K = MX; //Kp
}
else if (N == MX) {
K = MX; //Kp
}
hasilK = K;
hasilSd = 0;
hasilB = 0;
}

//eror ZE daya MN=============================================


else if ((e_speed == 0 ) && ( daya == 5.0 )) {
if (ZE < MN) {
Sd = ZE; //Kp
}
else if (ZE > MN) {
Sd = MN; //Kp
}
else if (ZE == MN) {
Sd = MN; //Kp
}
hasilK = 0;
hasilSd = Sd;
hasilB = 0;
}

//eror ZE daya S===================================================


else if ((e_speed == 0 ) && ( daya == 10.0 )) {
if (ZE < S) {
Sd = ZE; //Kp
}
else if (ZE > S) {
Sd = S; //Kp
}
else if (ZE == S) {
Sd = S; //Kp
}
hasilK = 0;
hasilSd = Sd;
hasilB = 0;
}

//eror ZE daya MX =================================================


else if ((e_speed == 0 ) && ( daya == 15.0 )) {
if (ZE < MX) {
Sd = ZE; //Kp
}
else if (ZE > MX) {
Sd = MX; //Kp
}
else if (ZE == MX) {
Sd = MX; //Kp
}
hasilK = 0;
hasilSd = Sd;
hasilB = 0;
}

//eror P daya MN ================================================


else if (( e_speed == 360 ) && ( daya == 5.0 )) {
if (P < MN) {
B = P; //Kp
}
else if (P > MN) {
B = MN; //Kp
}
else if (P == MN) {
B = MN; //Kp
}
hasilK = 0;
hasilSd = 0;
hasilB = B;
}

//eror P daya S ================================================


else if (( e_speed == 360 ) && ( daya == 10.0 )) {
if (P < S) {
B = P; //Kp
}
else if (P > S) {
B = S; //Kp
}
else if (P == S) {
B = S; //Kp
}
hasilK = 0;
hasilSd = 0;
hasilB = B;
}

//eror P daya MX ================================================


else if ((e_speed == 360 ) && ( daya == 15.0 )) {
if (P < MX) {
K = P; //Kp
}
else if (P > MX) {
K = MX; //Kp
}
else if (P == MX) {
K = MX; //Kp
}
hasilK = K;
hasilSd = 0;
hasilB = 0;
}

//==================================================
// Defuzzifikasi
//==================================================
//finetuning//matlabparameter
CogK = 0.66;//0.9// 0.66
CogxK = 4;//4

//finetuning//matlabparameter
CogSd = 1.05 ;//1.35//1.05
CogxSd = 5;//5
//finetuning//matlabparameter
CogB = 1.3;//1.6//1.3
CogxB = 5;//5

Totalkom = (CogK * hasilK) + (CogSd * hasilSd) + (CogB * hasilB);

Totalpen = (CogxK * hasilK) + (CogxSd * hasilSd) + (CogxB * hasilB);

Cog = Totalkom / Totalpen; // nilai COG sebagai parameter Kp

//PLX DAQ
=======================================================
milli_time = millis(); // untuk set waktu sampling
unsigned long cM = millis(); // store the current time
if (cM - pm >= per)
{ // check if 1000ms passed
pm = cM;
Serial.print("DATA,TIME,"); // computer time
Serial.print(milli_time / 1000); // menampilkan waktu sampling
Serial.print(",");
Serial.print(rerata); //menampilkan rerata kecepatan
Serial.print(",");
Serial.print(input_volt); // menampilkan tegangan
Serial.print(",");
Serial.print(Amps);
Serial.print(",");
Serial.println(daya);
}
}

//Mendeteksi pulse encoder=======================================


void detect_a()
{
encoder++;
}

//Interrupt service routine======================================


ISR(TIMER1_OVF_vect)
{
TCNT1 = timer1_counter; // set timer
//Pembacaan
RPM====================================================
pv_speed = 60 * (encoder / 200.0) / 0.5; // dari rumus RPM=60detik*(pulsa/PPR
motor)/waktu cuplik
encoder = 0;
int sv_speed = analogRead(A2) / 4;
digitalWrite(pin_fwd, 0); //run motor backward
digitalWrite(pin_bwd, 1); //run motor backward
// e_speed = sv_speed - pv_speed; //set kecepatan, enabled jika mau pake potensiometer
e_speed = set_speed - pv_speed; //set kecepatan, enabled jika mau pake setpoint
pwm_pulse = Cog * (e_speed + e_speed_sum * ki + (e_speed - e_speed_pre) * kd);
//Program PID ideal
e_speed_pre = e_speed; //menyimpan nominal eror sebelumnya
e_speed_sum += e_speed; //penjumlahan eror
if (e_speed_sum > 4000) e_speed_sum = 4000; //batas atas kumulatif error
if (e_speed_sum < -4000) e_speed_sum = -4000; // batas bawah kumulatif error
if (pwm_pulse < 255 & pwm_pulse > 0)
{
analogWrite(pin_pwm, pwm_pulse); //set kecepatan motor
}
else
{
if (pwm_pulse > 255)
{ //pembatasan nilai pwm
analogWrite(pin_pwm, 255);
}
else
{
analogWrite(pin_pwm, 0);
}
}
}

Anda mungkin juga menyukai