PMSM kontrolü

tb5byo

Yeni Üye
Katılım
22 Nisan 2025
Mesajlar
3
Arkadaşlar Merhaba bir PM senkron motoru kontrol etmeye çalışıyorum fakat yaşadığım bazı aksaklıklar ve kafamda soru işaretleri var. Araştırmalarımda pratik bilgiden çok teorik bilgi mevcut ve bunun uygulamada pek bir yararı olmuyor. kodların bir kısmını tamamladım ve test yaparak sisteme dahil etmeye çalışıyorum Aşağıya kullandığım kod bloklarını bırakıyorum.
Kullandığım motor 140TAST-01F2H4P ve PM5182029. iki motorda 83.3 hz 220v 1024 ppr enkoder mevcut.
sinüs ve cosinus hesaplamaları için bir lut tablosu oluşturdum. Doğruluğunu kontrol ettim. SVPWM koduna sırası ile 0 dan 360 a kadar değer gönderdim ve sonucunda ürettiği Ta,Tb ve Tz sürelerini bir excel de sektörlere göre hesaplayıp çıkan grafiği kontrol ettiğimde tam olarak istediğim sinyalleri görmekteyim (60 derecede bir sektör değişimi gerçekleştirdim).

Soruma gelirsek;
Biz sektörleri belirlerken elektriksel açı kullanıyoruz.
Elimdeki motora bakarsak sabit 20 mıknatıs ve 18 iç sargı mevcut. Manyetik kutup çifti göz önüne
alındığında dışta 10, içte 9 çift manyetik alan oluşturacak eleman var.
Delta fi = 360/9 - 360/10 = 360/90 = 4 derece
Her bir 360 derecelik 3 fazlı döngüden yola çıkarsak;
İç bobinin tam turluk dönüşü 360/9 =40 derece ve sabit mıknatısların 360 /90 = 4 derece dönmüş olur.
Arada 10 katlık bir yavaş dönüş farkı var
360/10= 36 derece yani sonuç olarak U, V, W sargılarına yapılacak her 360 derecelik bir faz döngüsü sonunda motor
tam olarak 36 derece döner. (bu hesaba bir forumda veya makalede denk gelmiştim nerede bulduğum konusunda tam emin değilim)

36 derecelik bir rotor hareketi için 360 derecelik elektriksel çevrim yapmak zorundayım. motor her meknaik turda 1024 pulse üretiyor ve her 36 turda 102,4 pulse tekamül ediyor ( pulse değeri tam sayı olduğu için aslında 102 pulse okuyorum). Ben bu 102 pulse içine 360 derecelik elektriksel dönüş sığdırmak zorunda kalıyorum buda bazı değerlerde kayıp yaşadığım anlamına geliyor yani her bir pulse artışında çoktan 3,52 derece geçmiş oluyor. 36 derecelik mekanik harekette 6 sektör sığdırmam lazım ve buda her sektörün 6 derecelik mekanik açıya denk gelmesi demek. Her pulse artışında 3,52 derece yol alırsam her sektörü maksimum 2 parametre sağlamış oluyorum buda kayıplara yol açıyor. Bunun önüne geçmek için enkoder ppr değerini artırmammı gerekli yoksa hesaplarımda bir hatamı mevcut? atladığım bir nokta veya hatam var ise düzeltirseniz sevinirim.

Motora elektriksel açı yerine doğrudan mekanik açıyı verdiğimde ve sektör olarak 60 derecede bir değişim yaptığımda aşağıdaki videolardaki hareketi almaktayım fakat burada da bazı sıkıntılar mevcut( açıyı her turda z pulse i geldiğinde sıfırlıyorum ve +7 eklemek zorunda kalıyorum bunları yapmadığım zaman istediğim hareketi alamamaktayım. aşağıdaki videodan açı eklenmesinin motora etkisi görülmektedir (sadece svpwm fonksiyonu çağırılmıştır ve magnitute değeri 1 verilmiştir, açı girişine doğrudan enkoderden okunan veri girilmiştir).

Biraz uzun ve karışık olduğunun farkındayım umarım derdimi anlatabilmişimdir. Bu konu haricinde daha önce bu motorun kontrolünü yapan var ise aşağıdaki kodlarımı kontrol ederse çok memnun kalırım. Teşekkürler iyi çalışmalar.

Kod:
void motor_control_loop() {


    //    //Clarke dönüşümü (örnek akım değerleri kullanılabilir)
    //    clarke_transform(Akim_U, Akim_V, Akim_W, &motor.ialpha, &motor.ibeta);

    //    // Park dönüşümü
    //    park_transform(motor.ialpha, motor.ibeta, motor.theta, &pid.id, &pid.iq);

    //    //PI Kontrol (hata hesapla ve kontrol et)
    //    pid.vd = pi_controller(pid.kp, pid.ki, current.id_ref - pid.id, &pid.integral_id, pid.dt);
    //    pid.vq = pi_controller(pid.kp, pid.ki, current.iq_ref - pid.iq, &pid.integral_iq, pid.dt);

    //Ters Park dönüşümü
//    inverse_park_transform(pid.vd, pid.vq, encoder.angle, &motor.valpha, &motor.vbeta);

    //Gerilim vektörünün büyüklüğü ve açısını hesapla
//    motor.magnitude = sqrtf(motor.valpha * motor.valpha + motor.vbeta * motor.vbeta);
//    V_angle = atan2f(motor.vbeta, motor.valpha) * RAD2DEG;  // Atan fonksiyonu radyan cinsinde çıkış verdiği için dereceye çevirildi.


//    if (V_angle < 0)
//    {// -180 ile +180 arasında çıkış verdiği için düzeltme gerçekleştirildi.
//        V_angle += 360.0f;
//    }

    //SVPWM fonksiyonunu çağır
    svpwm(V_angle, motor.magnitude);
}

Kod:
// PI Kontrol Fonksiyonu
float pi_controller(float kp, float ki, float error, float *integral, float dt) {
    *integral += error * dt;
    return kp * error + ki * (*integral);
}

// Clarke Dönüşümü
void clarke_transform(float a, float b, float c, float *alpha, float *beta) {
    *alpha = a;  // Basitleştirilmiş versiyon
    *beta = (b - c) / Square_3;

//    Clarke->Ialpha = Currents->Iu;
//    Clarke->Ibeta = SQRT3_OVER_1 * (Currents->Iu + 2.0f * Currents->Iv);
//#define SQRT3_OVER_1        0.57735027f
}


/*
 * Park Dönüşümü
 */
void park_transform(float ialpha, float ibeta, int theta, float *id, float *iq) {
    float sin_AngR = sin_LUT[theta];
    float cos_AngR = cos_LUT[theta];

    *id = ialpha * cos_AngR + ibeta * sin_AngR;
    *iq = -ialpha * sin_AngR + ibeta * cos_AngR;

}


/*
 * Ters Park Dönüşümü
 */
void inverse_park_transform(float vd, float vq, int theta, float *valpha, float *vbeta) {
    float sin_AngR = sin_LUT[theta];
    float cos_AngR = cos_LUT[theta];

    *valpha = vd * cos_AngR - vq * sin_AngR;
    *vbeta = vd * sin_AngR + vq * cos_AngR;
}


Kod:
// SVPWM Fonksiyonu
void svpwm(float angle, float Mag) {
    /*
     * DERECE CİNSİNDEN OLAN AÇI DEĞERİ NORMALDE RADYANA ÇEVİRİLMELİ FAKAT
     * BİZ OKUDUĞUMUZ DERECEYE GÖRE DAHA ÖNCEDEN GELECEK 0 İLE 359 ARASINDAKİ TÜM DERECELERİ ÖNCE RADYANA ÇEVİRDİK
     * DAHA SONRA TÜM DEĞERLERİN SİN VE COS HESABINI YAPIP TABLO HALİNE GETİRDİK.
     */

    // Açıyı LUT indexine çevirme
    int indeks = (int)(angle) % 60;  // 0-60 arasında bir indeks üret
    // LUT'ten değer çekme
    float sin_AngR = sin_LUT[indeks];
    float cos_AngR = cos_LUT[indeks];
    Ta = ((Mag * cos_AngR ) / MOD_INDEX) - (((Mag * sin_AngR ) / MOD_INDEX) * (1 / Square_3));
    Tb = ((Mag * sin_AngR ) / MOD_INDEX) * (2 / Square_3);
    Tz = (1 - (Ta + Tb)) / 2;

    switch (encoder.sector) {
    case 1:
        motor.MOTOR_U = Tz + Ta + Tb;
        motor.MOTOR_V = Tz + Tb;
        motor.MOTOR_W = Tz;
        break;
    case 2:
        motor.MOTOR_U = Tz + Ta;
        motor.MOTOR_V = Tz + Ta + Tb;
        motor.MOTOR_W = Tz;
        break;
    case 3:
        motor.MOTOR_U = Tz;
        motor.MOTOR_V = Tz + Ta + Tb;
        motor.MOTOR_W = Tz + Tb;
        break;
    case 4:
        motor.MOTOR_U = Tz;
        motor.MOTOR_V = Tz + Ta;
        motor.MOTOR_W = Tz + Ta + Tb;
        break;
    case 5:
        motor.MOTOR_U = Tz + Tb;
        motor.MOTOR_V = Tz;
        motor.MOTOR_W = Tz + Ta + Tb;
        break;
    case 6:
        motor.MOTOR_U = Tz + Ta + Tb;
        motor.MOTOR_V = Tz;
        motor.MOTOR_W = Tz + Ta;
        break;
    default:
        motor.MOTOR_U = Tz + Ta + Tb;
        motor.MOTOR_V = Tz;
        motor.MOTOR_W = Tz + Ta;
        break;
    }

    motor.MOTOR_U *= htim8.Init.Period;
    motor.MOTOR_V *= htim8.Init.Period;
    motor.MOTOR_W *= htim8.Init.Period;

    TIM8->CCR1 = (uint16_t)motor.MOTOR_W;
    TIM8->CCR2 = (uint16_t)motor.MOTOR_V;
    TIM8->CCR3 = (uint16_t)motor.MOTOR_U;

    TIM8->CCR4 = htim8.Init.Period/2; // akım ölçümü için tetikleme sinyali
}
 
Haftasonu bir bakacaktım ama aklıma gelenleri söyleyeyim.

Çözünürlük düşük bu yüzden düşük hızlarda sektörler arası geçişlerde sorun yaşatabilir. Bundan dolayı imkan varsa 0-4095 deneyin.

Bir de tüm açıları 0-359 arası çevirdik demişsiniz ama tabloda 60 üzerinden indeksliyorsunuz 360 üzerinden yapmanız gerekli değil mi?
 
Haftasonu bir bakacaktım ama aklıma gelenleri söyleyeyim.

Çözünürlük düşük bu yüzden düşük hızlarda sektörler arası geçişlerde sorun yaşatabilir. Bundan dolayı imkan varsa 0-4095 deneyin.

Bir de tüm açıları 0-359 arası çevirdik demişsiniz ama tabloda 60 üzerinden indeksliyorsunuz 360 üzerinden yapmanız gerekli değil mi?
aslında svpwm için lut tablosunu sadece 60 derece için yapmam yeterli olabiliyor fakat inverse park ve park fonksiyonlarım için 0 ile 2pi arasında hesap olduğundan dolayı 360 a kadar olan tüm değerler hesaplandı.
Aşağıdaki görselde svpwm kodlarının çıktısı görülmekte
1745571763102.png

Şu aşamada inverse park kodlarını da matlab üzerinde test ettim ve istenilen grafik çıktısını sağlıyor. sadece sektör belirleme yönteminden ve enkoder çözünürlüğünün yeterli olduğundan emin olmadığım için motor üstünde test gerçekleştiremedim.
 
Bu durumda senin istediğin şekilde çalışabilmesinin önündeki sorun enkoder gibi duruyor. Şu gönderdiğin grafik zaten svpwm için çalışma grafiğini oluşturmuş oluyor yani simülasyon doğru. Dediğim gibi bu durumda kalan şey daha yüksek çözünürlüklü enkoder bularak bakmak.
 
Tablodan sincos okuman gerektiginde aciyi mekanik acidan hesaplayacaksin. Elektrik aci ile mekanik aci arasinda faz kamasi kacinilmaz.

Encoderin devir basina verdigi pals sayisi 3 ve 2 nin tam kati olursa bahsettigin sorun kalmaz. Aksi halde komutasyon noktalarinda hata olur.
 
Tablodan sincos okuman gerektiginde aciyi mekanik acidan hesaplayacaksin. Elektrik aci ile mekanik aci arasinda faz kamasi kacinilmaz.

Encoderin devir basina verdigi pals sayisi 3 ve 2 nin tam kati olursa bahsettigin sorun kalmaz. Aksi halde komutasyon noktalarinda hata olur.
hocam daha çok merak ettiğim elektriksel açıyı belirleyen şeyin motorun stator sargısı ile sabit mıknatısın arasında bir bağlantı olup olmadığı. Burda biz elektriksel açıyı hesaplarken doğrudan mekanik açıyı mı hesaba katmalıyız yoksa mıknatıs sayısına bağlı olarak (yukarıda da hesapladığım gibi) 36 derecelik bir alanı mı göz önüne almalıyım ?
 
hocam daha çok merak ettiğim elektriksel açıyı belirleyen şeyin motorun stator sargısı ile sabit mıknatısın arasında bir bağlantı olup olmadığı. Burda biz elektriksel açıyı hesaplarken doğrudan mekanik açıyı mı hesaba katmalıyız yoksa mıknatıs sayısına bağlı olarak (yukarıda da hesapladığım gibi) 36 derecelik bir alanı mı göz önüne almalıyım ?
Böyle okuyunca daha net canlandı gözümde.

ElektrikselAçı = MekanikAçı*KutupÇifti

Aslında bu formül üzerinden bakığın zaman hangisini aldığının bir önemi yok önemli olan seçtiğine göre hesap yapıyor olman.
 

Forum istatistikleri

Konular
7,666
Mesajlar
127,771
Üyeler
3,097
Son üye
Queshen

Son kaynaklar

Son profil mesajları

Python Geliştirmeye eklediğim yapay zeka sunucusu, yeni başlayanlar için roket etkisi
Bir insanın zeka seviyesinin en kolay tesbiti, sorduğu sorulardır.
yapay zeka interneti yedi bitirdi, arama motoru kullanan, forumlara yazan kaldı mı ?
Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
az bilgili çok meraklı
Back
Top