Estimasi Pemodelan Sistem Kontrol Kecepatan Motor DC
December 24, 2023 Leave a comment
A. Bentuk fungsi transfer kecepatan motor DC
Pertama kita cari bentuk fungsi transfer dari motor DC [1]. didapat perhitungan fungsi transfer kecepatan motor DC sebagai berikut.
Dapat dilihat dari persamaan di atas bahwa motor DC mempunyai sistem orde 2. Sistem orde 2 sendiri mempunyai struktur sebagai berikut [2].
Jika saya sederhanakan, maka saya medapat bentuk sebgai berikut.
Sementara, berdasarkan bentuk respon step dan lokasi pole-zero, sistem dibagi beberapa klasifikasi[3].
Maka, dari data di atas bisa kita dapatkan bahwa.
1. omega-n = sqrt(20.02) = 4.47
2. zeta = 12/2/4.47 = 1.34
3. Sistem overdamped. Untuk menghitung settling time overdamped sistem[4]
ts = 3.91/p1 = 3.91/2 ≈ 2
Dari Kesimpulan di atas mari kita coba membuat estimasi dari sebuah motor DC + encoder yang akan kita kontrol dengan sebuah mikrokontroler.
B. Membuat estimasi model
Pertama kita coba tes step respon dari motor DC ini. Time step menggunakan 60ms dengan alasan bahwa proses kalkulasi PID dan trasmit data serial nanti membutuhkan sekitar 60ms. Kita coba berikan step input dengan nilai 100 PWM. Nilai kecepatan yang terbaca akan dikonversi ke rad/s. Dimana untuk satu putaran motor sama dengan 100 step. Jadi, kecepatan(rad/s) = step_encoder_terbaca/0.06/100.
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {//fungsi membaca variable dari interrupt
encPosRead = encPos;
}
deltaPos = encPosRead - prevEncPosRead;
prevEncPosRead = encPosRead;
//encoder pada motor ini, satu putaran 360 derajat didapatkan 100 step
//jadi kecepatan motor dihitung dalam rotasi/detik
speedMotor = (float)deltaPos/dt/100;//menghitung kecepatan
Berikut respon step hasil pengukuran.
Dari data tersebut, dapat dilihat bahwa settling time berada di 180 ms. Maka, sekarang kita coba estimasi model orde-2 dari motor DC tersebut. Saya ambil nilai zeta dari motor DC ini 1.01 dengan asumsi bahwa motor DC ini lebih responsif dari contoh model di atas. Dengan mengatur nilai omega-n dan menjaga nilai settling time, maka kita akan dapatkan sistem yang kita coba untuk perkirakan.
Saya coba simulasikan, sehingga didapat step respon sebagai berikut.
Nilai final input step saya masukan 5.67 sesuai dengan data di pengukuran tadi. Nilai gain saya set 1 karena sudah sesuai dengan grafik step respon data pengukuran tadi.
C. Pengujian Hasil Estimasi
Untuk menguji model apakah sudah sesuai dengan motor DC asli, maka saya coba membuat kontrol kecepatan motor DC dengan kontrol PI[5] lalu membandingkan step response keduanya.
Tes 1
Tes 2
Tes 3
Tes 4
Tes 5
Dilihat dari hasil tes di atas, maka saya kira estimasi pemodelan dari motor DC mendekati aslinya.
D. Lampiran
D.1. Tes motor, perbandingan PWM terhadap kecepatan
rad/s | pwm |
0 | 0 |
0 | 5 |
0 | 10 |
0 | 15 |
0 | 20 |
0.17 | 25 |
0 | 30 |
0.17 | 35 |
1 | 40 |
1.67 | 45 |
2.17 | 50 |
2.5 | 55 |
3.17 | 60 |
3.5 | 65 |
4.17 | 70 |
4.67 | 75 |
4.83 | 80 |
5.17 | 85 |
5.67 | 90 |
6 | 95 |
6.33 | 100 |
6.67 | 105 |
7.17 | 110 |
7.5 | 115 |
7.83 | 120 |
8.17 | 125 |
8.5 | 130 |
8.67 | 135 |
9.17 | 140 |
9.33 | 145 |
9.5 | 150 |
10.17 | 155 |
10.33 | 160 |
10.67 | 165 |
10.83 | 170 |
11.17 | 175 |
11.5 | 180 |
12 | 185 |
12 | 190 |
12.33 | 195 |
12.67 | 200 |
12.83 | 205 |
13.5 | 210 |
13.33 | 215 |
13.5 | 220 |
14 | 225 |
14.17 | 230 |
14.33 | 235 |
14.83 | 240 |
14.67 | 245 |
15 | 250 |
15.33 | 255 |
D.2. Code
#include <util/atomic.h> // For the ATOMIC_BLOCK macro
//motor directory
#define CW 0
#define CCW 1
//motor control pin
#define motorDirPin 7
#define motorPWMPin 9
#define enablePin 8
//encoder pin
#define encoderPinA 2
#define encoderPinB 4
//encoder var
volatile int encPos = 0; //variable fungsi interrupt
int encPosRead = 0;
int prevEncPosRead;
//variable pengukur kecepatan
int deltaPos;
float targetSpeed;
float speedMotor;
//PID control
float Kp = 0.3;
float Ki = 10;
float Kd = 0;
//variable rumus PID
float error;
float errortmin1;
float integral;
float derivative;
float dt = 0.060; //second
int dtMillis = dt*1000; //milisecond
float control;
long int currTime;
long int prevTime;
long int delTime;
//variable pengaturan PWM motor
float velocity;
int PWMvelocity;
int dirMotor = 0;
//mode program
char modeProg;
//fungsi external interrupt encoder
void doEncoderA()
{
digitalRead(encoderPinB)?encPos++:encPos--;
}
void setup()
{
//setup interrupt
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(encoderPinA), doEncoderA,RISING);
//setup motor driver
pinMode(motorDirPin, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, HIGH);
Serial.begin(9600); //setting serial
analogReadResolution(8); //setting adc 8bit
digitalWrite(motorDirPin, CW); //set arah motor default
modeProg = 0; //pilih mode cek speed 1, run 0
//========Mode cek speed==============
if(modeProg)
{
for(int j=0;j<=255;j+=5)
{
PWMvelocity = j; //test perbandingan speed dan PWM
prevTime = millis();
analogWrite(motorPWMPin, PWMvelocity);
do
{
currTime = millis();
delTime = currTime-prevTime;
}while(delTime<dtMillis);
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {//fungsi membaca variable dari interrupt
encPosRead = encPos;
encPos = 0;
}
deltaPos = encPosRead - prevEncPosRead;
prevEncPosRead = 0;
//encoder pada motor ini, satu putaran 360 derajat didapatkan 100 step
//kecepatan motor dihitung dalam 60 ms, satuan rad/s
speedMotor = (float)deltaPos/dt/100;//menghitung kecepatan
digitalWrite(motorDirPin, CW);
analogWrite(motorPWMPin, 0);
//Serial.print("raw_speed:");
Serial.println(speedMotor);
//pengendalian agar nilai dt sama tiap cycle
//tidak menggunakana delay
do
{
currTime = millis();
delTime = currTime-prevTime;
}while(delTime<1500);
}
while(1);
}
}
void loop()
{
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {//fungsi membaca variable dari interrupt
encPosRead = encPos;
}
deltaPos = encPosRead - prevEncPosRead;
prevEncPosRead = encPosRead;
//encoder pada motor ini, satu putaran 360 derajat didapatkan 100 step
//jadi kecepatan motor dihitung dalam rotasi/detik
speedMotor = (float)deltaPos/dt/100;//menghitung kecepatan
//max adc 255, nilai tengah 0, set kecepatan dari -125 CCW samapi 125 CW
targetSpeed = ((float)analogRead(A0)-125)/10;//dijadikan skala -12.5 sampai 12.5
//PID
error = targetSpeed - speedMotor;
integral += dt*error;
derivative = (error - errortmin1)/dt;
control = (Kp*error) + (Ki*integral) + (Kd*derivative);
//pengaturan PWM
//konversi dari kecepatan rad/sec ke PWM berdasarkan mode cek speed
velocity = (control*14.891)+12.135;
PWMvelocity = min(max(velocity, -255), 255);
if(PWMvelocity >= 0)
{
digitalWrite(motorDirPin, CW);
analogWrite(motorPWMPin, PWMvelocity);
}
else
{
digitalWrite(motorDirPin, CCW);
analogWrite(motorPWMPin, 255+PWMvelocity);
}
//===========Serial: ploter
Serial.print("nol:");
Serial.print(0);//titik tengah 0
Serial.print(" ");
Serial.print("target_speed:");
Serial.print(targetSpeed);
Serial.print(" ");
Serial.print("speedMotor:");
Serial.println(speedMotor); //plot data
//pengendalian agar nilai dt sama tiap cycle
//tidak menggunakana delay
//berdasarkan pengukuran, setiap serial print memakan waktu 5ms
//anggap saja kita mengambil dt aman di 60ms
do
{
currTime = millis();
delTime = currTime-prevTime;
}while(delTime<dtMillis);
prevTime = currTime;
errortmin1 = error;
}