parent
b2b05659dc
commit
542cb6a420
|
@ -201,6 +201,31 @@ int IdleController::getTargetRpm(float clt) const {
|
|||
return fsioBump + interpolate2d("cltRpm", clt, CONFIG(cltIdleRpmBins), CONFIG(cltIdleRpm));
|
||||
}
|
||||
|
||||
IIdleController::Phase IdleController::determinePhase(int rpm, int targetRpm, SensorResult tps) const {
|
||||
if (!engine->rpmCalculator.isRunning()) {
|
||||
return Phase::Cranking;
|
||||
}
|
||||
|
||||
if (!tps) {
|
||||
// If the TPS has failed, assume the engine is running
|
||||
return Phase::Running;
|
||||
}
|
||||
|
||||
// if throttle pressed, we're out of the idle corner
|
||||
if (tps.Value > CONFIG(idlePidDeactivationTpsThreshold)) {
|
||||
return Phase::Running;
|
||||
}
|
||||
|
||||
// If rpm too high (but throttle not pressed), we're coasting
|
||||
int maximumIdleRpm = targetRpm + CONFIG(idlePidRpmUpperLimit);
|
||||
if (rpm > maximumIdleRpm) {
|
||||
return Phase::Coasting;
|
||||
}
|
||||
|
||||
// No other conditions met, we are idling!
|
||||
return Phase::Idling;
|
||||
}
|
||||
|
||||
static percent_t manualIdleController(float cltCorrection DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||
|
||||
percent_t correctedPosition = cltCorrection * CONFIG(manIdlePosition);
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
#include "periodic_task.h"
|
||||
|
||||
struct IIdleController {
|
||||
enum class Phase : uint8_t {
|
||||
Cranking, // Below cranking threshold
|
||||
Idling, // Below idle RPM, off throttle
|
||||
Coasting, // Off throttle but above idle RPM
|
||||
Running, // On throttle
|
||||
};
|
||||
|
||||
virtual Phase determinePhase(int rpm, int targetRpm, SensorResult tps) const;
|
||||
virtual int getTargetRpm(float clt) const = 0;
|
||||
};
|
||||
|
||||
|
@ -29,6 +37,9 @@ public:
|
|||
|
||||
// TARGET DETERMINATION
|
||||
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;
|
||||
};
|
||||
|
||||
void updateIdleControl();
|
||||
|
|
|
@ -144,3 +144,43 @@ TEST(idle_v2, testTargetRpm) {
|
|||
EXPECT_FLOAT_EQ(100, dut.getTargetRpm(10));
|
||||
EXPECT_FLOAT_EQ(500, dut.getTargetRpm(50));
|
||||
}
|
||||
|
||||
using ICP = IIdleController::Phase;
|
||||
|
||||
TEST(idle_v2, testDeterminePhase) {
|
||||
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
|
||||
IdleController dut;
|
||||
INJECT_ENGINE_REFERENCE(&dut);
|
||||
|
||||
// TPS threshold 5% for easy test
|
||||
CONFIG(idlePidDeactivationTpsThreshold) = 5;
|
||||
// RPM window is 100 RPM above target
|
||||
CONFIG(idlePidRpmUpperLimit) = 100;
|
||||
|
||||
// First test stopped engine
|
||||
engine->rpmCalculator.setRpmValue(0);
|
||||
EXPECT_EQ(ICP::Cranking, dut.determinePhase(0, 1000, unexpected));
|
||||
|
||||
// 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));
|
||||
|
||||
// Valid TPS should now be inside the zone
|
||||
EXPECT_EQ(ICP::Idling, dut.determinePhase(1000, 1000, 0));
|
||||
|
||||
// Above TPS threshold should be outside the zone
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1000, 1000, 10));
|
||||
|
||||
// Above target, below (target + upperLimit) should be in idle zone
|
||||
EXPECT_EQ(ICP::Idling, dut.determinePhase(1099, 1000, 0));
|
||||
|
||||
// above upper limit and on throttle should be out of idle zone
|
||||
EXPECT_EQ(ICP::Running, dut.determinePhase(1101, 1000, 10));
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue