Sabit mesafede değişken hızlı ivmelenme Algoritması

Başlatan Mucit23, 08 Temmuz 2014, 18:13:38

Mucit23

Selamlar,

Enkoderli DC motor üzerinde yapmaya çalıştığım bir uygulama var. Motorun dönüş hızını PWM ile ayarlayabiliyorum. Nekadar döndüğünü ise Motor üzerine Tümleşik Encoderden gelen pals'leri sayarak tespit ediyorum. Elimde motora dair bu iki parametre var.

Yapmaya çalıştığım şeyi kısaca açıklayayım. Encoderden gelen puls'lara göre Timer değerim otomatikmen Motorun dönüş yönüne göre artıyor veya azalıyor. Burada Motor üzerinde sabit bir mesafe belirleyebiliyorum kendime. Örneğin başlangıçta timer değeri 0 iken motor 10 tur döndüğünde timer değerim 4000 oluyor.

4000 benim sabit mesafem. Bu mesafe içerisinde tamamlamak şartıyla motora kalkış rampası uygulamam gerekiyor. Yani bu 4000 puls'lık mesafe içerisinde belirli bir ivmelenme oranına göre PWM Duty değerini örneğin %80 Yapmam gerekiyor.

Bir grafik çizmeye çalıştım.

Grafikteki Ti süresi bu işi yapmak için geçen süre. Bu sürenin ne olduğu önemli değil. Önemli olan verilen ivmelenme hızına göre 4000puls'lık mesafe içerisinde yapılması.

Örneğin ben ivmelenme oranını 1 veriririm. Motor 0-4000 puls'luk mesafe içerisinde 0-%80 Duty oranına (Ti)3 saniyede çıkarken, İvmelenme oranını 5 verdiğimde (Ti)1 saniyede çıkabilmeli. Bu 3 saniye veya 1 saniye gibi değerlerin bi önemi yok.

4000puls'lık mesafe işi çok aklımı karıştırdı. Yani Belirli bir ivmelenme oranına göre 0'dan %80 Duty'ye çıkabilirim ama Bu işi nasıl 4000 puls'lık süre içerisinde tamamlayacağım? Çok kafam karıştı.

Bu iş için nasıl bir algoritma kurabilirim? Veya nasıl bir yöntem izleyebilirim?



trgtylcnky

#1
Şöyle bir sorun var: Diyelim ki PWM hızla doğru orantılı olsun, bu durumda 0-80 arasını ancak belli bir sürede çıkarsa 4000 pulse uzunluğunda yol kat edebilir. Yani bu ivmelenme hızı farklı değerler alamaz.

mesaj birleştirme:: 08 Temmuz 2014, 18:57:46

Bir hesap yaptım:
Çizdiğiniz grafikte eğime m diyelim. Burada PWM değerini de hız (v) olarak kabul edelim. Aynı zamanda pulse sayısını da yol (x) olarak kabul edelim.

v=mx
v=dx/dt   =>
dx/dt=mx  =>
dx/mx=dt   => iki tarafın integralini alalım
ln(x)/m=t+c  =>
x=C*e^mt    x(t) | t=0 =0 çünkü ilk başta hiç dönmemiş sayıyoruz yani C=0 =>
x=e^mt

Yani burada m sabit olduğuna göre x sadece zamana bağlı bir fonksiyon başka değişken yok.


Kabil ATICI

Tam hızda 1 sn de kaç  pals alıyorsun.? (motor rpm değeri?)
ambar7

Mucit23

Hocam aldığım puls'sayısının süreyle ilgisi yok. Şöyle düşünün motor miline bağlı bir enkoder var. Biz timer ile enkoderden gelen puls'ları sayıyoruz. Yani enkoderden 100 puls geldiğinde timerin değeride 100 oluyor.

Burada Motora uyguladığımız Frekansın veya motorun dakikada kaç rpm hızla döndüğünün hiçbir önemi yok.

Şöyle düşünelim. Ben PWM duty oranını arttırmaya başladığım zaman Motor dönmeye başlıyor ve enkoderden kara dalga gelmeye başlıyor.. Timerin değeride 0'dan itibaren artmaya başlıyor. Bu duty arttırma işlemini öyle bir yapmalıyımki Duty oranı %80 olduğunda Timerin değeri tam 4000 olsun. Buradaki Duty arrtırma hızınıda ivmelenme oranına göre yapmalıyım

Bu iş için bir algoritma kurmam lazım. Yorum yaparsanız sevinirim.

trgtylcnky

Hocam bu timer pulse sayısını saymıyor mu? Ben de diyorum ki ancak belli bir ivmelenmeyle bu pulse sayısı %80 ile yakalanabilir. Hızı biraz daha çabuk arttırsanız %80 olduğunda daha 4000 pulse etmemiş olur, biraz yavaş arttırsanız 4000 çoktan geçilmiş olur.

Kabil ATICI

 Duty oranı  %1 adımlarla artıracaksan olay lineer bir formüle dörer.
4000/80=50 yapar ki her 50 sayaç değerinde %1'lik Duty oranı artırman yeterli. Sonuçta %80'e 4000 darbenin sonunda erişirsin

Hız ne olursa olsun sonuçta sayıcı olayına göre olacağına göre tamam... İşlemci sayıcın bunu yakalayabilir mi bilmem...
ambar7

Mucit23

Alıntı yapılan: trgtylcnky - 08 Temmuz 2014, 22:28:27
Hocam bu timer pulse sayısını saymıyor mu? Ben de diyorum ki ancak belli bir ivmelenmeyle bu pulse sayısı %80 ile yakalanabilir. Hızı biraz daha çabuk arttırsanız %80 olduğunda daha 4000 pulse etmemiş olur, biraz yavaş arttırsanız 4000 çoktan geçilmiş olur.

Hocam sizin dediğiniz tam olarak birşey anlayamadım. Hız ve timerin artış hızı zaten Duty oranıyla orantılı bir şekilde artıyor. Yani öyle bir döngü kurmalıyımki Duty oranı arttırılırken enkoderden gelen puls sayısı 4000 olduğunda Duty oranım %80 olsun. Buradaki sorun Duty oranını lineer bir şekilde arttırsam bile Timerin artış hızının motorun devriyle alakalı olduğundan dolayı, timerin duty ile orantılı lineer bir artışının olmaması. Çünkü Duty oranını arttırmamla motor hızlanıyor dolayısıyla timerin artış hızıda artıyor. Problemim budur.

@ambar7 Hocam sizin dediğiniz mantık uyuyor aslında ama lineer bir artım olmuyor. Sebebi ise şöyle, Örneğin %10 duty açık iken 50 puls gelmesi örnek veriyorum 100ms sürerken, %70 duty verildiğinde motor dahada hızlanacağı için 50 puls gelmesi 10 ms'de gelecektir. Bu durumda gelen lineer olmayan bir artış söz konusu

Bu durumda yanılmıyorsam eğer aşağıdaki grafikteki gibi bir artış söz konusu oluyor.


Farklı fikirler, Farklı yöntemleride deneyebilirim. Kullandığım MCU STM32 serisinden birşey.  72 Mhz'de çalışıyorum. Enkoderden gelen puls'leri Timer donanımsal olarak sayıyorum. Yani ben timerin değerini okuduğumda motor ilk dönmeye başladığından itibaren kaç puls'lık bir dönüş yapmış görebiliyorum.

Farklı yöntemler farklı fikirlerde deneyebilirim. Yeterki şu sorunu aşayım.

Vallahi rüyalarıma girmeye başladı.  :-X

Kabil ATICI

Pulse-Duty arasında bir linerite istedin. Sonuçta senin istediğin doğrusallığı veriyor olması gerekir.  (aslında çösünürlükten dolayı merdiven şeklindedir.
İşin içine başka parametreleri ekleyeceksen o zaman işin rengi değişir tabii.
ambar7

sadogan

Farkılı bir fikir:
Motorun devri pwm değer artışına hemen çevap veremez.
4000 puls lik mesafeyi parcalara bölerek her parca için pwm
değerlerini deneme ile bulup ,motor un her parça için cevap verme süresi ölçülerek
belierlenen sürelerde deneme ile bulunan pwm değerleri ile test edilebilir.


mistek

(Sadece fikir)
PWM değerini lineer olarak arttırmayın.

Örneğin ilk 1000 pals için %40
Sonraki 1000 için %20
Sonraki için %10
Sonraki için %10 gibi.

Deneyerek sonuca varılır belki.
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Mucit23

Belkide lineer bir artışa ihtiyacım yoktur

Yapmaya çalıştığım şey kısaca şudur. DC100W gücünde Enkoderli bir motorum var.  Bu motor halatlı bir düzenek ile bir nesneyi ileri geri hareket ettiriyor. Motorun diyelimki ileri yönde nekadar hareket edebileceği enkoder vasıtasıyla daha önce belirlenmiş sabit bir değer. Örneğin 0-30000 puls arası olabilir. Ben bu parametreye bağlı kalarak motorun ileri ve geri yöndeki hareketinde Motora Hızlanma rampası, ve yavaşlama rampası uygulamam gerekiyor.

Şuanda Motor için IR2101 Mosfetli H köprüsü kurdum. Motoru İstediğim şekilde devrini ayarlayarak ileri geri döndürebiliyorum. Enkoderden de kaç puls gelmiş timer ile sürekli takip edebiliyorum. Yani başlangıç noktasından itibaren motor nekadar dönmüş, Timerin değerine bakarak anlayabiliyorum. Bu iki temel konuyu çözdüğümü söyleyebilirim.

Bazı değişken parametrelerim olacak bu parametrelere uymam gerekiyor.

1-) Hızlanma ivmesi
2-) Max. Hız
3-) Yavaşlama ivmesi
4-) Min Hız.

Bundan sonra yapmam gereken start emrini aldıktan sonra Hızlanma ivmesinde belirtilen parametre doğrultusunda motoru max. Hız'a ulaştırıp belirli bir süre max hızda hareket ettikten sonra yavaşlama ivmesi doğrultusunda motoru yavaşlatıp min. Hız'a  indirip ardından motoru durdurmak.

Motorun Max. Hareketi 30000 puls olduğunu varsayarsak ben ilk 4000 puls'lık mesafe içerisinde motoru max. hıza(%80 Duty) ulaştırıp, 22000 puls'lık mesafede max hızda hareket ettirip geriye kalan 4000 pulslık mesafedede motoru min. hıza indirip durdurmayı hedeflemiştim. Anlaşılan mesafe ile orantılı olarak motorun duty oranında değişim yapmak mümkün değil. Belki tablo ile felan olur ama esnek olmaz. Çünkü bu parametreler değişebilmeli.

Ben ambar7 nin bahsettiği yöntemi bir deniyeyim. Dediğim gibi belkide lineer bir artışa ihtiyacım yoktur. Bu konuda ne düşünürsünüz bilmiyorum ama önemli olan motoru yavaş  bir şekilde kaldırmak değilmidir. Zaten ilk başta yavaş bir kalkış yapılıyor. Sonrasında hızlı bir şekilde set değerine ulaşacaktır.

RaMu

Aşağıda anlattığım olay şu;
deneme yanılmayla bunu yapabilirsin,
misal 1 milisaniyede bir pwm duty değerini %1 arttır
taki %80 e gelene kadar bunu tekrarla
encoderdan okunan değeri ölç,
enceder 4000 okuyamamışsa
1 milisaniyede bir değilde 2 milisaniyede bir pwm duty %1 arttır
4000 den fazla okumuşsa 1 milisaniyeden daha kısa süre aralıklarıyla pwm duty %1 arttır,
bu şekilde 4000 okumasına erişmek için gerekli süreyi bulursun,
ve bu sayede pwm duty oranını sabit zaman aralıklaruyla arttırdığın için
pwm duty artış ile zaman arasında lineer bir bağ olur.



Öncelikle pwm duty ile motor dönüş hıza arasındaki ilişkiyi bulmak lazım
yada pwm duty ile encoder değeri arasındaki ilişki,
yani misal pwm duty %1 iken encoder saniyede x okuyor
pwm duty %2 iken encoder saniyede y okuyor,
pwm duty %80 iken encoder saniyede z okuyor,
x y z 1 2 80 ise ne güzel olur
pwm duty ile motor dönüş hızı lineer değişiyor deriz ki
bence bu olası bir durumdur, büyük ihtimal böyle olacaktır,
ama yinede bunu gözlemleyip bir tablo çıkarmalısın,
(özellikle pwm in ilk %20 ye kadar artışında motor belki dönmeyecektir bile)

sonra;
artık motorun pwm duty değişimine göre kaç tur atacağını biliyor durumdayız,
şimdi kendimize (0 dan %80 duty e çıkma) zaman dilimi belirleyeceğiz,
anlaşılır olması açısından,
motor %80 pwm duty ile saniyede 80 tur atıyor yok yok encoderdan  saniyede 80 okunuyor diyelim,
%79 pwm encoder 79
.
.
.
%1 pwm encoder 1

Eğer ben her saniyede pwm duty i %1 arttırırsam
enceder toplamda (0 dan 80 e kadar sayıların toplamı) değerini gösterir,
(80*81)/2 = 3240
toplamda 4000 olmasını istiyorduk
(4000/3240) saniyede bir pwm duty %1 arttırılmalı demektir,
yani 1.2346 saniyede bir pwm duty %1 arttırılmalı,

tabi burada pwm duty %1 iken dahi motorun döndüğünü,
pwm duty oranıyla motorun dönüş hızının doğru orantılı olduğunu
varsaydık, böyle değilse
bu oranlarda aynı hesaba dahil edilir.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

trgtylcnky

O zaman dinamik bir sistem olarak ele alıp şöyle düşünelim:
F=m*a
[Motorun uyguladığı kuvvet]-[Sürtünme]=[Hareket eden toplam kütle]*[ivme]
Motorun uyguladığı kuvvet motorun çektiği akımla doğru orantılıdır. Motor harekete geçmeden önce en fazla stall torku kadar tork uygulayabilir. Bu durumda  statik sürtünmeyi de hesaba katıp ne kadar tork uygulanacağını dolayısıyla PWM değerini bulursunuz. Bu değer sizin ihtiyacınız olan torkun stall torka oranıdır.
İlk hareketten sonra hızı sürekli kontrol edersiniz. Mesela bakarsınız 10 pulse kaç saniyede gelmiş, hızı bulursunuz. Eğer sizin planladığınız hızdan (sabit ivmeyle v=a*t) fazla ise PWM yüzdesini düşürür, az ise artırırsınız.
Ya da ilk hareketten sonra mesafeyi sürekli kontrol edersiniz ki bu bence daha kolay. Planlanan mesafeyi x=(1/2)*a*t^2 olarak bulup encoderden okuduğunuz değer bunu geçiyorsa PWM düşürür gerisinde kalıyorsa arttırırsınız.
Ama yine de söylüyorum, ilk baştaki dediğiniz iş şuna benziyor: 0'dan 100'e 3 saniyede çıkan bir arabayla 6 saniyede çıkan bir araba düşünün, 6 saniyede çıkan bu hızlanma esnasında daha fazla yol almış olur, bunu değiştiremeyiz bence.

Karışık yazdığımın farkındayım. Aslında anlamdığımdan. Mesela hızlanmanın sonunda ulaşılacak %80 max hızın %80'i mi yoksa sadece PWM %80 mi? Sabit ivmeli bir hızlanma mı istiyorsunuz ve bu sabitlik ne kadar önemli?

Reprap Marlin yazılımında bu gibi hareketleri planlayan bir algoritma var. Ben anlamadım ama belki siz anlarsınız: https://github.com/ErikZalm/Marlin/blob/Marlin_v1/Marlin/planner.cpp

EGE

Ben şöyle yapıyorum ,

Start yapıldığında motor beslemesini bir rezistans üzerinden geçir istediğin süre sonunda rezistansı devreden çıkart motor direk besleme ile çalışsın.

Stop zamanına yaklaştığında  yine Rezistansı devreye sok kısa bir süre içinde yine devreden çıkart .

Zaten bu istediklerin kıssa bir zaman dilimleri  içinde kalkış ve durma olacağı için rezistans çok fazla ısınmayacaktır.
Elektirkçilerde   yay şeklinde olan rezistansları rahatlıkla kullanabilirsin.   

hasankara

#14
pid le estimate yapacaksın. özetle ivme fonksiyonu çıkışı ile hedef eğri fonksiyon çıkışları sürekli olarak belli bir sıklıkta pid kontrol içinde karşılaştırma yaparak motora pwm uygulayacak. burada 3 farklı yoğunlaşman gereken nokta var. 1.pid 2.ivme fonksiyonu 3.hedef eğri fonksiyonu. pid için çok kasmana gerek olmayabilir.

        if (IFS0bits.T4IF) {
            IFS0bits.T4IF = 0;
            if (ReadADC10(9) > 910)if (OC1RS > 0)OC1RS--;
            if (ReadADC10(9) < 908)if (OC1RS < 1000)OC1RS++;
        }

bu şekilde basit bir işlem de olsa işlemciye fazla yük bindirmeyerek işini görebilir. kontrol algoritmasını daha da geliştirerek mesela gerçek bir pid algoritması kullanarak, hedeflediğin eğriye daha yakın şekilde sonuç alman mümkün, tabi bu tercihleri yaparken araç gereçlerinin sınırlarını her zamanda göz önünde bulundurman gerek işlemci hızı vs. aynı zamanda sen bu kodda if içindeki karşılaştırmaları, iki fonksiyonun çıkışlarını karşılaştırarak yapacaksın ve iki fonksiyonda dinamik olacak elbette kontrole girmeden önce fonksiyonların çıkışları güncellenmiş olacak.

ivme fonksiyonu; encoderden gelen değerlerin değişimleri ne kadar sürede olduğunu hesaplayacak. yani atıyorum 300 dür, ilk 300 olduğu andan itibaren timerin sayıyordur ve 1 artmasıyla birlikte timer den capture yaparsın, yani değeri okuyup timeri 0 larsın. okuduğun timer değeri ivme fonksiyon çıkış parametren olacak, ama dikkat edeceğin diğer nokta timer değeri artması demek ivmenin düşmesi demek yani ters orantı var. yaaani çıkış parametren a^-1 aslında, katsayısı var bunun daha ama en son deneme yanılma yapacağın için sadece hedef fonksiyon çıkışına katsayı koyman yeterli olacak. buna göre değerlendirmeni yapacaksın.

hedef fonksiyonu ise; ivmenin senin istediğin şekilde seyredeceği fonksiyondur. bu fonksiyon özel tanımlı bir fonksiyon olabilir, yani encoder 500.cü değerde ivme şu olsun 600.cü değerde ivme şu olsun yada exponansiyel artmasını istersin exp(encoder) şeklinde hedef ivme değerleri elde edebileceğin bir fonksiyon olabilir bu. anladığım kadarıyla sabit ivmeyle kontrol yapmak istiyorsun(1 veririm, 5 veririm demene göre). bu durumda benim yaptığım gibi hiç fonksiyona gerek olmadan belli bir sayıdan büyük mü ve küçük mü diyerek işin içinden sıyrılabilirsin. yani encoder kaçıncı değer olduğunun önemi yoktur hedef ivmen hep aynı değer zaten.

        if (new_capture) {
            new_capture = 0;
            if (capture < 910)if (pwm > 0)     pwm--;
            if (capture > 908)if (pwm < 255) pwm++;
        }


ivme= capture^-1 old için dikkat ettiysen ilk yazdığım kodla farklı olarak küçükse değeri azalt büyükse değeri arttır deyişim. 910 ve 908 ise senin vereceğin sabit hedef ivme değerinin katsayısıyla çarpılmış olan sayısal değeri. tüm bu kontrol kodlarını da if(encoder<4000) kontrolü içerisine aldığında bu yazdıkların sadece başlangıçta etkin olan bir kod bloku haline gelmiş olur.

mesaj birleştirme:: 09 Temmuz 2014, 09:18:22

birde şimdi fark ettim ilk hızsız başlayacağı için yeni encoder bilgisi hiç alınamayacak ve pwm e müdahale edilemeyecek.

if (new_capture||another_timer_flg) {
            new_capture = 0;
            another_timer_flg=0
            if (capture < 910)if (pwm > 0)     pwm--;
            if (capture > 908)if (pwm < 255) pwm++;
        }


bunun için başka bir timer ile de kontrol blokuna girmesini sağlamamız gerekiyor. motor hiç dönmez iken yeni capture alınamayacak. en kötü ihtimalle belli bir sürede (timeout gibi düşünebilirsin) bu algoritmaya girmesi gerekiyor.