Selectable VE axis override (#1769)

* add config fields

* config options

* new output channels

* dump out state to ts

* s

* implement override

* enums

* this test is no longer used

* test new behavior

* old

* comments
This commit is contained in:
Matthew Kennedy 2020-09-07 07:15:42 -07:00 committed by GitHub
parent 141cad585c
commit ef0b2f7be0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 99 additions and 45 deletions

View File

@ -158,8 +158,11 @@ typedef struct {
scaled_percent fuelTankLevel; // 98
float fuelConsumptionPerHour; // 100
// Y axis values for selectable tables
scaled_channel<uint16_t, 100> veTableYAxis; // 104
scaled_channel<uint16_t, 100> afrTableYAxis; // 106
// Knock
uint32_t knockCount; // 104
float knockLevel; // 108
// Mode, firmware, protocol, run time

View File

@ -532,6 +532,8 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
tsOutputChannels->fuelingLoad = getFuelingLoad(PASS_ENGINE_PARAMETER_SIGNATURE);
tsOutputChannels->ignitionLoad = getIgnitionLoad(PASS_ENGINE_PARAMETER_SIGNATURE);
tsOutputChannels->veTableYAxis = ENGINE(engineState.currentVeLoad);
tsOutputChannels->afrTableYAxis = ENGINE(engineState.currentAfrLoad);
// KLUDGE? we always show VBatt because Proteus board has VBatt input sensor hardcoded
// offset 28

View File

@ -1,14 +1,26 @@
#include "airmass.h"
#include "sensor.h"
#include "map.h"
EXTERN_ENGINE;
AirmassModelBase::AirmassModelBase(const ValueProvider3D& veTable) : m_veTable(&veTable) {}
float AirmassModelBase::getVeLoadAxis(float passedLoad) const {
switch(CONFIG(veOverrideMode)) {
case VE_None: return passedLoad;
case VE_MAP: return getMap(PASS_ENGINE_PARAMETER_SIGNATURE);
case VE_TPS: return Sensor::get(SensorType::Tps1).value_or(0);
default: return 0;
}
}
float AirmassModelBase::getVe(int rpm, float load) const {
efiAssert(OBD_PCM_Processor_Fault, m_veTable != nullptr, "VE table null", 0);
// TODO: allow override of the Y axis value based on a config field
// Override the load value if necessary
load = getVeLoadAxis(load);
float ve = m_veTable->getValue(rpm, load);
auto tps = Sensor::get(SensorType::Tps1);
@ -20,5 +32,6 @@ float AirmassModelBase::getVe(int rpm, float load) const {
}
ENGINE(engineState.currentVe) = ve;
ENGINE(engineState.currentVeLoad) = load;
return ve * 0.01f;
}

View File

@ -21,4 +21,6 @@ protected:
private:
const ValueProvider3D* const m_veTable;
float getVeLoadAxis(float passedLoad) const;
};

View File

@ -60,6 +60,8 @@ public:
efitick_t timeSinceLastTChargeK;
float currentVe = 0;
float currentVeLoad = 0;
float currentAfrLoad = 0;
int vssEventCounter = 0;

View File

@ -7,6 +7,8 @@ mass_t FuelComputerBase::getCycleFuel(mass_t airmass, int rpm, float load) const
float lambda = getTargetLambda(rpm, load);
float afr = stoich * lambda;
// TODO: override target AFR load axis value
ENGINE(engineState.currentAfrLoad) = load;
ENGINE(engineState.targetAFR) = afr;
return airmass / afr;

View File

@ -983,3 +983,17 @@ typedef enum __attribute__ ((__packed__)) {
GPPWM_GreaterThan = 0,
GPPWM_LessThan = 1,
} gppwm_compare_mode_e;
typedef enum __attribute__ ((__packed__)) {
VE_None = 0,
VE_MAP = 1,
VE_TPS = 2,
} ve_override_e;
typedef enum __attribute__ ((__packed__)) {
AFR_None = 0,
AFR_MAP = 1,
AFR_Tps = 2,
AFR_AccPedal = 3,
AFR_CylFilling = 4,
} afr_override_e;

View File

@ -761,7 +761,7 @@ bit is_enabled_spi_2
bit useIacTableForCoasting;+This setting allows the ECU to open the IAC during overrun conditions to help reduce engine breaking, this can be helpful for large engines in light weight cars. Used in Auto-PID Idle mode.
bit useNoiselessTriggerDecoder
bit useIdleTimingPidControl
bit useTPSBasedVeTable
bit unused744b25
bit is_enabled_spi_4
bit pauseEtbControl;+Disable the electronic throttle motor and DC idle motor for testing.\nThis mode is for testing ETB/DC idle position sensors, etc without actually driving the throttle.
bit alignEngineSnifferAtTDC
@ -1155,9 +1155,16 @@ int16_t tps2Max;Full throttle#2. tpsMax value as 10 bit ADC value. Not Voltage!\
#define can_baudrate_e_enum "100kbps", "250kbps" , "500kbps", "1Mbps"
custom can_baudrate_e 1 bits, U08, @OFFSET@, [0:1], @@can_baudrate_e_enum@@
can_baudrate_e canBaudRate; set can_baudrate
uint8_t un1used_former_warmup_target_afr;;"units", 1, 0, -20, 100, 0
#define ve_override_e_enum "None", "MAP", "TPS"
custom ve_override_e 1 bits, U08, @OFFSET@, [0:1] @@ve_override_e_enum@@
ve_override_e veOverrideMode;+Override the Y axis (load) value used for the VE table.\nAdvanced users only: If you aren't sure you need this, you probably don't need this.
can_baudrate_e can2BaudRate;
uint8_t unused_former_warmup_target_afr2;;"units", 1, 0, -20, 100, 0
#define afr_override_e_enum "None", "MAP", "TPS", "Acc Pedal", "Cyl Filling %"
custom afr_override_e 1 bits, U08, @OFFSET@, [0:2], @@afr_override_e_enum@@
afr_override_e afrOverrideMode;+Override the Y axis (load) value used for the AFR table.\nAdvanced users only: If you aren't sure you need this, you probably don't need this.
uint32_t verboseCan2BaseAddress;;"", 1, 0, 0, 536870911, 0
bit enableVerboseCan2Tx;+CAN broadcast using custom rusEFI protocol\nenable can_broadcast/disable can_broadcast

View File

@ -267,8 +267,11 @@ enable2ndByteCanID = false
fuelTankLevel = scalar, S16, 98, "amount",{1/@@PACK_MULT_PERCENT@@}, 0
fuelConsumptionPerHour=scalar,F32, 100, "kPa", 1, 0.0
; Y axis values for selectable tables
veTableYAxis = scalar, U16, 104, "%", 0.01, 0
afrTableYAxis = scalar, U16, 106, "%", 0.01, 0
; Knock
knockCount = scalar, U32, 104,"counter", 1, 0
knockLevel = scalar, F32, 108, "Volts", 1, 0
; Mode, firmware, protocol, run time
@ -787,7 +790,7 @@ enable2ndByteCanID = false
table = veTableTbl, veTableMap, "VE Table", 1
; constant, variable
xBins = veRpmBins, RPMValue
yBins = veLoadBins, fuelingLoad
yBins = veLoadBins, veTableYAxis
zBins = veTable
; gridHeight = 2.0
gridOrient = 250, 0, 340 ; Space 123 rotation of grid in degrees.
@ -817,7 +820,7 @@ enable2ndByteCanID = false
table = afrTableTbl, afrTableMap, "Target AFR Table", 1
; constant, variable
xBins = afrRpmBins, RPMValue
yBins = afrLoadBins, fuelingLoad
yBins = afrLoadBins, afrTableYAxis
zBins = afrTable
; gridHeight = 2.0
gridOrient = 250, 0, 340 ; Space 123 rotation of grid in degrees.
@ -868,7 +871,6 @@ gaugeCategory = Sensors - Extra 2
egt7Gauge = egt7, "EGT#7", "C", 0, 2000
egt8Gauge = egt8, "EGT#8", "C", 0, 2000
rpmAccelerationGa = rpmAcceleration, "rpm delta", "dRpm", 0, 3, 0, 1, 3, 4, 1, 1
knockCountGauge = knockCount,"Knock count", "count", 0, 120, 10, 10, 100, 100, 1, 1
knockLevelGauge = knockLevel,"Knock level", "volts", 0, 7, 10, 10, 100, 100, 1, 2
fuelTankLevelGauge = fuelTankLevel,"Fuel level", "x", 0, 7, 10, 10, 100, 100, 1, 2
speedToRpmRatioGauge = speedToRpmRatio, "speed2rpm", "", 0, 100, 0, 0, 100, 100, 4, 4
@ -1101,7 +1103,6 @@ gaugeCategory = Knock
entry = ignitionLoad, @@GAUGE_NAME_IGNITION_LOAD@@, float, "%.1f"
entry = ignitionAdvance, @@GAUGE_NAME_TIMING_ADVANCE@@, float, "%.2f"
entry = knockLevel, @@GAUGE_NAME_KNOCK_LEVEL@@, float, "%.2f"
entry = knockCount, @@GAUGE_NAME_KNOCK_COUNTER@@, int, "%d"
entry = vehicleSpeedKph, @@GAUGE_NAME_VVS@@, float, "%.2f"
entry = speedToRpmRatio, "s2rpm", float, "%.3f"
entry = rpmAcceleration, "dRPM", float, "%.3f"
@ -1578,7 +1579,9 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
field = "Mode", injectionMode, {isInjectionEnabled == 1}
field = "#Batch injection with individual wiring"
field = "Two wire batch emulation", twoWireBatchInjection, {isInjectionEnabled == 1 && injectionMode == 2}
field = "Use TPS instead of Load for VE table", useTPSBasedVeTable, {isInjectionEnabled == 1 && fuelAlgorithm == LM_SPEED_DENSITY}
field = "Override VE table load axis", veOverrideMode, { isInjectionEnabled }
;field = "Override AFR table load axis", afrOverrideMode, { isInjectionEnabled }
; ^^^ Not yet implemented, hidden for now! ^^^
dialog = ignitionOutputs, "Ignition Outputs"
field = "Ignition Pin Mode", ignitionPinMode, {isIgnitionEnabled == 1}

View File

@ -202,37 +202,3 @@ TEST(misc, testPinHelper) {
ASSERT_EQ(0, getElectricalValue(1, OM_INVERTED));
ASSERT_EQ(1, getElectricalValue(0, OM_INVERTED));
}
extern fuel_Map3D_t veMap;
TEST(fuel, testTpsBasedVeDefect799) {
WITH_ENGINE_TEST_HELPER(FORD_ASPIRE_1996);
engineConfiguration->fuelAlgorithm = LM_SPEED_DENSITY;
CONFIG(useTPSBasedVeTable) = true;
int mapFrom = 100;
// set MAP axis range
setLinearCurve(config->veLoadBins, mapFrom, mapFrom + FUEL_LOAD_COUNT - 1, 1);
// RPM does not matter - set table values to match load axis
for (int load = 0; load < FUEL_LOAD_COUNT;load++) {
for (int rpmIndex = 0;rpmIndex < FUEL_RPM_COUNT;rpmIndex++) {
veMap.pointers[load][rpmIndex] = mapFrom + load;
}
}
// just validating that we set 3D map as we wanted
ASSERT_EQ(107, veMap.getValue(2000, 107));
// set TPS axis range which does not overlap MAP range for this test
setLinearCurve(CONFIG(ignitionTpsBins), 0, 15, 1);
engine->mockMapValue = 107;
Sensor::setMockValue(SensorType::Tps1, 7);
engine->engineState.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
// value in the middle of the map as expected
ASSERT_EQ(107, engine->engineState.currentVe);
}

View File

@ -8,6 +8,8 @@
using ::testing::StrictMock;
using ::testing::FloatNear;
using ::testing::InSequence;
using ::testing::_;
TEST(FuelMath, getStandardAirCharge) {
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
@ -98,3 +100,41 @@ TEST(AirmassModes, MafNormal) {
EXPECT_NEAR(0.277777f * 0.75f, airmass.CylinderAirmass, EPS4D);
EXPECT_NEAR(70.9814f, airmass.EngineLoadPercent, EPS4D);
}
TEST(AirmassModes, VeOverride) {
StrictMock<MockVp3d> veTable;
{
InSequence is;
// Default
EXPECT_CALL(veTable, getValue(_, 10.0f)).WillOnce(Return(0));
// TPS
EXPECT_CALL(veTable, getValue(_, 30.0f)).WillOnce(Return(0));
}
struct DummyAirmassModel : public AirmassModelBase {
DummyAirmassModel(const ValueProvider3D& veTable) : AirmassModelBase(veTable) {}
AirmassResult getAirmass(int rpm) override {
// Default load value 10, will be overriden
getVe(rpm, 10.0f);
return {};
}
};
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
DummyAirmassModel dut(veTable);
INJECT_ENGINE_REFERENCE(&dut);
// Use default mode - will call with 10
dut.getAirmass(0);
EXPECT_FLOAT_EQ(ENGINE(engineState.currentVeLoad), 10.0f);
// Override to TPS
CONFIG(veOverrideMode) = VE_TPS;
Sensor::setMockValue(SensorType::Tps1, 30.0f);
dut.getAirmass(0);
EXPECT_FLOAT_EQ(ENGINE(engineState.currentVeLoad), 30.0f);
}