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:
parent
08d85b5dfd
commit
d5363b814a
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue