Encoderlı DC Motorun PID Controller ile Kontrolu ( Ayrık Zaman )
Proje Amacı
Microcontroller üzerine yazılmış yazılım ile encoderlı DC
motorun PID controller ile kontrol edilmesi amaçlanmaktadır. PID sistemin
katsayıları ve motorun çalışmasını istediğimiz RPM değerini bir arayuz ile
serial haberleşme kullanarak microcontroller a göndererek o değerlerde
çalışmasını istenmektedir.
Sistemin Çalışması
Mikro controller olarak Arduino Uno kullanılmıştır.
Encoderdan gelen pulseler için interrupt kullanılmıştır. RPM değerini bulmak
için ise pulseler arasındaki zaman farkından yararlanarak bulunmuştur.
Arayız tarafından gelen set RPM değeri ile motorumuzun RPM
değerini çıkartarak hatayı buluruz. Hatayı gerekli işlemlerden ve katsayılardan
geçirerek PID çıkışımızı elde etmiş olunur. Arduinonun pwm çıkışından motor
sürücüsüne giderek gerekli değerde motoru çalıştıracaktır.
Arayüz olarak Pytq5 kullanılmıştır. Sadece plot çizme işlemi
hazır kod ile kullanılmıştır.
GUI Analiz:
self.KP = QLineEdit(self) #############################
Kp box için
self.KP.resize(50, 50)
self.LAYOUT_A.addWidget(self.KP, * (1, 1))
hazır kodda sınıf içerisinde oluşturulmuştur. Bu nedenle
değerleri alabilmek için Textbox oluşturuldu. Widget fonksiyonundan
yararlanarak Textbox ‘ın yerini koordinatı verildi.
self.labelKp = QLabel('Kp', self)
self.LAYOUT_A.addWidget(self.labelKp, * (1, 0)) #
Qlabel ile etiket oluşturuldu. Widget ile arayüzdeki
bulunacak koordinatı verildi.
self.Set = QPushButton(text='Set')####################setting but
self.Set.setFixedSize(100, 50)
self.Set.clicked.connect(self.SetBtnAction)
self.LAYOUT_A.addWidget(self.Set, *(0, 0))
Set butonu oluşturuldu. Tıklandığında SetBtnAction
fonksiyonu çağırarak PID parametresini Arduino ‘a serial üzerinden iletecek.
def SetBtnAction(self): # burdan arduinoya
Kp = self.KP.text()
Ki = self.KI.text()
Kd = self.KD.text()
Rpm = self.RPM.text()
########### değerler girilmediyse bile bu değerleri alsınlar
if Kp =="":
Kp = "2.0"
if Ki == "":
Ki = "0.055"
if Kd =="":
Kd = "0.04"
if Rpm =="":
Rpm = "2000"
sendToArduino(Kp,Ki,Kd,Rpm)
return
Set butonuna basıldığında Textboxlarda veri yoksa defualt
olarak değerleri arduinoya atılcak.
def sendToArduino(Kp ,Ki ,Kd ,Rpm ):
massage = Kp + "," + Ki + "," + Kd + "," + Rpm
try:
arduino.write(massage.encode())
print("gönderildi", massage)
except:
print("gönderilmedi",massage)
Gidecek olan veriler tek bir mesaj olarak ayarlanır. Byte
veri tipine dönüştürerek serialden arduinoya yollanır.
while (True):
#time.sleep(0.0001)
x = arduino_read()
if x != None: ## gelen data bos değilse yazsın amacı plot edilcek değerin olması
mySrc.data_signal.emit(x)
print(x) # arduinodan gelen verileri yazıyo
arduinodan gelen RPM değerlerini yazıdırmak için hazırlanan
arduino_read() fonk çağırlır. Veri eğer uygun ise plot çizimi yapılır.
def arduino_read():
data = arduino.readline() # arduinodan line olarak veri çekiyo
data = byte_to_int(data) # byte i integer verisine ceviriiyo
return data
def byte_to_int(data): # integere cevirmek için gerekli işlemleri yapıyor
try:
str_rn = data.decode()
str = str_rn.rstrip()
i = int(str)
return (i)
except:
pass
ardunino_read() gelen verileri satır şeklinde alarak byte
verisini byte_to_int fonksiyonu ile integera çevrilir. Gelen veri plotu
çizilmek üzere retrun edilir.
Arduino kod Analizi:
KP = Serial.readStringUntil(',');
Serial.read();
·
Serial.readStringUntil() fonksiyonu ile gelen
veride “,” karakteri öncesindekileri almak için kullanılmıştır. Böylelikle
if (diff_time <=0)
now_rpm = 0;
else
now_rpm =(
(60000000/diff_time) /64 );
·
60000000 mikro-sn(1dk) ‘dır. Now_rpm de iki
yarık arasında interupt zamanı diff_time bölerek dakikadaki pulseleri sayar.
Bir turda 64 pulse olduğundan ,64 e bölerek bir turun hesabı yapılır .
PID_sistem() fonksiyonunda outputu oluşturmak için
katsayıları parametreler ile uygun bir şekilde çarparak outputu oluşturur. Hata
toplamı mutlak değerde max_rpm den buyuk ile max_rpm e eşitlenir hatayı sature
etmiş oluyoruz.
Mapping() fonksiyonunda 0< PID_value <255 arasında ise
direk PID_value değerini pwm olarak verilecek. PID_value>255 ise max pwm
değeri olan 255 output ( 5V )olarak motor sürücüsüne verilecek.
PID_value < 0 ise çıkış ise çıkış verilmeyecek.
Çalışma Diyagramı
Bağlantı Şeması:
Kaynakça
GUI için kullanılan kod :
https://thepoorengineer.com/en/motor-speed-control/
Yorumlar
Yorum Gönder