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:
parent
141cad585c
commit
ef0b2f7be0
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -21,4 +21,6 @@ protected:
|
|||
|
||||
private:
|
||||
const ValueProvider3D* const m_veTable;
|
||||
|
||||
float getVeLoadAxis(float passedLoad) const;
|
||||
};
|
||||
|
|
|
@ -60,6 +60,8 @@ public:
|
|||
efitick_t timeSinceLastTChargeK;
|
||||
|
||||
float currentVe = 0;
|
||||
float currentVeLoad = 0;
|
||||
float currentAfrLoad = 0;
|
||||
|
||||
int vssEventCounter = 0;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue