Arama butonu
Bu konudaki kullanıcılar: 1 misafir
13
Cevap
6884
Tıklama
0
Öne Çıkarma
Arduino PID Motor Kontrol
C
11 yıl
Teğmen
Konu Sahibi

Merhaba arkadaşlar,

Bitirme projesi olarak arduino ile pid motor kontrolü yapmamızı istedi hoca. Bir arkadaşımla birlikte yapıyorum ama ne ben ne de o programlama konusunda iyi sayılmayız.

Arduino uno aldık biraz üstünde çalıştık ama pid işi biraz karıştırıyor malesef.

hocanın bizden istediği şu; arduino nun pwm çıkışını alçak geçiren filtreden geçirdikten sonra laboratuvardaki motora vereceğiz ve feedback olarak da motorun şaftına bağlı olan tachogeneratorden gelen sinyali alacağız. input değerlerini arduino üzerinden potansiyometre ile vermemizi istiyor. Donanım olarak sıkıntımız yok zaten laboratuvardaki ekipmanları kullanıyoruz ama dediğim gibi büyük sıkıntı yazılım konusunda

pid yazılımı konusunda yardım edebilecek arkadaşlar varsa lütfen yardımlarını esirgemesinler.

şimdiden herkese teşekkür ediyorum.

DH forumlarında vakit geçirmekten keyif alıyor gibisin ancak giriş yapmadığını görüyoruz.

Üye olduğunda özel mesaj gönderebilir, beğendiğin konuları favorilerine ekleyip takibe alabilir ve daha önce gezdiğin konulara hızlıca erişebilirsin.

Üye Ol Şimdi Değil



F
11 yıl
Onbaşı

takipteyim benim de buna benzer bir projem var. Umarım cevap veren arkadaşlar çıkar.


Bu mesaja 1 cevap geldi.
C
11 yıl
Teğmen
Konu Sahibi

quote:

Orijinalden alıntı: faruközalp

takipteyim benim de buna benzer bir projem var. Umarım cevap veren arkadaşlar çıkar.

evet umarım cevap veren çıkar


Bu mesaja 1 cevap geldi.
A
11 yıl
Yüzbaşı

PID 'nin P si için

set değerinden gerçek ( ölçtüğün ) değeri çıkar

P katsayısıyla çarpıp arduino çıkışa ver

sanırım hazır bir motor sürücün var

arduinonun çıkışı ne olacak ? 0-10 V kontrol sinyali - bunu sürücünün hız kumanda girişine vereceksin


I kısmı için gene set değerinden ölçtüğün değeri çıkar

bunu long integer türünde bir değişkene her saykılda topla ( mesela her 10 milisaniyede bir )

sonra bunu I katsayısına böl ve deminki P değerine topla


D kısmı için de

bir önce ölçtüğün değeri en son ölçtüğün değerden çıkar

bunu D katsayısıyla çarpıp gene deminki PI toplamıyla topla

temeli bu , yalnız D parçası osilasyona sebep olabilir bunun katsayısını küçük tut

bir de PID de oluşan ham değerlerin kendisi değil (-1) ile çarpılmışı yani tersi gerekebilir

onu deneyerek bulacaksın

nasıl bulacaksın ?

mesela önce P ile başladın ve kontrol çevrimini kapatınca motor hızı uçtu o zaman sinyalin yönü ters olması gerekirmiş - bunun gibi


Bu mesaja 1 cevap geldi.
C
11 yıl
Teğmen
Konu Sahibi

quote:

Orijinalden alıntı: anotherbrick

PID 'nin P si için

set değerinden gerçek ( ölçtüğün ) değeri çıkar

P katsayısıyla çarpıp arduino çıkışa ver

sanırım hazır bir motor sürücün var

arduinonun çıkışı ne olacak ? 0-10 V kontrol sinyali - bunu sürücünün hız kumanda girişine vereceksin


I kısmı için gene set değerinden ölçtüğün değeri çıkar

bunu long integer türünde bir değişkene her saykılda topla ( mesela her 10 milisaniyede bir )

sonra bunu I katsayısına böl ve deminki P değerine topla


D kısmı için de

bir önce ölçtüğün değeri en son ölçtüğün değerden çıkar

bunu D katsayısıyla çarpıp gene deminki PI toplamıyla topla

temeli bu , yalnız D parçası osilasyona sebep olabilir bunun katsayısını küçük tut

bir de PID de oluşan ham değerlerin kendisi değil (-1) ile çarpılmışı yani tersi gerekebilir

onu deneyerek bulacaksın

nasıl bulacaksın ?

mesela önce P ile başladın ve kontrol çevrimini kapatınca motor hızı uçtu o zaman sinyalin yönü ters olması gerekirmiş - bunun gibi




Hocam öncelikle cevabın için çok teşekkür ediyorum.

Ama PID kısmını bende zihnimde oluşturabiliyorum, dediğim gibi asıl sıkıntı kod kısmında yani giriş çıkış verme pinleri atama falan yapıyorum ama pid yi koda dökmede sıkıntı yaşıyorum o konuda yardımcı olabilir misiniz.

bu arada sürücüm yok ama labdaki deney seti üzerindeki filtre ve power amplifier üzerinden motoru sürmeyi planlıyoruz. (en azından hoca öyle dedi)


Bu mesaja 1 cevap geldi.
C
11 yıl
Teğmen
Konu Sahibi

arkadaşlar şu forumda arduino programlamadan anlayan üstatlar yok mu ya şu imdat çağrıma bir cevap verin lütfen


Bu mesaja 1 cevap geldi.
A
11 yıl
Teğmen

beyler ardunıo yu bılmıyorum ama hı-tech c ile yaptığım pid kontrollü çizgi izleyen robot var isterseniz örneğini atayım ona göre ardunio kodları ile değiştirip uygularsınız.


Bu mesaja 1 cevap geldi.
C
11 yıl
Teğmen
Konu Sahibi

quote:

Orijinalden alıntı: Apollo-07

beyler ardunıo yu bılmıyorum ama hı-tech c ile yaptığım pid kontrollü çizgi izleyen robot var isterseniz örneğini atayım ona göre ardunio kodları ile değiştirip uygularsınız.

valla burada paylaşabilirsen çok makbüle geçer


Bu mesaja 1 cevap geldi.
A
11 yıl
Teğmen

Üniversite de yazmaya çalışmıştım isis de çalışmıştı ama devre üstünde bir türlü çalıştıramadım donanımsal dı sanırım hatalar.
şimdi tekrardan bakayım dedım de unutmuşum proğramlamayı neredeyse :D

// hı-tech pid deneme 877a
#include <htc.h>
#include "delay.h"
char deger=0;
long k=0,i,a,sens[8],maxdeg[8]={500,500,500,500,500,500,500,500},mindeg[8]={500,500,500,500,500,500,500,500};
long fon=0,fon2=0,say=0,sensor,last_sensor,duz;
long last_error,error,correction=0,mak=250,pr,der,derr;
char kp=0.45,kd=5.25,m=0;
void duz_hareket()
{
T2CKPS1=1; // Prescaler 1:16 oluyor
T2CKPS0=1;
TOUTPS3=0; // Postscale 1:1 oluyor
TOUTPS2=0;
TOUTPS1=0;
TOUTPS0=0;
PR2=250;

CCPR1L=0x3E; // Duty registere 250 yükleniyor
CCP1X=1; // Duty cycle 1ms periyodunda
CCP1Y=0;
CCP1M0=1; // CCP1 PWM modunda
CCP1M1=1;
CCP1M2=1;
CCP1M3=1;

CCPR2L=0x3E; // Duty registere 250 yükleniyor
CCP2X=1; // Duty cycle 1ms periyodunda
CCP2Y=0;
CCP2M0=1; // CCP2 PWM modunda
CCP2M1=1;
CCP2M2=1;
CCP2M3=1;

TMR2ON=1; // Timer 2 çalıGtırılıyor*/
PORTB=4;
DelayMs(250);
PORTB=0;
char j=0;
for(j=10;j<250;j++)
{
RB2=~RB2;
CCPR1L=j;
CCPR2L=j;
DelayMs(1);
}
CCPR1L=250;
CCPR2L=250;
PORTB=0x0f;
}
void sifirla() // sıfırlanması gereken değerleri sıfırla...
{
fon=0;
fon2=0;
say=0;
duz=0;
}
void sensor_oku()
{
RB2=~RB2;
CHS2=0; // AN0 seçiliyor
CHS1=0;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[0]=deger;
CHS2=0; // AN1 seçiliyor
CHS1=0;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[1]=deger;
CHS2=0; // AN2 seçiliyor
CHS1=1;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[2]=deger;
CHS2=0; // AN3 seçiliyor
CHS1=1;
CHS0=1;
DelayUs(35);
deger=(ADRESH*256+ADRESL);
GO=1; // Çevrim baGlatılıyor
while(GO);
sens[3]=deger;
CHS2=1; // AN4 seçiliyor
CHS1=0;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[4]=deger;
CHS2=1; // AN5 seçiliyor
CHS1=0;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[5]=deger;
CHS2=1; // AN6 seçiliyor
CHS1=1;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[6]=deger;
CHS2=1; // AN7 seçiliyor
CHS1=1;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[7]=deger;
for(i=0;i<8;i++)
{
sens=(int)((1000*(sens-mindeg))/(maxdeg-mindeg));
if(sens<250)
{
sens=0;
}
else if(sens>850)
{
sens=1000;
}
fon=fon+(sens*say);
fon2=fon2+sens;
say=say+1000;
duz=duz+sens;
if((fon/fon2)==0)
{
sensor=last_sensor;
}
else
{
sensor=(fon/fon2);
}
last_sensor=sensor;
}
}
void ilk_ayar()
{
for(a=0;a<25;a++)
{
PORTB=0;
for(i=0;i<255;i++)
{
CHS2=0; // AN0 seçiliyor
CHS1=0;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[0]=deger;
CHS2=0; // AN1 seçiliyor
CHS1=0;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[1]=deger;
CHS2=0; // AN2 seçiliyor
CHS1=1;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[2]=deger;
CHS2=0; // AN3 seçiliyor
CHS1=1;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[3]=deger;
CHS2=1; // AN4 seçiliyor
CHS1=0;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[4]=deger;
CHS2=1; // AN5 seçiliyor
CHS1=0;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[5]=deger;
CHS2=1; // AN6 seçiliyor
CHS1=1;
CHS0=0;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[6]=deger;
CHS2=1; // AN7 seçiliyor
CHS1=1;
CHS0=1;
DelayUs(35);
GO=1; // Çevrim baGlatılıyor
while(GO);
deger=(ADRESH*256+ADRESL);
sens[7]=deger;
for(k=0;k<8;k++)
{
if(sens[k]>maxdeg[k])
{
maxdeg[k]=sens[k];
}
if(sens[k]<mindeg[k])
{
mindeg[k]=sens[k];
}
}
}
}
for(m=0;m<=5;m++)
{
DelayMs(250);DelayMs(250);
RB1=~RB1;
}

}
void main(void)
{

TRISA=0xEF; // analog okumalar acıldı
TRISE=0xFF; // RA0 ve RA1 giriG
TRISC=0xF0; // PORTC çıkıG olarak ayarlanıyor
TRISB=0xF0; // RB4..RB7 giriG, diğerleri çıkıG
PORTB=0x00; // PORTB sıfırlanıyor
PORTC=0;
PCFG3=0; // AN0-AN7 analog girişleri açıldı
PCFG2=0;
PCFG1=0;
PCFG0=0;

ADFM=1; // Sağa dayalı yazılıyor
ADON=1;
// ADIF=0; // ADC bayrağı temizleniyor
// ADIE=1; // ADC kesmesi izni veriliyor
TMR2IF=0;
TMR2IE=1;
PEIE=1; // Genel ve yardımcı kesme izinleri veriliyor
GIE=1;
ilk_ayar();
for(;;)
{
duz_hareket();
PORTB=255;
PORTD=0;
while(1)
{
sensor_oku();
error=sensor-750;
if(error>-70 && error<70)
{
CCPR1L=200;
CCPR2L=200;
}
else
{
CCPR1L=250;
CCPR2L=250;
}
pr=(error*kp); // oransal deger = hata *kp
der=(error-last_error);
derr=der*kd;
last_error=error;
correction=pr+derr;
if(correction>mak)
{
correction=mak;
}
if(correction<-mak)
{
correction=-mak;
}
if(correction>0)
{
CCPR1L=(mak-correction);
CCPR2L=250;
}
else
{
CCPR2L=(mak+correction);
CCPR1L=250;
}
sifirla();
}
}
}

void interrupt
an_dig(void)
{
// if(ADIF) // Çevrim bitiş kesmesi bekleniyor
// {
// deger=ADRESH*256+ADRESL;
// ADIF=0; // Kesme bayrağı sıfırlanıyor
// }
if(TMR2IF)
{
TMR2IF=0;
}
}




Bu mesajda bahsedilenler: @CybeR_chaqaL
C
11 yıl
Çavuş

Hocam benimde aslinda pek bilgim yok ama bir onerim olcak. Arduinoturkiye foruma bakarsaniz kesinlikle yardimci olurlar.



< Bu ileti mobil sürüm kullanılarak atıldı >
Bu mesaja 1 cevap geldi.

Bu mesajda bahsedilenler: @CybeR_chaqaL
A
10 yıl
Binbaşı

M
10 yıl
Binbaşı

Yaptığım çizgi izleyene ait PID kısmından bir örnek. analogWrite komutu ile sinyali PWM kanalına aktarmış oluyoruz.
 
else if ((sensor_counter > black_up) && (sensor_counter != 8)) {
calculateLinePos(BLP);
motorDIR(0, 0);

P = ((reference_point - black_line_pos) * KP);

I = ((I + (reference_point - black_line_pos)) * KI);

D = (((reference_point - black_line_pos) - last_error) * KD);

last_error = reference_point - black_line_pos;

PID = ((P + I + D) / prescaler);

if (PID > 0) {
sagHiz = maxSpeed - PID;
solHiz = maxSpeed;

if (sagHiz < 0)
sagHiz = 0;
}

if (PID == 0) {
solHiz = maxSpeed;
sagHiz = maxSpeed;
}

if (PID < 0) {
sagHiz = maxSpeed;
solHiz = maxSpeed + PID;

if (solHiz < 0)
solHiz = 0;
}
analogWrite(PWMA, sagHiz);
analogWrite(PWMB, solHiz);
}


Bu mesaja 1 cevap geldi.

Bu mesajda bahsedilenler: @CybeR_chaqaL
M
9 yıl
Çavuş

Burada cevabı arayanlar için arduino sitesinde çok güzel bir kütüphane oluşturulmuş, rahatça yapabilirsiniz.
http://playground.arduino.cc/Code/PIDLibrary


Bu mesaja 1 cevap geldi.
F
9 yıl
Onbaşı

http://playground.arduino.cc/Code/PIDLibrary kullanarak yaptığım bir çalışmayı aşağıdaki videodan izleyebilirsiniz.

https://www.youtube.com/watch?v=6iFlfeCihDY

ana döngüde tek yaptığım aşağıdaki yazılım.
PID kontrolün en önemli özelliği linear time invariant sistemler için kullanılabiliyor olması.
Eğer sisteminizin tepkileri zamanla değişiyorsa sistemi modelleyip adaptive tuning yapmanız gerekir.

myPID.Compute();
ServoOutput=servocenter+Output;
myServo.writeMicroseconds(ServoOutput);

Kolay gelsin



DH Mobil uygulaması ile devam edin. Mobil tarayıcınız ile mümkün olanların yanı sıra, birçok yeni ve faydalı özelliğe erişin. Gizle ve güncelleme çıkana kadar tekrar gösterme.