čtvrtek 18. února 2016

DTC - Přímé řízení momentu asynchronního motoru

Varování: Příspěvek není návodem ale inspirací pro možný návrh podobného zařízení kvalifikovanou osobou případně pod dozorem jako školní projekt. Obsahuje části pod napětím životu nebezpečným. Autor nenese odpovědnost za újmy na zdraví nebo majetku vzniklé v souvislosti s následujícím příspěvkem. Autor si vyhrazuje právo příspěvek kdykoli změnit. 

DTC – Direct Torque Control, přímé řízení momentu. Jedná se o hysterezní metodu řízení toku a momentu určenou především pro asynchronní motory s kotvou nakrátko. Verze popsaná zde vychází z U1 – I modelu.
Schema
 Obr. 1: Blokové schema

1) Měření proudu

Prostorový vektor:



Platí:







Složky proudu získáme měřením ve dvou fázích pomocí transformace Clarkové:



 , kde K volíme 2/3, dále pro vinutí bez vyvedeného středu platí




Výsledné výpočty obsažené v bloku transformace potom:





2) Měření napětí

Složky napětí získáme podle aktuální kombinace sepnutí obdobným způsobem jako složky proudu z napětí meziobvodu UM:





3) Výpočet toků:

Bloky realizují integraci napětí v čase.





Velikost toku je potom:



4) Výpočet momentu:

Bloky násobiček a sčítačka dají výsledný moment, který je třeba korigovat konstantou inverzní k té, co byla zanesena v bloku výpočtu složek proudů.
 
, kde pp je počet pólpárů.


5) Přepínací tabulka

Její výstupy přímo řídí konfiguraci sepnutí tranzistorů v třífázovém můstku. Na vstupech má hysterezní regulátory toku a momentu.
 
Obr. 2: Přepínací tabulka

Hysterezní regulátor toku rozhoduje o tom, kdy se má přepnout na následující prostorový vektor.
 



Pro menší žádaný tok se přepíná dříve a prostorový vektor se tedy pohybuje po menším šeštiúhelníku. Pro větší naopak. Cyklickým přepínáním pracovních oblastí je dosaženo točivého magnetického pole. Tokové vektory působí kolmo k cívkám statoru.

Hysterezní regulátor momentu potom rozhoduje o tom, jestli budou tranzistory sepnuté do aktivního stavu 1 až 6 nebo do konfigurace nulového fázového napětí, tedy stavu 0 nebo 7 podle toho, který je dosažen jediným přepnutím. Tímto řízením je v rámci hystereze dosažen konstantní, kruhový průběh momentu.

Výstupem přepínací tabulky jsou potom tři logické signály každý pro jednu fázi rozhodující o tom, jestli je sepnutý horní nebo dolní tranzistor v dané fázi.

6) Třífázový můstek

Tranzistory, nejčastěji IGBT, zajišťují rozstřídání stejnosměrného napětí meziobvodu podle signálů z přepínací tabulky na jednotlivé fáze asynchronního motoru. Uvedené schema je velmi zjednodušené, pouze pro definování polarity řídících signálů, chybí např. generování deadtimu.

Obr. 3: zjednodušené schema třífázového můstku
Závěr:
Z principu je patrné, že tranzistory nejsou řízeny PWM s fixní spínací frekvencí. Jak často dochází k přepínání je dáno především nastavením hystereze regulátoru momentu, který opakovaně spíná a vypíná aktivní a pasivní stav v oblasti, kde se dle přepínací tabulky zrovna nachází prostorový vektor a tím se snaží udržet žádaný moment motoru.

Šestiúhelník je možno zvětšovat až do maximálního omezeného napětím meziobvodu. Dále pak motor při vyšších otáčkách samovolně přechází do režimu odbuzování, tedy klesá moment.

Realizace v MCU
Chtěl jsem ze zvědavosti zkusit realizovat výpočet uvedený výše, který je vlastně přepisem odevzdávaného protokolu, v MCU na prototypové desce s 3f můstkem, který jsem do té doby používal se skalární regulací. Zde je schema, pár fotek a videa, jak to zatím vypadá. V příloze pak kousek upraveného kódu.




S namontovaným chladičem

Úvodní video ze začátků ladění, aneb když to konečně začalo nějak fungovat



Příloha:
Z průbehu vypočteného toku je vidět, že algoritmus nefungoval úplně koretně ještě a vnášel tam jistý offset. (vykresleno přímo z dat přenesených z MCU)

Příloha:
/* Transformace */
        I_alpha = I_a;
        I_beta = (I_a + 2*I_b);
        I_beta = I_beta*57735/100000;
/* Stanoveni fazovych napeti */
        switch(vektor)
        {
            case 0:
            {
                U_alpha = 0;
                U_beta = 0;
            }
            break;
            case 1:
            {
                U_alpha = U_m;
                U_beta = 0;
            }
            break;
            case 2:
            {
                U_alpha = U_m/2;
                U_beta = U_m*86603/100000;
            }
            break;
            case 3:
            {
                U_alpha = -U_m/2;
                U_beta = U_m*86603/100000;                
            }
            break;
            case 4:
            {
                U_alpha = -U_m;
                U_beta = 0;
            }
            break;
            case 5:
            {
                U_alpha = -U_m/2;
                U_beta = -U_m*86603/100000;
            }
            break;
            case 6:
            {
                U_alpha = U_m/2;
                U_beta = -U_m*86603/100000;
            }
            break;
            case 7:
            {
                U_alpha = 0;
                U_beta = 0;
            }
            break;
        }
        
    /* Vypocet slozek toku    */    
    psi_alpha = psi_alpha + U_alpha - I_alpha/Gs;
    psi_beta = psi_beta + U_beta - I_beta/Gs;     
    
    /* Vypocet toku    */
    psi_druha = psi_alpha*psi_alpha + psi_beta*psi_beta; //druha mocnina psi
    
    /* Vypocet druhe odmocniny */
    psi_b = 1 << (32-2);
  psi = 0;
  while (psi_b != 0)
    {
    if (psi_druha >= psi + psi_b)
        {
      psi_druha -= psi + psi_b;
      psi += psi_b << 1;
    }
    psi >>= 1;
        psi_b >>= 2;
  }
    
    /* Vypocet momentu */
    moment = (psi_alpha*I_beta/154 - psi_beta*I_alpha/154)*3/2; //130*154=20kHz => mNm
    
    /* Vyber sektoru */
    switch(sektor)
    {
        case 0:
        {
            if(psi_beta*1732 > psi_alpha*1000)
            {
                sektor = 1;
                otacky++;
            }
            if(-psi_beta*1732 > psi_alpha*1000)
            {
                sektor = 5;
                otacky--;
            }
        }
        break;
        case 1:
        {
            if(psi_alpha < 0)
            {
                sektor = 2;
                otacky++;
            }
            if(psi_beta*1732 < psi_alpha*1000)
            {
                sektor = 0;
                otacky--;
            }
        }
        break;
        case 2:
        {
            if(psi_beta*1732 < -psi_alpha*1000)
            {
                sektor = 3;
                otacky++;
            }
            if(psi_alpha > 0)
            {
                sektor = 1;
                otacky--;
            }
        }
        break;
        case 3:
        {
            if(psi_beta*1732 < psi_alpha*1000)
            {
                sektor = 4;
                otacky++;
            }
            if(psi_beta*1732 > -psi_alpha*1000)
            {
                sektor = 2;
                otacky--;
            }
        }
        break;
        case 4:
        {
            if(psi_alpha > 0)
            {
                sektor = 5;
                otacky++;
            }
            if(psi_beta*1732 > psi_alpha*1000)
            {
                sektor = 3;
                otacky--;
            }
        }
        break;
        case 5:
        {
            if(-psi_beta*1732 < psi_alpha*1000)
            {
                sektor = 0;
                otacky++;
            }
            if(psi_alpha < 0)
            {
                sektor = 4;
                otacky--;
            }
        }
        break;
    }
    
    /* Regulator toku */
    psi_delta = psi_zadane - psi;
    if(psi_delta > psi_epsilon)
    {
        psi_hystereze = 1; //tok nahoru
    }
    if(psi_delta < -psi_epsilon)
    {    
        psi_hystereze = 0; //tok dolu
    }
    
    /* Regulator momentu */
    moment_delta = moment_zadany - moment;
    switch(psi_stav)
    {
        case 0:
        {
            if(moment_delta > moment_epsilon)
            {
                psi_stav = 1;
            }
            if(moment_delta < -moment_epsilon)
            {
                psi_stav = 2;
            }
            moment_hystereze = 0;
        }
        break;
        case 1:
        {
            if(moment_delta <= 0)
            {
                psi_stav = 0;
            }
            moment_hystereze = 1; //moment nahoru
        }
        break;
        case 2:
        {
            if(moment_delta >= 0)
            {
                psi_stav = 0;
            }
            moment_hystereze = -1; //moment dolu, nemame kam rekuperovat
        }
        break;
    }
    
    /* Prepinaci tabulka */
    if(psi_hystereze) //tok nahoru
    {
        if(moment_hystereze == 0)
        {
            vektor = 0; //lichy do nul, sudy do jednicek
        }
        if(moment_hystereze == 1)
        {
            vektor = 1 + (6 + sektor + 1)%6; //dopredu ven
        }
        if(moment_hystereze == -1)
        {
            vektor = 1 + (6 + sektor - 1)%6; //zpet ven
        }
    }
    else
    {
        if(moment_hystereze == 0)
        {
            vektor = 0;
        }
        if(moment_hystereze == 1)
        {
            vektor = 1 + (6 + sektor + 2)%6; //dopredu dovnitr
        }
        if(moment_hystereze == -1)
        {
            vektor = 1 + (6 + sektor - 2)%6; //zpet dovnitr
        }
    }
    
    /* Zapis do komparacnich jednotek 3f mustku */
        switch(vektor)
        {
            case 0:
            {
                TIM1->CCR1 = 0;
                TIM1->CCR2 = 0;
                TIM1->CCR3 = 0;
            }
            break;
            case 1:
            {
                TIM1->CCR1 = 4200;
                TIM1->CCR2 = 0;
                TIM1->CCR3 = 0;
            }
            break;
            case 2:
            {
                TIM1->CCR1 = 4200;
                TIM1->CCR2 = 4200;
                TIM1->CCR3 = 0;
            }
            break;
            case 3:
            {
                TIM1->CCR1 = 0;
                TIM1->CCR2 = 4200;
                TIM1->CCR3 = 0;
            }
            break;
            case 4:
            {
                TIM1->CCR1 = 0;
                TIM1->CCR2 = 4200;
                TIM1->CCR3 = 4200;
            }
            break;
            case 5:
            {
                TIM1->CCR1 = 0;
                TIM1->CCR2 = 0;
                TIM1->CCR3 = 4200;
            }
            break;
            case 6:
            {
                TIM1->CCR1 = 4200;
                TIM1->CCR2 = 0;
                TIM1->CCR3 = 4200;
            }
            break;
            case 7:
            {
                TIM1->CCR1 = 4200;
                TIM1->CCR2 = 4200;
                TIM1->CCR3 = 4200;
            }
            break;
        }
    }


Žádné komentáře: