Toyota ETCS-i [02/02]: RedundantSensor: partial second (avoid average, etc.) (#431)

This commit is contained in:
Nathan Schulte 2024-07-16 04:08:43 -05:00 committed by GitHub
parent d37a5c1405
commit 50f7a653a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 76 deletions

View File

@ -48,27 +48,28 @@ SensorResult RedundantSensor::get() const {
} else {
// Sensor is partially redundant; useful for some sensors: e.g. Ford and Toyota ETCS-i
// The threshold at which to switch to partial redundancy, just below maximum to avoid misbehavior near 100%
// The partial redundancy threshold, slightly less than 100% to avoid issues near full-range
float threshold = m_secondMaximum * 0.95f;
// The scaled second sensor, proportioning it to the first sensor
// Scale the second sensor value accordingly, proportioning to the first sensor
float scaledSecond = sensor2.Value * m_secondMaximum / 100;
// Check second sensor is below partial redundancy switch-over threshold
if (scaledSecond <= threshold) {
float delta = absF(sensor1.Value - scaledSecond);
if (delta <= m_maxDifference) {
// All is well: sensors are valid and values check out, return the average value
return (sensor1.Value + scaledSecond) / 2;
// All is well: sensors are valid and values check out, return the primary value
return sensor1.Value;
}
} else {
// Check first sensor is at or above partial redundancy switch-over threshold
if (sensor1.Value >= m_secondMaximum - m_maxDifference) {
// All is well: sensors are valid and values check out, return the primary value
return sensor1.Value;
}
}
}
// Fall-through and any other condition indicates an unexpected discrepancy, return inconsistency error
// Any other condition indicates an unexpected discrepancy, return inconsistency error
return UnexpectedCode::Inconsistent;
}

View File

@ -10,7 +10,7 @@ public:
SensorType secondSensor
);
void configure(float maxDifference, bool ignoreSecondSensor, float secondaryMaximum);
void configure(float maxDifference, bool ignoreSecondSensor, float secondaryMaximum = 100);
SensorResult get() const override;

View File

@ -401,7 +401,7 @@ injector_s injector
injector_s injectorSecondary
bit isForcedInduction;Does the vehicle have a turbo or supercharger?
bit useFordRedundantTps;On some Ford and Toyota vehicles one of the throttle sensors is not linear on the full range, i.e. in the specific range of the positions we effectively have only one sensor.
bit unusedFordTps
bit lambdaProtectionEnable
bit overrideTriggerGaps
bit enableFan1WithAc;Turn on this fan when AC is on.
@ -423,7 +423,7 @@ bit useTLE8888_stepper
bit usescriptTableForCanSniffingFiltering
bit verboseCan,"Print all","Do not print";Print incoming and outgoing first bus CAN messages in FOME console
bit artificialTestMisfire,"Danger Mode","No thank you";Experimental setting that will cause a misfire\nDO NOT ENABLE.
bit useFordRedundantPps;On some Ford and Toyota vehicles one of the pedal sensors is not linear on the full range, i.e. in the specific range of the positions we effectively have only one sensor.
bit unusedFordPps
bit cltSensorPulldown
bit iatSensorPulldown
bit allowIdenticalPps
@ -1413,8 +1413,8 @@ uint8_t alsEtbPosition;;"", 1, 0, 0, 20000, 0
uint8_t ALSMaxDriverThrottleIntent;;"%", 1, 0, 0, 10, 0
pin_input_mode_e ALSActivatePinMode;
uint8_t autoscale tpsSecondaryMaximum;For Ford TPS, use 53%. For Toyota ETCS-i, use ~65%;"%", 0.5, 0, 0, 100, 1
uint8_t autoscale ppsSecondaryMaximum;For Toyota ETCS-i, use ~69%;"%", 0.5, 0, 0, 100, 1
uint8_t autoscale tpsSecondaryMaximum;For Ford TPS, use 53%. For Toyota ETCS-i, use ~65%. 0 and 100 disable, <20 invalid, rest will avoid sensor averaging.;"%", 0.5, 0, 0, 100, 1
uint8_t autoscale ppsSecondaryMaximum;For Toyota ETCS-i, use ~69%. 0 and 100 disable, <20 invalid, rest will avoid sensor averaging.;"%", 0.5, 0, 0, 100, 1
pin_input_mode_e[LUA_DIGITAL_INPUT_COUNT iterate] luaDigitalInputPinModes;
uint8_t autoscale rpmHardLimitHyst;If the hard limit is 7200rpm and hysteresis is 200rpm, then when the ECU sees 7200rpm, fuel/ign will cut, and stay cut until 7000rpm (7200-200) is reached;"RPM", 10, 0, 0, 2500, 0

View File

@ -4461,21 +4461,22 @@ dialog = tcuControls, "Transmission Settings"
field = "Disable after revolutions", acrRevolutions
field = "Disable after engine phase", acrDisablePhase
dialog = parkingLotRedundantSensors, "Sensor Redundancy"
field = "Partial Secondary TPS Maximum", tpsSecondaryMaximum
field = "Partial Secondary PPS Maximum", ppsSecondaryMaximum
field = "BRZ/FRS/GT86 pedal", allowIdenticalPps
dialog = parkingLot, "Experimental/Broken"
field = "I understand ECU Locking", yesUnderstandLocking
field = "Tune read/write password", tuneHidingKey, { yesUnderstandLocking == 1 }
field = "#System hacks"
field = "Global fuel correction", globalFuelCorrection
field = "MAP Averaging Logic @", mapAveragingSchedulingAtIndex
field = "Ford redundant TPS mode", useFordRedundantTps
field = "Secondary TPS maximum", tpsSecondaryMaximum, {useFordRedundantTps}
field = "Ford redundant PPS mode", useFordRedundantPps
field = "Secondary PPS maximum", ppsSecondaryMaximum, {useFordRedundantPps}
field = "ADC vRef voltage", adcVcc
field = "CLT sensor is pulldown instead of pullup", cltSensorPulldown
field = "IAT sensor is pulldown instead of pullup", iatSensorPulldown
field = "Analog divider ratio", analogInputDividerCoefficient@@if_ts_show_analog_divider
field = "BRZ/FRS/GT86 pedal", allowIdenticalPps
panel = parkingLotRedundantSensors
field = "Artificial Misfire", artificialTestMisfire
field = "Instant Rpm Range", instantRpmRange
field = "Always use instant RPM", alwaysInstantRpm

View File

@ -24,7 +24,7 @@ protected:
ASSERT_TRUE(m1.Register());
ASSERT_TRUE(m2.Register());
dut.configure(5.0f, false, 100);
dut.configure(5.0f, false);
}
void TearDown() override
@ -58,23 +58,11 @@ TEST_F(SensorRedundant, SetOnlyOneSensor)
auto result = dut.get();
EXPECT_FALSE(result.Valid);
}
}
TEST_F(SensorRedundant, SetTwoSensors)
{
// Don't set any sensors - expect invalid
{
auto result = dut.get();
EXPECT_FALSE(result.Valid);
EXPECT_EQ(result.Code, UnexpectedCode::Inconsistent);
}
// Set one sensor
m1.set(24.0f);
// Set the other sensor
m2.set(26.0f);
// Should now be valid - and the average of the two input
// Should now be valid - and the average of both sensors
{
auto result = dut.get();
EXPECT_TRUE(result.Valid);
@ -82,6 +70,18 @@ TEST_F(SensorRedundant, SetTwoSensors)
}
}
TEST_F(SensorRedundant, CheckOnlySecondInvalid)
{
// Set second sensor only
m2.set(66.0f);
// Should be invalid - only one is set!
{
auto result = dut.get();
EXPECT_FALSE(result.Valid);
}
}
TEST_F(SensorRedundant, DifferenceNone)
{
// Set both sensors to the same value
@ -136,7 +136,6 @@ TEST_F(SensorRedundant, DifferenceOverLimitSwapped)
}
}
class SensorRedundantIgnoreSecond : public ::testing::Test
{
protected:
@ -159,7 +158,7 @@ protected:
ASSERT_TRUE(m1.Register());
ASSERT_TRUE(m2.Register());
dut.configure(5.0f, true, 100);
dut.configure(5.0f, true);
}
void TearDown() override
@ -175,6 +174,7 @@ TEST_F(SensorRedundantIgnoreSecond, CheckIsRedundant)
EXPECT_FALSE(dut.isRedundant());
}
}
TEST_F(SensorRedundantIgnoreSecond, OnlyFirst)
{
// Don't set any sensors - expect invalid
@ -184,7 +184,7 @@ TEST_F(SensorRedundantIgnoreSecond, OnlyFirst)
EXPECT_EQ(result.Code, UnexpectedCode::Unknown);
}
// Set one sensor
// Set first sensor
m1.set(44.0f);
// Should be valid - we don't care about second sensor
@ -193,17 +193,20 @@ TEST_F(SensorRedundantIgnoreSecond, OnlyFirst)
EXPECT_TRUE(result.Valid);
EXPECT_FLOAT_EQ(result.Value, 44.0f);
}
}
TEST_F(SensorRedundantIgnoreSecond, OnlySecond)
{
// Don't set any sensors - expect invalid
// Set the second sensor too
m2.set(46.0f);
// Should be valid, but only get the value from m1
{
auto result = dut.get();
EXPECT_FALSE(result.Valid);
EXPECT_EQ(result.Code, UnexpectedCode::Unknown);
EXPECT_TRUE(result.Valid);
EXPECT_FLOAT_EQ(result.Value, 44.0f);
}
}
TEST_F(SensorRedundantIgnoreSecond, CheckOnlySecondInvalid)
{
// Set second sensor only
m2.set(66.0f);
@ -214,27 +217,6 @@ TEST_F(SensorRedundantIgnoreSecond, OnlySecond)
}
}
TEST_F(SensorRedundantIgnoreSecond, SetBothIgnoreSecond)
{
// Don't set any sensors - expect invalid
{
auto result = dut.get();
EXPECT_FALSE(result.Valid);
EXPECT_EQ(result.Code, UnexpectedCode::Unknown);
}
// Set both sensors
m1.set(74.0f);
m2.set(76.0f);
// Should be valid, but only get the value from m1
{
auto result = dut.get();
EXPECT_TRUE(result.Valid);
EXPECT_FLOAT_EQ(result.Value, 74.0f);
}
}
class SensorRedundantPartialSecond : public ::testing::Test
{
protected:
@ -273,7 +255,7 @@ TEST_F(SensorRedundantPartialSecond, CheckIsRedundant)
}
}
TEST_F(SensorRedundantPartialSecond, SetOnlyOneSensor)
TEST_F(SensorRedundantPartialSecond, SetNone)
{
// Don't set any sensors - expect invalid
{
@ -281,7 +263,10 @@ TEST_F(SensorRedundantPartialSecond, SetOnlyOneSensor)
EXPECT_FALSE(result.Valid);
EXPECT_EQ(result.Code, UnexpectedCode::Inconsistent);
}
}
TEST_F(SensorRedundantPartialSecond, SetOnlyOneSensor)
{
// Set first sensor
m1.set(24.0f);
@ -294,23 +279,28 @@ TEST_F(SensorRedundantPartialSecond, SetOnlyOneSensor)
TEST_F(SensorRedundantPartialSecond, SetTwoSensors)
{
// Don't set any sensors - expect invalid
{
auto result = dut.get();
EXPECT_FALSE(result.Valid);
EXPECT_EQ(result.Code, UnexpectedCode::Inconsistent);
}
// Set first sensor
m1.set(12.0f);
// Set second sensor at double the first
m2.set(28.0f);
m1.set(0.0f);
// Set second sensor
m2.set(0.0f);
// Should now be valid - and the average of the two input
// Should now be valid, and output the primary
{
auto result = dut.get();
EXPECT_TRUE(result.Valid);
EXPECT_FLOAT_EQ(result.Value, 13.0f);
EXPECT_FLOAT_EQ(result.Value, 0.0f);
}
}
TEST_F(SensorRedundantPartialSecond, CheckOnlySecondInvalid)
{
// Set second sensor only
m2.set(66.0f);
// Should be invalid - only one is set!
{
auto result = dut.get();
EXPECT_FALSE(result.Valid);
}
}
@ -320,7 +310,7 @@ TEST_F(SensorRedundantPartialSecond, DifferenceNone)
m1.set(10);
m2.set(20);
// Expect valid, and 10 output
// Expect valid, and output the primary
{
auto result = dut.get();
EXPECT_TRUE(result.Valid);
@ -334,11 +324,11 @@ TEST_F(SensorRedundantPartialSecond, DifferenceNearLimit)
m1.set(7.501f);
m2.set(2 * 12.499f);
// Expect valid, and 10 output
// Expect valid, and output the primary
{
auto result = dut.get();
EXPECT_TRUE(result.Valid);
EXPECT_FLOAT_EQ(result.Value, 10.0f);
EXPECT_FLOAT_EQ(result.Value, 7.501f);
}
}
@ -374,7 +364,7 @@ TEST_F(SensorRedundantPartialSecond, PartialRedundancyRange)
m1.set(75);
m2.set(100);
// expect valid, at 75%
// Expect valid, and output the first
{
auto result = dut.get();
EXPECT_TRUE(result.Valid);