STM32 İLE AÇIK ÇEVRİMDE BLDC SERVO MOTOR SÜRMEK

Daha önce fırçasız servo motor -BLDC- kontrolu konusunda iki yayınım oldu. O yayınlarda temel bilgiler verdikten sonra ST Microelectronics firmasının Nucleo64 kitini, IHM07M1 motor sürücüsünü ve STSPN7 paket yazılımını kullandığım bir uygulamayı anlatmıştım.

Bu defa, kendi MOSFET sürücümü, IR2103 MOSFET sürücü tümleşik devresini kullanarak, ama kendi geliştirdiğim kodlarla BLDC sürmeye girişiyorum. Bunun da ilk adımı burada anlatacağım gibi, motoru “açık çevrim” kontrolu altında çalıştırmak olacak.

Bu işi öğrenmek amacı ile yapanlara, önce motoru açık çevrim altında çalıştırmayı denemelerini hararetle öneririm.

Bu şekilde motorun uyguladığımız PWM besleme gerilimlerine, faz zamanlamalarına, motorda endüklenen ters gerilimlere -BEMF- tepkilerini görüp anlamamız kolaylaşıyor. Motor uçlarında oluşan gerilimlerin osiloskop ekranında görülen dalga şekillerini anlayıp açıklayabilmek, motorun neden kilitlendiğini, ne zaman dönmeye başladığını anlamak da yeterli olgunluğa ulaşmanın bir yolu. Bu etkileşimleri kavradıktan sonra kapalı çevrim kontroluna geçmek daha verimli bir sonuç verecektir, en azından benim için böyle oluyor.

Önceki yayınlar şunlar: Bu yayından önce bunlardan özellikle birincisine bakılmasını önereceğim :

BLDC MOTOR SÜRMEK – 1 : BLDC Motorların yapısı ve bunları 6 adım tekniği ile sürmek için uygulanacak gerilimler.
BLDC MOTOR SÜRMEK – 2 : ST Microelectronics in STM32F302 Nucleo64 geliştirme kiti, IHM07M1 motor sürücü modülü ve STSPN7 yazılım paketi kullanılarak BLDC sürülmesi

BU YAYININ SİSTEM KONFİGÜRASYONU

Donanım :

  • STM32F103C8 Pico adaptör modülü
  • MOSFET Sürücü modülü : IR2103 / IRF540 tabanlı Aralık 2020 yapımı
  • BLDC Motor : INTECNO BLS022.240 V26 4000 rpm, 0.22 Nm
  • Motor güç kaynağı : Modifiye ATX – 12V

Yazılım :

selcuk_F103C8_Pico_IR2104_R2 20 Aralık 2020

ÖNCE BİRAZ TEMEL BİLGİ

Bu yayını izlerken ikide bir öncekileri açıp bakmak zorunda kalmamak için birkaç önemli bilgiyi buraya tekrardan koymak istiyorum. Bunlar BLDC motoru sürmek için faz bobinlerinin uçlarına uygulamamız gereken gerilimler ve bobinlerde oluşan BEMF gerilimleri ile ilgili olan diyagramlar. Biraz daha detay için önceki yayınlara bakmak gerekecek.

BOBİNLERE UYGULANAN GERİLİMLER

Bobinlere altı adımlık bir senaryoya uygun olarak aşağıdaki gerilimleri uyguluyoruz. Görüldüğü gibi bir birini izleyen fazlar arasında ikişer adımlık – sinüzoidal olsaydı 120 derece diyeceğimiz zaman farkları var.

Motorun üç adet faz sargısının her birine gerilim uyguladığımız, açıkta bıraktığımız ve 0 hattına bağladığımız adımlar var. Bu şekilde her bir bobinde artı ve eksi yönde akan akımların bulunduğu adımlar olduğu gibi, hiç akım akıtmadığımız “Nc” ile işaretli adımlar da var.

Artı yönde akım akıtmak için uyguladığımız pozitif gerilimleri PWM – Darbe Kod Modülasyonu- ile kontrollu olarak veriyoruz, bu şekilde akım kontrolunu sağlıyoruz.

Motorun üç kutup sargısına bu sırayla uyguladığımız gerilimler sayesinde motor içinde dönen bir manyetik alan oluşturuyoruz, üzerine sabit mıknatıslar yerleştirilmiş olan rotor da bu alanı izleyerek dönmeye başlıyor.

ENDÜKLENEN GERİLİM – BEMF

Rotor dönerken bunu çevreleyen stator bobinlerinde, bizim uyguladığımız gerilimlere ters yönde bir Ters Elektromotor Gerilimi –BEMF : Back Electro Motor Force- endüklüyor. Bu gerilimin etkisi bizim bobin akımlarını frenleyecek yönde oluyor.

Bu nedenledir ki, motor bobinlerine gerilim uygulanmakta iken rotorun dönmesini engellersek -akım sınırlaması da yok ise- motorun yanmasına yol açıyoruz.

Bu BEMF gerilimini de diyagramımıza eklersek aşağıdaki gibi bir durumla karşılaşıyoruz. Bu çizimde sadece U bobininde endüklenen BEMF’i gösterdim, diğerlerinin buna göre 120o faz farklı olacağını biliyorsunuz.

Elbette bu çizim rotorun, uyguladığımız gerilimleri tam olarak izleyebildiği bir durum için geçerli. Eğer rotor, ister mekanik ataleti, ister üzerindeki yük nedeni ile olsun bizim yarattığımız dönen alanı izleyemeyecek olursa bu sinüsün U-V-W gerilimlerine göre geride kaldığını görürüz. Bu konuya ilerideki paragraflarda osiloskop ile görüntülenen gerçek dalga şekillerini incelerken tekrar değineceğiz.

Görüldüğü gibi bu BEMF gerilimi, rotorun herhangi bir andaki pozisyonunu algılamak için kullanılabilir. Tabiki bunun için rotorun dönüyor olması gerekir, durmakta olan rotor endükleme yapmayacağından pozisyon algılamak için bakılacak bir BEMF de olmayacaktır.

Rotor pozisyonunu bilmenin kapalı çevrim kontrolunda önemi var. Burada anlattığım açık çevrim kontrolunda ise rotor pozisyonu ile ilgilenmiyoruz, bobinlere gerilimlerimizi uyguluyor, rotorun da bunu izleyeceğini kabul ediyoruz. Eğer motor, uyguladığımız gerilimlerle dönmüyorsa PWM ve 6 adım periyod ayarlarını değiştirerek rotoru döndürecek uygun parametreleri belirliyoruz.

Bobin uçlarını pozitif ve negatif besleme hatlarına bağladığımız adımlar var. Bu adımlarda bobin uçlarında BEMF etkisini görmemiz mümkün değil. Ama bobin uçlarını açıkta bıraktığımız adımlarda bu gerilimi gözleyebiliriz. Bunu dikkate alarak bobin gerilimlerini tekrar çizersek aşağıdaki sonuca ulaşırız.

Şekli sadece U fazı için çizdim, diğer fazlarda da aynı durum oluşacaktır.

MOSFET MOTOR SÜRÜCÜ DEVRE

Görüldüğü gibi her bir bobin ucunu pozitif hatta, negatif hatta bağladığımız ve açıkta bıraktığımız üç konum söz konusu.

Bu şu anlama geliyor; bobin ucunu pozitif besleme yoluna bağlayan bir MOSFET ile negatif besleme yoluna bağlayacak bir ikinci MOSFET’e ihtiyacımız var. Bu MOSFET ler sırası ile iletime geçerek görev yapacaklar, her ikisinin de kesimde olduğu durumlarda da uç açıkta kalmış olacak. Bu MOSFET lerden pozitif tarafta olana “üst”, negatif tarafta olanına da “alt” (İngilizce literatürde “High side” ve “Low side” olarak kullanılmakta) olarak anacağız.

Bu amaçla üst tarafta P kanal, alt tarafta da N kanal MOSFET ler kullanılabilir. Böyle bir konfigürasyonda MOSFET lerin sürülmeleri daha basit oluyor. Öte yandan her iki MOSFET’in de N kanal olması daha kullanışlı ve ucuz bulunabilir. Ben bu uygulamada her ikisini de N kanal kullanabilmek için IR2103 tümleşik MOSFET sürücüsünden yararlandım.

NOT : Burada blog siteme ilgi gösterip yorum yaptığında tanıştığım Sn Hüseyin Hilmi Çelebi'yi anmadan geçemeyeceğim. En azından bu dönemde, böyle bir "açık çevrim BLDC kontrolu" çalışması yapmak önceliklerim arasında değil iken, beni soruları ile, yaptıkları denemeler hakkında bilgi vererek bu çalışmayı yapmaya motive etti. IR2103 ve çift N kanal MOSFET ile çalışma seçimlerim de Hüseyin Bey ile tecrübelerimizi paylaşabilmek için yaptığım bir tercih oldu. Kendisine teşekkür ediyorum.

IR2103 data sheet’inden aldığım şemayı uygulayarak çalıştım.

Aşağıdaki de kullandığım IRF540 N kanal MOSFET leri de içeren devre şemasının tamamı.

Sol taraftaki konnektörler STM32F103C8 Pico adaptör kiti ile uyumlu olacak şekilde tasarlandı. Şemadaki 7805 ve 5V Vcc etiketlemesi bir hata, ben yayını revize edene kadar bunları 10V ila 20V olarak okuyunuz.

DONANIM KURULUM AYRINTILARI

Yukarıda şemasını verdiğim devrenin baskılı devresini tek yüzlü olarak tasarlayıp masa üstü CNC de ürettim. Tek taraflı PCB ye sığmayan bağlantılar nedeniyle 9-10 tane de kablolu atlama gerekti.

Mikrodenetleyici olarak STM32F103C8 tabanlı Pico adaptör modülümü kullandım. (Modül hakkında bilgi için burayı tıklayınız.)

Mikrodenetleyici ile sürücü arasındaki bağlantılar şöyle :

Faz U – HIN (PWM) : PA8 – TIM1 CH1
Faz U – LIN (0 V) : PA3 output PP
Faz V – HIN (PWM) : PA9 – TIM1 CH2
Faz V – LIN (0 V) : PB10 – output PP
Faz W-HIN (PWM) : PA10 – TIM1 CH3
Faz W-LIN (0 V) : PB11 – output PP

Adım süresi ayar potansiyometresi : PA0 – ADC1 IN0
PWM duty Cycle ayar potansiyometresi : PA1 – ADC1 IN1

Uyumlu konnektör tasarımı sayesinde STM32 Mikrodenetleyici adaptör modülümü sürücü kartına doğrudan takabiliyorum. Denk düşüremediğim 3 adet bağlantı için jumper kablolar kullanmak zorunda kaldım.

Soğutucum biraz sade, salgın koşulları altında elimin altında ne varsa onu kullanmak zorundayım. Zaten 12 Voltluk motor gerilimleri ile ve 2-3 amperin altında akımlarla çalışacağımdan bu aşamada fazlasıyla yeterlidir.

Sağ taraftaki 0.22 Ohm direnç akım ölçümü için MOSFET toprak dönüş yoluna koyduğum şönt direnç. Onu bu proje kapsamında kullanmayacağım.

KODLAR

STM32 Cube IDE ile kurulum bilgilerini vereyim :

GPIO AYARLARI

Buradaki SPI1, PA4 ve PB5 ayarları TFT için. Kullanılacak ekrana göre bunlara ya da başka bir şeye ihtiyaç olabilir.

SİSTEM SAAT AYARLARI

72 MHz de çalışıyoruz, ADC için gereken 14 MHz maksimum sınırına dikkat etmek gerekiyor. Adc Prescaler in /6 seçeneğinin verdiği 12 MHz bizim için yeterli.

TIMER AYARLARI

Pozitif beslemeler için PWM üretimini TIM1 üzerinden yapıyoruz. TIM1 in PWM çıkışlarını A8-A9 ve A10 üzerindeki CH1, CH2 ve CH3 kanalları üzerinden dışarı alıyoruz.

Ana saati 72 ye bölerek 1µs lik sayaç darbeleri elde ediyor, 100µs lik PWM periyodları elde etmek üzere sayıcı periyodunu 100 olarak ayarlıyoruz.

Her bir PWM çıkış kanalının “pulse” karşılaştırma periyodu başlangıçta varsayılan olarak 50 olarak, yani %50 ye ayarlı, ama bu değer program içinde ADC1 e bağlı bir potansiyometre ile değiştiriliyor.

ADC AYARLARI

ADC1 i birisi PWM Duty Cycle oranını, diğeri de motor adım periyodunu belirleyen iki adet potansiyometrenin orta uç gerilimlerini ölçmek için kullanıyoruz.

Programın ana çevriminin her bir devrinde motoru bir adım ilerletiyoruz, bu çevrimin başlangıcında da ADC yi bir set ölçüm yapmak üzere HAL_ADC_Start_DMA() fonksiyonu ile tetikliyoruz. ADC1 her starttan sonra iki girişten ölçüm yapacak şekilde, DMA modunda çalışıyor. Böylece PA0 ve PA1 girişlerindeki 0. ve 1. ADC kanalları örneklenerek sayısallaştırılıyor.

Bunlar da ADC1 in DMA ayarları

KODLAR

Cube IDE ile yukarıdaki ayarlarla proje oluşturulduktan sonra çok fazla bir kod yok. Sadece U, V ve W fazlarının 6 motor adımına karşı düşen ayarlarını bir diziye yerleştiriyorum. Açıklamalar kodun içinde yazılı. Motorun adım süresini HAL_Delay() fonksiyonu ile kontrol ediyorum ama bu geçici bir uygulama, nihai durumda bu görevi bir Timer ile yerine getireceğiz.

Aşağıdaki başlangıç ayarlarında :

  • “0” fazın negatif besleme hattına bağlandığını, yani alt MOSFET’in iletimde olduğunu,
  • “1” fazın pozitif besleme hattına bağlı olduğunu, yani üst MOSFET’in iletimde olduğunu (ki bu durumda bu bobine pozitif gerilimi PWM ile veriyoruz.)
  • “2” faz ucunun açıkta bırakıldığını, yani her iki MOSFET’in de kesimde olduğunu gösteriyor.

MAIN.C KODLARI

/* USER CODE END Header /
 / Includes ------------------------------------------------------------------*/
 include "main.h"
 /* Private includes ----------------------------------------------------------/
 / USER CODE BEGIN Includes */
 include "tft_basic.h"
 /* USER CODE END Includes */
 /* Private typedef -----------------------------------------------------------/
 / USER CODE BEGIN PTD */
 /* USER CODE END PTD */
 /* Private define ------------------------------------------------------------/
 / USER CODE BEGIN PD / / USER CODE END PD */
 /* Private macro -------------------------------------------------------------/
 / USER CODE BEGIN PM */
 /* USER CODE END PM */
 /* Private variables ---------------------------------------------------------*/
 ADC_HandleTypeDef hadc1;
 ADC_HandleTypeDef hadc2;
 DMA_HandleTypeDef hdma_adc1;
 SPI_HandleTypeDef hspi1;
 TIM_HandleTypeDef htim1;
 /* USER CODE BEGIN PV */
 uint8_t phase_state[7][3];
 uint8_t stepDuration = 5, step = 1;
 uint16_t speed,pwm,current;
 uint8_t dutyCycle, dutyCycleOld = 20;
 uint32_t adcValues[2], adcBuffer[2];
 /* USER CODE END PV */
 /* Private function prototypes -----------------------------------------------/ 
 void SystemClock_Config(void);
 static void MX_GPIO_Init(void);
 static void MX_DMA_Init(void);
 static void MX_SPI1_Init(void);
 static void MX_TIM1_Init(void);
 static void MX_ADC1_Init(void);
 static void MX_ADC2_Init(void);
 /* USER CODE BEGIN PFP */
 uint16_t adcOku(ADC_HandleTypeDef* phadc);
 /* USER CODE END PFP */
 /* Private user code ---------------------------------------------------------/ 
 / USER CODE BEGIN 0 */
 /* USER CODE END 0 */

int main(void) {
 /* USER CODE BEGIN 1 */
 /* USER CODE END 1 */
 /* MCU Configuration--------------------------------------------------------*/
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 /* USER CODE BEGIN Init */
 /* USER CODE END Init */
 /* Configure the system clock */
 SystemClock_Config();
 /* USER CODE BEGIN SysInit */
 /* USER CODE END SysInit */
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_SPI1_Init();
 MX_TIM1_Init();
 MX_ADC1_Init();
 MX_ADC2_Init();
 /* USER CODE BEGIN 2 */

 /* Faz bilgilerinin ayarlanması
  *
 Adım 1: U :  PWM     V:  0      W:  NC       (1,0,2)
 Adım 2: U :  PWM     V:  NC     W:  0        (1,2,0)
 Adım 3: U :   NC     V: PWM     W:  0        (2,1,0)
 Adım 4: U :   0      V: PWM     W:  NC       (0,1,2)
 Adım 5: U :   0      V:  NC     W:  PWM      (0,2,1)
 Adım 6: U :   NC     V:  0      W:  PWM      (2,0,1)
 */
 /* Step 0 dummy - Adımlar 1..6 arasında */
 phase_state[0][0] = 0;
 phase_state[0][1] = 0;
 phase_state[0][2] = 0; 
 phase_state[1][0] = 1;
 phase_state[1][1] = 0;
 phase_state[1][2] = 2;
 phase_state[2][0] = 1;
 phase_state[2][1] = 2;
 phase_state[2][2] = 0;
 phase_state[3][0] = 2;
 phase_state[3][1] = 1;
 phase_state[3][2] = 0;
 phase_state[4][0] = 0;
 phase_state[4][1] = 1;
 phase_state[4][2] = 2;
 phase_state[5][0] = 0;
 phase_state[5][1] = 2;
 phase_state[5][2] = 1;
 phase_state[6][0] = 2;
 phase_state[6][1] = 0;
 phase_state[6][2] = 1;
 HAL_Delay(1000);
 TFT_Init();
 #ifdef TFT_320x240
 TFT_Rotate(Landscape_Vnorm_Hnorm_24TP); // 240x320 2.4" SPI TP de boyle
 #endif
 #ifdef TFT_480x320
   TFT_Rotate(Landscape_normal_35P);     // 320x480 3.5" TFT_P de böyle
 #endif
 TFT_ShowString(10, 150, 12, "*****  SERVO&IR2104 R2       *****",YELLOW, 0);
 TFT_ShowString(10, 150, 12, "*****   SELCUK OZBAYRAKTAR   *****",YELLOW, 0);
 
 uint16_t sysfrq = SystemCoreClock/1000000;
 TFT_Printf(0,200,24,"SYS CORE CLK: %d",sysfrq);
 HAL_Delay(2000);
 TFT_Clear(BLUE);
   /* USER CODE END 2 */
   /* Infinite loop */
   /* USER CODE BEGIN WHILE */
   while (1)
   {
 HAL_ADC_Start_DMA(&hadc1, adcBuffer, 2);
 
   /*  U bobini ayarları */
 
    if (phase_state[step][0] == 0) { // PWM yok, OutH = 0 OutL = 1
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
    HAL_GPIO_WritePin(L_U_GPIO_Port, L_U_Pin, GPIO_PIN_RESET);
    }
    if (phase_state[step][0] == 1) {   // PWM var, OutH = PWM OutL = 0
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    HAL_GPIO_WritePin(L_U_GPIO_Port, L_U_Pin, GPIO_PIN_SET);
    }
    if (phase_state[step][0] == 2) { // Nc state,  OutH = 0  OutL = 0
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
    HAL_GPIO_WritePin(L_U_GPIO_Port, L_U_Pin, GPIO_PIN_SET);
    }
 
   /*  V bobini ayarları  */
 
    if (phase_state[step][1] == 0) {
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
    HAL_GPIO_WritePin(L_V_GPIO_Port, L_V_Pin, GPIO_PIN_RESET);
    }
    if (phase_state[step][1] == 1) {
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
    HAL_GPIO_WritePin(L_V_GPIO_Port, L_V_Pin, GPIO_PIN_SET);
    }
    if (phase_state[step][1] == 2) {
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
    HAL_GPIO_WritePin(L_V_GPIO_Port, L_V_Pin, GPIO_PIN_SET);
    }
 
   /*   W bobini ayarları  */
 
    if (phase_state[step][2] == 0) {
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
    HAL_GPIO_WritePin(L_W_GPIO_Port, L_W_Pin, GPIO_PIN_RESET);
    }
    if (phase_state[step][2] == 1) {
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
    HAL_GPIO_WritePin(L_W_GPIO_Port, L_W_Pin, GPIO_PIN_SET);
    }
    if (phase_state[step][2] == 2) {
    HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
    HAL_GPIO_WritePin(L_W_GPIO_Port, L_W_Pin, GPIO_PIN_SET);
    }
    if (step < 6)
    step++;
    else
    step = 1;
 
  speed = adcBuffer[0]/4; //0-4096 arasındaki ADC değerlerini 0-1024 arasına getiriyoruz
  pwm = adcBuffer[1]/4;
 
      if(speed>1000) speed = 1000;
      if(speed<10) speed = 10;
      stepDuration = speed/10;//Adım süresi Pot gerilimi ile düz,hız ile ters orantılı
 
      if(pwm<100) pwm = 100;
      if(pwm>800) dutyCycle = 80; // %80 den fazla olmasın
      else dutyCycle = pwm/10;

     if(dutyCycle != dutyCycleOld) {
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, dutyCycle);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, dutyCycle);
    dutyCycleOld = dutyCycle;
      }
 //TFT_Printf(10,20,16,"pulse: %d pwm: %d crnt : %d", stepDuration, dutyCycle, current);
 HAL_Delay(stepDuration);
     /* USER CODE END WHILE */

     /* USER CODE BEGIN 3 */
   }
   /* USER CODE END 3 */
 }
 

SİSTEMİN ÇALIŞMASI VE ÖLÇÜM SONUÇLARI

Şimdi servo motoru sürücünün 3 telli çıkışına bağlayarak test edelim. Ancak bu teste geçmeden önce motor yerine birbirine birer uçlarından yıldız yapıda bağlanmış 3 direnç bağlayarak osiloskop ile çıkış dalga şekillerine bakalım.
Motorun BEMF gerilimlerinin bobin uçlarındaki dalga şekillerini değiştirdiğini anlatmıştım, bunun etkisi olmaksızın devremizin çalıştığından emin olalım.

Bunlar da dirençler üzerindeki çıkış gerilimlerinin osiloskop görüntüleri. Yüksek dikdörtgenler o fazdan pozitif PWM verilen aralıklara karşı düşüyor. O esnada bir diğer bobinin ucu da negatif (0V hattı) hatta bağlandığından bu bobinden PWM pozitif akım akıyor, diğerinden de negatif yönde.

Yarım tepe değerlerine sahip PWM sinyali görünen zaman dilimlerinde ise bu fazın ucu açıkta, ne 0 ne de + hatta bağlı. Bu aralıklarda diğer fazlara ait bobin çiftinin uçlarına uygulanmış olan PWM geriliminin yarısını görüyoruz.

Bu ölçüm ortalama %50 gibi bir PWM oranı ile yapıldı. Eğer %80 ve daha yukarı bir değerde PWM uygulayarak baksaydık aşağıdaki gibi bir sonuç elde edecektik.

MOTOR BAĞLANDIKTAN SONRA FAZ GERİLİMLERİ

Şimdi motoru bağlayarak aynı gerilimleri gözleyelim. Motor bağlanıp sistem çalıştırılınca motorun dönmeye başlaması için PWM ve periyod potansiyometreleri ile biraz oynamak gerekebilir.

Bu denemeye PWM oranının %50 ya da daha düşük olduğu bir noktadan başlamak iyi olur, aksi halde motor dönmez iken akacak aşırı akımlar MOSFET'ler, motor ya da güç kaynağının zarar görmesine, en azından sigortalarınızın atmasına yol açabilir.

Motorun stabil olarak dönmeye başlamasından sonra aşağıdaki gibi dalga şekilleri elde ediyoruz. Benim motorum yüksüz durumda sürekli dönerken 12V besleme kaynağından 0.2A civarında (PWM ortalaması) akım çekiyor.

Burada faz ucunun açıkta kaldığı zaman dilimlerinden bazılarında – PWM uygulamasının öncesindeki adımlarda- BEMF sinüs geriliminin eklendiğini görebiliyoruz. Ama daha önceki açıklamalara göre, PWM periyodu sonrasındaki adımda da bu sinüsün devamını görmemiz gerekmiyor muydu?

Bu sorunun yanıtı şu : Motora uyguladığımız gerilimlerin zamanlaması, hızı ve periyodu rotorun dönüşü ile tam uyumlu değil. Yukarıdaki osiloskop görüntülerinde BEMF sinüsünün tepe noktasına ulaşıldığını görüyoruz , bunun devamı da bobine PWM uygulanan adımların içinde kalıyor.

Bu açıklamayı desteklemek üzere PWM oranları ve adım periyodları ile oynayarak biraz daha senkronize bir durum elde etmeye çalışalım. Bu defa sadece U fazını görüntülemekle yetineceğim.

Biraz daha yaklaştıralım :

İşte optimal durum bu. BEMF geriliminin tepe değeri PWM uygulama aralığının ortasına getirilmiş. Motorun en stabil çalıştığı ayarlar böyle. Ancak bu durumu açık çevrim kontrolundayken potansiyometrelerle yapılan ayarlarla, değişen yükler altında sürdürebilmek çok zor. Ayrıca, tehlikeli de, senkronizasyon bozulup motor durakladığında bobinlerden çok yüksek akımlar akmaya başlıyor.

İşte kapalı çevrim kontroluna da bundan dolayı ihtiyaç duyuyoruz.

Biraz daha kurcalarsak daha da farklı sonuçlar elde edebiliriz ama yukarıdaki ideal durumdan uzaklaştığımızda motorun stabilitesi bozulacaktır.

Bu defa, alt ve üst MOSFET ler arasındaki ilişkinin görülebilmesi için aynı ekrana U fazı ile birlikte buna ait alt MOSFET’e uyguladığımız kontrol gerilimini de koydum. Bilindiği gibi bu MOSFET’ in Gate’ine pozitif gerilim uyguladığımız aralıklar bobinimizin “0” hattına bağlı olduğu zaman dilimleri.

Bu konumda BEMF geriliminin artık iyice kayarak PWM ile senkronizasyonu kaybettiğini görüyoruz. Motor bu durumda çalışmayı sürdüremeyecektir.

Aşağıda manuel ayarlarla elde edebildiğim en yüksek hıza ilişkin sonuçları veriyorum, 4ms lik adımlara kadar inebildim. Motor bu sırada 12V dan 0.24A çekiyor. Motorum 40V,3A lik bir servo ama ben 12V ile çalıştırıyorum. Çalışma limitlerine ulaşabilirsem 4000 devir ile çalıştırabilmem gerek, şu anda 1200 devir/dk ile dönüyor.

SONUÇ

3 Amper, 40 Voltluk BLDC servo motorumu bu ev yapımı MOSFET sürücü ve basit bir kod ile, STM32F103C8 gibi mütevazi bir mikrodenetleyici ile açık çevrimde çalıştırdım. Motor dönüyor ama hız ve yük değişiklikleri olduğunda potansiyometrelerle ayarları yenilemek gerekiyor.

Bundan sonraki aşama BEMF gerilimlerini izleyerek motoru kapalı çevrim kontrolu altında çalıştırmak olacak. Belki de önce küçük bir revizyon ile adım periyodunu HAL_Delay() fonksiyonu yerine bir Timer’a kontrol ettirmek iyi olur.

Bir uyarı daha : Motoru 12 Voltun çok üzerinde gerilimlerle çalıştırmak mümkün, ancak 20 Volt un üzerine çıkıldığında IR2103 ün Vcc gerilimini -data sheet bilgilerine göre- 20 Volt ile sınırlamak gerekiyor. Ben devreye bu amaçla bir 78XX regülatörü koydum. Şemada görülen 7805 etiketini gözardı edin, o Eagle’da devreyi çizerken elime gelen ilk sembol olduğu için öyle kaldı. Bu gerilimin 10 V ila 20 V arasında olması gerekiyor. Ben devremi denerken 78XX i pas geçerek 12 Volt’u doğrudan Vcc ye verdim.

Daha önce STM in STSPN7 paketi ile bu işi yapmıştım, bu çalışma bir bakıma tekerleği yeniden keşfetmek oluyor, ama konuya tam olarak hakim olmak için böyle yapmak zorundayız sanırım.

Bu yayının sonu – Selçuk Özbayraktar Aralık 2020

15 Replies to “STM32 İLE AÇIK ÇEVRİMDE BLDC SERVO MOTOR SÜRMEK”

  1. Selçuk hocam merhaba,
    cubemx’de pwm ayarlarını pwm generation ch1 ch1n olarak seçiyorum diğer ayarlarıda yaptıktan sonra dosyayı oluşturuyorum.
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,Duty); Bu fonksiyonu kullandığımda mosfet sürücüde HO ya bağlı mosfet açılıyor LO ya bağlı mosfeti açamıyorum. LO ya bağlı mosfeti nasıl açabilirim?

    1. Merhaba,

      IR2104 ya da IR2103 kullanmanıza göre değişir. Hangisini kullanıyorsunuz? Ayrıca ch1 ve ch1n çıkışlarını IR210X in hangi pinlerine bağladınız?

      1. Elimde olduğu için IR2101 kullandım CH1’i HIN girişine CH1N’i LIN girişine bağladım.

        1. IR2101 in lojiği diğerlerinden farklı. Sözünü ettiğiniz bağlantı şekliyle H ve L tarafındaki MOSFET lerin sıra ile açılıp kapanması lazım. Elimde IR2101 olmadığı için bir ölçüm yapamıyorum.Ama siz HIN ve LIN girişlerini mikrodenetleyiciden ayırıp LIN girişine -HIN 0 V da olmalı ! – 3.3V vererek LO çıkışındaki gerilimi ölçebilir, buna bağlı MOSFET’in iletime geçip geçmediğini kontrol edebilirsiniz. IR2101 Vcc sinin 10 ila 20V arasında olması gerektiğini unutmayın. Bu gerilim 10V un altında ise çalışmaz.

          1. Hocam dediğinizi denedim LO çıkışına bağlı mosfet iletime geçiyor ama ben yazılımla nasıl iletime geçireçeğimi anlayamadım. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,Duty); bu fonksiyon ile sadece HO pinine bağlı mosfeti iletime geçirebiliyorum. Ayrıca yardım ettiğiniz için çok teşekkür ederim.

          2. O halde doğru sinyal geldiğinde MOSFET iletime geçiyor demektir. LO çıkışı HO çıkışının tersi, yani HO “1” olduğunda LO “0” oluyor ve tersi. HO çalışıyorsa bunun tersi olan LO da çalışıyordur. MOSFET çıkışını nasıl ölçtüğünüzü bilmiyorum, ama multimetre ile iletime geçtiğini anlayamayabilirsiniz. Zira, yüksek duty cycle oranlarında HO uzun sürelerle, LO ise çok kısa sürelerle iletimde kalır. Bunu da multimetre ile göremezsiniz. Ancak osiloskobunuz var ise görebilirsiniz. LO çıkışının MOSFET’i iletime geçiremediği sonucuna nasıl varıyorsunuz? Duty cycle ı %50 nin altına düşürüp LO yu öyle ölçün bakalım.

  2. Selçuk Bey Merhaba,
    Tüm seriyi zevk alarak okudum açıklayıcı ve güzel bir dille yazmışsınız ellerinize sağlık. Ben bir şey merak ettim onu sormak istiyorum pwm frekansını 10khz olarak ayarlamışsınız yaptığınız ayarları şöyle yapsaydık ne değişirdi motorun çalışmasında bir problem yaşanırmıydı?
    prescaler = 2
    counter period = 3600
    Bu değerlerle hesaplayınca 10khz’lik bir frekans oluşuyor.
    (Yazının devamını sabırsızlıkla bekliyorum )

    1. Hakan Bey, ilgi ve yorumunuz için teşekkür ederim.

      Prescaler ve periyod değerlerini dediğiniz gibi, ya da başka değerlere ayarlayarak aynı pwm frekansını elde etmek elbette mümkün. Sadece PWM oranını veren “pulse” parametresini yeni duruma göre ayarlamak gerekecektir. Sizin belirttiğiniz ayarlarla %50 PWM elde etmek için pulse değerini 50 değil, 1800 olarak seçmek gerekir. Yani 2/3600 seti ile daha hassas PWM ayarı yapabilirsiniz.

      Yazının devamı biraz gecikebilir, zira şu sıralarda masamda başka projeler var.

      Selamlarımla,

  3. Selçuk hocam bldc motoru ters yöne doğru çevirmek için adımları tersten başlayarak mı uygulamamız gerekiyor? Mesala ileri giderken 1. adımdan 6. adıma kadar ters dönerken 6. adımdan 1. adıma doğru mu ilerleyecek?

  4. Selçuk Hocam elinize sağlık. Bu konuda Türkçe bir kaynak bulmak beni çok sevindirdi. Anladığım kadarıyla tasarımda 3 pot bulunmakta. ADC2 ‘yi TFT için mi kullandınız? Bir de motor adımı için pot kullanıyorsunuz. O kısmı pek anlamadım kısaca açıklarsanız çok sevinirim. İyi çalışmalar.

    1. Zeki Bey merhaba,
      İki adet pot kullanıyorum. Birisi PWM oranını, diğeri de motor hızını yani adım süresini ayarlamak için. Devre şemasında pot-pwm ve pot-pulse olarak görünüyorlar. STM32 nin ayak isimlendirmesinde de pwm_pot ve speed_pot adlı A0/A1 pinlerine bağlılar. A2 pinini de başlangıçta ADC2 girişi olarak tanımlamıştım ama sonra kullanmaktan vazgeçtim.

      Selamlarımla,

      1. Merhaba emeğiniz için teşekkürler. Benim size sorum şu kalcak. Duty cycle oranını artirdiginizda otomatik olarak bldc motor hızlanır diye biliyorum. Bir daha motor hızı için neden ayrı bir pot kullandınız.

        1. Mesut Bey merhaba,

          Yanıtımda sonradan farkettiğim hatalarımı düzeltmek üzere bir güncelleme yapıyorum:

          BLDC motorda duty cycle artırıldığında motor hızlanmaz, sadece bobin akımları ortalaması -akım kontrolunuzun izin verdiği kadar- daha yüksek değerlere çıkar. Daha fazla tork elde edersiniz. Motor hızlandıkça da PWM oranının artması gerekir ama bunun amacı motor devrini arttırmak değil, bobin akımını adım süresi ve gereken tork ile uyumlu olarak ayarlamaktır.

          Motor devir hızını belirleyen şey PWM oranı ile birlikte komütasyon periyodudur. Sonuç olarak PWM oranı tek başına motor hızını belirleyen parametre değildir.

          Motorun herhangi bir adımında iken sadece PWM oranını arttırdığınızı düşünün, motor bu adıma ilişkin pozisyona gelecek ve orada bir sonraki adım için komütasyon yapılmasını beklemeye başlayacaktır, kendiliğinden bir sonraki adıma geçmeyecektir. Bu esnada duraksadığı için de BEMF sıfırlanacak, bobin akımı aşırı yükselecektir. İkinci pot’u adım süresini -diğer deyişle komütasyon hızını- ayarlamak için kullanıyoruz. PWM oranı ve komütasyon hızı uyumlu olmak zorunda.

          Sizin söylediğiniz PWM ile DC motor sürdüğünüz durumlar için geçerlidir.

          Selamlarımla,

Comments are closed.