diff --git a/Driver.cpp b/Driver.cpp index 46369124..dec7cc3b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3131,6 +3131,14 @@ bool TController::IncSpeed() { // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga zerowania kierunku) // mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0); } + if (mvControlling->EIMCtrlType > 0) { + if (true == Ready) + { + DizelPercentage = (mvControlling->Vel > mvControlling->dizel_minVelfullengage ? 100 : 1); + } + break; + } + else if( true == Ready ) { if( ( mvControlling->Vel > mvControlling->dizel_minVelfullengage ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn > 0 ) ) { @@ -3193,6 +3201,12 @@ bool TController::DecSpeed(bool force) mvControlling->DecMainCtrl(3 + 3 * floor(0.5 + fabs(AccDesired))); break; case TEngineType::DieselEngine: + if (mvControlling->EIMCtrlType > 0) + { + DizelPercentage = 0; + break; + } + if ((mvControlling->Vel > mvControlling->dizel_minVelfullengage)) { if (mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0) @@ -3516,6 +3530,37 @@ void TController::SetTimeControllers() } } //5. Check Main Controller in Dizels + //5.1. Digital controller in DMUs with hydro + if ((mvControlling->EngineType == TEngineType::DieselEngine) && (mvControlling->EIMCtrlType == 3)) + { + DizelPercentage_Speed = DizelPercentage; + double Factor = 10 * (mvControlling->Vmax) / (mvControlling->Vmax + 3*mvControlling->Vel); + double DesiredPercentage = (VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0); + DesiredPercentage = clamp(DesiredPercentage, 0.0, 1.0); + if (VelDesired < 0.5 * mvControlling->Vmax && VelDesired - mvControlling->Vel < 10) + DesiredPercentage = std::min(DesiredPercentage, 0.75); + if (VelDesired < mvControlling->hydro_TC_LockupSpeed) DizelPercentage = std::min(DizelPercentage,1); + int DizelActualPercentage = 100.4 * mvControlling->eimic_real; + int PosInc = mvControlling->MainCtrlPosNo; + int PosDec = 0; + for(int i=PosInc;i>=0;i--) + if ((mvControlling->UniCtrlList[i].SetCtrlVal <= 0) && (mvControlling->UniCtrlList[i].SpeedDown > 0.01)) + { + PosDec = i; + break; + } + DizelPercentage_Speed = round(double(DizelPercentage*DesiredPercentage)); + if (VelDesired < mvControlling->hydro_TC_LockupSpeed) DizelPercentage = std::min(DizelPercentage_Speed, 1); + if (abs(DizelPercentage_Speed - DizelActualPercentage)>(DizelPercentage>1?3:0)) + { + if (((DizelPercentage_Speed == 0 && DizelActualPercentage > 10) || (DizelActualPercentage - DizelPercentage_Speed > 50)) && PosDec > 0) PosDec -= 1; //pozycję wczesniej powinno byc szybkie zejscie, jeśli trzeba + int DesiredPos = (DizelPercentage_Speed > DizelActualPercentage ? PosInc : PosDec); + while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1); + while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1); + } + } + else + //5.2. Analog direct controller if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->Vmax>30)) { int MaxPos = mvControlling->MainCtrlPosNo; @@ -3575,6 +3620,24 @@ void TController::CheckTimeControllers() mvOccupied->ScndCtrlPos = 2; } } + + //5. Check Main Controller in Dizels + //5.1. Digital controller in DMUs with hydro + if ((mvControlling->EngineType == TEngineType::DieselEngine) && (mvControlling->EIMCtrlType == 3)) + { + int DizelActualPercentage = 100.4 * mvControlling->eimic_real; + int NeutralPos = mvControlling->MainCtrlPosNo - 1; //przedostatnia powinna wstrzymywać - hipoteza robocza + for (int i = mvControlling->MainCtrlPosNo; i >= 0; i--) + if ((mvControlling->UniCtrlList[i].SetCtrlVal <= 0) && (mvControlling->UniCtrlList[i].SpeedDown < 0.01)) //niby zero, ale nie zmniejsza procentów + { + NeutralPos = i; + break; + } + if ((DizelActualPercentage >= DizelPercentage_Speed) && (mvControlling->MainCtrlPos > NeutralPos)) + while (mvControlling->MainCtrlPos > NeutralPos) mvControlling->DecMainCtrl(1); + if ((DizelActualPercentage <= DizelPercentage_Speed) && (mvControlling->MainCtrlPos < NeutralPos)) + while (mvControlling->MainCtrlPos < NeutralPos) mvControlling->IncMainCtrl(1); + } }; // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT diff --git a/Driver.h b/Driver.h index 96067b79..85177dbe 100644 --- a/Driver.h +++ b/Driver.h @@ -256,6 +256,8 @@ public: int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller + int DizelPercentage = 0; // oczekiwane procenty jazdy/hamowania szynobusem + int DizelPercentage_Speed = 0; // oczekiwane procenty jazdy/hamowania szynobusem w związku z osiąganiem VelDesired private: bool Psyche = false; int HelperState = 0; //stan pomocnika maszynisty diff --git a/DynObj.cpp b/DynObj.cpp index 6f2f3eaf..f60f1fdb 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2758,7 +2758,14 @@ bool TDynamicObject::Update(double dt, double dt1) if (Mechanik) { // Ra 2F3F: do Driver.cpp to przenieść? MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG - if( ( Mechanik->Primary() ) + if ((Mechanik->Primary()) + && (MoverParameters->EngineType == TEngineType::DieselEngine) + && (MoverParameters->EIMCtrlType > 0)) { + MoverParameters->CheckEIMIC(dt1); + MoverParameters->eimic_real = MoverParameters->eimic; + MoverParameters->SendCtrlToNext("EIMIC", MoverParameters->eimic, MoverParameters->CabNo); + } + if( ( Mechanik->Primary() ) && ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) { // jesli glowny i z asynchronami, to niech steruje hamulcem i napedem lacznie dla calego pociagu/ezt auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index fb83ef35..624bf0db 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -4567,7 +4567,7 @@ double TMoverParameters::TractionForce( double dt ) { EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 ); if( MainCtrlPowerPos() > 1 ) { // dodatkowe opory z powodu sprezarki} - dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); +// dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); //yB: skąd to w ogóle się bierze?! } break; } @@ -6114,9 +6114,20 @@ void TMoverParameters::CheckEIMIC(double dt) } break; case 3: - eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedDown); //odejmuj do X - eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X - eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); + if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay)) + { + eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, (MainCtrlActualPos == MainCtrlPos ? dt * UniCtrlList[MainCtrlPos].SpeedDown : sign(UniCtrlList[MainCtrlPos].SpeedDown) * 0.01)); //odejmuj do X + eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, (MainCtrlActualPos == MainCtrlPos ? dt * UniCtrlList[MainCtrlPos].SpeedUp : sign(UniCtrlList[MainCtrlPos].SpeedUp) * 0.01)); //dodawaj do X + eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); + } + if (MainCtrlActualPos == MainCtrlPos) + LastRelayTime += dt; + else + { + LastRelayTime = 0; + MainCtrlActualPos = MainCtrlPos; + } + //BrakeLevelSet(UniCtrlList[MainCtrlPos].mode); } auto const eimicpowerenabled { ( ( true == Mains ) || ( Power == 0.0 ) ) @@ -6239,6 +6250,17 @@ bool TMoverParameters::dizel_AutoGearCheck(void) if (Mains) { + if (EIMCtrlType > 0) //sterowanie komputerowe + { + if (dizel_automaticgearstatus == 0) + if ((hydro_TC && hydro_TC_Fill > 0.01 )||( eimic_real > 0.0 )) + dizel_EngageSwitch(1.0); + else + dizel_EngageSwitch(0.0); + else + dizel_EngageSwitch(0.0); + } + else if (dizel_automaticgearstatus == 0) // ustaw cisnienie w silowniku sprzegla} switch (RList[MainCtrlPos].Mn) { @@ -6385,6 +6407,7 @@ bool TMoverParameters::dizel_Update(double dt) { double TMoverParameters::dizel_fillcheck(int mcp) { auto realfill { 0.0 }; + auto reg_factor { 0.98 }; if( ( true == Mains ) && ( MainCtrlPosNo > 0 ) @@ -6399,11 +6422,20 @@ double TMoverParameters::dizel_fillcheck(int mcp) } else { // napelnienie zalezne od MainCtrlPos - realfill = RList[ mcp ].R; + if (EIMCtrlType > 0) + { + realfill = std::max(0.0, eimic_real); + reg_factor = 1.0; + } + else + realfill = RList[mcp].R; } if (dizel_nmax_cutoff > 0) { auto nreg { 0.0 }; + if (EIMCtrlType > 0) + nreg = (eimic_real > 0 ? dizel_nmax : dizel_nmin); + else switch (RList[MainCtrlPos].Mn) { case 0: @@ -6442,7 +6474,7 @@ double TMoverParameters::dizel_fillcheck(int mcp) realfill = 0; if (enrot < nreg) //pod predkoscia regulatora dawka zadana realfill = realfill; - if ((enrot < dizel_nmin * 0.98)&&(RList[mcp].R>0.001)) //jesli ponizej biegu jalowego i niezerowa dawka, to dawaj pelna + if ((enrot < dizel_nmin * reg_factor)&&(RList[mcp].R>0.001)) //jesli ponizej biegu jalowego i niezerowa dawka, to dawaj pelna realfill = 1; } } @@ -6485,10 +6517,11 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) if (hydro_TC) //jesli przetwornik momentu { //napelnianie przetwornika - if ((MainCtrlPowerPos() > 0) && (Mains) && (enrot>dizel_nmin*0.9)) + bool IsPower = (EIMCtrlType > 0 ? eimic_real > 0 : MainCtrlPowerPos() > 0); + if ((IsPower) && (Mains) && (enrot>dizel_nmin*0.9)) hydro_TC_Fill += hydro_TC_FillRateInc * dt; //oproznianie przetwornika - if (((IsMainCtrlNoPowerPos()) && (Vel<3)) + if (((!IsPower) && (Vel<3)) || (!Mains) || (enrot hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (MainCtrlPowerPos() > 0)) + if ((Vel > hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (IsPower)) hydro_TC_LockupRate += hydro_TC_FillRateInc*dt; //luzowanie sprzegla blokujacego - if ((Vel < (MainCtrlPowerPos() > 0 ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) + if ((Vel < (IsPower ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) hydro_TC_LockupRate -= hydro_TC_FillRateDec*dt; //obcinanie zakresu hydro_TC_LockupRate = clamp(hydro_TC_LockupRate, 0.0, 1.0); @@ -7860,7 +7893,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) startRLIST = false; continue; } - if (issection("END-RL", inputline)) { + if (issection("END-UCL", inputline)) { startBPT = false; startUCLIST = false; continue; @@ -8073,7 +8106,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) startBPT = false; fizlines.emplace("UCList", inputline); startUCLIST = true; LISTLINE = 0; - LoadFIZ_RList(inputline); + LoadFIZ_UCList(inputline); continue; } @@ -8127,7 +8160,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) continue; } if (true == startUCLIST) { - readRList(inputline); + readUCList(inputline); continue; } if( true == startDLIST ) { diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 6a482e81..b7bbc34a 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -882,7 +882,9 @@ debug_panel::update_section_ai( std::vector &Output ) { + "\n brake threshold: " + to_string( mechanik.fAccThreshold, 2 ) + ", delays: " + to_string( mechanik.fBrake_a0[ 0 ], 2 ) + "+" + to_string( mechanik.fBrake_a1[ 0 ], 2 ) - + "\n virtual brake position: " + to_string(mechanik.BrakeCtrlPosition, 2); + + "\n virtual brake position: " + to_string(mechanik.BrakeCtrlPosition, 2) + + "\n desired diesel percentage: " + to_string(mechanik.DizelPercentage, 0) + + "/" + to_string(mechanik.DizelPercentage_Speed, 0); Output.emplace_back( textline, Global.UITextColor );