Main relay shutdown rebase (#3880)
* aggregate * main relay controller handles delayed shutoff * main relay controller handles delayed shutdown Co-authored-by: Matthew Kennedy <matthewkennedy@outlook.com> Co-authored-by: rusefillc <sdfsdfqsf2334234234>
This commit is contained in:
parent
9b8de47b72
commit
42deca0fd0
|
@ -650,6 +650,7 @@ static void updateIgnition(int rpm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateFlags() {
|
static void updateFlags() {
|
||||||
|
engine->outputChannels.isMainRelayOn = enginePins.mainRelay.getLogicValue();
|
||||||
engine->outputChannels.isFuelPumpOn = enginePins.fuelPumpRelay.getLogicValue();
|
engine->outputChannels.isFuelPumpOn = enginePins.fuelPumpRelay.getLogicValue();
|
||||||
engine->outputChannels.isFanOn = enginePins.fanRelay.getLogicValue();
|
engine->outputChannels.isFanOn = enginePins.fanRelay.getLogicValue();
|
||||||
engine->outputChannels.isFan2On = enginePins.fanRelay2.getLogicValue();
|
engine->outputChannels.isFan2On = enginePins.fanRelay2.getLogicValue();
|
||||||
|
@ -710,7 +711,7 @@ void updateTunerStudioState() {
|
||||||
|
|
||||||
// 104
|
// 104
|
||||||
tsOutputChannels->rpmAcceleration = engine->rpmCalculator.getRpmAcceleration();
|
tsOutputChannels->rpmAcceleration = engine->rpmCalculator.getRpmAcceleration();
|
||||||
|
|
||||||
// Output both the estimated air flow, and measured air flow (if available)
|
// Output both the estimated air flow, and measured air flow (if available)
|
||||||
tsOutputChannels->mafMeasured = Sensor::getOrZero(SensorType::Maf);
|
tsOutputChannels->mafMeasured = Sensor::getOrZero(SensorType::Maf);
|
||||||
tsOutputChannels->mafEstimate = engine->engineState.airflowEstimate;
|
tsOutputChannels->mafEstimate = engine->engineState.airflowEstimate;
|
||||||
|
|
|
@ -6,7 +6,20 @@ void MainRelayController::onSlowCallback() {
|
||||||
isBenchTest = engine->isInMainRelayBench();
|
isBenchTest = engine->isInMainRelayBench();
|
||||||
|
|
||||||
#if EFI_MAIN_RELAY_CONTROL
|
#if EFI_MAIN_RELAY_CONTROL
|
||||||
mainRelayState = isBenchTest | hasIgnitionVoltage;
|
hasIgnitionVoltage = Sensor::getOrZero(SensorType::BatteryVoltage) > 5;
|
||||||
|
|
||||||
|
if (hasIgnitionVoltage) {
|
||||||
|
m_lastIgnitionTime.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
delayedShutoffRequested = engine->module<MainRelayController>()->needsDelayedShutoff();
|
||||||
|
|
||||||
|
// Query whether any engine modules want to keep the lights on
|
||||||
|
// todo: fix this amazing C++ lambda magic
|
||||||
|
// delayedShutoffRequested = engine->engineModules.aggregate([](auto& m, bool prev) { return m->needsDelayedShutoff() | prev; }, false);
|
||||||
|
// TODO: delayed shutoff timeout?
|
||||||
|
|
||||||
|
mainRelayState = isBenchTest | hasIgnitionVoltage | delayedShutoffRequested;
|
||||||
#else // not EFI_MAIN_RELAY_CONTROL
|
#else // not EFI_MAIN_RELAY_CONTROL
|
||||||
mainRelayState = !isBenchTest;
|
mainRelayState = !isBenchTest;
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,6 +27,9 @@ void MainRelayController::onSlowCallback() {
|
||||||
enginePins.mainRelay.setValue(mainRelayState);
|
enginePins.mainRelay.setValue(mainRelayState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainRelayController::onIgnitionStateChanged(bool ignitionOn) {
|
bool MainRelayController::needsDelayedShutoff() {
|
||||||
hasIgnitionVoltage = ignitionOn;
|
// Prevent main relay from turning off if we had igniton voltage in the past 1 second
|
||||||
|
// This avoids accidentally killing the car during a transient, for example
|
||||||
|
// right when the starter is engaged.
|
||||||
|
return !m_lastIgnitionTime.hasElapsedSec(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
#include "engine_module.h"
|
#include "engine_module.h"
|
||||||
#include "main_relay_generated.h"
|
#include "main_relay_generated.h"
|
||||||
|
|
||||||
struct MainRelayController : public EngineModule, public main_relay_s {
|
class MainRelayController : public EngineModule, public main_relay_s {
|
||||||
|
public:
|
||||||
void onSlowCallback() override;
|
void onSlowCallback() override;
|
||||||
void onIgnitionStateChanged(bool ignitionOn) override;
|
bool needsDelayedShutoff() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Timer m_lastIgnitionTime;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,4 +13,7 @@ public:
|
||||||
|
|
||||||
// Called whenever the ignition switch state changes
|
// Called whenever the ignition switch state changes
|
||||||
virtual void onIgnitionStateChanged(bool /*ignitionOn*/) { }
|
virtual void onIgnitionStateChanged(bool /*ignitionOn*/) { }
|
||||||
|
|
||||||
|
// Queried to determine whether this module needs a delayed shutoff, defaults to false
|
||||||
|
virtual bool needsDelayedShutoff() { return false; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1274,6 +1274,7 @@ gaugeCategory = DynoView
|
||||||
; minor info
|
; minor info
|
||||||
indicator = { isFanOn }, "fan off", "fan on", white, black, green, black
|
indicator = { isFanOn }, "fan off", "fan on", white, black, green, black
|
||||||
indicator = { isFan2On }, "fan 2 off", "fan 2 on", white, black, green, black
|
indicator = { isFan2On }, "fan 2 off", "fan 2 on", white, black, green, black
|
||||||
|
indicator = { isMainRelayOn }, "main relay off", "main relay on", white, black, green, black
|
||||||
indicator = { isCylinderCleanupActivated}, "no cyl cleanup", "cyl cleanup", white, black, yellow, black
|
indicator = { isCylinderCleanupActivated}, "no cyl cleanup", "cyl cleanup", white, black, yellow, black
|
||||||
indicator = { isFuelPumpOn}, "pump off", "pump on", white, black, green, black
|
indicator = { isFuelPumpOn}, "pump off", "pump on", white, black, green, black
|
||||||
indicator = { clutchUpState }, "Clutch Up", "clutch Up", white, black, red, black
|
indicator = { clutchUpState }, "Clutch Up", "clutch Up", white, black, red, black
|
||||||
|
@ -1436,7 +1437,7 @@ menuDialog = main
|
||||||
|
|
||||||
subMenu = crankingCltCurve, "Fuel CLT multiplier"
|
subMenu = crankingCltCurve, "Fuel CLT multiplier"
|
||||||
subMenu = crankingCltCurveE100, "Fuel CLT multiplier (Flex Fuel E100)", 0, { flexSensorPin != @@ADC_CHANNEL_NONE@@ }
|
subMenu = crankingCltCurveE100, "Fuel CLT multiplier (Flex Fuel E100)", 0, { flexSensorPin != @@ADC_CHANNEL_NONE@@ }
|
||||||
subMenu = crankingDurationCurve, "Fuel duration multiplier"
|
subMenu = crankingDurationCurve, "Fuel duration multiplier"
|
||||||
subMenu = crankingTpsCurve, "Fuel TPS multiplier"
|
subMenu = crankingTpsCurve, "Fuel TPS multiplier"
|
||||||
subMenu = std_separator
|
subMenu = std_separator
|
||||||
|
|
||||||
|
@ -2111,7 +2112,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
|
||||||
field = "Offset cyl 8", timing_offset_cylinder8, {cylindersCount > 7}
|
field = "Offset cyl 8", timing_offset_cylinder8, {cylindersCount > 7}
|
||||||
field = "Offset cyl 9", timing_offset_cylinder9, {cylindersCount > 8}
|
field = "Offset cyl 9", timing_offset_cylinder9, {cylindersCount > 8}
|
||||||
field = "Offset cyl 10", timing_offset_cylinder10, {cylindersCount > 9}
|
field = "Offset cyl 10", timing_offset_cylinder10, {cylindersCount > 9}
|
||||||
field = "Offset cyl 11", timing_offset_cylinder11, {cylindersCount > 10}
|
field = "Offset cyl 11", timing_offset_cylinder11, {cylindersCount > 10}
|
||||||
field = "Offset cyl 12", timing_offset_cylinder12, {cylindersCount > 11}
|
field = "Offset cyl 12", timing_offset_cylinder12, {cylindersCount > 11}
|
||||||
|
|
||||||
dialog = multisparkDwellParams, "Delay & Dwell"
|
dialog = multisparkDwellParams, "Delay & Dwell"
|
||||||
|
|
|
@ -45,6 +45,14 @@ struct type_list {
|
||||||
others.apply_all(f);
|
others.apply_all(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Applies an accumulator function over the sequence of elements.
|
||||||
|
// The specified seed value is used as the initial accumulator value,
|
||||||
|
// and the specified function is used to select the result value.
|
||||||
|
template<typename return_t, typename func_t>
|
||||||
|
auto aggregate(func_t const& accumulator, return_t seed) {
|
||||||
|
return others.aggregate(accumulator, first.aggregate(accumulator, seed));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the container object for type get_t.
|
* Return the container object for type get_t.
|
||||||
*
|
*
|
||||||
|
@ -92,6 +100,11 @@ public:
|
||||||
f(me);
|
f(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename return_t, typename func_t>
|
||||||
|
auto aggregate(func_t const& accumulator, return_t seed) {
|
||||||
|
return accumulator(me, seed);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename has_t>
|
template<typename has_t>
|
||||||
static constexpr bool has() {
|
static constexpr bool has() {
|
||||||
return std::is_same_v<has_t, base_t>;
|
return std::is_same_v<has_t, base_t>;
|
||||||
|
|
|
@ -2,18 +2,17 @@
|
||||||
|
|
||||||
#include "main_relay.h"
|
#include "main_relay.h"
|
||||||
|
|
||||||
TEST(MainRelay, mr) {
|
TEST(MainRelay, mainRelayLogic) {
|
||||||
EngineTestHelper eth(TEST_ENGINE);
|
EngineTestHelper eth(TEST_ENGINE);
|
||||||
|
|
||||||
MainRelayController dut;
|
MainRelayController dut;
|
||||||
|
|
||||||
// Ignition is off, MR is off
|
// Ignition is off, MR is off
|
||||||
dut.onIgnitionStateChanged(false);
|
|
||||||
dut.onSlowCallback();
|
dut.onSlowCallback();
|
||||||
EXPECT_EQ(enginePins.mainRelay.getLogicValue(), false);
|
EXPECT_EQ(enginePins.mainRelay.getLogicValue(), false);
|
||||||
|
|
||||||
// Ignition is now on, MR is on
|
// Battery above threshold - MR is on
|
||||||
dut.onIgnitionStateChanged(true);
|
Sensor::setMockValue(SensorType::BatteryVoltage, 13);
|
||||||
dut.onSlowCallback();
|
dut.onSlowCallback();
|
||||||
EXPECT_EQ(enginePins.mainRelay.getLogicValue(), true);
|
EXPECT_EQ(enginePins.mainRelay.getLogicValue(), true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue