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 isMapError : 1; // bit 20
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 hasCriticalError : 1; // bit 24
unsigned int isWarnNow : 1; // bit 25

View File

@ -729,7 +729,6 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
tsOutputChannels->clutchUpState = engine->clutchUpState;
tsOutputChannels->clutchDownState = engine->clutchDownState;
tsOutputChannels->brakePedalState = engine->brakePedalState;
tsOutputChannels->acSwitchState = engine->acSwitchState;
#if EFI_ENGINE_CONTROL
// 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;
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);
if (!cltValid) {
// If CLT is broken, turn the fan on
pin.setValue(true);
} else if (enableWithAc && ENGINE(acSwitchState)) {
} else if (enableWithAc && acActive) {
pin.setValue(true);
} else if (clt > fanOnTemp) {
// 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 (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);
fanControl(acActive, enginePins.fanRelay, CONFIG(fanOnTemperature), CONFIG(fanOffTemperature), CONFIG(enableFan1WithAc) 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"
void updateFans(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void updateFans(bool acActive DECLARE_ENGINE_PARAMETER_SUFFIX);

View File

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

View File

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

View File

@ -105,7 +105,6 @@ FsioPointers::FsioPointers() : fsioLogics() {
static FsioPointers state;
static LEElement * acRelayLogic;
static LEElement * fuelPumpLogic;
static LEElement * starterRelayDisableLogic;
@ -497,10 +496,6 @@ void runFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
*/
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 (engineConfiguration->useFSIO4ForSeriousEngineWarning) {
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) {
#if EFI_PROD_CODE || EFI_SIMULATOR
efiPrintf("sys used %d/user used %d", sysPool.getSize(), userPool.getSize());
showFsio("a/c", acRelayLogic);
showFsio("fuel", fuelPumpLogic);
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);
#endif /* EFI_FUEL_PUMP */
acRelayLogic = sysPool.parseExpression(AC_RELAY_LOGIC);
#if EFI_MAIN_RELAY_CONTROL
if (isBrainPinValid(CONFIG(mainRelayPin)))
mainRelayLogic = sysPool.parseExpression(MAIN_RELAY_LOGIC);
@ -767,10 +759,6 @@ void runHardcodedFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
if (isBrainPinValid(CONFIG(starterRelayDisablePin))) {
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
if (isBrainPinValid(CONFIG(fuelPumpPin))) {
enginePins.fuelPumpRelay.setValue((getTimeNowSeconds() < engine->triggerActivitySecond + engineConfiguration->startUpFuelPumpDuration) || (engine->rpmCalculator.getRpm() > 0));

View File

@ -21,8 +21,6 @@
// Human-readable: 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
// 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
AC_RELAY_LOGIC=ac_on_switch & (rpm > 850)
# Combined RPM, CLT and VBATT warning light
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
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
pid_s alternatorControl;

View File

@ -199,6 +199,7 @@ enable2ndByteCanID = false
; ind_map_error = bits, U32, 0, [20:20], "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_hasFatalError=bits, U32, 0, [24:24], "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 = { clutchDownState }, "clutch", "cltch Down", white, black, yellow, 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 = { isIdleCoasting }, "not coasting", "coasting", white, black, green, black
@ -1392,6 +1394,7 @@ menuDialog = main
subMenu = starterRelay, "Starter Disable relay"
subMenu = fuelPump, "Fuel pump"
subMenu = fanSetting, "Fan"
subMenu = acSettings, "Air Conditioning"
subMenu = tachSettings, "Tachometer"
subMenu = malfunction, "Check engine light"
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"
field = "A/C Relay", acRelayPin
field = "A/C Relay Mode", acRelayPinMode
field = "Max RPM", maxAcRpm
field = "Max CLT", maxAcClt
field = "Max TPS", maxAcTps
dialog = fanSetting, "Fan Settings"
panel = fan1Settings
panel = fan2Settings
panel = acSettings
dialog = fuelPump, "Fuel Pump"
field = "Pin", fuelPumpPin

View File

@ -9,41 +9,38 @@ TEST(FanControl, fan1) {
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);
updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Between thresholds, should still be off
Sensor::setMockValue(SensorType::Clt, 85);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
// Hot, fan should turn on
Sensor::setMockValue(SensorType::Clt, 95);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Between thresholds, should stay on
Sensor::setMockValue(SensorType::Clt, 85);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Below threshold, should turn off
Sensor::setMockValue(SensorType::Clt, 75);
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
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);
updateFans(true PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(true, enginePins.fanRelay.getLogicValue());
// Turn off AC, fan should turn off too.
engine->acSwitchState = false;
updateFans(PASS_ENGINE_PARAMETER_SIGNATURE);
updateFans(false PASS_ENGINE_PARAMETER_SUFFIX);
EXPECT_EQ(false, enginePins.fanRelay.getLogicValue());
}