mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-15 18:44:12 +01:00
fix: EN57 brakes hauled with the brake hose alone, Knorr EP brake without control power
eu07/maszyna#87: the EP2 (and EP1) valve charged its auxiliary reservoir only from the main reservoir pipe. A dead EN57 hauled by a locomotive coupled with the hook and the brake hose alone ("3") never charged it, its control reservoir stopped at about 2.5 bar and the unit didn't brake. The valve now refills the auxiliary reservoir from the brake pipe through the slide valve's check valve, as every ESt does (TESt::FillBrakeRes, shared with TESt::GetPF, which stays bit for bit the same). With the main reservoir pipe charged the auxiliary reservoir stays above the brake pipe and nothing changes; the reservoir now also takes air from the brake pipe while it is below it, e.g. at start-up before the compressor has charged the main reservoir pipe. eu07/maszyna#134: the EP brake of the Knorr St113 handle (EN57-001) worked with the reverser in neutral, the battery off or the EP fuse switched off (Ctrl+Z). It now needs the control powered, as the Oerlikon handle's does (EPBrakeControlPowered: battery, reverser out of neutral, EP fuse), and an EP brake switched on drops out (holding the cylinder pressure) when the control loses power. The positions of the EP release and brake were already moved by 810b7ad07; a test pins them. No change to game data needed.
This commit is contained in:
@@ -2413,6 +2413,8 @@ class TMoverParameters
|
||||
bool BrakeReleaser(int state);
|
||||
bool UniversalBrakeButton(int button, int state); /*uniwersalny przycisk hamulca*/
|
||||
bool SwitchEPBrake(int state);
|
||||
// whether the EP brake control of the cab has power: battery, the reverser out of neutral and the EP fuse on
|
||||
bool EPBrakeControlPowered() const;
|
||||
bool AntiSlippingButton(void); /*! reczny wlacznik urzadzen antyposlizgowych*/
|
||||
|
||||
/*funkcje dla ukladow pneumatycznych*/
|
||||
|
||||
@@ -4161,7 +4161,8 @@ bool TMoverParameters::SwitchEPBrake(int state)
|
||||
OK = false;
|
||||
if (BrakeHandle == TBrakeHandle::St113 && CabOccupied != 0)
|
||||
{
|
||||
if (state > 0)
|
||||
// the handle works the EP contactors pneumatically, their supply is cut as the Oerlikon handle's is
|
||||
if (state > 0 && EPBrakeControlPowered())
|
||||
EpForce = Handle->GetEP(); // TODO: przetlumaczyc
|
||||
else
|
||||
EpForce = 0;
|
||||
@@ -4173,6 +4174,11 @@ bool TMoverParameters::SwitchEPBrake(int state)
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool TMoverParameters::EPBrakeControlPowered() const
|
||||
{
|
||||
return Power24vIsAvailable && DirActive != 0 && EpFuse;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160711
|
||||
// zwiększenie ciśnienia hamowania
|
||||
@@ -4706,7 +4712,7 @@ void TMoverParameters::UpdatePipePressure(double dt)
|
||||
|
||||
if ((BrakeHandle == TBrakeHandle::FVel6 || BrakeHandle == TBrakeHandle::FVE408) && CabOccupied != 0)
|
||||
{
|
||||
if (Power24vIsAvailable && DirActive != 0 && EpFuse) // tu powinien byc jeszcze bezpiecznik EP i baterie -
|
||||
if (EPBrakeControlPowered()) // tu powinien byc jeszcze bezpiecznik EP i baterie -
|
||||
// temp = (Handle as TFVel6).GetCP
|
||||
EpForce = Handle->GetEP();
|
||||
else
|
||||
@@ -4725,6 +4731,11 @@ void TMoverParameters::UpdatePipePressure(double dt)
|
||||
// Ra 2014-11: na tym się wysypuje, ale nie wiem, w jakich warunkach
|
||||
SendCtrlToNext("Brake", EpForce, CabActive);
|
||||
}
|
||||
else if (BrakeHandle == TBrakeHandle::St113 && CabOccupied != 0 && std::abs(EpForce) > 0.001 && !EPBrakeControlPowered())
|
||||
{
|
||||
// the EP brake switched on with the button drops out with the control's supply
|
||||
SwitchEPBrake(0);
|
||||
}
|
||||
|
||||
Pipe->Act();
|
||||
PipePress = Pipe->P();
|
||||
|
||||
@@ -968,6 +968,28 @@ double TESt::BVs(double const BCP) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refills the auxiliary reservoir (ZP) from the valve pre-chamber through the
|
||||
/// check valve of the slide valve, opened as far as <see cref="BVs"/> says for the
|
||||
/// given cylinder (or impulse-chamber) pressure, while the pre-chamber is more
|
||||
/// than 0.05 bar above the reservoir. The flows wait for the caller's Act().
|
||||
/// </summary>
|
||||
/// <param name="BCP">Brake cylinder (or impulse-chamber) pressure.</param>
|
||||
/// <param name="dt">Time step [s].</param>
|
||||
/// <returns>Volume taken into the auxiliary reservoir, 0.96 of it drawn from the brake pipe.</returns>
|
||||
double TESt::FillBrakeRes(double const BCP, double const dt)
|
||||
{
|
||||
double const BVP{BrakeRes->P()};
|
||||
double const VVP{ValveRes->P()};
|
||||
double const temp{BVs(BCP)};
|
||||
double dv{0.0};
|
||||
if (VVP - 0.05 > BVP)
|
||||
dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt;
|
||||
BrakeRes->Flow(dv);
|
||||
ValveRes->Flow(-0.04 * dv);
|
||||
return dv;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One-step Oerlikon ESt distributor advance: runs CheckState/CheckReleaser,
|
||||
/// integrates the ZS <-> PG, ZP <-> cylinder, ZP <-> pre-chamber and
|
||||
@@ -1021,15 +1043,7 @@ double TESt::GetPF(double const PP, double const dt, double const Vel)
|
||||
BrakeCyl->Flow(-dv);
|
||||
|
||||
// przeplyw ZP <-> rozdzielacz
|
||||
temp = BVs(BCP);
|
||||
// if(BrakeStatus and b_hld)=b_off then
|
||||
if (VVP - 0.05 > BVP)
|
||||
dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt;
|
||||
else
|
||||
dv = 0;
|
||||
BrakeRes->Flow(dv);
|
||||
dV1 = dV1 + dv * 0.96;
|
||||
ValveRes->Flow(-0.04 * dv);
|
||||
dV1 = dV1 + FillBrakeRes(BCP, dt) * 0.96;
|
||||
// przeplyw PG <-> rozdzielacz
|
||||
dv = PF(PP, VVP, 0.01) * dt;
|
||||
ValveRes->Flow(-dv);
|
||||
@@ -1191,6 +1205,10 @@ double TEStEP2::GetPF(double const PP, double const dt, double const Vel)
|
||||
ValveRes->Flow(-0.04 * dv);
|
||||
dV1 = dV1 - 0.96 * dv;
|
||||
|
||||
// przeplyw ZP <-> rozdzielacz: as in every ESt, the auxiliary reservoir also charges from the brake pipe,
|
||||
// not from the main reservoir pipe alone, so a unit hauled with the brake hose alone charges and brakes
|
||||
dV1 = dV1 + FillBrakeRes(BCP, dt) * 0.96;
|
||||
|
||||
// hamulec EP
|
||||
EPCalc(dt);
|
||||
|
||||
|
||||
@@ -620,6 +620,15 @@ class TESt : public TBrake
|
||||
/// <param name="BCP">Brake cylinder pressure.</param>
|
||||
/// <returns>Dimensionless opening coefficient.</returns>
|
||||
double BVs(double BCP) const; // napelniacz pomocniczego
|
||||
/// <summary>
|
||||
/// Refills the auxiliary reservoir (ZP) from the valve pre-chamber through the
|
||||
/// check valve of the slide valve, opened as far as <see cref="BVs"/> says, while
|
||||
/// the pre-chamber is above the reservoir. The flows wait for the caller's Act().
|
||||
/// </summary>
|
||||
/// <param name="BCP">Brake cylinder (or impulse-chamber) pressure for <see cref="BVs"/>.</param>
|
||||
/// <param name="dt">Time step [s].</param>
|
||||
/// <returns>Volume taken into the auxiliary reservoir, 0.96 of it drawn from the brake pipe.</returns>
|
||||
double FillBrakeRes(double BCP, double dt); // napelnianie pomocniczego z rozdzielacza
|
||||
/// <summary>Vents the valve, brake and control reservoirs to zero.</summary>
|
||||
void ForceEmptiness() override; // wymuszenie bycia pustym
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "golden.h"
|
||||
#include "real_vehicles.h"
|
||||
#include "drive.h"
|
||||
#include "consist.h"
|
||||
|
||||
#include "McZapkie/hamulce.h"
|
||||
|
||||
@@ -152,3 +153,105 @@ TEST_CASE("brake handles: the overload and the high pressure buttons of the MHZ
|
||||
trace.check();
|
||||
}
|
||||
}
|
||||
|
||||
// eu07/maszyna#134: the Knorr St113 of the EN57-001 releases the EP brake in the running position (bh_RP, Num 6)
|
||||
// and applies it one position on (Num 8), short of the lap position (Num 5); the positions are those the keys
|
||||
// select, and the EP brake works only with the control of the cab powered: the battery, the reverser out of
|
||||
// neutral and the EP fuse on (Ctrl+Z), as the Oerlikon handle's
|
||||
namespace {
|
||||
|
||||
// the front car of the EN57-001 driven from its cab, with the motor car behind it, which has the battery of the two;
|
||||
// air in the reservoirs, the battery on
|
||||
void ready_knorr_ep(test::consist &Unit) {
|
||||
Unit.add(definition::fiz("en57_v1/6bai"), 1);
|
||||
Unit.add(definition::fiz("en57_v1/5bgb"));
|
||||
auto &cab{Unit[0]};
|
||||
REQUIRE(cab->BrakeHandle == TBrakeHandle::St113);
|
||||
cab->BatterySwitch(true);
|
||||
cab->CabActivisation();
|
||||
cab.hold_brake_pipe(5.0);
|
||||
cab->BrakeLevelSet(cab->Handle->GetPos(bh_RP));
|
||||
Unit.run(60.0);
|
||||
}
|
||||
|
||||
// the EP brake button pressed in the given handle position, held for Seconds; the cylinder pressure of the cab car
|
||||
double ep_brake(test::consist &Unit, double Position, double Seconds) {
|
||||
auto &cab{Unit[0]};
|
||||
cab->BrakeLevelSet(Position);
|
||||
Unit.run(0.1);
|
||||
cab->SwitchEPBrake(1);
|
||||
Unit.run(Seconds);
|
||||
return cab->BrakePress;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("brake handles: the positions of the Knorr St113 EP brake") {
|
||||
test::consist unit;
|
||||
ready_knorr_ep(unit);
|
||||
auto &cab{unit[0]};
|
||||
auto &handle{*cab->Handle};
|
||||
auto const ep_at{[&unit, &cab, &handle](double Position) {
|
||||
cab->BrakeLevelSet(Position);
|
||||
unit.run(0.1);
|
||||
return handle.GetEP();
|
||||
}};
|
||||
// the keys: Num 6 running, Num 8 the first position on, Num 5 the middle of the handle
|
||||
CHECK(handle.GetPos(bh_RP) == doctest::Approx(0.0));
|
||||
CHECK(ep_at(0.0) == doctest::Approx(-1.0)); // EP release
|
||||
CHECK(ep_at(1.0) == doctest::Approx(1.0)); // EP brake
|
||||
CHECK(ep_at(cab->BrakeCtrlPosNo / 2) == doctest::Approx(0.0)); // lap, Num 5
|
||||
CHECK(ep_at(handle.GetPos(bh_FB)) == doctest::Approx(0.0));
|
||||
CHECK(ep_at(handle.GetPos(bh_EPR)) == doctest::Approx(-1.0));
|
||||
CHECK(ep_at(handle.GetPos(bh_EPB)) == doctest::Approx(1.0));
|
||||
}
|
||||
|
||||
TEST_CASE("brake handles: the Knorr St113 EP brake needs the control of the cab powered") {
|
||||
for (std::string const cut : {"reverser in neutral", "EP fuse off", "battery off"}) {
|
||||
CAPTURE(cut);
|
||||
test::consist unit;
|
||||
ready_knorr_ep(unit);
|
||||
auto &cab{unit[0]};
|
||||
cab->DirectionForward();
|
||||
unit.run(1.0);
|
||||
REQUIRE(cab->EPBrakeControlPowered());
|
||||
if (cut == "reverser in neutral") {
|
||||
cab->DirectionBackward();
|
||||
}
|
||||
else if (cut == "EP fuse off") {
|
||||
cab->EpFuseSwitch(false);
|
||||
}
|
||||
else {
|
||||
cab->BatterySwitch(false);
|
||||
}
|
||||
unit.run(1.0);
|
||||
REQUIRE_FALSE(cab->EPBrakeControlPowered());
|
||||
// the button in the EP brake position does nothing
|
||||
CHECK(ep_brake(unit, 1.0, 5.0) < 0.1);
|
||||
CHECK(cab->EpForce == doctest::Approx(0.0));
|
||||
cab->SwitchEPBrake(0);
|
||||
}
|
||||
|
||||
test::consist unit;
|
||||
ready_knorr_ep(unit);
|
||||
auto &cab{unit[0]};
|
||||
cab->DirectionForward();
|
||||
unit.run(1.0);
|
||||
// powered, the EP brake applies
|
||||
auto const applied{ep_brake(unit, 1.0, 2.0)};
|
||||
CHECK(applied > 0.5);
|
||||
// the reverser put to neutral with the button still held: the EP brake drops out and holds what it applied
|
||||
cab->DirectionBackward();
|
||||
unit.run(0.1);
|
||||
CHECK(cab->EpForce == doctest::Approx(0.0));
|
||||
auto const held{cab->BrakePress};
|
||||
unit.run(5.0);
|
||||
CHECK(cab->BrakePress < held + 0.05);
|
||||
CHECK(cab->BrakePress > 0.2);
|
||||
// and doesn't release either, until the control is powered again
|
||||
CHECK(ep_brake(unit, 0.0, 5.0) > 0.2);
|
||||
cab->SwitchEPBrake(0);
|
||||
cab->DirectionForward();
|
||||
unit.run(0.1);
|
||||
CHECK(ep_brake(unit, 0.0, 10.0) < 0.1);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "doctest.h"
|
||||
#include "vehicle.h"
|
||||
#include "consist.h"
|
||||
|
||||
using test::definition;
|
||||
using test::vehicle;
|
||||
@@ -91,3 +92,48 @@ TEST_CASE("brakes: service braking stops a heavier wagon too") {
|
||||
wagon.run(40.0 /* s */, test::track{0.15 /* friction */, 0.0 /* gradient */});
|
||||
CHECK(std::abs(wagon.speed()) < 0.1);
|
||||
}
|
||||
|
||||
// eu07/maszyna#87: the ESt4d of the EN57's EP2 valve charged its auxiliary reservoir from the main reservoir pipe
|
||||
// alone, so a dead unit hauled by a locomotive coupled with the hook and the brake hose ("3") never charged it,
|
||||
// its control reservoir stopped half way, and it didn't brake. Like every ESt, it charges from the brake pipe too
|
||||
TEST_CASE("brakes: a dead EN57 hauled with the brake hose alone charges from the brake pipe and brakes") {
|
||||
test::consist train;
|
||||
auto &locomotive{train.add(definition::fiz("sm42_v1/6d1"))};
|
||||
train.add(definition::fiz("en57_v1/5bgb"), 0, coupling::coupler | coupling::brakehose);
|
||||
train.add(definition::fiz("en57_v1/6ba_840"));
|
||||
train.add(definition::fiz("en57_v1/5bgaiii_led_spot"));
|
||||
// a unit standing dead: no air anywhere, nothing in its main reservoir pipe
|
||||
for (std::size_t i = 1; i < train.size(); ++i) {
|
||||
auto &car{train[i].mover()};
|
||||
REQUIRE(car.BrakeValve == TBrakeValve::EP2);
|
||||
car.Hamulec->ForceEmptiness();
|
||||
car.Pipe->CreatePress(0.0);
|
||||
car.Pipe->Act();
|
||||
car.Pipe2->CreatePress(0.0);
|
||||
car.Pipe2->Act();
|
||||
car.CompressedVolume = 0.0;
|
||||
}
|
||||
locomotive.hold_brake_pipe(5.0);
|
||||
train.run(900.0);
|
||||
for (std::size_t i = 1; i < train.size(); ++i) {
|
||||
CAPTURE(i);
|
||||
auto &car{train[i].mover()};
|
||||
REQUIRE(car.ScndPipePress < 0.1); // no main reservoir pipe
|
||||
CHECK(car.Hamulec->GetBRP() > 4.8);
|
||||
CHECK(car.Hamulec->GetCRP() > 4.8);
|
||||
CHECK(car.BrakePress < 0.1);
|
||||
}
|
||||
// a full service application brakes the unit, and it releases again
|
||||
locomotive.hold_brake_pipe(3.5);
|
||||
train.run(20.0);
|
||||
for (std::size_t i = 1; i < train.size(); ++i) {
|
||||
CAPTURE(i);
|
||||
CHECK(train[i]->BrakePress > 2.0);
|
||||
}
|
||||
locomotive.hold_brake_pipe(5.0);
|
||||
train.run(60.0);
|
||||
for (std::size_t i = 1; i < train.size(); ++i) {
|
||||
CAPTURE(i);
|
||||
CHECK(train[i]->BrakePress < 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user