Implement `Minimum Vehicle Speed` setting #6783

This commit is contained in:
kifir 2024-12-06 17:24:12 +02:00 committed by kifir23917
parent 8d904f9c01
commit 4d8b3229fa
17 changed files with 170 additions and 8 deletions

View File

@ -59,6 +59,7 @@ namespace engine_configuration_defaults {
constexpr lua_gauge_meaning_e NITROUS_LUA_GAUGE_MEANING = LUA_GAUGE_LOWER_BOUND;
constexpr float NITROUS_LUA_GAUGE_ARMING_VALUE = 0.0f;
constexpr uint16_t NITROUS_MINIMUM_VEHICLE_SPEED = 0;
constexpr int NITROUS_MINIMUM_TPS = 80;
constexpr uint8_t NITROUS_MINIMUM_CLT = 60;
constexpr uint16_t NITROUS_MAXIMUM_MAP = 0;

View File

@ -1,6 +1,7 @@
struct_no_prefix nitrous_control_state_s
bit isArmed
bit isNitrousSpeedConditionSatisfied
bit isTpsConditionSatisfied
bit isCltConditionSatisfied
bit isMapConditionSatisfied

View File

@ -10,14 +10,15 @@
void NitrousController::onSlowCallback() {
if (engineConfiguration->nitrousControlEnabled) {
updateArmingState();
updateSpeedConditionSatisfied();
updateTpsConditionSatisfied();
updateCltConditionSatisfied();
updateMapConditionSatisfied();
updateAfrConditionSatisfied();
updateRpmConditionSatisfied();
isNitrousConditionSatisfied = (
isArmed && isTpsConditionSatisfied && isCltConditionSatisfied && isMapConditionSatisfied
&& isAfrConditionSatisfied && isNitrousRpmConditionSatisfied
isArmed && isTpsConditionSatisfied && isNitrousSpeedConditionSatisfied && isCltConditionSatisfied
&& isMapConditionSatisfied && isAfrConditionSatisfied && isNitrousRpmConditionSatisfied
);
} else {
isNitrousConditionSatisfied = false;
@ -50,6 +51,16 @@ void NitrousController::updateArmingState() {
}
}
void NitrousController::updateSpeedConditionSatisfied() {
if (engineConfiguration->nitrousMinimumVehicleSpeed != 0) {
const expected<float> speed = Sensor::get(SensorType::VehicleSpeed);
isNitrousSpeedConditionSatisfied =
speed.Valid && (engineConfiguration->nitrousMinimumVehicleSpeed <= speed.Value);
} else {
isNitrousSpeedConditionSatisfied = true;
}
}
void NitrousController::updateTpsConditionSatisfied() {
if (engineConfiguration->nitrousMinimumTps != 0) {
const expected<float> tps = Sensor::get(SensorType::DriverThrottleIntent);

View File

@ -15,6 +15,7 @@ public:
float getFuelCoefficient() const;
private:
void updateArmingState();
void updateSpeedConditionSatisfied();
void updateTpsConditionSatisfied();
void updateCltConditionSatisfied();
void updateMapConditionSatisfied();

View File

@ -1803,7 +1803,9 @@ uint8_t autoscale knockFuelTrim;Fuel trim when knock, max 30%;"%", 1, 0, 0, 30,
int8_t nitrousFuelAdderPercent;;"%", 1, 0, 0, 100, 0
float nitrousIgnitionRetard;Retard timing to remove from actual final timing (after all corrections) due to additional air.;"deg", 1, 0, -180, 180, 2
#define END_OF_CALIBRATION_PADDING 68
uint16_t nitrousMinimumVehicleSpeed;;"Kph", 1, 0, 0, 300, 0
#define END_OF_CALIBRATION_PADDING 66
uint8_t[END_OF_CALIBRATION_PADDING] unusedOftenChangesDuringFirmwareUpdate;;"units", 1, 0, 0, 1, 0
! end of engine_configuration_s

View File

@ -4991,6 +4991,7 @@ dialog = tcuControls, "Transmission Settings"
dialog = NitrousControlSettings, "Settings"
field = "Nitrous Relay", nitrousRelayPin
field = "Nitrous Relay Mode", nitrousRelayPinMode
field = "Minimum Vehicle Speed", nitrousMinimumVehicleSpeed
field = "Minimum TPS", nitrousMinimumTps
field = "Minimum CLT", nitrousMinimumClt
field = "Maximum MAP", nitrousMaximumMap

View File

@ -14,6 +14,7 @@ void NitrousTestBase::setUpTestConfiguration(
.setNitrousControlEnabled({ true })
.setNitrousControlArmingMethod({ DIGITAL_SWITCH_INPUT })
.setNitrousControlTriggerPin({ TEST_NITROUS_CONTROL_ARMING_PIN })
.setNitrousMinimumVehicleSpeed({ TEST_MIN_VEHICLE_SPEED })
.setNitrousMinimumTps({ TEST_MIN_TPS })
.setNitrousMinimumClt({ TEST_MIN_CLT })
.setNitrousMaximumMap({ TEST_MAX_MAP })
@ -33,6 +34,12 @@ void NitrousTestBase::armNitrousControl() {
EXPECT_TRUE(getModule<NitrousController>().isArmed);
}
void NitrousTestBase::satisfySpeedCondition() {
updateVehicleSpeed(TEST_MIN_VEHICLE_SPEED, &TestBase::periodicSlowCallback);
EXPECT_TRUE(getModule<NitrousController>().isNitrousSpeedConditionSatisfied);
}
void NitrousTestBase::satisfyTpsCondition() {
updateApp(TEST_MIN_TPS, &TestBase::periodicSlowCallback);
@ -65,6 +72,7 @@ void NitrousTestBase::satisfyRpmCondition() {
void NitrousTestBase::activateNitrousControl() {
armNitrousControl();
satisfySpeedCondition();
satisfyTpsCondition();
satisfyCltCondition();
satisfyMapCondition();
@ -79,6 +87,12 @@ void NitrousTestBase::unarmNitrousControl() {
EXPECT_FALSE(getModule<NitrousController>().isArmed);
}
void NitrousTestBase::unsatisfySpeedCondition() {
updateVehicleSpeed(TEST_MIN_VEHICLE_SPEED - EPS5D, &TestBase::periodicSlowCallback);
EXPECT_FALSE(getModule<NitrousController>().isNitrousSpeedConditionSatisfied);
}
void NitrousTestBase::unsatisfyTpsCondition() {
updateApp(TEST_MIN_TPS - EPS5D, &TestBase::periodicSlowCallback);
@ -111,6 +125,7 @@ void NitrousTestBase::unsatisfyRpmCondition() {
void NitrousTestBase::deactivateNitrousControl() {
unarmNitrousControl();
unsatisfySpeedCondition();
unsatisfyTpsCondition();
unsatisfyCltCondition();
unsatisfyMapCondition();

View File

@ -9,6 +9,7 @@
class NitrousTestBase : public TestBase {
protected:
static constexpr switch_input_pin_e TEST_NITROUS_CONTROL_ARMING_PIN = Gpio::A13;
static constexpr uint16_t TEST_MIN_VEHICLE_SPEED = 25;
static constexpr int TEST_MIN_TPS = 34;
static constexpr uint8_t TEST_MIN_CLT = 51;
static constexpr int TEST_MAX_MAP = 45;
@ -26,6 +27,7 @@ protected:
);
void armNitrousControl();
void satisfySpeedCondition();
void satisfyTpsCondition();
void satisfyCltCondition();
void satisfyMapCondition();
@ -35,6 +37,7 @@ protected:
void activateNitrousControl();
void unarmNitrousControl();
void unsatisfySpeedCondition();
void unsatisfyTpsCondition();
void unsatisfyCltCondition();
void unsatisfyMapCondition();

View File

@ -18,6 +18,7 @@ namespace {
setUpTestConfiguration();
EXPECT_FALSE(getModule<NitrousController>().isArmed);
EXPECT_FALSE(getModule<NitrousController>().isNitrousSpeedConditionSatisfied);
EXPECT_FALSE(getModule<NitrousController>().isTpsConditionSatisfied);
EXPECT_FALSE(getModule<NitrousController>().isCltConditionSatisfied);
EXPECT_FALSE(getModule<NitrousController>().isMapConditionSatisfied);
@ -29,20 +30,26 @@ namespace {
armNitrousControl();
checkNitrousCondition(false, "Armed condition is satisfied");
satisfySpeedCondition();
checkNitrousCondition(false, "Armed + Speed conditions are satisfied");
satisfyTpsCondition();
checkNitrousCondition(false, "Armed + TPS conditions are satisfied");
checkNitrousCondition(false, "Armed + Speed + TPS conditions are satisfied");
satisfyCltCondition();
checkNitrousCondition(false, "Armed + TPS + CLT conditions are satisfied");
checkNitrousCondition(false, "Armed + Speed + TPS + CLT conditions are satisfied");
satisfyMapCondition();
checkNitrousCondition(false, "Armed + TPS + CLT + MAP conditions are satisfied");
checkNitrousCondition(false, "Armed + Speed + TPS + CLT + MAP conditions are satisfied");
satisfyAfrCondition();
checkNitrousCondition(false, "Armed + TPS + CLT + MAP + AFR conditions are satisfied");
checkNitrousCondition(false, "Armed + Speed + TPS + CLT + MAP + AFR conditions are satisfied");
satisfyRpmCondition();
checkNitrousCondition(true, "Armed + TPS + CLT + MAP + AFR + RPM conditions are satisfied");
checkNitrousCondition(
true,
"Armed + Speed + TPS + CLT + MAP + AFR + RPM conditions are satisfied"
);
}
TEST_F(NitrousConditionTest, checkWithoutArmedNitrousControl) {
@ -50,6 +57,11 @@ namespace {
checkNitrousCondition(false, "Without armed condition");
}
TEST_F(NitrousConditionTest, checkWithoutSatisfiedSpeedCondition) {
unsatisfySpeedCondition();
checkNitrousCondition(false, "Without speed condition");
}
TEST_F(NitrousConditionTest, checkWithoutSatisfiedTpsCondition) {
unsatisfyTpsCondition();
checkNitrousCondition(false, "Without TPS condition");

View File

@ -0,0 +1,83 @@
//
// Created by kifir on 11/28/24.
//
#include "pch.h"
#include "engine_configuration_defaults.h"
#include "util/test_base.h"
namespace {
struct SpeedConditionTestData {
const std::optional<float> speed;
const bool expectedSpeedCondition;
const char* const context;
};
class NitrousSpeedConditionTest : public TestBase {
protected:
static constexpr uint16_t TEST_MIN_VEHICLE_SPEED = 33;
void checkSpeedCondition(const std::vector<SpeedConditionTestData>& testData);
};
void NitrousSpeedConditionTest::checkSpeedCondition(const std::vector<SpeedConditionTestData>& testData) {
for (const SpeedConditionTestData& item: testData) {
updateVehicleSpeed(item.speed, &TestBase::periodicSlowCallback);
EXPECT_EQ(getModule<NitrousController>().isNitrousSpeedConditionSatisfied, item.expectedSpeedCondition)
<< item.context;
}
}
TEST_F(NitrousSpeedConditionTest, checkDefault) {
checkSpeedCondition({
{ {}, false, "default" },
{ { 0.0f }, false, "0.0" },
{ { TEST_MIN_VEHICLE_SPEED - EPS5D }, false, "TEST_MIN_VEHICLE_SPEED - EPS5D" },
{ { TEST_MIN_VEHICLE_SPEED }, false, "TEST_MIN_VEHICLE_SPEED" },
{ { TEST_MIN_VEHICLE_SPEED + EPS5D }, false, "TEST_MIN_VEHICLE_SPEED + EPS5D" },
});
}
TEST_F(NitrousSpeedConditionTest, checkDefaultWithDisabledNitrousControl) {
setUpEngineConfiguration(EngineConfig().setNitrousControlEnabled({ false }));
checkSpeedCondition({
{ {}, false, "default" },
{ { 0.0f }, false, "0.0" },
{ { TEST_MIN_VEHICLE_SPEED - EPS5D }, false, "TEST_MIN_VEHICLE_SPEED - EPS5D" },
{ { TEST_MIN_VEHICLE_SPEED }, false, "TEST_MIN_VEHICLE_SPEED" },
{ { TEST_MIN_VEHICLE_SPEED + EPS5D }, false, "TEST_MIN_VEHICLE_SPEED + EPS5D" },
});
}
TEST_F(NitrousSpeedConditionTest, checkZeroMinimumSpeed) {
setUpEngineConfiguration(
EngineConfig()
.setNitrousControlEnabled({ true })
.setNitrousMinimumVehicleSpeed(0.0f)
);
checkSpeedCondition({
{ {}, true, "default" },
{ { 0.0f }, true, "0.0" },
{ { TEST_MIN_VEHICLE_SPEED - EPS5D }, true, "TEST_MIN_VEHICLE_SPEED - EPS5D" },
{ { TEST_MIN_VEHICLE_SPEED }, true, "TEST_MIN_VEHICLE_SPEED" },
{ { TEST_MIN_VEHICLE_SPEED + EPS5D }, true, "TEST_MIN_VEHICLE_SPEED + EPS5D" },
});
}
TEST_F(NitrousSpeedConditionTest, checkMinimumSpeed) {
setUpEngineConfiguration(
EngineConfig()
.setNitrousControlEnabled({ true })
.setNitrousMinimumVehicleSpeed({ TEST_MIN_VEHICLE_SPEED })
);
checkSpeedCondition({
{ {}, false, "default" },
{ { 0.0f }, false, "0.0" },
{ { TEST_MIN_VEHICLE_SPEED - EPS5D }, false, "TEST_MIN_VEHICLE_SPEED - EPS5D" },
{ { TEST_MIN_VEHICLE_SPEED }, true, "TEST_MIN_VEHICLE_SPEED" },
{ { TEST_MIN_VEHICLE_SPEED + EPS5D }, true, "TEST_MIN_VEHICLE_SPEED + EPS5D" },
});
}
}

View File

@ -73,6 +73,7 @@ TESTS_SRC_CPP = \
tests/shift_torque_reduction/test_shift_torque_reduction_angle_advance.cpp \
tests/nitrous_control/nitrous_test_base.cpp \
tests/nitrous_control/test_nitrous_arming.cpp \
tests/nitrous_control/test_nitrous_speed_condition.cpp \
tests/nitrous_control/test_nitrous_tps_condition.cpp \
tests/nitrous_control/test_nitrous_clt_condition.cpp \
tests/nitrous_control/test_nitrous_map_condition.cpp \

View File

@ -219,6 +219,11 @@ EngineConfig EngineConfig::setNitrousLuaGaugeArmingValue(const std::optional<flo
return *this;
}
EngineConfig EngineConfig::setNitrousMinimumVehicleSpeed(const std::optional<uint16_t> value) {
m_nitrousMinimumVehicleSpeed = value;
return *this;
}
EngineConfig EngineConfig::setNitrousMinimumTps(const std::optional<int> value) {
m_nitrousMinimumTps = value;
return *this;

View File

@ -69,6 +69,7 @@ public:
std::optional<lua_gauge_meaning_e> getNitrousLuaGaugeMeaning() const { return m_nitrousLuaGaugeMeaning; }
std::optional<float> getNitrousLuaGaugeArmingValue() const { return m_nitrousLuaGaugeArmingValue; }
std::optional<uint16_t> getNitrousMinimumVehicleSpeed() const { return m_nitrousMinimumVehicleSpeed; }
std::optional<int> getNitrousMinimumTps() const { return m_nitrousMinimumTps; }
std::optional<uint8_t> getNitrousMinimumClt() const { return m_nitrousMinimumClt; }
std::optional<uint16_t> getNitrousMaximumMap() const { return m_nitrousMaximumMap; }
@ -136,6 +137,7 @@ public:
EngineConfig setNitrousLuaGaugeMeaning(std::optional<lua_gauge_meaning_e> value);
EngineConfig setNitrousLuaGaugeArmingValue(std::optional<float> value);
EngineConfig setNitrousMinimumVehicleSpeed(std::optional<uint16_t> value);
EngineConfig setNitrousMinimumTps(std::optional<int> value);
EngineConfig setNitrousMinimumClt(std::optional<uint8_t> value);
EngineConfig setNitrousMaximumMap(std::optional<uint16_t> value);
@ -200,6 +202,7 @@ private:
std::optional<lua_gauge_meaning_e> m_nitrousLuaGaugeMeaning;
std::optional<float> m_nitrousLuaGaugeArmingValue;
std::optional<uint16_t> m_nitrousMinimumVehicleSpeed;
std::optional<int> m_nitrousMinimumTps;
std::optional<uint8_t> m_nitrousMinimumClt;
std::optional<uint16_t> m_nitrousMaximumMap;

View File

@ -87,6 +87,7 @@ void TestBase::setUpEngineConfiguration(const EngineConfig& config) {
getTestEngineConfiguration().configureNitrousLuaGaugeMeaning(config.getNitrousLuaGaugeMeaning());
getTestEngineConfiguration().configureNitrousLuaGaugeArmingValue(config.getNitrousLuaGaugeArmingValue());
getTestEngineConfiguration().configureNitrousMinimumVehicleSpeed(config.getNitrousMinimumVehicleSpeed());
getTestEngineConfiguration().configureNitrousMinimumTps(config.getNitrousMinimumTps());
getTestEngineConfiguration().configureNitrousMinimumClt(config.getNitrousMinimumClt());
getTestEngineConfiguration().configureNitrousMaximumMap(config.getNitrousMaximumMap());
@ -111,6 +112,10 @@ void TestBase::periodicSlowCallback() {
engine->periodicSlowCallback();
}
void TestBase::updateVehicleSpeed(const std::optional<float> speed, void (TestBase::* const postAction)()) {
updateSensor(SensorType::VehicleSpeed, speed, postAction);
}
void TestBase::updateRpm(const std::optional<float> rpm, void (TestBase::* const postAction)()) {
updateSensor(SensorType::Rpm, rpm, postAction);
}

View File

@ -23,6 +23,10 @@ protected:
public:
void periodicSlowCallback();
protected:
void updateVehicleSpeed(
std::optional<float> speed,
void (TestBase::*postAction)() = &TestBase::periodicFastCallback
);
void updateRpm(std::optional<float> rpm, void (TestBase::*postAction)() = &TestBase::periodicFastCallback);
void updateApp(std::optional<float> app, void (TestBase::*postAction)() = &TestBase::periodicFastCallback);
void updateClt(std::optional<float> clt, void (TestBase::*postAction)() = &TestBase::periodicFastCallback);

View File

@ -477,6 +477,19 @@ void TestEngineConfiguration::configureNitrousLuaGaugeArmingValue(const std::opt
}
}
void TestEngineConfiguration::configureNitrousMinimumVehicleSpeed(
const std::optional<uint16_t> nitrousMinimumVehicleSpeed
) {
if (nitrousMinimumVehicleSpeed.has_value()) {
engineConfiguration->nitrousMinimumVehicleSpeed = nitrousMinimumVehicleSpeed.value();
} else {
ASSERT_EQ(
engineConfiguration->nitrousMinimumVehicleSpeed,
engine_configuration_defaults::NITROUS_MINIMUM_VEHICLE_SPEED
); // check default value
}
}
void TestEngineConfiguration::configureNitrousMinimumTps(const std::optional<int> nitrousMinimumTps) {
if (nitrousMinimumTps.has_value()) {
engineConfiguration->nitrousMinimumTps = nitrousMinimumTps.value();

View File

@ -72,6 +72,7 @@ public:
void configureNitrousLuaGaugeMeaning(std::optional<lua_gauge_meaning_e> luaGaugeMeaning);
void configureNitrousLuaGaugeArmingValue(std::optional<float> luaGaugeArmingValue);
void configureNitrousMinimumVehicleSpeed(std::optional<uint16_t> nitrousMinimumVehicleSpeed);
void configureNitrousMinimumTps(std::optional<int> nitrousMinimumTps);
void configureNitrousMinimumClt(std::optional<uint8_t> nitrousMinimumClt);
void configureNitrousMaximumMap(std::optional<uint16_t> nitrousMaximumMap);