better VSS configuration (#3542)

* vss uses real values

* some defaults

* test and correct math

* km, not miles!

* comment

* tooltip

* that macro went away

* 100hz and default settings gives 9kph

* changelog

* order of operations safety

* make the test like the pwm test

* housekeeping

* this is why we need sensor automation

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2021-11-27 05:49:07 -08:00 committed by GitHub
parent 08d85b5dfd
commit d5363b814a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 91 additions and 93 deletions

View File

@ -27,6 +27,9 @@ All notable user-facing or behavior-altering changes will be documented in this
## Month 202x Release - "Release Name"
## Added
- Improved vehicle speed sensor configuration: now uses real physical constants about tires, gear ratio, sensor, etc.
### Fixed
- Faster engine sync + startup on engines with crank-speed primary trigger

View File

@ -687,12 +687,12 @@ void setMiataNB2_Proteus_TCU() {
// "VR 1"
engineConfiguration->triggerInputPins[0] = GPIOE_7;
engineConfiguration->vehicleSpeedCoef = 1;
// "VR 2"
engineConfiguration->vehicleSpeedSensorInputPin = GPIOE_8;
engineConfiguration->driveWheelRevPerKm = 544; // 205/50R15
engineConfiguration->vssGearRatio = 4.3;
engineConfiguration->vssToothCount = 22;
// "Highside 2"
engineConfiguration->tcu_solenoid[0] = GPIOA_8;

View File

@ -697,8 +697,9 @@ static void setDefaultEngineConfiguration() {
engineConfiguration->isAlternatorControlEnabled = false;
engineConfiguration->vehicleSpeedCoef = 1.0f;
engineConfiguration->driveWheelRevPerKm = 500;
engineConfiguration->vssGearRatio = 3.73;
engineConfiguration->vssToothCount = 21;
engineConfiguration->mapErrorDetectionTooLow = 5;
engineConfiguration->mapErrorDetectionTooHigh = 250;

View File

@ -4,7 +4,20 @@
class VehicleSpeedConverter : public SensorConverter {
public:
SensorResult convert(float frequency) const override {
auto speed = frequency * engineConfiguration->vehicleSpeedCoef;
return speed;
auto vssRevPerKm = engineConfiguration->driveWheelRevPerKm * engineConfiguration->vssGearRatio;
auto pulsePerKm = (vssRevPerKm * engineConfiguration->vssToothCount);
if (pulsePerKm == 0) {
// avoid div by 0
return 0;
}
auto kmPerPulse = 1 / pulsePerKm;
// 1 pulse 3600 sec 1 km km
// --------- * ---------- * --------- = ----
// sec 1 hr 1 pulse hr
return frequency * 3600 * kmPerPulse;
}
};

View File

@ -1143,11 +1143,8 @@ static void setValue(const char *paramStr, const char *valueStr) {
currentI++;
}
if (strEqualCaseInsensitive(paramStr, "vsscoeff")) {
engineConfiguration->vehicleSpeedCoef = valueF;
#if EFI_ALTERNATOR_CONTROL
} else if (strEqualCaseInsensitive(paramStr, "alt_t")) {
if (strEqualCaseInsensitive(paramStr, "alt_t")) {
if (valueI > 10) {
engineConfiguration->alternatorControl.periodMs = valueI;
}
@ -1156,14 +1153,9 @@ static void setValue(const char *paramStr, const char *valueStr) {
engineConfiguration->alternatorControl.offset = valueI;
} else if (strEqualCaseInsensitive(paramStr, "alt_p")) {
setAltPFactor(valueF);
} else
#endif /* EFI_ALTERNATOR_CONTROL */
// } else if (strEqualCaseInsensitive(paramStr, "cranking_rpm")) {
// } else if (strEqualCaseInsensitive(paramStr, "cranking_rpm")) {
// } else if (strEqualCaseInsensitive(paramStr, "cranking_rpm")) {
// } else if (strEqualCaseInsensitive(paramStr, "cranking_rpm")) {
// } else if (strEqualCaseInsensitive(paramStr, "cranking_rpm")) {
// } else if (strEqualCaseInsensitive(paramStr, "cranking_rpm")) {
} else if (strEqualCaseInsensitive(paramStr, "warning_period")) {
if (strEqualCaseInsensitive(paramStr, "warning_period")) {
engineConfiguration->warningPeriod = valueI;
} else if (strEqualCaseInsensitive(paramStr, "dwell")) {
setConstantDwell(valueF);

View File

@ -68,12 +68,13 @@ void efiExtiEnablePin(const char *msg, brain_pin_e brainPin, uint32_t mode, Exti
return;
}
ioline_t line = PAL_LINE(port, index);
palEnableLineEvent(line, mode);
channel.Name = msg;
channel.Callback = cb;
channel.CallbackData = cb_data;
channel.Timestamp = 0;
ioline_t line = PAL_LINE(port, index);
palEnableLineEvent(line, mode);
}
void efiExtiDisablePin(brain_pin_e brainPin)
@ -101,6 +102,7 @@ void efiExtiDisablePin(brain_pin_e brainPin)
palDisableLineEvent(line);
/* mark unused */
channel.Timestamp = 0;
channel.Name = nullptr;
channel.Callback = nullptr;
channel.CallbackData = nullptr;

View File

@ -534,8 +534,7 @@ float vbattDividerCoeff;+This is the ratio of the resistors for the battery volt
float fanOnTemperature;+Cooling fan turn-on temperature threshold, in Celsius;"deg C", 1, 0, 0, 150, 0
float fanOffTemperature;+Cooling fan turn-off temperature threshold, in Celsius;"deg C", 1, 0, 0, 150, 0
float vehicleSpeedCoef;+This coefficient translates vehicle speed input frequency (in Hz) into vehicle speed, km/h;"coef", 1, 0, 0.01, 2000, 2
float driveWheelRevPerKm;Number of revolutions per kilometer for the wheels your vehicle speed sensor is connected to. Use an online calculator to determine this based on your tire size.;"revs/km", 1, 0, 100, 1000, 1
custom can_nbc_e 4 bits, U32, @OFFSET@, [0:4], "None", "FIAT", "VAG", "MAZDA RX8", "BMW", "W202", "BMW E90", "Haltech", "VAG MQB", "Nissan VQ35", "Genesis Coupe", "Honda K", "type 12", "type 13", "type 14", "INVALID"
can_nbc_e canNbcType;set can_mode X
@ -638,8 +637,11 @@ uint8_t knockRetardAggression;+Ignition timing to remove when a knock event occu
uint8_t knockRetardReapplyRate;+After a knock event, reapply timing at this rate.;"deg/s", 0.1, 0, 0, 10, 1
uint8_t knockRetardMaximum;+Maximum amount of knock retard.;"deg", 1, 0, 0, 30, 0
uint8_t mapCamDetectionThreshold;;"", 1, 0, 0, 240, 0
float unused616;;"", 1, 0, 0, 1, 0
uint8_t mapCamDetectionThreshold;;"", 1, 0, 0, 240, 0
uint16_t autoscale vssGearRatio;Number of turns of your vehicle speed sensor per turn of the wheels. For example if your sensor is on the transmission output, enter your axle/differential ratio. If you are using a hub-mounted sensor, enter a value of 1.0.; "ratio", 0.001, 0, 0, 60, 3
uint8_t vssToothCount;Number of pulses output per revolution of the shaft where your VSS is mounted. For example, GM applications of the T56 output 17 pulses per revolution of the transmission output shaft.;"count", 1, 0, 1, 100, 0
uint8_t unusedNearVss;;"", 1, 0, 0, 1, 0
! todo: rename to triggerSimulatorRpm
int triggerSimulatorFrequency;+Same RPM is used for two ways of producing simulated RPM. See also triggerSimulatorPins (with wires)\nSee also directSelfStimulation (no wires, bypassing input hardware)\nrpm X\nTODO: rename to triggerSimulatorRpm;"Rpm", 1, 0, 0, 30000, 0

View File

@ -3166,7 +3166,9 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
dialog = speedSensorAnalog
field = "Input pin", vehicleSpeedSensorInputPin
field = "revolution to speed mult", vehicleSpeedCoef
field = "Wheel revolutions per kilometer", driveWheelRevPerKm
field = "Speed sensor gear ratio", vssGearRatio
field = "Speed sensor tooth count", vssToothCount
dialog = speedSensorCan
field = "Vss Car Type", canVssNbcType, { enableCanVss }

View File

@ -29,24 +29,27 @@ public class VssHardwareLoopTest extends RusefiTestBase {
@Test
public void test() {
ecu.setEngineType(engine_type_e.FRANKENSO_MIATA_NA6_MAP);
ecu.sendCommand(getEnableCommand(Fields.CMD_EXTERNAL_STIMULATION));
ecu.changeRpm(1400);
ecu.changeRpm(1000);
// moving second trigger to another pin
ecu.sendCommand(CMD_TRIGGER_PIN + " 1 PA8");
ecu.sendCommand(CMD_TRIGGER_SIMULATOR_PIN + " 0 none");
ecu.sendCommand(CMD_TRIGGER_SIMULATOR_PIN + " 1 none");
ecu.sendCommand(CMD_TRIGGER_PIN + " 1 none");
// Hook up 1khz idle on formerly-trigger-stim pin
ecu.sendCommand(CMD_IDLE_PIN + " PD2");
ecu.sendCommand("set idle_solenoid_freq 1000");
EcuTestHelper.assertSomewhatClose("VSS no input", 0, SensorCentral.getInstance().getValue(Sensor.VSS));
// attaching VSS to trigger simulator since there is a jumper on test discovery
// attaching VSS to idle output since there is a jumper on test discovery
ecu.sendCommand("set " + CMD_VSS_PIN + " pa5");
sleep(2 * Timeouts.SECOND);
EcuTestHelper.assertSomewhatClose("VSS with input", 3, SensorCentral.getInstance().getValue(Sensor.VSS));
EcuTestHelper.assertSomewhatClose("VSS with input", 92, SensorCentral.getInstance().getValue(Sensor.VSS));
// not related to VSS test, just need to validate this somewhere, so this random test is as good as any
if (ControllerConnectorState.firmwareVersion == null)
throw new IllegalStateException("firmwareVersion has not arrived");
}
}

View File

@ -27,7 +27,7 @@ public enum Sensor {
// RPM, vss
RPM(GAUGE_NAME_RPM, SensorCategory.SENSOR_INPUTS, FieldType.UINT16, 4, 1, 0, 8000, "RPM"),
SPEED2RPM("SpeedToRpm", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 6, 1.0 / PACK_MULT_PERCENT, 0, 5, "RPM/kph"),
VSS(GAUGE_NAME_VVS, SensorCategory.OPERATIONS, FieldType.UINT8, 8, 1, 0, 150, "kph"),
VSS(GAUGE_NAME_VVS, SensorCategory.OPERATIONS, FieldType.UINT8, 10, 1, 0, 150, "kph"),
// Temperatures
INT_TEMP(GAUGE_NAME_CPU_TEMP, SensorCategory.OPERATIONS, FieldType.INT8, 11, 1, 0, 5, "C"),

View File

@ -1,73 +1,53 @@
#include "pch.h"
#include "vehicle_speed_converter.h"
static constexpr engine_type_e ENGINE_TEST_HELPER = TEST_ENGINE;
#define EXPECT_NEAR_M3(x, y) EXPECT_NEAR((x), (y), 1e-3)
class VehicleSpeedConverterTest : public ::testing::Test {
float GetVssFor(float revPerKm, float axle, float teeth, float hz) {
EngineTestHelper eth(TEST_ENGINE);
public:
EngineTestHelper eth;
VehicleSpeedConverter dut;
VehicleSpeedConverterTest() : eth(ENGINE_TEST_HELPER) {
}
engineConfiguration->driveWheelRevPerKm = revPerKm;
engineConfiguration->vssGearRatio = axle;
engineConfiguration->vssToothCount = teeth;
void SetUp() override {
}
void SetCoef(float new_coef) {
engineConfiguration->vehicleSpeedCoef = new_coef;
}
float GetFrequencyBySpeedAndCoef(float speed, float coef) {
return (speed / coef);
}
void TestForSpeedWithCoef(float expectedSpeed, float coef)
{
SetCoef(coef);
auto inputFreq = GetFrequencyBySpeedAndCoef(expectedSpeed, coef);
auto result = dut.convert(inputFreq);
ASSERT_TRUE(result.Valid);
ASSERT_NEAR(expectedSpeed, result.Value, 0.01f);
}
};
/*
* Converter must return valid and expected result for setted coef
*/
TEST_F(VehicleSpeedConverterTest, returnExpectedResultForSettedCoef) {
TestForSpeedWithCoef(0.0f, 0.5f);
TestForSpeedWithCoef(0.5f, 0.5f);
TestForSpeedWithCoef(10.0f, 0.5f);
TestForSpeedWithCoef(0.0f, 10.0f);
TestForSpeedWithCoef(0.5f, 10.0f);
TestForSpeedWithCoef(10.0f, 10.0f);
return dut.convert(hz).value_or(-1);
}
/*
* Converter must always return strong float zero if coef == 0.0f
*/
TEST_F(VehicleSpeedConverterTest, zeroCoefReturnsZeroSpeedOnAnyInput) {
SetCoef(0.0f);
TEST(VehicleSpeed, FakeCases) {
// 0hz -> 0kph
EXPECT_NEAR_M3(0, GetVssFor(500, 5, 10, 0));
{
auto result = dut.convert(0.0f);
ASSERT_TRUE(result.Valid);
ASSERT_FLOAT_EQ(0.0f, result.Value);
}
// 1000hz -> 144 kph
EXPECT_NEAR_M3(144, GetVssFor(500, 5, 10, 1000));
{
auto result = dut.convert(0.5f);
ASSERT_TRUE(result.Valid);
ASSERT_FLOAT_EQ(0.0f, result.Value);
}
// Half size tires -> half speed
EXPECT_NEAR_M3(72, GetVssFor(1000, 5, 10, 1000));
{
auto result = dut.convert(10.0f);
ASSERT_TRUE(result.Valid);
ASSERT_FLOAT_EQ(0.0f, result.Value);
}
// Double the axle ratio -> half the speed
EXPECT_NEAR_M3(72, GetVssFor(500, 10, 10, 1000));
// Twice as many teeth -> half speed
EXPECT_NEAR_M3(72, GetVssFor(500, 5, 20, 1000));
}
TEST(VehicleSpeed, RealCases) {
// V8 Volvo
// 205/50R16 tire -> 521 rev/km
// 3.73 axle ratio
// 17 tooth speedo gear
EXPECT_NEAR_M3(108.970f, GetVssFor(521, 3.73, 17, 1000));
// NB miata
// 205/50R15 tire -> 544 rev/km
// 4.3 axle ratio
// 21 tooth speedo gear
EXPECT_NEAR_M3(73.285f, GetVssFor(544, 4.3, 21, 1000));
// Some truck with ABS sensors
// 265/65R18 tire -> 391 rev/km
// 1.0 ratio because ABS sensors are hub mounted
// 48 tooth abs sensor
EXPECT_NEAR_M3(191.816f, GetVssFor(391, 1, 48, 1000));
}