diff --git a/firmware/controllers/actuators/idle_thread.cpp b/firmware/controllers/actuators/idle_thread.cpp index 955e3ae0ad..3b5b704277 100644 --- a/firmware/controllers/actuators/idle_thread.cpp +++ b/firmware/controllers/actuators/idle_thread.cpp @@ -246,8 +246,10 @@ float IdleController::getRunningOpenLoop(float clt, SensorResult tps) const { // Now we bump it by the AC/fan amount if necessary running += engine->acSwitchState ? CONFIG(acIdleExtraOffset) : 0; - // TODO: fan idle bump needs its own config field - running += enginePins.fanRelay.getLogicValue() ? CONFIG(acIdleExtraOffset) : 0; + running += enginePins.fanRelay.getLogicValue() ? CONFIG(fan1ExtraIdle) : 0; + + // TODO: once we have dual fans, enable + //running += enginePins.fanRelay2.getLogicValue() ? CONFIG(fan2ExtraIdle) : 0; // Now bump it by the specified amount when the throttle is opened (if configured) // nb: invalid tps will make no change, no explicit check required diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 5c0e64a0b7..683ff29251 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -808,7 +808,7 @@ custom adc_channel_mode_e 4 bits, U32, @OFFSET@, [0:1], "Off", "Slow", "Fas brain_pin_e canRxPin;set_can_rx_pin X pin_input_mode_e throttlePedalUpPinMode; - uint8_t fsio_visible acIdleExtraOffset;+Additional idle PID offset while A/C is active;"Percent", 1, 0, 0, 255, 0 + uint8_t fsio_visible acIdleExtraOffset;+Additional idle % while A/C is active;"%", 1, 0, 0, 100, 0 int can2SleepPeriodMs;+CANbus thread period, ms;"ms", 1, 0, 0, 1000.0, 2 uint16_t wastegatePositionMin;+Voltage when the wastegate is closed.\nYou probably don't have one of these!;"mv", 1, 0, 0, 5000, 0 @@ -1322,7 +1322,7 @@ float[MAP_ACCEL_TAPER] mapAccelTaperMult;;"mult", 1, 0, 0.0, 300, float tChargeMaxRpmMaxTps;;"mult", 1, 0, 0, 3, 4 fsio_pwm_freq_t[CAMS_PER_BANK iterate] auxPidFrequency; - uint8_t unused1301;;"units", 1, 0, -20, 100, 0 + uint8_t fan1ExtraIdle;+Additional idle % when fan #1 is active;"%", 1, 0, 0, 100, 0 int alternatorPwmFrequency;;"Hz", 1, 0, 0, 3000.0, 0 int unused2260;;"units", 1, 0, -20, 100, 0 @@ -1330,7 +1330,8 @@ float[MAP_ACCEL_TAPER] mapAccelTaperMult;;"mult", 1, 0, 0.0, 300, float[NARROW_BAND_WIDE_BAND_CONVERSION_SIZE] narrowToWideOxygen;;"ratio", 1, 0, -40.0, 40.0, 2 vvt_mode_e[CAMS_PER_BANK iterate] vvtMode;set vvt_mode X uint8_t[CAMS_PER_BANK_padding] vvtModePadding;; - uint8_t[22] unusedOldBiquad;;"units", 1, 0, -20, 100, 0 + uint8_t fan2ExtraIdle;+Additional idle % when fan #2 is active;"%", 1, 0, 0, 100, 0 + uint8_t[21] unusedOldBiquad;;"units", 1, 0, -20, 100, 0 float[CLT_TIMING_CURVE_SIZE] cltTimingBins;CLT-based timing correction;"C", 1, 0, -100.0, 250.0, 1 float[CLT_TIMING_CURVE_SIZE] cltTimingExtra;;"degree", 1, 0, -400.0, 400.0, 0 custom tle8888_mode_e 1 bits, U08, @OFFSET@, [0:1], "Auto", "SemiAuto", "Manual", "Hall" diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 37dc60957c..760b3059f6 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -2624,13 +2624,19 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00" field = "use Cic Pid", useCicPidForIdle field = "Use IAC PID Multiplier Table", useIacPidMultTable + dialog = idleOpenLoop, "Open Loop Idle" + slider = "Open loop base position", manIdlePosition, horizontal + field = "A/C adder", acIdleExtraOffset + field = "Fan #1 adder", fan1ExtraIdle + ;field = "Fan #2 adder", fan2ExtraIdle + field = "Extra idle air if throttle pressed", iacByTpsTaper + dialog = idleGating, "Idle Detection Thresholds" field = "TPS threshold", idlePidDeactivationTpsThreshold field = "RPM upper limit", idlePidRpmUpperLimit field = "RPM deadzone", idlePidRpmDeadZone dialog = idleExtra, "Extra Idle Features" - field = "Extra idle air if throttle pressed", iacByTpsTaper field = "Use idle ignition table", useSeparateAdvanceForIdle field = "Use idle VE table", useSeparateVeForIdle field = "Use coasting idle table", useIacTableForCoasting, {idleMode == 0} @@ -2641,10 +2647,9 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00" field = "Idle control mode", idleMode field = "! Solenoid idle control is disabled at zero RPM" - slider = "Open loop idle position", manIdlePosition, horizontal - field = "" panel = idleGating + panel = idleOpenLoop panel = idlePidSettings, { idleMode == 0} panel = idleExtra diff --git a/unit_tests/tests/test_idle_controller.cpp b/unit_tests/tests/test_idle_controller.cpp index 3c18aa9b03..60dfcaba63 100644 --- a/unit_tests/tests/test_idle_controller.cpp +++ b/unit_tests/tests/test_idle_controller.cpp @@ -194,7 +194,44 @@ TEST(idle_v2, runningOpenLoopBasic) { EXPECT_FLOAT_EQ(25, dut.getRunningOpenLoop(50, 0)); } -// TODO: test AC/fan open loop compensation +TEST(idle_v2, runningFanAcBump) { + WITH_ENGINE_TEST_HELPER(TEST_ENGINE); + IdleController dut; + INJECT_ENGINE_REFERENCE(&dut); + + engineConfiguration->manIdlePosition = 50; + engineConfiguration->acIdleExtraOffset = 9; + engineConfiguration->fan1ExtraIdle = 7; + engineConfiguration->fan2ExtraIdle = 3; + + setArrayValues(config->cltIdleCorr, 1.0f); + + // Start with fan off + enginePins.fanRelay.setValue(0); + + // Should be base position + EXPECT_FLOAT_EQ(50, dut.getRunningOpenLoop(10, 0)); + + // Turn on AC! + engine->acSwitchState = true; + EXPECT_FLOAT_EQ(50 + 9, dut.getRunningOpenLoop(10, 0)); + engine->acSwitchState = false; + + // Turn the fan on! + enginePins.fanRelay.setValue(1); + EXPECT_FLOAT_EQ(50 + 7, dut.getRunningOpenLoop(10, 0)); + enginePins.fanRelay.setValue(0); + + // Turn on the other fan! + //enginePins.fanRelay2.setValue(1); + //EXPECT_FLOAT_EQ(50 + 3, dut.getRunningOpenLoop(10, 0)); + + // Turn on everything! + engine->acSwitchState = true; + enginePins.fanRelay.setValue(1); + ///nginePins.fanRelay2.setValue(1); + EXPECT_FLOAT_EQ(50 + 9 + 7 /* + 3 */, dut.getRunningOpenLoop(10, 0)); +} TEST(idle_v2, runningOpenLoopTpsTaper) { WITH_ENGINE_TEST_HELPER(TEST_ENGINE);