Gate closed loop idle on road speed (#2901)

* implement

* test

* b

* config
This commit is contained in:
Matthew Kennedy 2021-07-04 06:35:12 -07:00 committed by GitHub
parent 90e43040c7
commit 007a390f2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 17 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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