Move AC logic out of FSIO (#2872)

* new impl

* remove fsio

* inject "is ac active" to fan

* include the correct code

* include

* test

* more AC features

* AC switch vs. actual AC indicators

* include

* duh
This commit is contained in:
Matthew Kennedy 2021-06-27 15:51:34 -07:00 committed by GitHub
parent 41060a1235
commit cd5eb6a77c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 107 additions and 38 deletions

View File

@ -71,7 +71,7 @@ struct TunerStudioOutputChannels {
unsigned int isCltError : 1; // bit 19 unsigned int isCltError : 1; // bit 19
unsigned int isMapError : 1; // bit 20 unsigned int isMapError : 1; // bit 20
unsigned int isIatError : 1; // bit 21 unsigned int isIatError : 1; // bit 21
unsigned int unusedAt22 : 1; // bit 22 unsigned int acState : 1; // bit 22 - 1 if AC is engaged, 0 otherwise
unsigned int isTriggerError : 1; // bit 23 unsigned int isTriggerError : 1; // bit 23
unsigned int hasCriticalError : 1; // bit 24 unsigned int hasCriticalError : 1; // bit 24
unsigned int isWarnNow : 1; // bit 25 unsigned int isWarnNow : 1; // bit 25

View File

@ -729,7 +729,6 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
tsOutputChannels->clutchUpState = engine->clutchUpState; tsOutputChannels->clutchUpState = engine->clutchUpState;
tsOutputChannels->clutchDownState = engine->clutchDownState; tsOutputChannels->clutchDownState = engine->clutchDownState;
tsOutputChannels->brakePedalState = engine->brakePedalState; tsOutputChannels->brakePedalState = engine->brakePedalState;
tsOutputChannels->acSwitchState = engine->acSwitchState;
#if EFI_ENGINE_CONTROL #if EFI_ENGINE_CONTROL
// tCharge depends on the previous state, so we should use the stored value. // tCharge depends on the previous state, so we should use the stored value.

View File

@ -0,0 +1,72 @@
#include "ac_control.h"
#include "engine.h"
#include "deadband.h"
#include "efi_gpio.h"
#include "sensor.h"
#include "tunerstudio_outputs.h"
EXTERN_ENGINE;
// Deadbands to prevent rapid switching on/off of AC
static Deadband<200> maxRpmDeadband;
static Deadband<5> maxCltDeadband;
static Deadband<5> maxTpsDeadband;
static bool getAcState(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
auto rpm = Sensor::get(SensorType::Rpm).value_or(0);
// Engine too slow, disable
if (rpm < 500) {
return false;
}
// Engine too fast, disable
auto maxRpm = CONFIG(maxAcRpm);
if (maxRpm != 0) {
if (maxRpmDeadband.gt(rpm, maxRpm)) {
return false;
}
}
auto clt = Sensor::get(SensorType::Clt);
// No AC with failed CLT
if (!clt) {
return false;
}
// Engine too hot, disable
auto maxClt = CONFIG(maxAcClt);
if (maxClt != 0) {
if (maxCltDeadband.gt(maxClt, clt.Value)) {
return false;
}
}
// TPS too high, disable
auto maxTps = CONFIG(maxAcTps);
if (maxTps != 0) {
auto tps = Sensor::get(SensorType::Tps1).value_or(0);
if (maxTpsDeadband.gt(maxTps, tps)) {
return false;
}
}
// All conditions allow AC, simply pass thru switch
return ENGINE(acSwitchState);
}
bool updateAc(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
bool isEnabled = getAcState(PASS_ENGINE_PARAMETER_SIGNATURE);
enginePins.acRelay.setValue(isEnabled);
#if EFI_TUNER_STUDIO
tsOutputChannels.acSwitchState = engine->acSwitchState;
tsOutputChannels.acState = isEnabled;
#endif // EFI_TUNER_STUDIO
return isEnabled;
}

View File

@ -0,0 +1,6 @@
#pragma once
#include "engine_ptr.h"
// Returns true if AC is currently active
bool updateAc(DECLARE_ENGINE_PARAMETER_SIGNATURE);

View File

@ -7,13 +7,13 @@
EXTERN_ENGINE; EXTERN_ENGINE;
static void fanControl(OutputPin& pin, int8_t fanOnTemp, int8_t fanOffTemp, bool enableWithAc DECLARE_ENGINE_PARAMETER_SUFFIX) { static void fanControl(bool acActive, OutputPin& pin, int8_t fanOnTemp, int8_t fanOffTemp, bool enableWithAc DECLARE_ENGINE_PARAMETER_SUFFIX) {
auto [cltValid, clt] = Sensor::get(SensorType::Clt); auto [cltValid, clt] = Sensor::get(SensorType::Clt);
if (!cltValid) { if (!cltValid) {
// If CLT is broken, turn the fan on // If CLT is broken, turn the fan on
pin.setValue(true); pin.setValue(true);
} else if (enableWithAc && ENGINE(acSwitchState)) { } else if (enableWithAc && acActive) {
pin.setValue(true); pin.setValue(true);
} else if (clt > fanOnTemp) { } else if (clt > fanOnTemp) {
// If hot, turn the fan on // If hot, turn the fan on
@ -26,13 +26,13 @@ static void fanControl(OutputPin& pin, int8_t fanOnTemp, int8_t fanOffTemp, bool
} }
} }
void updateFans(DECLARE_ENGINE_PARAMETER_SIGNATURE) { void updateFans(bool acActive DECLARE_ENGINE_PARAMETER_SUFFIX) {
#if EFI_PROD_CODE #if EFI_PROD_CODE
if (isRunningBenchTest()) { if (isRunningBenchTest()) {
return; // let's not mess with bench testing return; // let's not mess with bench testing
} }
#endif #endif
fanControl(enginePins.fanRelay, CONFIG(fanOnTemperature), CONFIG(fanOffTemperature), CONFIG(enableFan1WithAc) PASS_ENGINE_PARAMETER_SUFFIX); fanControl(acActive, 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); fanControl(acActive, enginePins.fanRelay2, CONFIG(fan2OnTemperature), CONFIG(fan2OffTemperature), CONFIG(enableFan2WithAc) PASS_ENGINE_PARAMETER_SUFFIX);
} }

View File

@ -2,4 +2,4 @@
#include "engine_ptr.h" #include "engine_ptr.h"
void updateFans(DECLARE_ENGINE_PARAMETER_SIGNATURE); void updateFans(bool acActive DECLARE_ENGINE_PARAMETER_SUFFIX);

View File

@ -35,6 +35,7 @@
#include "dynoview.h" #include "dynoview.h"
#include "boost_control.h" #include "boost_control.h"
#include "fan_control.h" #include "fan_control.h"
#include "ac_control.h"
#if EFI_MC33816 #if EFI_MC33816
#include "mc33816.h" #include "mc33816.h"
#endif // EFI_MC33816 #endif // EFI_MC33816
@ -229,7 +230,8 @@ void Engine::periodicSlowCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
runHardcodedFsio(PASS_ENGINE_PARAMETER_SIGNATURE); runHardcodedFsio(PASS_ENGINE_PARAMETER_SIGNATURE);
#endif /* EFI_FSIO */ #endif /* EFI_FSIO */
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); bool acActive = updateAc(PASS_ENGINE_PARAMETER_SIGNATURE);
updateFans(acActive PASS_ENGINE_PARAMETER_SUFFIX);
updateGppwm(); updateGppwm();

View File

@ -12,6 +12,7 @@ CONTROLLERSSRC =
CONTROLLERS_SRC_CPP = \ CONTROLLERS_SRC_CPP = \
$(CONTROLLERS_DIR)/actuators/electronic_throttle.cpp \ $(CONTROLLERS_DIR)/actuators/electronic_throttle.cpp \
$(CONTROLLERS_DIR)/actuators/ac_control.cpp \
$(CONTROLLERS_DIR)/actuators/alternator_controller.cpp \ $(CONTROLLERS_DIR)/actuators/alternator_controller.cpp \
$(CONTROLLERS_DIR)/actuators/boost_control.cpp \ $(CONTROLLERS_DIR)/actuators/boost_control.cpp \
$(CONTROLLERS_DIR)/actuators/dc_motors.cpp \ $(CONTROLLERS_DIR)/actuators/dc_motors.cpp \

View File

@ -105,7 +105,6 @@ FsioPointers::FsioPointers() : fsioLogics() {
static FsioPointers state; static FsioPointers state;
static LEElement * acRelayLogic;
static LEElement * fuelPumpLogic; static LEElement * fuelPumpLogic;
static LEElement * starterRelayDisableLogic; static LEElement * starterRelayDisableLogic;
@ -497,10 +496,6 @@ void runFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
*/ */
enginePins.o2heater.setValue(engine->rpmCalculator.isRunning()); enginePins.o2heater.setValue(engine->rpmCalculator.isRunning());
if (isBrainPinValid(CONFIG(acRelayPin))) {
setPinState("A/C", &enginePins.acRelay, acRelayLogic PASS_ENGINE_PARAMETER_SUFFIX);
}
#if EFI_ENABLE_ENGINE_WARNING #if EFI_ENABLE_ENGINE_WARNING
if (engineConfiguration->useFSIO4ForSeriousEngineWarning) { if (engineConfiguration->useFSIO4ForSeriousEngineWarning) {
updateValueOrWarning(MAGIC_OFFSET_FOR_ENGINE_WARNING, "eng warning", &ENGINE(fsioState.isEngineWarning) PASS_ENGINE_PARAMETER_SUFFIX); updateValueOrWarning(MAGIC_OFFSET_FOR_ENGINE_WARNING, "eng warning", &ENGINE(fsioState.isEngineWarning) PASS_ENGINE_PARAMETER_SUFFIX);
@ -567,7 +562,6 @@ static void showFsio(const char *msg, LEElement *element) {
static void showFsioInfo(void) { static void showFsioInfo(void) {
#if EFI_PROD_CODE || EFI_SIMULATOR #if EFI_PROD_CODE || EFI_SIMULATOR
efiPrintf("sys used %d/user used %d", sysPool.getSize(), userPool.getSize()); efiPrintf("sys used %d/user used %d", sysPool.getSize(), userPool.getSize());
showFsio("a/c", acRelayLogic);
showFsio("fuel", fuelPumpLogic); showFsio("fuel", fuelPumpLogic);
for (int i = 0; i < CAM_INPUTS_COUNT ; i++) { for (int i = 0; i < CAM_INPUTS_COUNT ; i++) {
@ -690,8 +684,6 @@ void initFsioImpl(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
fuelPumpLogic = sysPool.parseExpression(FUEL_PUMP_LOGIC); fuelPumpLogic = sysPool.parseExpression(FUEL_PUMP_LOGIC);
#endif /* EFI_FUEL_PUMP */ #endif /* EFI_FUEL_PUMP */
acRelayLogic = sysPool.parseExpression(AC_RELAY_LOGIC);
#if EFI_MAIN_RELAY_CONTROL #if EFI_MAIN_RELAY_CONTROL
if (isBrainPinValid(CONFIG(mainRelayPin))) if (isBrainPinValid(CONFIG(mainRelayPin)))
mainRelayLogic = sysPool.parseExpression(MAIN_RELAY_LOGIC); mainRelayLogic = sysPool.parseExpression(MAIN_RELAY_LOGIC);
@ -767,10 +759,6 @@ void runHardcodedFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
if (isBrainPinValid(CONFIG(starterRelayDisablePin))) { if (isBrainPinValid(CONFIG(starterRelayDisablePin))) {
enginePins.starterRelayDisable.setValue(engine->rpmCalculator.getRpm() < engineConfiguration->cranking.rpm); enginePins.starterRelayDisable.setValue(engine->rpmCalculator.getRpm() < engineConfiguration->cranking.rpm);
} }
// see AC_RELAY_LOGIC
if (isBrainPinValid(CONFIG(acRelayPin))) {
enginePins.acRelay.setValue(getAcToggle(PASS_ENGINE_PARAMETER_SIGNATURE) && engine->rpmCalculator.getRpm() > 850);
}
// see FUEL_PUMP_LOGIC // see FUEL_PUMP_LOGIC
if (isBrainPinValid(CONFIG(fuelPumpPin))) { if (isBrainPinValid(CONFIG(fuelPumpPin))) {
enginePins.fuelPumpRelay.setValue((getTimeNowSeconds() < engine->triggerActivitySecond + engineConfiguration->startUpFuelPumpDuration) || (engine->rpmCalculator.getRpm() > 0)); enginePins.fuelPumpRelay.setValue((getTimeNowSeconds() < engine->triggerActivitySecond + engineConfiguration->startUpFuelPumpDuration) || (engine->rpmCalculator.getRpm() > 0));

View File

@ -21,8 +21,6 @@
// Human-readable: coolant > 120 // Human-readable: coolant > 120
#define TOO_HOT_LOGIC "coolant 120 >" #define TOO_HOT_LOGIC "coolant 120 >"
// Human-readable: ac_on_switch & (rpm > 850)
#define AC_RELAY_LOGIC "ac_on_switch rpm 850 > &"
// Combined RPM, CLT and VBATT warning light // Combined RPM, CLT and VBATT warning light
// Human-readable: (rpm > fsio_setting(2)) | ((coolant > fsio_setting(3)) | (vbatt < fsio_setting(4))) // Human-readable: (rpm > fsio_setting(2)) | ((coolant > fsio_setting(3)) | (vbatt < fsio_setting(4)))

View File

@ -13,8 +13,6 @@ FUEL_PUMP_LOGIC=((time_since_boot >= 0) & (time_since_boot < startup_fuel_pump_d
TOO_HOT_LOGIC=coolant > 120 TOO_HOT_LOGIC=coolant > 120
AC_RELAY_LOGIC=ac_on_switch & (rpm > 850)
# Combined RPM, CLT and VBATT warning light # Combined RPM, CLT and VBATT warning light
COMBINED_WARNING_LIGHT=(rpm > fsio_setting(2)) | ((coolant > fsio_setting(3)) | (vbatt < fsio_setting(4))) COMBINED_WARNING_LIGHT=(rpm > fsio_setting(2)) | ((coolant > fsio_setting(3)) | (vbatt < fsio_setting(4)))

View File

@ -1182,7 +1182,10 @@ custom pin_mode_e 1 bits, U08, @OFFSET@, [0:6], @@pin_mode_e_enum@@
! todo: rename field remove 'ms' since unusual case of dual-purpose field - it could be either ms or percent ! todo: rename field remove 'ms' since unusual case of dual-purpose field - it could be either ms or percent
float tachPulseDuractionMs;;"", 1, 0, 0, 100, 2 float tachPulseDuractionMs;;"", 1, 0, 0, 100, 2
int unused1708;;"units", 1, 0, -20, 100, 0 uint16_t maxAcRpm;+Above this RPM, disable AC. Set to 0 to disable check.;"rpm", 1, 0, 0, 10000, 0
uint8_t maxAcTps;+Above this TPS, disable AC. Set to 0 to disable check.;"%", 1, 0, 0, 100, 0
uint8_t maxAcClt;+Above this CLT, disable AC to prevent overheating the engine. Set to 0 to disable check.;"deg C", 1, 0, 0, 150, 0
float wwaeTau;+Length of time the deposited wall fuel takes to dissipate after the start of acceleration. ;"Seconds", 1, 0, 0, 3, 2 float wwaeTau;+Length of time the deposited wall fuel takes to dissipate after the start of acceleration. ;"Seconds", 1, 0, 0, 3, 2
pid_s alternatorControl; pid_s alternatorControl;

View File

@ -199,6 +199,7 @@ enable2ndByteCanID = false
; ind_map_error = bits, U32, 0, [20:20], "true", "false"; ; ind_map_error = bits, U32, 0, [20:20], "true", "false";
ind_iat_error = bits, U32, 0, [21:21], "true", "false"; ind_iat_error = bits, U32, 0, [21:21], "true", "false";
acState = bits, U32, 0, [22:22], "true", "false";
ind_isTriggerError = bits, U32, 0, [23:23], "true", "false"; ind_isTriggerError = bits, U32, 0, [23:23], "true", "false";
ind_hasFatalError=bits, U32, 0, [24:24], "true", "false"; ind_hasFatalError=bits, U32, 0, [24:24], "true", "false";
ind_isWarnNow =bits, U32, 0, [25:25], "true", "false"; ind_isWarnNow =bits, U32, 0, [25:25], "true", "false";
@ -1203,7 +1204,8 @@ gaugeCategory = DynoView
indicator = { clutchUpState }, "clutch", "cltch Up", white, black, red, black indicator = { clutchUpState }, "clutch", "cltch Up", white, black, red, black
indicator = { clutchDownState }, "clutch", "cltch Down", white, black, yellow, black indicator = { clutchDownState }, "clutch", "cltch Down", white, black, yellow, black
indicator = { brakePedalIndicator }, "brake", "brake down", white, black, red, black indicator = { brakePedalIndicator }, "brake", "brake down", white, black, red, black
indicator = { acSwitchState }, "AC off", "AC on", white, black, blue, white indicator = { acSwitchState }, "AC switch off", "AC switch on", white, black, blue, white
indicator = { acState }, "AC off", "AC on", white, black, blue, white
indicator = { isIdleClosedLoop }, "not idling", "idling", white, black, green, black indicator = { isIdleClosedLoop }, "not idling", "idling", white, black, green, black
indicator = { isIdleCoasting }, "not coasting", "coasting", white, black, green, black indicator = { isIdleCoasting }, "not coasting", "coasting", white, black, green, black
@ -1392,6 +1394,7 @@ menuDialog = main
subMenu = starterRelay, "Starter Disable relay" subMenu = starterRelay, "Starter Disable relay"
subMenu = fuelPump, "Fuel pump" subMenu = fuelPump, "Fuel pump"
subMenu = fanSetting, "Fan" subMenu = fanSetting, "Fan"
subMenu = acSettings, "Air Conditioning"
subMenu = tachSettings, "Tachometer" subMenu = tachSettings, "Tachometer"
subMenu = malfunction, "Check engine light" subMenu = malfunction, "Check engine light"
subMenu = statusLeds, "Status LEDs" subMenu = statusLeds, "Status LEDs"
@ -2698,11 +2701,13 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
dialog = acSettings, "A/C Settings" dialog = acSettings, "A/C Settings"
field = "A/C Relay", acRelayPin field = "A/C Relay", acRelayPin
field = "A/C Relay Mode", acRelayPinMode field = "A/C Relay Mode", acRelayPinMode
field = "Max RPM", maxAcRpm
field = "Max CLT", maxAcClt
field = "Max TPS", maxAcTps
dialog = fanSetting, "Fan Settings" dialog = fanSetting, "Fan Settings"
panel = fan1Settings panel = fan1Settings
panel = fan2Settings panel = fan2Settings
panel = acSettings
dialog = fuelPump, "Fuel Pump" dialog = fuelPump, "Fuel Pump"
field = "Pin", fuelPumpPin field = "Pin", fuelPumpPin

View File

@ -9,41 +9,38 @@ TEST(FanControl, fan1) {
engineConfiguration->fanOnTemperature = 90; engineConfiguration->fanOnTemperature = 90;
engineConfiguration->fanOffTemperature = 80; engineConfiguration->fanOffTemperature = 80;
engineConfiguration->enableFan1WithAc = false; engineConfiguration->enableFan1WithAc = false;
engine->acSwitchState = false;
// Cold, fan should be off // Cold, fan should be off
Sensor::setMockValue(SensorType::Clt, 75); Sensor::setMockValue(SensorType::Clt, 75);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Between thresholds, should still be off // Between thresholds, should still be off
Sensor::setMockValue(SensorType::Clt, 85); Sensor::setMockValue(SensorType::Clt, 85);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Hot, fan should turn on // Hot, fan should turn on
Sensor::setMockValue(SensorType::Clt, 95); Sensor::setMockValue(SensorType::Clt, 95);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Between thresholds, should stay on // Between thresholds, should stay on
Sensor::setMockValue(SensorType::Clt, 85); Sensor::setMockValue(SensorType::Clt, 85);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Below threshold, should turn off // Below threshold, should turn off
Sensor::setMockValue(SensorType::Clt, 75); Sensor::setMockValue(SensorType::Clt, 75);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE); updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
engineConfiguration->enableFan1WithAc = true; engineConfiguration->enableFan1WithAc = true;
// Now AC is on, fan should turn on! // Now AC is on, fan should turn on!
engine->acSwitchState = true; updateFans(true PASS_ENGINE_PARAMETER_SUFFIX);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Turn off AC, fan should turn off too. // Turn off AC, fan should turn off too.
engine->acSwitchState = false; updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue()); EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
} }