Autor Wątek:  Fizyka silników trakcyjnych lokomotyw spalinowych.  (Przeczytany 5050 razy)

0 użytkowników i 1 Gość przegląda ten wątek.

Offline MichałŁ

  • Wiadomości: 1179
    • Zobacz profil
  • Otrzymane polubienia: 37
Fizyka silników trakcyjnych lokomotyw spalinowych.
« dnia: 20 Września 2015, 12:00:01 »
Witam.
Jak wiadomo silnik szeregowy ma moment obrotowy zależny od prądu więc w przybliżeniu też siła pociągowa lokomotywy zależna jest od wartości prądu podawanego na silniki trakcyjne. Robiłem próby z elektrowozami i spalinówkami przy prędkościach do 30km/h  odczytując siłę pociągową przy tałej określonej wartości prądu.
 I dla elektrowozów fizyka silnika trakcyjnego zachowuje się prawidłowo czyli dla określonego prądu siła pociągowa też jest mniej więcej stała np.
303E
300A 9300kG
400A 13000kG

ET21
200A 10000kG

ET42
300A 7500kG

Spalinówki zachowują się całkiem inaczej
Su46
2000A 11000-14000kG

SM42
1000A 5300 7000kG

SU45
2000A 1900-10000kG

Więc takie wyniki raczej nie są zgodne z rzeczywistością najgorzej jest w SU45 gdzie zdarzają się gwałtowne skoki siły pociągowej z np 9000kG na 4000kG przy praktycznie stałej wartości prądu. 
Patrząc w pliki fizyki widzę że silniki trakcyjne z elektrowozów i spalinówek maja całkiem inny sposób opisania. Czy jest jakaś możliwość przerobienia tego aby praca silników trakcyjnych byłą zgodna z rzeczywistością ?

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: Fizyka silników trakcyjnych lokomotyw spalinowych.
« Odpowiedź #1 dnia: 20 Września 2015, 21:43:59 »
A chcesz się w to wgłębić bardziej akademicko? Fizyka silnika spalinowego jest do napisania od nowa, tylko mądrego z dojściem do wymaganych danych brak. Masz na gicie kod źródłowy, możesz prześledzić wg jakich wzorów symulator przelicza te wartości. Ja względnie ogarnąłem przekładnie mechaniczną na potrzeby drezynek, ale do diesel-electric nawet nie patrzyłem.
Mój kanał youtube

Offline adamst

  • Zasłużony dla Symulatora
  • Wiadomości: 354
    • Zobacz profil
  • Otrzymane polubienia: 75
Odp: Fizyka silników trakcyjnych lokomotyw spalinowych.
« Odpowiedź #2 dnia: 21 Września 2015, 07:18:40 »
O ile wiem youby pracuje/pracował nad nową fizyką spal-ele w ramach DizelPacka2. Korzystałem z jego wskazówek tworząc swoją fizykę spal-ele dla SU45 w Trainz.

Offline MichałŁ

  • Wiadomości: 1179
    • Zobacz profil
  • Otrzymane polubienia: 37
Odp: Fizyka silników trakcyjnych lokomotyw spalinowych.
« Odpowiedź #3 dnia: 21 Września 2015, 20:01:57 »
Jakich parametrów potrzeba może coś pójdzie wykombinować. Bo na programowaniu to się nie znam.

Offline Ryszard-san

  • Wiadomości: 214
    • Zobacz profil
  • Otrzymane polubienia: 1
Odp: Fizyka silników trakcyjnych lokomotyw spalinowych.
« Odpowiedź #4 dnia: 22 Września 2015, 17:44:32 »
Witam
Co do stalinówek to silnik spalinowy jest dość prosto obliczyć moc bo w loku masz skokową zmianę obrotów (wzbudzenia) i wiadomo że np dla 1000 obr masz xx KW na wale odejmujesz moc pobieraną na cele nie trakcyjne i zostanie ci tyle co masz do dyspozycji. I właśnie w tym momencie zaczynają się klocki bo masz współpracujące 2 maszyny, prądnica - silnik(i), a obie mają zmienne charakterystyki zależne od prądu, i od stanu maszyny. Dlatego też trafiają się spalinki które są mocne i takie co są mułowate mimo że to ta sama seria. Ale to taka dygresja. Nie możesz porównywać siły pociągowej bo np EU-07, EP-07, EP-08 to są takie same silniki a różne przekładnie i każda będzie miała przy tym samym prądzie różną siłę pociągową.

Kiedyś proponowałem aby zrobić tablicę dla każdej pozycji nastawnika (obrotów silnika) na-podstawie charakterystyk w której by była zależność prąd - napięcie prądnicy. wczytywało by się to z "chk" tak jak pozycje oporowe dla elektryków. Wtedy dla danej pozycji nastawnika można by odczytywać wartość i podstawiać do charakterystyki silnika  trakcyjnego (która jest dopracowana), przy odpowiednio dobranej czasowej chodziło by to płynnie. Działało by to na zasadzie: prąd dla t = x, napięcie dla t=y jeśli napięcie z tabeli dla prądu x mniejsze niż y to dla dla t+1 bierzemy napięcie z następnej pozycji w tabeli. Jeśli większe niż y to bierzemy pozycje niżej. I taką wartość podstawiamy do silników.

Pozdrawiam Ryszard

Offline adamst

  • Zasłużony dla Symulatora
  • Wiadomości: 354
    • Zobacz profil
  • Otrzymane polubienia: 75
Odp: Fizyka silników trakcyjnych lokomotyw spalinowych.
« Odpowiedź #5 dnia: 23 Września 2015, 08:26:50 »
W mojej trainzowej SU45 wygląda to następująco (może uda mi się nie pomieszać):
 - silniki trakcyjne mają fizykę liczoną tak, jak Maszynowe elektrowozy (parametry fi,Isat,mfi,mIsat dostałem od youBy'a)
 - prądnica ma charakterystykę również opracowaną przez youBy'a, która uwzględnia zależność napięcia od prądu obciążenia, prądu wzbudzenia i obrotów
 - prąd wzbudzenia jest funkcją napięcia wzbudnicy (proporcjonalne do obrotów) oraz oporu w obwodzie wzbudzenia, ten ostatni jest częściowo regulowany przez regulator Woodwarda, a część oporów jest przełączana przez styczniki pozycji wstępnych sterowane nastawnikiem

I teraz, silnik spalinowy i regulator obrotów:
Nastawnik ustala dla danej pozycji zadane obroty silnika. Podstawowym parametrem silnika jest "moc brutto" - jest to moc silnika w funkcji obrotów odczytana z charakterystyki - w praktyce dla silnika 2112SSF daje się to z bardzo dobrym przybliżeniem opisać odcinkiem paraboli (w zakresie powyżej 500rpm). Aby uzyskać aktualną moc oddawaną przez silnik na wale, mnożę "moc brutto" przez "gaz", czyli zmienną opisującą relatywne położenie listwy paliwowej względem położenia znamionowego dla danej pozycji - normalnie jest to 1. Od tak wyliczonej mocy odejmowane są wszystkie obciążenia (silniki trakcyjne, maszyny pomocnicze, ogrzewanie, no i opory samego silnika), i wynik tego bilansu określa nam przyspieszenie lub opóźnienie silnika - tzn. przy nadwyżce mocy obroty będą wzrastały, a przy przeciążeniu - spadały. I tutaj wkracza nam regulator Woodwarda, tj. regulator mocy i obrotów. Dąży on do utrzymania obrotów znamionowych dla danej pozycji. W momencie wykrycia odchyłki obrotów silnika od wartości znamionowej zmienia on położenie listwy paliwowej (zmienna "gaz") aby dopasować moc silnika do aktualnego obciążenia. Równolegle, po wykryciu wychylenia listwy paliwowej od pozycji znamionowej (czyli "gaz" != 1), reguluje on wzbudzenie prądnicy (zmieniając wartość regulowanej rezystancji w obwodzie wzbudzenia), tak aby obciążenie odpowiadało mocy znamionowej. Te operacje są wykonywane aż układ nie powróci do stanu równowagi, czyli obroty równe obrotom znamionowym dla danej pozycji, a "gaz" równy 1 - co oznacza że obciążenie odpowiada mocy znamionowej silnika.

Opracowałem również uproszczony model cieplny silnika, z wymianą ciepła silnik <> woda w głównym obiegu, silnik <> otoczenie, silnik <> olej, olej <> woda w obiegu pomocniczym, woda w obiegu głównym <> otoczenie (przez chłodnicę 1), woda w obiegu pomocniczym <> otoczenie (chłodnica 2). Współczynniki wymiany ciepła w chłodnicy są modyfikowane przez załączenie wentylatorów i żaluzji (z uwzględnieniem prędkości obrotowej wentylatora w pierwszym przypadku i prędkości jazdy w drugim), sterowane termostatami.

Fragmenty kodu - starałem się pokomentować, żeby mniej-wiecej było wiadomo o co chodzi:
class dane
{
//opory w obwodzie wzbudzenia
public float RO;

public float R1;
public float R2;
public float R3;
public float R4;
public float R5;

public float RRW;

//nastawy przekaźnika nadmiarowego i przekaźnika bocznikowania
public float Imax;
public float Imin;
public float Iminb;

//parametry paraboli mocy silnika spalinowego
public float a;
public float c;

//parametry silników trakcyjnych
public float fi0, fi1, fi2, fi3, Isat0, Isat1, Isat2, Isat3, mfi0, mfi1, mfi2, mfi3, mIsat0, mIsat1, mIsat2, mIsat3;
};

/ciach/

// zmienne przekaznikow i stycznikow
        public bool PZB2,PWB,PCZ,PR,PPT,PZZ,PA,PWZ,PZS,PPR,PT,PUW1,PUW2,PTC1,PTC2,PZB1,PPB1,PPB2,SPL,SWP,SWW,SPP,SP0,SWM,SW1,SW2,SRW1,SRW2,SPW,SWR,PB,SB1,SB2,SB3,RW,SWMx,PWMin = 0;
        public int SP1,SP2,SP3,SST,SP4 = 0;
        public bool SLB = 0;  //stycznik ladowania baterii
        //ich PODPIERACZE
        public bool PZB2p,PWBp,PCZp,PRp,PPTp,PZZp,PAp,PWZp,PZSp,PPRp,PTp,PUW1p,PUW2p,PTC1p,PTC2p,PZB1p,PPB1p,PPB2p,SPLp,SWPp,SWWp,SPPp,SP0p,SP1p,SP2p,SP3p,SWMp,SW1p,SW2p,SRW1p,SRW2p,SPWp,SWRp;

/ciach/

//termodynamika ;-)
        public float Cw = 4.189, qs = 44700, Cs, Qs, Ts, kfs, dTss;
        public float kf, kw, kv, gw, gw3, gwmin, gwmax, Ge, Qd, Qch, Qp, dTs, dTch, Twy, Twe, Te, Tsr, gw2, gwmin2, gwmax2, Qch2, dTs2, dTch2, Twy2, Twe2, Tsr2, kf2, To, dTo, Co;
        public bool wentylator1, zaluzje1, wentylator2, zaluzje2, obieg, TCH1, TW1, TW2, TCH2, TW3;



/ciach/

// fragment głównej pętli odpowiedzialny za termostaty i przekaźnik awarii (uniemożliwia rozruch/zrzuca obroty na bieg jałowy)

obieg = ((temperatura1 > 71) or (obieg and temperatura1 > 66)) and (silnik > 0 or pompa_wodna == true);
TCH1 = (((temperatura1 > 82) or (TCH1 and temperatura1 > 74)) and (silnik > 0) and !bezpompy and (Vb > 70) and !awaria_chlodzenia) or chlodzenie;
TW1 = (temperatura1 > 90) or (TW1 and temperatura1 > 81);
TW2 = ((silnik != 0) and (temperatura1 > 30)) or (temperatura1 > 40);
TCH2 = (((temperatura2 > 60) or (TCH2 and temperatura2 > 50)) and (silnik > 0)and !bezpompy and (Vb > 70) and !awaria_chlodzenia) or chlodzenie;
TW3 = (temperatura2 > 70) or (TW3 and temperatura2 > 66);

sd.c.PT = (!TW1 and !TW3 and TW2 and !awaria_termostatow) or sd.c.PTp;
sd.c.PPT = !sd.c.PT and !sd.c.PPTp;
sd.c.PA = (!zamkniecie or niedomkniecie or sd.c.PPT) and !sd.c.PAp;

/ciach/

//bilans cieplny silnika
//Ge - ilość paliwa spalonego w danym kroku czasowym - obliczona na podstawie charakterystyk
//Qd - ciepło wytwarzane w silniku - obliczone jako energia spalonego paliwa minus moc użyteczna

thread void termo()
{
float kfo = 25;
for ( ; ;)
{
qs = 44700;
Cw = 4.189;
Co = 1.885;
kw = 0.35;
kv = 0.6;
gwmin = 400;
gwmax = 4000;
gwmin2 = 400;
gwmax2 = 4000;
Cs = 11000;
kfs = 80;


   gw = gwmin + (rpm/1500)*(gwmax-gwmin) + (float)pompa_wodna * 1000;
   gw3 = gwmin + (rpm/1500)*(gwmax-gwmin);
      gw2 = gwmin2 + (rpm/1500)*(gwmax2-gwmin2) + (float)pompa_wodna * 1000;
rpmw = 80 * rpm / ((0.5 * rpm) + 500);
kf = (float)obieg * (((kw * (float)wentylator1)) * rpmw + (kv * ((float)zaluzje1 + 0.7) * Math.Fabs(predkosc) / 3.6)+ 3) + 3;
kf2 = (((kw * (float)wentylator2)) * rpmw + (kv * ((float)zaluzje2 + 0.7) * Math.Fabs(predkosc) / 3.6)) + 3;
Ge = (float)(silnik > 0)*(0.21 * mocsilnika + 12) / 3600;
if (typ=="SP45")
Qp = (float)(podgrzewacz and pompa_wodna and (Twy < 55) and (Twy2 < 55)) * 1000;
else
Qp = (float)(podgrzewacz and pompa_wodna and (Twy < 60) and (Twy2 < 60)) * 1000;

Qd = qs * Ge - obciazenie;
Qs = (Qd - (kfs * (Ts - Tsr)) - (15 * (0.2 + 0.8 * (float)okienko) * (Ts - Te)));            //silnik oddaje czesc ciepla do wody chlodzacej, a takze pewna niewielka czesc do otoczenia, modyfikowane przez okienko
dTss = Qs / Cs;
Ts = Ts + (dTss * 0.5);
dTo = ((kfo * (Ts - To)) - (kfs * (0.2 * (float)(cisnienie > 0.01) + 0.1) * (To - Tsr2))) / (gw3 * Co);  // olej oddaje ciepło do wody gdy krazy przez wymiennik ciepla == wlaczona pompka lub silnik
To = To + (dTo * 0.5);

dTs = ((kfs * (Ts - Tsr))) / (gw * Cw);
dTs2 = ((kfs * (0.2 * (float)(cisnienie > 0.01) + 0.1) * (To - Tsr2))) / (gw2 * Cw);
Qch = -kf * (Tsr - Te) + Qp;
Qch2 = -kf2 * (Tsr2 - Te) + (80 * (float)(podgrzewacz_zawor == true) * (Twy - Tsr2));  //przy otwartym kurku B mały obieg jest dogrzewany przez duży - stosujemy przy korzystaniu z podgrzewacza oraz w zimie
dTch = Qch / (gw * Cw);
dTch2 = Qch2 / (gw2 * Cw);
Twe = Twy + (dTch * 0.5);
Twy = Twe + (dTs * 0.5);
Tsr = 0.5 * (Twy + Twe);
Twe2 = Twy2 + (dTch2 * 0.5);
Twy2 = Twe2 + (dTs2 * 0.5);
Tsr2 = 0.5 * (Twy2 + Twe2);

temperatura1 = Twy;
temperatura2 = Twy2;
fuelConsumed = fuelConsumed + (Ge * 0.5);

            while(fuelConsumed >= 0.83)
            {
                fuelConsumed = fuelConsumed - 0.83;
                fuelQueue.DestroyProductMatching(null,1);
            }//if

Sleep(0.5);
}
}

/ciach/

//głowny wątek fizyki
//zmienna "silnik" to określenie fazy pracy silnika. 0 - zgaszony, 1 - normalna praca, 2 - rozruch, faza I, 3 - rozruch, faza II - zapłon.

thread void regulator()
{
float bilans,opory,drpm,arpm,rpm_doc;
for ( ; ; )
{
bool dodajgazu = ((rpm_zadane > 696) and (pozycja < (pozycja_zadana - 1)));

// sprawdzenie mocy i regulacja napiecia
prad_razem = prad_silnika[1] + prad_silnika[2] + prad_silnika[3] + prad_silnika[4] + prad_silnika[5] + prad_silnika[6];
                        moc = napiecie * Math.Fabs(prad_razem);
                        if ((gaz > 0.03 and !dodajgazu) or PZB1 == 1 or nastawnik < 2)
                           {
                           if (PZB1 == 1)
                                woodward = woodward - 0.04;
                           if (PZB1 == 0)
                                woodward = woodward - 0.002;
                           }
                        if ((gaz < 0 or dodajgazu) and PZB1 == 0)
                           woodward = woodward + 0.005;
                        if (woodward < 0)
                           woodward = 0;
                        if (woodward > 1)
                           woodward = 1;

//sterowanie bocznikami:

SWMx = (woodward > 0.98) and !PWB and SPL and SLB;
PWMin = (woodward < 0.003) or (PWMin and (woodward < 0.01));
PB = (Math.Fabs(prad_silnika[3]) > parametry.Imin or (PB and Math.Fabs(prad_silnika[3]) > parametry.Iminb));
bool PZB1pom = PZB1 or SWMx;
PWB = (PB or nastawnik < 11 or !SPL) and !sd.c.PWBp and nastawnik != 0;
PZB1 = ((sd.c.bocznik_enable == 1) and !PWB and !PZB2 and PZB1pom and !SB3 and (sd.c.OSW == 3) and (sd.c.OST == 0)) and SPL and (!SB1 or (SB1 and PPB1 and !SB2) or (SB2 and PPB2));
PZB2 = (PWMin and !PWB and SPL) or sd.c.PZB2p;
PPB1 = (predkosc > 11.11) and nastawnik > 7 ;
PPB2 = (predkosc > 13.88);
SB3 = SB1 and SB2 and (SB3 or (PZB2 and PPB2)) and !PWB and SPL and PPB2;
SB2 = SB1 and (SB2 or (PZB2 and PPB1)) and (PPB2 or !PWB) and SPL and PPB1;
SB1 = (SB1 or PZB2) and (PPB1 or !PWB);

//wyliczenie mocy na wale silnika:

if (rpm > 550)
{
mocbrutto = 0.15 * rpm + (((parametry.a * rpm * rpm) + parametry.c) / 1.36);  //parabola mocy, działa w zakresie obrotów roboczych

}
if (rpm < 551)
{
mocbrutto = 0.029 * rpm;   //dla zakresu poniżej, przybliżenie liniowe. W zasadzie ma znaczenie tylko przy rozruchu
}

mocsilnika = (1 + gaz) * mocbrutto;

if (silnik == 0)
   obciazenie = 0;
if (silnik == 1)
   obciazenie = ((moc / 950) + mocgrzania + 70);
if (silnik > 1 and rpm_zadane > 0)
   obciazenie = 80;
mocrozrusznika = (float)(silnik == 2) * 0.04 * rpm;

if (silnik == 2 and rpm_zadane > 100)    //obliczenie rezystancji zastępczej prądnicy w trakcie rozruchu - używane do obliczenia prądu rozruchowego i rozładowania baterii
           Rroz = 0.1 + 0.0002 * rpm;
else
    Rroz = 99999;

if (rpm > 0 and silnik == 0)
    rpm = rpm - 1;
if (rpm < rpm_docelowe and silnik == 2)
    rpm = rpm + 2;
if (silnik == 2 and rpm_zadane > 0)
    rpm = rpm + 0.4;
if (silnik == 3 and rpm < rpm_docelowe)
    rpm = rpm + 10;


 bilans = (mocsilnika - obciazenie + mocrozrusznika);
 opory = 0.15 * rpm;
 arpm = bilans - opory;
 drpm = arpm * 1.5;
 if (silnik == 1)
  rpm = rpm + 0.05 * drpm;  //0.05 - dt, czyli krok czasowy tej pętli
if (rpm < 0)
   rpm = 0;
if (silnik == 1 and rpm < 600)
 rpm = 600;


  rpm_docelowe = rpm_zadane + 1.5 * (mocsilnika - obciazenie + mocrozrusznika);
  rpm_doc = Math.Fmin(rpm+(rpm_zadane/(rpm+0.01))*65,rpm_zadane);

if (mocbrutto > 0)
 dgaz = ((obciazenie + 0.15 * rpm_doc * (rpm_doc/(rpm+0.01)))/mocbrutto) - 1;

if (Math.Fabs(rpm_zadane - rpm) > 40)  //przy dużych odchyłkach regulator zmienia dawkę paliwa szybciej.
 gaz = 0.5 * gaz + 0.5 * dgaz;
else
 gaz = 0.9*gaz + 0.1 * dgaz;

  if (gaz < -1)
     gaz = -1;
  if (gaz > 1)
     gaz = 1;

/ciach/


// wyliczenie pradu



float prad_nowy;

for (silniki = 6; silniki > 0; silniki--)
                        {
// prądnica
                        if (SPL and nastawnik > 1 and baterie and WSG and WSW)
                        {
                        Uw = (190 * rpm) / 1500;
                        if (rpm > 0)
                            pIsat = 8 * 1500 / rpm;
                        RRW = parametry.RRW * (1 - woodward);
                        RWO = (parametry.R1 * (1 - SP3)) + (parametry.R2 * (1 - SP2)) + (parametry.R3 * (1 - SP1)) + (parametry.R4 * SP4) + (parametry.R5 * SST);
                        Rp = parametry.RO + RWO + RRW + 3.56;
                        pfi = 0.88;
                        I0 = Uw / Rp;
                        if ((I0 - aS *  (prad_razem * nawrotnik) + pIsat) != 0)
                        sem = (rpm * pfi * (I0 + Ir - aS * (prad_razem * nawrotnik)) / (I0 - aS *  (prad_razem * nawrotnik) + pIsat));
                         else
                        {
                         sem = 0;
                           PN[silniki] = true;
                           prad_silnika[silniki] = 0;
                           SPL = false;
                        }
                           napiecie = 0.9 * napiecie + 0.1 * sem;
// silniki trakcyjne

                        Isf = nawrotnik * Isat;
                        U = nawrotnik * napiecie;
                        R = 0.2;
                        b = R * Isf + Mn * fi * obroty - U;
                        delta = b * b + 4 * U * Isf * R;

                        if (delta >= 0)
                             prad_nowy = (-1 * b + nawrotnik * Math.Sqrt(delta)) / (2 * R);

                        }
                        else
                        {
                           sem = 0;
                           napiecie = sem;
                           prad_nowy =  0;
                        }

                    prad_silnika[silniki] = (0.9 * prad_silnika[silniki] + 0.1 * prad_nowy) * (float)(SL[silniki] and SPL);
                        if (Math.Fabs(prad_silnika[silniki]) > parametry.Imax or (awaria_silnika[silniki] == true and SE[silniki] == true)) {
                           PN[silniki] = true;
                           prad_silnika[silniki] = 0;
                           SPL = false;
                           }

                        moment[silniki] = mfi * Math.Fabs(prad_silnika[silniki]) * (1 - 1/((Math.Fabs(prad_silnika[silniki]) / mIsat)+1));
                        }

//wyliczanie sily
                           sila = Math.Fabs(2 * (moment[1] + moment[2] + moment[3] + moment[4] + moment[5] + moment[6])/(1000 * 1.1 * 0.29));
                            prad = prad_silnika[6];        //dla amperomierza w szafie

/ciach/

Sleep(0.05);
}
}

- tak to wygląda w praktyce, nagrywane parę dni temu. Widać tu np. chwilowe spadki obrotów w momencie załączania boczników - co oznacza skokowy wzrost obciążenia, bo jest podparty przekaźnik PZB2, więc nie ma odwzbudzenia prądnicy przed załączeniem bocznika. Gdybym jechał bez podparcia, z pełną automatyką bocznikowania, to z kolei w momentach załączania boczników miałbym spadek napięcia do wartości minimalnej i chwilowy podskok obrotów.
« Ostatnia zmiana: 23 Września 2015, 12:18:37 wysłana przez adamst »