Preload ve Akım Kontrolü üzerine

Başlatan Cemre., 22 Ocak 2017, 02:34:23

Cemre.

Merhaba,

Bir süredir üzerinde çalıştığım BLDC sürücüm ile nihayet "sensörlü" de olsa, "kontrolsüz" de olsa motor çevirmeyi başardım. (Çok fazla yoğunlaşamadığım için bu kadar uzun sürdü  8-))

Hatta duty'yi fazla kaçırıp mosfet yaktığım bile oldu. (ya da bilmiyorum başka bir sebepten...)

Şimdi sırada güzel bir akım kontrolü yapmak var. PI kontrol rutini yazacağım. Ancak bundan önce MCU ile ilgili kafama takılan kısmı çözmek istiyorum.

Komütasyon işlemini (fazları enerjilendirme anı) hall effect sensor okuyarak yapıyorum. Hall effect sensor okumak için XOR yapısına giriyor üç kanal bilgi, buradan bir komütasyon sinyali çıkıyor. Komütasyon olayı oluştuğunda hall effect sensorlerin Lojik durumlarına bakıp hangi fazı enerjilendireceğime karar veriyorum.

Ancak "duty" ile ilgili herhangi bir işlem yapmıyorum. Debug aşamasında duty'i elle ayarlayıp motorun hızlandığını, akımın arttığını vs. gördüm sadece bu kadar. Bu yüzden şimdi sıra akım kontrolünde diyorum.

Sadede gelip sorularımı sorayım.

TIMER'larda Preload nedir? (Aslında bunu anladım ama yine de sorayım.)
Daha önemlisi, nasıl aktif edilir? (Ya da zaten aktif midir?)


Preload reg.'deki değerin shadow reg.'e yazılma anı "update" anı diye okudum. Kafamda şu canlanıyor.

Akımı oku, hata hesapla, PI rutinine gir, hesaplanan duty değerini Preload reg.'e yükle, update event'ını beklesin.

Akım ne zaman okunmalı?
Bununla ilgili birkaç bir şey okumuştum. PWM ON süresinin ortasında yapılmasının mantıklı olduğunu hatırlıyorum. Ya da, on süresince bir kaç kez okuyup yazılımsal filtreleme yapılmalı diyordu. Dökümanları şimdi bulamadım ama tekrar bakacağım. Diyelim ki ON süresinin ortasında okumalıyız. Bu işlemi nasıl yaparız?

Konu ilerledikçe diğer aklıma takılanları da buradan sorarım...

Teşekkürler.

Ekleme: MCU STM32F103C8T6

Bir de Max Current Limit durumu vardı, bunu yazmayı unuttum. Tamam akımı kontrol ederek bir kontrol sağlayabiliriz ancak, güç katının da sağlayabileceği maksimum bir akım var ve bu sınırı aşacak duty değerinin hesaplanmaması için bir sebep yok. Bunu da sürekli akımı kontrol edip threshold'ı geçtiği anda yine bir sonraki PWM cycle'a kadar anahtarı kapatacak bir işlem yapılması gerekiyor sanırım. Bu konuda da bilgiye ihtiyacım var.

Cemre.

Preload konusunda hala bir sonuca ulaşamadım.

@Klein hocam, siz bir kaynak önerebilir misiniz?

Klein

#2
preload konusunda datasheet haricinde kaynağa ihtiyacınız yok ki.
preload enable disable biti var.
Preload enable ise yükleme değeri shadow registere atılır ve update olayı gerçekleştiğinde registere yazılır. Diğer türlü direk yazılır.
STD_LIB kullanıyorsanız

TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

şeklinde tanımlı fonksiyonu var.
Register düzeyinde yazıyorsanız , yanılmıyorsam CR registerinde bşir bit vardı. bulamazsan datasheeti karıştırır bulurum.

CR1 registerinin 7. biti.

Cemre.

#3
Alıntı yapılan: Klein - 23 Ocak 2017, 23:46:21
preload konusunda datasheet haricinde kaynağa ihtiyacınız yok ki.
preload enable disable biti var.
Preload enable ise yükleme değeri shadow registere atılır ve update olayı gerçekleştiğinde registere yazılır. Diğer türlü direk yazılır.
STD_LIB kullanıyorsanız

TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

şeklinde tanımlı fonksiyonu var.
Register düzeyinde yazıyorsanız , yanılmıyorsam CR registerinde bşir bit vardı. bulamazsan datasheeti karıştırır bulurum.

CR1 registerinin 7. biti.

Hocam teşekkürler. Yarın inceleyip sonucu bildiririm.

-----

@Klein hocam, HAL kütüphanesi kullanıyordum, tüm kütüphane dosyaları içinde bu Reg. ile ilgili bir işlem yapılmış mı diye arattım ancak sadece define edilip bırakılmış. Bu bana çok ilginç geldi, Std Lib.de doğrudan aktif etmek için bir fonksiyon yazılmışken HAL'da olmaması?

Neyse, şimdilik akım kontrolüne ara verip basit bir düzenek hazırladım ve minik bir fan motorunun hızını her Update Event callback'inde  PI döngüsüne sokarak kontrol etmeye çalışıyorum. Değişkenlerimi başlangıçta float olarak tanımladım FPU olmamasına rağmen sorunsuz çalıştı. Şimdi rutini fixed-point aritmetik ile yazmaya çalışacağım.

https://www.embeddedrelated.com/showarticle/121.php Bu döküman epey bir incelemiş konuyu. Bu konuda öneriniz varsa duymak isterim.

İyi günler, iyi çalışmalar.

Cemre.

#4
@Klein hocam,

Sanırım donanıma tam olarak hakim olamadığımdan bir noktada takıldım.

Şuan TIM1'i 6 kanal drive sinyallerini üretmek için kullanıyorum.
TIM2'yi ise hall effect sensor bilgisi ile TIM1 commutation event'ı oluşturmak için kullanıyorum.

Sırada yapmak istediğim ise, TIM1 update event'inden kısa bir süre sonra (amacım anahtarlama anında oluşan parazitleri atlayıp gerçek akım değerini okumak) ADC çevrimini başlatmak.

Bunun için Injected Conversion kullanmam gerektiğini düşünüyorum.
Bu noktada update event gerçekleştiğinde ille update event interrupt aktif edip UpEvnt callback'inde adc çevrimini yazılımsal olarak mı başlatmalıyım?

Yoksa doğrudan update anında adc çevrimini başlatmamı sağlayacak bir yöntem var mı?

CubeMX'in bana sunduğu seçenekler şunlardır;

  • Injected Conversion launched by software
  • Timer 1 Trigger Out Event
  • Timer 1 Capture Compare 4 Event
  • Timer 2 Trigger Out Event
  • Timer 2 Capture Compare 1 Event
  • Timer 3 Capture Compare 4 Event
  • Timer 4 Trigger Out Event

Ekleme;

Buna alternatif olarak PWM Mode 2 Counter Mode: Down yapılıp, capture compare event gerçekleştikten kısa bir süre sonra adc çevrimi devreye sokulabilir sanırım ama bu durumda akım sınırlama rutinleri için zaman kalmama ihtimali artıyor sanırım. Tam olarak kafamda canlandıramasam da bu yöntemden uzak durmam gerektiğini düşündüm :)

Ekleme 2;

Atladığım bir nokta, tamam referans akıma ulaşmak için PI kontrolde kullanılacak feedback akım bilgisini injected mode ile okuyacağım ama, bir de akım sınırı için update anı dışında her an tekrar tekrar regular continuous mode ile çevrim yapıp değeri kontrol etmem gerekiyor sanırım.
Zaten injected mode'un amacı da "regular sen bir dur, benim işim acele araya kaynak yapıyorum" değil mi?,

Ekleme 3;

Preload disable olduğu durumda, misal CCR1 değerim 500, CNT değerim 100, daha çıkışın low olmasına 400 clk var. Bu anda örneğin CCR1'e 100'den küçük bir değer yazarsam (örn "0") çıkış low mu olur?

Klein

Konu CUBE_MX ve HAL olunca  bilgim yetersiz ne yazık ki.
ADC'için trigger seçenekleri oldukça geniş.
Yazılımla başlatma, DMA ile başlatma, Timer ile başlatma, harici pinden başlatma gibi bir sürü seçenek var.
Ayrıca çift ADC ile çalışma ,  interleaved , simultaneous mod gibi o kadar çok opsiyon var ki.
Bunları kafadan hatırlamam mümkün değil. Datasheet'e gömülmem gerek. ama şu sıralar gözüm yemiyor.

Cemre.

#6
Nasıl aklıma gelmedi?

Injected modu başka bir timer ile mi tetiklemeliyim diye düşünüyorum iki gündür. Hiç gerek yok.
TIM1 Channel 4 ne güne duruyor? Hem de senkron. Hem de diğer aktif kanalın duty'sine göre ölçeklendirebilirim CCR4 değerini. Süper...

Peki bir soru daha. Sampling Time 1.5Cycle + 12.5Cycle kullansam 12MHz'de 1.16uS'de çevrim tamamlanacak. Bu çok abartılı bir kullanım mı olur? 50uS periyotlu bir PWM sinyali için. Çevrime girmek için bir süre beklenecek, çevrim bitince de PI gibi kontrol algoritamalarına dallanacak sistem.

Tamam, son olarak kontrol edelim. Şu anki konfigurasyonum;

ADC Regular ve Injected olmak üzere iki modda çalışacak.

Regular mod Timer 3 Trigger Out event ile master slave ilişkisinde, 2uS'de bir dönüştürme işlemi yapacak. (1,16uS toplam çevrim süresini göz önünde bulundurarak 2uS'de karar kıldım umarım hata yoktur.)

Injected mod Timer 1 Channel 4 CCP event'ında dönüştürme işlemi yapacak. Timer 1 20kHz'de çalışan 6 adet pwm çıkışı olan bir birim. Burada Timer1 CCR değeri ayarlarken CCR4 değeri diğer kanalların CCR değerine oranla bir değer seçilecek veya sabit bir değer de seçilebilir.

Bu sayede,
Regular mod 2us'de bir çevrime girerek aşırı akım koruması işlemi için gereken feedback verisini sağlayacak.
Injected mod High Side mosfet anahtarlama anından belirli bir süre sonra çevrim yaparak PI regülatöre gereken feedback verisini sağlacak. Bu veri akım regülasyonu için Cycle by Cycle kontrolde kullanılacak.

Bu senaryoyu değerlendirebilir misiniz @Klein hocam?

İyi günler, iyi çalışmalar.

Bilgi eki: Injected mod'da "Injected offset" değeri ile oynayarak ADC değerinizi kaydırabilirsiniz. Misal benim uygulamamda 0-3.3V arası -20A ile +20A arasını temsil ediyor. Bu durumda 0-2047 arası -20A ile 0 arasını temsil ediyor. Ancak Offset değerini 2048 yaparsam, artık ADC sonucum -2048 ile +2047 arasında üretiliyor. PID rutinine girmeden önce değişiklik yapma gereksinimini ortadan kaldırıyor. Süper değil mi?
Ancak bu özellik maalsef Regular modda yok...

Klein

2us'de bir kesme alacaksın , PI hesabı yapacaksın vs... vs.. Hem de bunları HAL kütüphanesi ile yapacaksın.
Sıkı çalışman lazım.  Z hoca ile biraz ASM mesaisi yapmanda fayda olabilir.
Olmaz demiyorum ama uğraştırır bence.


Cemre.

#8
Alıntı yapılan: Klein - 26 Ocak 2017, 18:51:06
2us'de bir kesme alacaksın , PI hesabı yapacaksın vs... vs.. Hem de bunları HAL kütüphanesi ile yapacaksın.
Sıkı çalışman lazım.  Z hoca ile biraz ASM mesaisi yapmanda fayda olabilir.
Olmaz demiyorum ama uğraştırır bence.
2uS ile yalnızca akım sınırını kontrol edeceğim.

PI rutini 50uS'de bir çağırılacak.

Aslında haklısınız, kesme içi işlemler ASM ile ya da en kötü sadece CMSIS fonksiyonları - tanımlamaları kullanılarak yazılırsa çok daha iyi olabilir.

Bu noktada işlemci komutlarını da öğrenmeye çalışıyorum. Misal __SSAT bir değeri saturation işlemine sokabiliyor. Bunu en basit haliyle if elseif elseif şeklinde yazabilecekken tek inst cycle'da halletmek mükemmel bir durum...

Çok sorun yaşarsam M4 serisi 160 küsür MHz bir işlemciye de geçebilirim artık ne yapalım... Bülent hocaya kalsa F103 bile fazla bu iş için de :D
Görünmüyor ortalıkta, taşınacağım diyordu... @Zoroaster

mistek

@Cemre. Hocam yukarıdaki senaryoyu uygulayabildiniz mi ? Benzer bir duruma benimde ihtiyacım var.
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Cemre.

@mistek Hocam denemeler yapıyorum ancak kafamda bazı soru işaretleri var. MCU gerçekten bu sürelerde kesmeye girebildi mi nasıl anlarım bilemiyorum. Debug aracılığıyla bunu anlamanın bir yolu var mı bilmiyorum. Okul açılınca scope kullanma şansım olacak o zaman bir GPIO pinini ADC callback'inde toggle ederek zamanlamanın düzgün olup olmadığını anlamaya çalışacağım. Sorun yoksa bu şekilde kullanacağım.