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
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.
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;
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);
//==========================================================
//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);
}
//Millis2
unsigned long pm = 0;
const long per = 1000;
//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);
//===========================================================
==
//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
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;
}
//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
}
}
//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);
}
}
}
//Millis2
unsigned long pm = 0;
const long per = 1000;
//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);
//=============================================================
//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;
}
//======================
// 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;
}
//==================================================
// 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
//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);
}
}