From c27549b2e88c50e3cffe8002d6155f3082ee83f7 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Fri, 11 Jun 2021 03:25:12 -0700 Subject: [PATCH] hard coded fan logic (#2805) * remove fsio * hard code impl * test it * enable fan with AC * make commented stuff match --- .../controllers/actuators/fan_control.cpp | 38 ++++++++++++++ firmware/controllers/actuators/fan_control.h | 5 ++ firmware/controllers/algo/engine.cpp | 3 ++ firmware/controllers/controllers.mk | 1 + firmware/controllers/core/fsio_impl.cpp | 13 ----- firmware/controllers/system_fsio.h | 3 -- firmware/controllers/system_fsio.txt | 4 -- firmware/integration/rusefi_config.txt | 8 +-- firmware/tunerstudio/rusefi.input | 18 ++++++- unit_tests/tests/test_fan_control.cpp | 49 +++++++++++++++++++ unit_tests/tests/test_logic_expression.cpp | 10 ---- unit_tests/tests/tests.mk | 1 + 12 files changed, 117 insertions(+), 36 deletions(-) create mode 100644 firmware/controllers/actuators/fan_control.cpp create mode 100644 firmware/controllers/actuators/fan_control.h create mode 100644 unit_tests/tests/test_fan_control.cpp diff --git a/firmware/controllers/actuators/fan_control.cpp b/firmware/controllers/actuators/fan_control.cpp new file mode 100644 index 0000000000..f8e51552ed --- /dev/null +++ b/firmware/controllers/actuators/fan_control.cpp @@ -0,0 +1,38 @@ +#include "fan_control.h" +#include "engine.h" + +#include "bench_test.h" +#include "efi_gpio.h" +#include "sensor.h" + +EXTERN_ENGINE; + +static void fanControl(OutputPin& pin, int8_t fanOnTemp, int8_t fanOffTemp, bool enableWithAc DECLARE_ENGINE_PARAMETER_SUFFIX) { + auto [cltValid, clt] = Sensor::get(SensorType::Clt); + + if (!cltValid) { + // If CLT is broken, turn the fan on + pin.setValue(true); + } else if (enableWithAc && ENGINE(acSwitchState)) { + pin.setValue(true); + } else if (clt > fanOnTemp) { + // If hot, turn the fan on + pin.setValue(true); + } else if (clt < fanOffTemp) { + // If cold, turn the fan off + pin.setValue(false); + } else { + // no condition met, maintain previous state + } +} + +void updateFans(DECLARE_ENGINE_PARAMETER_SIGNATURE) { +#if EFI_PROD_CODE + if (isRunningBenchTest()) { + return; // let's not mess with bench testing + } +#endif + + fanControl(enginePins.fanRelay, CONFIG(fanOnTemperature), CONFIG(fanOffTemperature), CONFIG(enableFan1WithAc) PASS_ENGINE_PARAMETER_SUFFIX); + //fanControl(enginePins.fanRelay2, CONFIG(fan2OnTemperature), CONFIG(fan2OffTemperature), CONFIG(enableFan2WithAc) PASS_ENGINE_PARAMETER_SUFFIX); +} diff --git a/firmware/controllers/actuators/fan_control.h b/firmware/controllers/actuators/fan_control.h new file mode 100644 index 0000000000..d98572c399 --- /dev/null +++ b/firmware/controllers/actuators/fan_control.h @@ -0,0 +1,5 @@ +#pragma once + +#include "engine_ptr.h" + +void updateFans(DECLARE_ENGINE_PARAMETER_SIGNATURE); diff --git a/firmware/controllers/algo/engine.cpp b/firmware/controllers/algo/engine.cpp index d3c7f204eb..e7710ffea0 100644 --- a/firmware/controllers/algo/engine.cpp +++ b/firmware/controllers/algo/engine.cpp @@ -34,6 +34,7 @@ #include "tachometer.h" #include "dynoview.h" #include "boost_control.h" +#include "fan_control.h" #if EFI_MC33816 #include "mc33816.h" #endif // EFI_MC33816 @@ -228,6 +229,8 @@ void Engine::periodicSlowCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) { runHardcodedFsio(PASS_ENGINE_PARAMETER_SIGNATURE); #endif /* EFI_FSIO */ + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + updateGppwm(); updateIdleControl(); diff --git a/firmware/controllers/controllers.mk b/firmware/controllers/controllers.mk index 4e1b6255d0..b66af648ff 100644 --- a/firmware/controllers/controllers.mk +++ b/firmware/controllers/controllers.mk @@ -15,6 +15,7 @@ CONTROLLERS_SRC_CPP = \ $(CONTROLLERS_DIR)/actuators/alternator_controller.cpp \ $(CONTROLLERS_DIR)/actuators/boost_control.cpp \ $(CONTROLLERS_DIR)/actuators/dc_motors.cpp \ + $(CONTROLLERS_DIR)/actuators/fan_control.cpp \ $(CONTROLLERS_DIR)/actuators/idle_hardware.cpp \ $(CONTROLLERS_DIR)/actuators/idle_thread.cpp \ $(CONTROLLERS_DIR)/actuators/pwm_tester.cpp \ diff --git a/firmware/controllers/core/fsio_impl.cpp b/firmware/controllers/core/fsio_impl.cpp index 25515ac324..ef9685c6ff 100644 --- a/firmware/controllers/core/fsio_impl.cpp +++ b/firmware/controllers/core/fsio_impl.cpp @@ -107,7 +107,6 @@ static FsioPointers state; static LEElement * acRelayLogic; static LEElement * fuelPumpLogic; -static LEElement * radiatorFanLogic; static LEElement * alternatorLogic; static LEElement * starterRelayDisableLogic; @@ -507,10 +506,6 @@ void runFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) { // setPinState("alternator", &enginePins.alternatorField, alternatorLogic, engine PASS_ENGINE_PARAMETER_SUFFIX); // } - if (isBrainPinValid(CONFIG(fanPin))) { - setPinState("fan", &enginePins.fanRelay, radiatorFanLogic PASS_ENGINE_PARAMETER_SUFFIX); - } - #if EFI_ENABLE_ENGINE_WARNING if (engineConfiguration->useFSIO4ForSeriousEngineWarning) { updateValueOrWarning(MAGIC_OFFSET_FOR_ENGINE_WARNING, "eng warning", &ENGINE(fsioState.isEngineWarning) PASS_ENGINE_PARAMETER_SUFFIX); @@ -579,7 +574,6 @@ static void showFsioInfo(void) { efiPrintf("sys used %d/user used %d", sysPool.getSize(), userPool.getSize()); showFsio("a/c", acRelayLogic); showFsio("fuel", fuelPumpLogic); - showFsio("fan", radiatorFanLogic); showFsio("alt", alternatorLogic); for (int i = 0; i < CAM_INPUTS_COUNT ; i++) { @@ -703,7 +697,6 @@ void initFsioImpl(DECLARE_ENGINE_PARAMETER_SIGNATURE) { #endif /* EFI_FUEL_PUMP */ acRelayLogic = sysPool.parseExpression(AC_RELAY_LOGIC); - radiatorFanLogic = sysPool.parseExpression(FAN_CONTROL_LOGIC); alternatorLogic = sysPool.parseExpression(ALTERNATOR_LOGIC); @@ -782,12 +775,6 @@ void runHardcodedFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) { if (isBrainPinValid(CONFIG(starterRelayDisablePin))) { enginePins.starterRelayDisable.setValue(engine->rpmCalculator.getRpm() < engineConfiguration->cranking.rpm); } - // see FAN_CONTROL_LOGIC - if (isBrainPinValid(CONFIG(fanPin))) { - auto clt = Sensor::get(SensorType::Clt); - enginePins.fanRelay.setValue(!clt.Valid || (enginePins.fanRelay.getLogicValue() && (clt.Value > engineConfiguration->fanOffTemperature)) || - (clt.Value > engineConfiguration->fanOnTemperature) || !clt.Valid); - } // see AC_RELAY_LOGIC if (isBrainPinValid(CONFIG(acRelayPin))) { enginePins.acRelay.setValue(getAcToggle(PASS_ENGINE_PARAMETER_SIGNATURE) && engine->rpmCalculator.getRpm() > 850); diff --git a/firmware/controllers/system_fsio.h b/firmware/controllers/system_fsio.h index d73f83c650..c8156fc679 100644 --- a/firmware/controllers/system_fsio.h +++ b/firmware/controllers/system_fsio.h @@ -15,9 +15,6 @@ // different way to have the same result would be using "self" // (self and (coolant > fan_off_setting)) | (coolant > fan_on_setting) | is_clt_broken -// Human-readable: (fan and (coolant > cfg_fanOffTemperature)) | (coolant > cfg_fanOnTemperature) | is_clt_broken -#define FAN_CONTROL_LOGIC "fan coolant cfg_fanofftemperature > and coolant cfg_fanontemperature > | is_clt_broken |" - // Human-readable: ((time_since_boot >= 0) & (time_since_boot < startup_fuel_pump_duration)) | (time_since_trigger < 1) #define FUEL_PUMP_LOGIC "time_since_boot 0 >= time_since_boot startup_fuel_pump_duration < & time_since_trigger 1 < |" diff --git a/firmware/controllers/system_fsio.txt b/firmware/controllers/system_fsio.txt index 128001069b..7d28c0b95d 100644 --- a/firmware/controllers/system_fsio.txt +++ b/firmware/controllers/system_fsio.txt @@ -9,10 +9,6 @@ # Andrey Belomutskiy, (c) 2012-2017 # -# different way to have the same result would be using "self" -# (self and (coolant > fan_off_setting)) | (coolant > fan_on_setting) | is_clt_broken -FAN_CONTROL_LOGIC=(fan and (coolant > cfg_fanOffTemperature)) | (coolant > cfg_fanOnTemperature) | is_clt_broken - FUEL_PUMP_LOGIC=((time_since_boot >= 0) & (time_since_boot < startup_fuel_pump_duration)) | (time_since_trigger < 1) ALTERNATOR_LOGIC=vbatt < 14.5 diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 45d6ea508b..05633e991e 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -528,8 +528,8 @@ bit isForcedInduction bit useFordRedundantTps;+On Ford vehicles one of the sensors is not linear on the full range, i.e. in the specific range of the positions we effectively have only one sensor. bit isVerboseAuxPid1 bit overrideTriggerGaps -bit unused_294_4 -bit unused_294_5 +bit enableFan1WithAc;+Turn on this fan when AC is on. +bit enableFan2WithAc;+Turn on this fan when AC is on. bit unused_294_6 bit unused_294_7 bit unused_294_8 @@ -637,8 +637,8 @@ angle_t globalTriggerAngleOffset;+Angle between Top Dead Center (TDC) and the fi float analogInputDividerCoefficient;+Ratio/coefficient of input voltage dividers on your PCB. For example, use '2' if your board divides 5v into 2.5v. Use '1.66' if your board divides 5v into 3v.;"coef", 1, 0, 0.01, 10.0, 2 float vbattDividerCoeff;+This is the ratio of the resistors for the battery voltage, measure the voltage at the battery and then adjust this number until the gauge matches the reading.;"coef", 1, 0, 0.01, 99.0, 2 -float fsio_visible fanOnTemperature;+Cooling fan turn-on temperature threshold, in Celsius;"*C", 1, 0, 0, 1000.0, 0 -float fsio_visible fanOffTemperature;+Cooling fan turn-off temperature threshold, in Celsius;"*C", 1, 0, 0, 1000.0, 0 +float fanOnTemperature;+Cooling fan turn-on temperature threshold, in Celsius;"deg C", 1, 0, 0, 150, 0 +float fanOffTemperature;+Cooling fan turn-off temperature threshold, in Celsius;"deg C", 1, 0, 0, 150, 0 float vehicleSpeedCoef;+This coefficient translates vehicle speed input frequency (in Hz) into vehicle speed, km/h;"coef", 1, 0, 0.01, 2000.0, 2 diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index 1c02b3f7ec..ff8688a050 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -2669,15 +2669,29 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00" field = "#Use debug mode 'Timing' to view idle timing adjustment" ; Engine->Fan Settings - dialog = fanSetting, "Fan Settings" + dialog = fan1Settings, "Fan 1" field = "Pin", fanPin field = "Pin mode", fanPinMode field = "On temperature", fanOnTemperature field = "Off temperature", fanOffTemperature -; this one has build-in FSIO logic + field = "Enable with AC", enableFan1WithAc + + ;dialog = fan2Settings, "Fan 2" + ; field = "Pin", fan2Pin + ; field = "Pin mode", fan2PinMode + ; field = "On temperature", fan2OnTemperature + ; field = "Off temperature", fan2OffTemperature + ; field = "Enable with AC", enableFan2WithAc + + dialog = acSettings, "A/C Settings" field = "A/C Relay", acRelayPin field = "A/C Relay Mode", acRelayPinMode + dialog = fanSetting, "Fan Settings" + panel = fan1Settings + ;panel = fan2Settings + panel = acSettings + dialog = fuelPump, "Fuel Pump" field = "Pin", fuelPumpPin field = "Pin mode", fuelPumpPinMode diff --git a/unit_tests/tests/test_fan_control.cpp b/unit_tests/tests/test_fan_control.cpp new file mode 100644 index 0000000000..1240d2235f --- /dev/null +++ b/unit_tests/tests/test_fan_control.cpp @@ -0,0 +1,49 @@ +#include "efi_gpio.h" +#include "engine_test_helper.h" +#include "fan_control.h" +#include "sensor.h" + +TEST(FanControl, fan1) { + WITH_ENGINE_TEST_HELPER(TEST_ENGINE); + + engineConfiguration->fanOnTemperature = 90; + engineConfiguration->fanOffTemperature = 80; + engineConfiguration->enableFan1WithAc = false; + engine->acSwitchState = false; + + // Cold, fan should be off + Sensor::setMockValue(SensorType::Clt, 75); + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); + + // Between thresholds, should still be off + Sensor::setMockValue(SensorType::Clt, 85); + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); + + // Hot, fan should turn on + Sensor::setMockValue(SensorType::Clt, 95); + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(true, enginePins.fanRelay.getLogicValue()); + + // Between thresholds, should stay on + Sensor::setMockValue(SensorType::Clt, 85); + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(true, enginePins.fanRelay.getLogicValue()); + + // Below threshold, should turn off + Sensor::setMockValue(SensorType::Clt, 75); + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); + + engineConfiguration->enableFan1WithAc = true; + // Now AC is on, fan should turn on! + engine->acSwitchState = true; + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(true, enginePins.fanRelay.getLogicValue()); + + // Turn off AC, fan should turn off too. + engine->acSwitchState = false; + updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); + EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); +} diff --git a/unit_tests/tests/test_logic_expression.cpp b/unit_tests/tests/test_logic_expression.cpp index 6039f04269..3dd120fb29 100644 --- a/unit_tests/tests/test_logic_expression.cpp +++ b/unit_tests/tests/test_logic_expression.cpp @@ -248,16 +248,6 @@ TEST(fsio, testLogicExpressions) { ASSERT_EQ(0, c.calcLogValue[0]); } - { - WITH_ENGINE_TEST_HELPER_SENS(FORD_INLINE_6_1995, sensorVals); - engineConfiguration->fanOnTemperature = 0; - engineConfiguration->fanOffTemperature = 0; - - testExpression2(0, "cfg_fanOffTemperature", 0, engine); - testExpression2(0, FAN_CONTROL_LOGIC, 1, engine); - testExpression2(0, "coolant cfg_fanOffTemperature >", 1, engine); - } - { WITH_ENGINE_TEST_HELPER_SENS(FORD_INLINE_6_1995, sensorVals); engine->fsioState.mockRpm = 900; diff --git a/unit_tests/tests/tests.mk b/unit_tests/tests/tests.mk index 450717a94b..9f4a5a91fc 100644 --- a/unit_tests/tests/tests.mk +++ b/unit_tests/tests/tests.mk @@ -35,6 +35,7 @@ TESTS_SRC_CPP = \ tests/test_idle_controller.cpp \ tests/test_issue_898.cpp \ tests/test_etb.cpp \ + tests/test_fan_control.cpp \ tests/test_vvt.cpp \ tests/test_launch.cpp \ tests/test_fuel_map.cpp \