Gate closed loop idle on road speed (#2901)
* implement * test * b * config
This commit is contained in:
parent
90e43040c7
commit
007a390f2b
|
@ -39,6 +39,7 @@
|
|||
#include "engine.h"
|
||||
#include "periodic_task.h"
|
||||
#include "allsensors.h"
|
||||
#include "vehicle_speed.h"
|
||||
#include "sensor.h"
|
||||
#include "dc_motors.h"
|
||||
|
||||
|
@ -207,7 +208,7 @@ int IdleController::getTargetRpm(float clt) const {
|
|||
return target;
|
||||
}
|
||||
|
||||
IIdleController::Phase IdleController::determinePhase(int rpm, int targetRpm, SensorResult tps) const {
|
||||
IIdleController::Phase IdleController::determinePhase(int rpm, int targetRpm, SensorResult tps, float vss) const {
|
||||
if (!engine->rpmCalculator.isRunning()) {
|
||||
return Phase::Cranking;
|
||||
}
|
||||
|
@ -228,6 +229,12 @@ IIdleController::Phase IdleController::determinePhase(int rpm, int targetRpm, Se
|
|||
return Phase::Coasting;
|
||||
}
|
||||
|
||||
// If the vehicle is moving too quickly, disable CL idle
|
||||
auto maxVss = CONFIG(maxIdleVss);
|
||||
if (maxVss != 0 && vss > maxVss) {
|
||||
return Phase::Running;
|
||||
}
|
||||
|
||||
// No other conditions met, we are idling!
|
||||
return Phase::Idling;
|
||||
}
|
||||
|
@ -467,7 +474,7 @@ float IdleController::getClosedLoop(IIdleController::Phase phase, float tpsPos,
|
|||
m_lastTargetRpm = targetRpm;
|
||||
|
||||
// Determine what operation phase we're in - idling or not
|
||||
auto phase = determinePhase(rpm, targetRpm, tps);
|
||||
auto phase = determinePhase(rpm, targetRpm, tps, getVehicleSpeed());
|
||||
m_lastPhase = phase;
|
||||
|
||||
engine->engineState.isAutomaticIdle = tps.Valid && engineConfiguration->idleMode == IM_AUTO;
|
||||
|
|
|
@ -21,7 +21,7 @@ struct IIdleController {
|
|||
Running, // On throttle
|
||||
};
|
||||
|
||||
virtual Phase determinePhase(int rpm, int targetRpm, SensorResult tps) const = 0;
|
||||
virtual Phase determinePhase(int rpm, int targetRpm, SensorResult tps, float vss) const = 0;
|
||||
virtual int getTargetRpm(float clt) const = 0;
|
||||
virtual float getCrankingOpenLoop(float clt) const = 0;
|
||||
virtual float getRunningOpenLoop(float clt, SensorResult tps) const = 0;
|
||||
|
@ -42,7 +42,7 @@ public:
|
|||
int getTargetRpm(float clt) const override;
|
||||
|
||||
// PHASE DETERMINATION: what is the driver trying to do right now?
|
||||
Phase determinePhase(int rpm, int targetRpm, SensorResult tps) const override;
|
||||
Phase determinePhase(int rpm, int targetRpm, SensorResult tps, float vss) const override;
|
||||
|
||||
// OPEN LOOP CORRECTIONS
|
||||
float getCrankingOpenLoop(float clt) const override;
|
||||
|
|
|
@ -628,7 +628,7 @@ custom ignition_mode_e 4 bits, U32, @OFFSET@, [0:1], "Single Coil", "Individual
|
|||
ignition_mode_e ignitionMode;+Single coil = distributor\nIndividual coils = one coil per cylinder (COP, coil-near-plug), requires sequential mode\nWasted spark = Fires pairs of cylinders together, either one coil per pair of cylinders or one coil per cylinder\nTwo distributors = A pair of distributors, found on some BMW, Toyota and other engines\nset ignition_mode X
|
||||
|
||||
int8_t gapTrackingLengthOverride;;"count", 1, 0, 0, @@GAP_TRACKING_LENGTH@@, 0
|
||||
int8_t[1] unusedOldIgnitionOffset;;"unused", 1, 0, 0, 1, 0
|
||||
uint8_t maxIdleVss;+Above this speed, disable closed loop idle control. Set to 0 to disable (allow closed loop idle at any speed).;"kph", 1, 0, 0, 100, 0
|
||||
uint16_t minOilPressureAfterStart;+Expected oil pressure after starting the engine. If oil pressure does not reach this level within 5 seconds of engine start, fuel will be cut. Set to 0 to disable and always allow starting.;"kPa", 1, 0, 0, 1000, 0
|
||||
|
||||
custom timing_mode_e 4 bits, U32, @OFFSET@, [0:0], "dynamic", "fixed"
|
||||
|
|
|
@ -2650,6 +2650,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
|
|||
field = "TPS threshold", idlePidDeactivationTpsThreshold
|
||||
field = "RPM upper limit", idlePidRpmUpperLimit
|
||||
field = "RPM deadzone", idlePidRpmDeadZone
|
||||
field = "Max vehicle speed", maxIdleVss
|
||||
|
||||
dialog = idleExtra, "Extra Idle Features"
|
||||
field = "Use idle ignition table", useSeparateAdvanceForIdle
|
||||
|
|
|
@ -123,33 +123,38 @@ TEST(idle_v2, testDeterminePhase) {
|
|||
CONFIG(idlePidDeactivationTpsThreshold) = 5;
|
||||
// RPM window is 100 RPM above target
|
||||
CONFIG(idlePidRpmUpperLimit) = 100;
|
||||
// Max VSS for idle is 10kph
|
||||
CONFIG(maxIdleVss) = 10;
|
||||
|
||||
// First test stopped engine
|
||||
engine->rpmCalculator.setRpmValue(0);
|
||||
EXPECT_EQ(ICP::Cranking, dut.determinePhase(0, 1000, unexpected));
|
||||
EXPECT_EQ(ICP::Cranking, dut.determinePhase(0, 1000, unexpected, 0));
|
||||
|
||||
// Now engine is running!
|
||||
// Controller doesn't need this other than for isCranking()
|
||||
engine->rpmCalculator.setRpmValue(1000);
|
||||
|
||||
// Test invalid TPS, but inside the idle window
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1000, 1000, unexpected));
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1000, 1000, unexpected, 0));
|
||||
|
||||
// Valid TPS should now be inside the zone
|
||||
EXPECT_EQ(ICP::Idling, dut.determinePhase(1000, 1000, 0));
|
||||
EXPECT_EQ(ICP::Idling, dut.determinePhase(1000, 1000, 0, 0));
|
||||
|
||||
// Inside the zone, but vehicle speed too fast
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1000, 1000, 0, 25));
|
||||
|
||||
// Above TPS threshold should be outside the zone
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1000, 1000, 10));
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1000, 1000, 10, 0));
|
||||
|
||||
// Above target, below (target + upperLimit) should be in idle zone
|
||||
EXPECT_EQ(ICP::Idling, dut.determinePhase(1099, 1000, 0));
|
||||
EXPECT_EQ(ICP::Idling, dut.determinePhase(1099, 1000, 0, 0));
|
||||
|
||||
// above upper limit and on throttle should be out of idle zone
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1101, 1000, 10));
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1101, 1000, 10, 0));
|
||||
|
||||
// Below TPS but above RPM should be outside the zone
|
||||
EXPECT_EQ(ICP::Coasting, dut.determinePhase(1101, 1000, 0));
|
||||
EXPECT_EQ(ICP::Coasting, dut.determinePhase(5000, 1000, 0));
|
||||
EXPECT_EQ(ICP::Coasting, dut.determinePhase(1101, 1000, 0, 0));
|
||||
EXPECT_EQ(ICP::Coasting, dut.determinePhase(5000, 1000, 0, 0));
|
||||
}
|
||||
|
||||
TEST(idle_v2, crankingOpenLoop) {
|
||||
|
@ -383,7 +388,7 @@ TEST(idle_v2, closedLoopDeadzone) {
|
|||
|
||||
struct IntegrationIdleMock : public IdleController {
|
||||
MOCK_METHOD(int, getTargetRpm, (float clt), (const, override));
|
||||
MOCK_METHOD(ICP, determinePhase, (int rpm, int targetRpm, SensorResult tps), (const, override));
|
||||
MOCK_METHOD(ICP, determinePhase, (int rpm, int targetRpm, SensorResult tps, float vss), (const, override));
|
||||
MOCK_METHOD(float, getOpenLoop, (ICP phase, float clt, SensorResult tps), (const, override));
|
||||
MOCK_METHOD(float, getClosedLoop, (ICP phase, float tps, int rpm, int target), (override));
|
||||
};
|
||||
|
@ -404,7 +409,7 @@ TEST(idle_v2, IntegrationManual) {
|
|||
.WillOnce(Return(1000));
|
||||
|
||||
// Determine phase will claim we're idling
|
||||
EXPECT_CALL(dut, determinePhase(950, 1000, expectedTps))
|
||||
EXPECT_CALL(dut, determinePhase(950, 1000, expectedTps, 0))
|
||||
.WillOnce(Return(ICP::Idling));
|
||||
|
||||
// Open loop should be asked for an open loop position
|
||||
|
@ -434,7 +439,7 @@ TEST(idle_v2, IntegrationAutomatic) {
|
|||
.WillOnce(Return(1000));
|
||||
|
||||
// Determine phase will claim we're idling
|
||||
EXPECT_CALL(dut, determinePhase(950, 1000, expectedTps))
|
||||
EXPECT_CALL(dut, determinePhase(950, 1000, expectedTps, 0))
|
||||
.WillOnce(Return(ICP::Idling));
|
||||
|
||||
// Open loop should be asked for an open loop position
|
||||
|
@ -467,7 +472,7 @@ TEST(idle_v2, IntegrationClamping) {
|
|||
.WillOnce(Return(1000));
|
||||
|
||||
// Determine phase will claim we're idling
|
||||
EXPECT_CALL(dut, determinePhase(950, 1000, expectedTps))
|
||||
EXPECT_CALL(dut, determinePhase(950, 1000, expectedTps, 0))
|
||||
.WillOnce(Return(ICP::Idling));
|
||||
|
||||
// Open loop should be asked for an open loop position
|
||||
|
|
Loading…
Reference in New Issue