diff --git a/firmware/CHANGELOG.md b/firmware/CHANGELOG.md index a79d1b2920..9f230e7eff 100644 --- a/firmware/CHANGELOG.md +++ b/firmware/CHANGELOG.md @@ -40,7 +40,7 @@ or - MAF filtering for better transient response - Minimum injector pulse width setting - Allow selection of DTC severity #625 - - AC pressure switch & startup delay (#623, #660, #661, #662) + - AC pressure switch & startup delay (#623, #660, #661, #662, #663) - Y axis override for VVT target - Feature to skip initial trigger pulses for noisy triggers #634 - VVT open loop "hold" table #638 diff --git a/firmware/controllers/actuators/ac_control.cpp b/firmware/controllers/actuators/ac_control.cpp index f25d72c54d..d37666c9b3 100644 --- a/firmware/controllers/actuators/ac_control.cpp +++ b/firmware/controllers/actuators/ac_control.cpp @@ -87,3 +87,8 @@ void AcController::onSlowCallback() { bool AcController::isAcEnabled() const { return m_acEnabled; } + +// accounts for A/C delay +bool AcController::isAcCompressorEnabled() const { + return acCompressorState; +} diff --git a/firmware/controllers/actuators/ac_control.h b/firmware/controllers/actuators/ac_control.h index e16c8b8c30..682dc1e698 100644 --- a/firmware/controllers/actuators/ac_control.h +++ b/firmware/controllers/actuators/ac_control.h @@ -10,6 +10,7 @@ class AcController : public ac_control_s, public EngineModule { void onSlowCallback() override; virtual bool isAcEnabled() const; + virtual bool isAcCompressorEnabled() const; Timer timeSinceStateChange; diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index d8f03be127..a12f70020d 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -30,8 +30,7 @@ IIdleController::TargetInfo IdleController::getTargetRpm(float clt) { // Why do we bump based on button not based on actual A/C relay state? // Because AC output has a delay to allow idle bump to happen first, so that the airflow increase gets a head start on the load increase // alternator duty cycle has a similar logic - targetRpmAcBump = (!hasAcPressure() || engine->module().unmock().acPressureSwitchState) - && engine->module().unmock().acButtonState ? engineConfiguration->acIdleRpmBump : 0; + targetRpmAcBump = engine->module().unmock().isAcEnabled() ? engineConfiguration->acIdleRpmBump : 0; auto target = targetRpmByClt + targetRpmAcBump + luaAddRpm; @@ -131,8 +130,7 @@ percent_t IdleController::getRunningOpenLoop(float rpm, float clt, SensorResult openLoopBase = running; // Now we bump it by the AC/fan amount if necessary - openLoopAcBump = (!hasAcPressure() || engine->module().unmock().acPressureSwitchState) - && engine->module().unmock().acButtonState ? engineConfiguration->acIdleExtraOffset : 0; + openLoopAcBump = engine->module().unmock().isAcEnabled() ? engineConfiguration->acIdleExtraOffset : 0; openLoopFanBump = (enginePins.fanRelay.getLogicValue() ? engineConfiguration->fan1ExtraIdle : 0) + (enginePins.fanRelay2.getLogicValue() ? engineConfiguration->fan2ExtraIdle : 0); diff --git a/unit_tests/tests/test_idle_controller.cpp b/unit_tests/tests/test_idle_controller.cpp index ca18300613..33a659ecce 100644 --- a/unit_tests/tests/test_idle_controller.cpp +++ b/unit_tests/tests/test_idle_controller.cpp @@ -181,9 +181,16 @@ TEST(idle_v2, runningOpenLoopBasic) { TEST(idle_v2, runningFanAcBump) { EngineTestHelper eth(engine_type_e::TEST_ENGINE); - IdleController dut; + //IdleController dut; + + engine->rpmCalculator.setRpmValue(1000); + Sensor::setMockValue(SensorType::Rpm, 1000); engineConfiguration->manIdlePosition = 50; + engineConfiguration->maxAcRpm = 5000; + engineConfiguration->maxAcClt = 200; + engineConfiguration->maxAcTps = 100; + engineConfiguration->acIdleExtraOffset = 9; engineConfiguration->fan1ExtraIdle = 7; engineConfiguration->fan2ExtraIdle = 3; @@ -193,12 +200,19 @@ TEST(idle_v2, runningFanAcBump) { // Start with fan off enginePins.fanRelay.setValue(0); + //auto dut = engine->module(); + // Should be base position - EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(0, 10, 0)); + EXPECT_FLOAT_EQ(50, engine->module()->getRunningOpenLoop(0, 10, 0)); // Turn on A/C! + //engineConfiguration->acSwitch = Gpio::G1; + //setMockState(engineConfiguration->acSwitch, true); engine->module()->acButtonState = true; - EXPECT_FLOAT_EQ(50 + 9, dut.getRunningOpenLoop(0, 10, 0)); + //engineConfiguration->acPressureSwitch = Gpio::G2; + engine->module()->onSlowCallback(); + + EXPECT_FLOAT_EQ(50 + 9, engine->module()->getRunningOpenLoop(0, 10, 0)); engine->module()->acButtonState = false; // Begin A/C Pressure Switch testing @@ -207,40 +221,46 @@ TEST(idle_v2, runningFanAcBump) { //setMockState(engineConfiguration->acSwitch, false); //setMockState(engineConfiguration->acPressureSwitch, false); engine->module()->acPressureSwitchState = false; - EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(0, 10, 0)); + engine->module()->onSlowCallback(); + EXPECT_FLOAT_EQ(50, engine->module()->getRunningOpenLoop(0, 10, 0)); //setMockState(engineConfiguration->acSwitch, true); engine->module()->acButtonState = true; - EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(0, 10, 0)); + engine->module()->onSlowCallback(); + EXPECT_FLOAT_EQ(50, engine->module()->getRunningOpenLoop(0, 10, 0)); //setMockState(engineConfiguration->acPressureSwitch, true); engine->module()->acPressureSwitchState = true; - EXPECT_FLOAT_EQ(50 + 9, dut.getRunningOpenLoop(0, 10, 0)); + engine->module()->onSlowCallback(); + EXPECT_FLOAT_EQ(50 + 9, engine->module()->getRunningOpenLoop(0, 10, 0)); //setMockState(engineConfiguration->acSwitch, false); engine->module()->acButtonState = false; - EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(0, 10, 0)); + engine->module()->onSlowCallback(); + EXPECT_FLOAT_EQ(50, engine->module()->getRunningOpenLoop(0, 10, 0)); //engineConfiguration->acSwitch = Gpio::Unassigned; //setMockState(engineConfiguration->acPressureSwitch, false); engineConfiguration->acPressureSwitch = Gpio::Unassigned; engine->module()->acPressureSwitchState = false; + engine->module()->onSlowCallback(); // End A/C Pressure Switch testing // Turn the fan on! enginePins.fanRelay.setValue(1); - EXPECT_FLOAT_EQ(50 + 7, dut.getRunningOpenLoop(0, 10, 0)); + EXPECT_FLOAT_EQ(50 + 7, engine->module()->getRunningOpenLoop(0, 10, 0)); enginePins.fanRelay.setValue(0); // Turn on the other fan! enginePins.fanRelay2.setValue(1); - EXPECT_FLOAT_EQ(50 + 3, dut.getRunningOpenLoop(0, 10, 0)); + EXPECT_FLOAT_EQ(50 + 3, engine->module()->getRunningOpenLoop(0, 10, 0)); // Turn on everything! engine->module()->acButtonState = true; enginePins.fanRelay.setValue(1); enginePins.fanRelay2.setValue(1); - EXPECT_FLOAT_EQ(50 + 9 + 7 + 3, dut.getRunningOpenLoop(0, 10, 0)); + engine->module()->onSlowCallback(); + EXPECT_FLOAT_EQ(50 + 9 + 7 + 3, engine->module()->getRunningOpenLoop(0, 10, 0)); } TEST(idle_v2, runningOpenLoopTpsTaper) {