Asenkron motorun skaler kontrolü

erdemtr55

Üye
Katılım
3 Mart 2025
Mesajlar
293
Selamın Aleyküm arkadaşlar,
Asenkron motorun Skaler kontrol için evde denemeler yapıyorum. Githubdan indirdiğim kodları denedim. Malesef IR2110 3 de yandı.
STM32 kodunu ve sinyal çıkışları size yolluyorum.
1.resimde B ve C fazları 30hz.
2.resimde A ve B fazı 30hz
1.sorum neden A fazı B ,C fazlarını dibi tam dolulukta olmuyor?

main.c ise ise şu şekilde kodlanmış;
void sineValuesGeneration(int freq){
nValues = 2*floor(9000/freq);
phaseB = 1*floor(nValues/3.00) + phaseA;
phaseC = 2*floor(nValues/3.00) + phaseA;
for(uint16_t i = 0; i < (nValues/2); i++){
sinValues = round(999.00*(0.5*m*sin(i*2*3.14159265358979323846/nValues)+0.5));
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){

if((counter + phaseA)%nValues < (nValues/2)){
TIM1->CCR1 = sinValues[(counter + phaseA)];
}
else{
TIM1->CCR1 = 999-sinValues[(counter + phaseA)%(nValues/2)];
}
if((counter + phaseB)%nValues < (nValues/2)){
TIM1->CCR2 = sinValues[counter + phaseB];
}
else{
TIM1->CCR2 = 999-sinValues[(counter + phaseB)%(nValues/2)];
}
if((counter + phaseC)%nValues < (nValues/2)){
TIM1->CCR3 = sinValues[counter + phaseC];
}
else{
TIM1->CCR3 = 999-sinValues[(counter + phaseC)%(nValues/2)];
}
counter++;
if(counter > nValues) counter = 0;
}


arr 1000-1,prsecaler 8-1 dir.
 

Ekler

  • 1.png
    1.png
    120.9 KB · Görüntüleme: 28
  • 2.png
    2.png
    130.9 KB · Görüntüleme: 28
  • main.c
    main.c
    8 KB · Görüntüleme: 20
Son düzenleme:
Yardımcı olacak var mı?
ben tam olarak spwm tekniğini anlamadım.
9khz pwm üzerine kaç hz li ve kaç doluluklu sinyali koyacam?
 
Aşağıdaki kod parçası daha önce denediğim ve sorunsuz çalışan bir uygulamaya ait.
Yalnız burada yazılım kadar donanım da önemli. Devreyi nasıl kurdun ve asıl amaç nedir?

Mesela benim uygulalamam basit olduğu için ben 64 adımlı sinüs tablsou kullandım.


C++:
#include "pwm.h"

const uint32_t sinTable[64] = {
                                0,        660,   1320,  1980,  2639,  3298,  3955,  4611,
                                5266,  5919,  6570,  7219,  7867,  8511,  9153,  9793,
                                10429, 11062, 11692, 12318, 12941, 13559, 14174, 14784,
                                15389, 15990, 16586, 17177, 17763, 18343, 18918, 19487,
                                20050, 20607, 21158, 21702, 22239, 22770, 23294, 23811,
                                24321, 24823, 25317, 25804, 26283, 26754, 27217, 27672,
                                28118, 28555, 28984, 29404, 29815, 30217, 30610, 30993,
                                31368, 31732, 32087, 32432, 32767, 33092, 33407, 33712
                              };

uint32_t angleStep = 0, currentSector = 0, angleSector = 0, angleCircle = 0, angleIntegral = 0;
uint32_t angleStepBuffer, modIndexBuffer;
uint32_t modIndex = 0;
uint16_t pwmA = 0, pwmB = 0, pwmC = 0;

extern uint8_t calcFlag;

uint32_t freq = MIN_FREQ;
uint32_t magnitute = MIN_MAGNITUDE;
uint32_t ts = 2048;
uint32_t ta, tb, tz;


inline void svmUpdate()
{
    if(calcFlag == 0)
    {
        angleStep = angleStepBuffer;
        modIndex = modIndexBuffer;
    }

    angleIntegral += angleStep;
    angleCircle = ((angleIntegral >> 16) / 10);

    if(angleCircle >= 360)
    {
        angleCircle = angleCircle - 360;
        angleIntegral = (angleCircle << 16) * 10;
    }

    if(angleCircle > 0)
    {
        currentSector = angleCircle / 60;
    }
    else
    {
        currentSector = 0;
    }

    angleSector = angleCircle % 60;

    ta = sinTable[60 - angleSector];
    tb = sinTable[angleSector];

    ta = (ts * sinTable[60 - angleSector]) >> 15;
    ta = (ta * modIndex) >> 15;
    ta = ta / 100;

    tb = (ts * sinTable[angleSector]) >> 15;
    tb = (tb * modIndex) >> 15;
    tb = tb / 100;

    tz = ts - (ta + tb);
    tz = tz >> 1;

    switch(currentSector)
    {
        case 0:
        {
            pwmA = tz + ta + tb;
            pwmB = tz + tb;
            pwmC = tz;
            break;
        }

        case 1:
        {
            pwmA = tz + ta;
            pwmB = tz + ta + tb;
            pwmC = tz;
            break;
        }

        case 2:
        {
            pwmA = tz;
            pwmB = tz + ta + tb;
            pwmC = tz + tb;
            break;
        }

        case 3:
        {
            pwmA = tz;
            pwmB = tz + ta;
            pwmC = tz + ta + tb;
            break;
        }

        case 4:
        {
            pwmA = tz + tb;
            pwmB = tz;
            pwmC = tz + ta + tb;
            break;
        }

        case 5:
        {
            pwmA = tz + ta + tb;
            pwmB = tz;
            pwmC = tz + ta;
            break;
        }

    }

    TIM1->CCR1 = pwmA;
    TIM1->CCR2 = pwmB;
    TIM1->CCR3 = pwmC;
}
 
Aşağıdaki kod parçası daha önce denediğim ve sorunsuz çalışan bir uygulamaya ait.
Yalnız burada yazılım kadar donanım da önemli. Devreyi nasıl kurdun ve asıl amaç nedir?

Mesela benim uygulalamam basit olduğu için ben 64 adımlı sinüs tablsou kullandım.


C++:
#include "pwm.h"

const uint32_t sinTable[64] = {
                                0,        660,   1320,  1980,  2639,  3298,  3955,  4611,
                                5266,  5919,  6570,  7219,  7867,  8511,  9153,  9793,
                                10429, 11062, 11692, 12318, 12941, 13559, 14174, 14784,
                                15389, 15990, 16586, 17177, 17763, 18343, 18918, 19487,
                                20050, 20607, 21158, 21702, 22239, 22770, 23294, 23811,
                                24321, 24823, 25317, 25804, 26283, 26754, 27217, 27672,
                                28118, 28555, 28984, 29404, 29815, 30217, 30610, 30993,
                                31368, 31732, 32087, 32432, 32767, 33092, 33407, 33712
                              };

uint32_t angleStep = 0, currentSector = 0, angleSector = 0, angleCircle = 0, angleIntegral = 0;
uint32_t angleStepBuffer, modIndexBuffer;
uint32_t modIndex = 0;
uint16_t pwmA = 0, pwmB = 0, pwmC = 0;

extern uint8_t calcFlag;

uint32_t freq = MIN_FREQ;
uint32_t magnitute = MIN_MAGNITUDE;
uint32_t ts = 2048;
uint32_t ta, tb, tz;


inline void svmUpdate()
{
    if(calcFlag == 0)
    {
        angleStep = angleStepBuffer;
        modIndex = modIndexBuffer;
    }

    angleIntegral += angleStep;
    angleCircle = ((angleIntegral >> 16) / 10);

    if(angleCircle >= 360)
    {
        angleCircle = angleCircle - 360;
        angleIntegral = (angleCircle << 16) * 10;
    }

    if(angleCircle > 0)
    {
        currentSector = angleCircle / 60;
    }
    else
    {
        currentSector = 0;
    }

    angleSector = angleCircle % 60;

    ta = sinTable[60 - angleSector];
    tb = sinTable[angleSector];

    ta = (ts * sinTable[60 - angleSector]) >> 15;
    ta = (ta * modIndex) >> 15;
    ta = ta / 100;

    tb = (ts * sinTable[angleSector]) >> 15;
    tb = (tb * modIndex) >> 15;
    tb = tb / 100;

    tz = ts - (ta + tb);
    tz = tz >> 1;

    switch(currentSector)
    {
        case 0:
        {
            pwmA = tz + ta + tb;
            pwmB = tz + tb;
            pwmC = tz;
            break;
        }

        case 1:
        {
            pwmA = tz + ta;
            pwmB = tz + ta + tb;
            pwmC = tz;
            break;
        }

        case 2:
        {
            pwmA = tz;
            pwmB = tz + ta + tb;
            pwmC = tz + tb;
            break;
        }

        case 3:
        {
            pwmA = tz;
            pwmB = tz + ta;
            pwmC = tz + ta + tb;
            break;
        }

        case 4:
        {
            pwmA = tz + tb;
            pwmB = tz;
            pwmC = tz + ta + tb;
            break;
        }

        case 5:
        {
            pwmA = tz + ta + tb;
            pwmB = tz;
            pwmC = tz + ta;
            break;
        }

    }

    TIM1->CCR1 = pwmA;
    TIM1->CCR2 = pwmB;
    TIM1->CCR3 = pwmC;
}
sbt frekans anladığım kadarı ile
Ben vfd istiyorum
 
@ex_machina sadece kodun girişinden sonuna inio baktım sizin attığınız SVPWM, konuda istenen SPWM.

Konuda modülasyon ve kontrol tekniği karışıklığı var bence. Spwm bir modülasyon şekli, frekansı sabit değişken vs modülasyon üzerinde böyle oynamalar yapılabilir tabiki(pwm fazları kaydırılabilir, frekansı değiştirilebilir). Ama vfd istiyorum modülasyon üzerinden tek başına söylenecek bir şey değil.
 
Frekansı svmUpdate fonkisyonunu çağırma periyodun belirliyor. Gerilim ise modIndex(modülasyon indexi) değişkeni ile kontrol ediliyor.

@ex_machina sadece kodun girişinden sonuna inio baktım sizin attığınız SVPWM, konuda istenen SPWM.

Konuda modülasyon ve kontrol tekniği karışıklığı var bence. Spwm bir modülasyon şekli, frekansı sabit değişken vs modülasyon üzerinde böyle oynamalar yapılabilir tabiki(pwm fazları kaydırılabilir, frekansı değiştirilebilir). Ama vfd istiyorum modülasyon üzerinden tek başına söylenecek bir şey değil.

Çok bişey farketmiyor aslında. Sonuçta gerilimi ve frekansı orantılı artırıp azaltacak.
 
@ex_machina sadece kodun girişinden sonuna inio baktım sizin attığınız SVPWM, konuda istenen SPWM.

Konuda modülasyon ve kontrol tekniği karışıklığı var bence. Spwm bir modülasyon şekli, frekansı sabit değişken vs modülasyon üzerinde böyle oynamalar yapılabilir tabiki(pwm fazları kaydırılabilir, frekansı değiştirilebilir). Ama vfd istiyorum modülasyon üzerinden tek başına söylenecek bir şey değil.
svpwm vekörel kontrol değil mi? dtc veya foc
 
Değil. Svpwm sadece bir modülasyon tekniği V/F sürüp svpwm de yapabilirsin keyfine kalmış. Kontrolü nasıl yaptığın ve nasıl modülasyon yaptığın farklı şeyler. Vektör kontrol dediğin şey aslında field oriented control(foc) un diğer adı gibi bir şey kabul ediliyor. DTC de vektör bazlı bir kontrol yapıyor olmasına rağmen, genellikle vektör kontrol foc ile eşlenik gibi kullanıldığından farklı bir şey gibi algılanıyor. Maalesef bu konulardaki terminoloji bence ortak olarak benimsenmiş durumda değil, o yüzden anlaşılmak için biraz uzun uzun yazmak gerekiyor. Bütün bu kontrol teknikleri en temelde VSI a sahip olduğun sürece uygulayacağın gerilimleri veriyor, ama bu gerilimlerin nasıl uygulanacağı noktası modülasyon.

Skaler kontrol dediğin şey V/F kontrol gibi anlıyorum, eğer buysa zaten sen aslında her bir kontrol cycle ının sonunda Va Vb Vc voltajlarına sahipsin, bu voltajları uygulamak için spwm kullanmak pratik. Spwm herhangi bir şekilde senin uyguladığın frekansı bilmek zorunda değil, sadece o spesifik time da olan gerilime ihtiyacı var. Sen o fonksiyona verdiğin gerilimleri istediğin frekans da değiştirebilirsin. Fonksiyon u pwm update frekansının üstü bir hızda çağırman anlamsız vs kısımlarını konuşmaya gerek olmadığını düşünüyorum. Eğer bu kısımda aynı sayfadaysak kodu bu şekilde bölersen yardımcı olmak kolaylaşır.
 

Çevrimiçi üyeler

Forum istatistikleri

Konular
9,096
Mesajlar
146,758
Üyeler
3,684
Son üye
habaca

Son kaynaklar

Back
Top