Enkoder ile Açı Hesaplama

Başlatan Mucit23, 17 Nisan 2018, 19:40:47

Mucit23

Selamlar

Elimde 360PPR çözünürlüğe sahip bir enkoder var ve ben bunu BLDC motora bir kaplin ile bağladım. Motorun şaft açısını doğru bir şekilde ölçmeye çalışıyorum fakat bir sorunum var.

Enkoderi Timerin XOR girişine bağladım. Dolayısıyla Timerin Enkoderden gelen A ve B sinyallerine göre otomatikmen artıp azalıyor. Enkoder'in A ve B fazları Xordan geçtiği için Enkoder çözünürlüğüm 360x4=1440 oluyor. Yani Enkoder milinin Tam 1 turunda Timerim 0'dan 1440'a kadar artmış oluyor. Buraya kadar herşey normal.

Açı ölçmek için Yaptığım işlem şudur. Timer'in önceki değeri ile yeni değeri arasında ne kadarlık bir fark olduğunu bulup bir sayıcıya bulduğum fark değerini ekliyorum her seferinde. Daha sonra Sayıcının 360'a bölümünden kalanına bakıyorum. Fakat burda bir hata var.

Benim Timerim 16 bitlik ve 0-65535 arası değişiyor. Ve 65535 değeri 1440'a tam bölünmediği için Timer 65535'den sonra sıfırlandığından dolayı bir miktar açısal hata yapıyorum. Benim motor mili kaç tur dönerse dönsün başlangıcı sıfır kabul ederek milin olduğu konumun açısını bulmam gerekiyor.

Bunun için nasıl bir yol izleyebilirim? 

Cemre.

Encoder'in Z sinyalini Timer CNT değerini sıfırlayacak şekilde kullanırsanız sürekli 0-1439 arasında sayarsınız :)

Endorfin35+

Merhaba.

Neden timer kullanmak istediniz anlamadim. 2 adet interrupt pini kullanarak high low degisimleri sayarak yine  360x4 cozunurlugu elde edersiniz.. Sayac her 1440 a geldiginde sayaci sifirlayin. Isterseniz sifirlama sirasinda tur sayisi +1 mantigi ile turda sayin. Motor durdugu zaman sayac/360 olarak motor milinin ilk posizyona gore acisini hesaplayabilirsiniz. 
"İşi bilen yapar, az bilen akıl verir, bilmeyen eleştirir, yapamayan çamur atar."

Mucit23

Alıntı yapılan: Cemre. - 17 Nisan 2018, 20:19:30Encoder'in Z sinyalini Timer CNT değerini sıfırlayacak şekilde kullanırsanız sürekli 0-1439 arasında sayarsınız :)

Timeri Donanımsal olarak sıfırlamak mümkünmü? Bildiğim kadarıyla böyle bir seçenek yok. Eğer Extint ile Z sinyalini yakalayıp Timeri sıfırlamaktan bahsediyorsanız buda bana pek mantıklı gelmiyor. Program Extint kesmeye zıplayana kadar birkaç puls atlanabilir. Özellikle yüksek hızlarda. Bunu matematiksel olarak çözsem güzel olacak.

Alıntı yapılan: Endorfin35+Merhaba.

Neden timer kullanmak istediniz anlamadim. 2 adet interrupt pini kullanarak high low degisimleri sayarak yine  360x4 cozunurlugu elde edersiniz.. Sayac her 1440 a geldiginde sayaci sifirlayin. Isterseniz sifirlama sirasinda tur sayisi +1 mantigi ile turda sayin. Motor durdugu zaman sayac/360 olarak motor milinin ilk posizyona gore acisini hesaplayabilirsiniz.

STM32'nin Timerlerinde Encoder İnterface modu var. A ve B sinyallerini takip edip otomatikmen counteri arttırıp azaltabiliyor.

Cemre.

#4
Alıntı yapılan: Cemre. - 17 Nisan 2018, 20:19:30Encoder'in Z sinyalini Timer CNT değerini sıfırlayacak şekilde kullanırsanız sürekli 0-1439 arasında sayarsınız :)

Timer Enkoder interface ayarlanınca Slave Mode kullanılamıyormuş, sözümü geri aldım :/

Belki şöyle bir şey olabilir.
Timer ARR değeri enkoder pulse değerininin katı olan bir sayıya ayarlanır (1440*k). Timer aktive edilmek için Z sinyalinin yükselen kenarı beklenir. Z sinyali gelene kadar Timer saymaz. Zaten starting algorithm oluşturmak zorundasınız çünkü başlangıçta rotor pozisyonu bilemeyeceksiniz. Z sinyalini bulana kadar motor fazlarını sırayla enerjilendirip Z gelince 0'dan başlayarak çalıştırabilirsiniz motoru. Eğer sorun yaratacağını düşünüyorsanız EXT Interrupt'ı da disable edersiniz.

Mucit23

Anladım. O işi Çözdüm gibi.

Şunu sormak istiyorum ek olarak.Amacım Hall sensör yerine Enkoder kullanarak Blok komutasyon yapmak.  Enkoder den konum bilgisini okuduk diyelim. Şuanda 0-1440 Arası değişen Enkoder bilgisi var. Bu enkoder Bilgisine Göre komutasyon nasıl yapacağım?

Aslında birşeyler yaptım ama hatam var. Anlamadığım nokta şu. Motor Miline Enkoderi Rastgele bağladık. Motor mili hangi konumda olursa olsun sistem ilk açılışta konumu sıfır kabul ediyor. Daha sonra gelen encoder sinyallerine göre şaft şu kadar döndü diyoruz. Ama rotor pozisyonunu tam olarak bilmiyoruz. Bu yüzden enkoderden gelen sinyallere göre komutasyon yaptığımda rotor pozisyonunu doğru olarak nerde olduğunu bilmediğim için yanlış fazı enerjilendiriyorum ve motor dönmüyor. Böyle bir sorunum var.

Bunu nasıl yapacağımı anlayamadım.

ilyas KAYA

Kaliteli bir potans takin sizin bütün işinizi görür.
Encodere de gerek kalmaz.
Sorun filan çıkarmaz 10 yıldır çalışanını biliyorum.

Cemre.

Alıntı yapılan: Mucit23 - 18 Nisan 2018, 14:12:59Anladım. O işi Çözdüm gibi.

Şunu sormak istiyorum ek olarak.Amacım Hall sensör yerine Enkoder kullanarak Blok komutasyon yapmak.  Enkoder den konum bilgisini okuduk diyelim. Şuanda 0-1440 Arası değişen Enkoder bilgisi var. Bu enkoder Bilgisine Göre komutasyon nasıl yapacağım?

Aslında birşeyler yaptım ama hatam var. Anlamadığım nokta şu. Motor Miline Enkoderi Rastgele bağladık. Motor mili hangi konumda olursa olsun sistem ilk açılışta konumu sıfır kabul ediyor. Daha sonra gelen encoder sinyallerine göre şaft şu kadar döndü diyoruz. Ama rotor pozisyonunu tam olarak bilmiyoruz. Bu yüzden enkoderden gelen sinyallere göre komutasyon yaptığımda rotor pozisyonunu doğru olarak nerde olduğunu bilmediğim için yanlış fazı enerjilendiriyorum ve motor dönmüyor. Böyle bir sorunum var.

Bunu nasıl yapacağımı anlayamadım.

Nasıl çözdünüz?

Mucit23

int32 lik bir değişkende sayac değerimi tutuyorum. +2147483647 ile -2147483647 arasında bir değişim aralığım var. Bu aralık içerisinde taşma olmadan çalışabiliyorum. 

Ayrıca şöyle bir fonksiyon yazdım.

uint32_t Get_Encoder_Counter(void)
{
  uint16_t Current_Tim_Counter = TIM3->CNT;
	int16_t Delta_Pos = (int16_t)(Current_Tim_Counter - Old_Tim_Counter);
	Old_Tim_Counter=Current_Tim_Counter;
	
	Encoder_Position += Delta_Pos;
	
	return Encoder_Position;
}

uint16_t Get_Shaft_Position(void)
{
	 int16_t Enc_Shaft_Pos_Temp=Get_Encoder_Counter() % ENCODER_PPR;
  
	 if(Enc_Shaft_Pos_Temp<0)
     Encoder_Shaft_Position = ENCODER_PPR + Enc_Shaft_Pos_Temp;
	 else
	   Encoder_Shaft_Position = Enc_Shaft_Pos_Temp;
	 
	 return Enc_Shaft_Pos_Temp;
}

Bu fonksiyon ile Şaft pozisyonuna göre 0-1440 arası değerler alıyorum. Hocam şimdi Enkoderi düzgün çalıştırdık diyelim. Komutasyon işini çözemedim. Motor Saftı ile nasıl senkronize komutasyon yapacağım. Doğru sektörü hesaplama işine takıldım.

Mucit23

Selamlar

Encoder kullanarak Block komutasyon yöntemi ile motoru bir türlü çalıştıramadım. Doğru açıyı bir türlü bulamıyorum. Yaptıklarımı ve anladıklarımı anlatayım hatam varsa söyleyin

İlk başta Enkoder ile Motoru birbirine senkronladım. Bunun için Motorun Ürettiği EMK ya baktım. Faz uclarına 3 adet 10K direnç bağlayıp dirençlerin diğer uclarını birleştirerek yıldız noktası oluşturdum. Osiloskobun Cansız ucunu yıldız noktasına canlı ucunuda U fazına bağladım. Enkoderin Z sinyalini U fazının tam sıfır geçişine göre ayarladım.

Bunun dışında şimdi düşünürsek eğer Mekanik periyot ve elektriksel periyot olmak üzere 2 farklı kavram var. 360 derecelik 1 mekaniksel periyot sonunda Enkoder veya timerim bana 1440 puls üretiyor

Yani 1 Mper 1440 Pulse diyebiliriz.

Elektriksel(Eper) periyot ise şöyle. Motor 14 mıknatıslı dolayısıyla 7 çift kutba sahip. Yani 1 Mper için 7 adet Eper oluşacak. Gerçektende öyle. Osiloskop ile baktığımda iki Z sinyali arasında tam 7 periyotluk U fazına Ait EMK görüyorum. 

Şimdi Sistemin Kendisini Sıfırlaması için başlangıçta Z sinyalini bekliyorum ve Z sinyali geldiğinde Sayacı ve Timeri Sıfırlıyorum. Dolayısıyla sonraki turlarda Motor ve Enkoder senkronize bir şekilde çalışıyor.(öyle olması lazım.)

Sorun şu. Hangi Sektörde olduğumu düzgün bir şekilde bulamıyorum. Yaptığım hesaplar şöyle. Motor 7 kutuplu dedik. Yani 1 Mper için 7 Adet Eper oluşacak. 1440/7=205.71 pulse Yapar. Yani Her 205 pulse'da bir Eper tamamlanacak.

Elektriksel periyodu bulabilmek  Eper = Shaft_Position % 205 yapıyorum. Dolayısıyla Mekanik periyot tamamlanıncaya kadar benim elimde 0-205 arası değişen Eper olacak. Bu elektriksel periyot içerisinde de sektörü bulabilmem lazım. Bunun içinde sector=Eper/35 işlemini yapıyorum. Eper 205 pulse'da tamamlandığına göre ve 6 Sektör olduğuna göre 205/6=35 gibi bir değer elde ettim.

Mantıken bu şekilde işlemler yaptım ama görünen o ki hala kavrayamadığım bazı olaylar var. Bir türlü motoru adam akıllı döndüremedim.

Atladığım nokta nedir anlamıyorum. Kafam durdu resmen..

M.Salim GÜLLÜCE

#10
Alıntı yapılan: Mucit23 - 23 Nisan 2018, 16:18:54Selamlar

Encoder kullanarak Block komutasyon yöntemi ile motoru bir türlü çalıştıramadım. Doğru açıyı bir türlü bulamıyorum. Yaptıklarımı ve anladıklarımı anlatayım hatam varsa söyleyin

Elektriksel periyodu bulabilmek  Eper = Shaft_Position % 205 yapıyorum. Dolayısıyla Mekanik periyot tamamlanıncaya kadar benim elimde 0-205 arası değişen Eper olacak. Bu elektriksel periyot içerisinde de sektörü bulabilmem lazım. Bunun içinde sector=Eper/35 işlemini yapıyorum. Eper 205 pulse'da tamamlandığına göre ve 6 Sektör olduğuna göre 205/6=35 gibi bir değer elde ettim.

Mantıken bu şekilde işlemler yaptım ama görünen o ki hala kavrayamadığım bazı olaylar var. Bir türlü motoru adam akıllı döndüremedim.

Atladığım nokta nedir anlamıyorum. Kafam durdu resmen..
Dediğin şekilde yapınca motorun tepkisi nedir.
Birde kullandığın encoder için Datasheet warmı?

Mucit23

Enkoderin Datasheeti budur

http://www.ateksensor.com/content/img/ARX_S_50_Tr.pdf

Bu şekilde çalıştırınca motor sağa sola titriyor, dönmüyor aşırı akım çekiliyor.