forked from rusefi/rusefi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_accel_enrichment.cpp
More file actions
202 lines (154 loc) · 7.58 KB
/
Copy pathtest_accel_enrichment.cpp
File metadata and controls
202 lines (154 loc) · 7.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
* @file test_accel_enrichment.cpp
*
* See also test_fuel_wall_wetting.cpp
*
* @date Apr 29, 2014
* Author: Dmitry Sidin
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "pch.h"
#include "accel_enrichment.h"
TEST(fuel, testTpsAccelEnrichmentMath) {
printf("====================================================================================== testAccelEnrichment\r\n");
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
engine->rpmCalculator.setRpmValue(600);
engine->periodicFastCallback();
engine->module<TpsAccelEnrichment>()->setLength(4);
engine->module<TpsAccelEnrichment>()->onNewValue(0);
ASSERT_EQ( 0, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta";
engine->module<TpsAccelEnrichment>()->onNewValue(10);
ASSERT_EQ( 10, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta#1";
engine->module<TpsAccelEnrichment>()->onNewValue(30);
ASSERT_EQ( 20, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta#2";
engine->module<TpsAccelEnrichment>()->onNewValue(0);
ASSERT_EQ( 20, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta#3";
engine->module<TpsAccelEnrichment>()->onNewValue(0);
ASSERT_EQ( 20, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta#4";
engine->module<TpsAccelEnrichment>()->onNewValue(0);
ASSERT_EQ( 0, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta#5";
engine->module<TpsAccelEnrichment>()->onNewValue(0);
ASSERT_EQ( 0, engine->module<TpsAccelEnrichment>()->getMaxDelta()) << "maxDelta";
}
TEST(fuel, testTpsAccelEnrichmentScheduling) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
setCrankOperationMode();
engineConfiguration->tpsAccelEnrichmentThreshold = 5;
engineConfiguration->tpsAccelLookback = 2;
eth.setTriggerType(trigger_type_e::TT_HALF_MOON);
Sensor::setMockValue(SensorType::Tps1, 0);
engine->periodicSlowCallback();
Sensor::setMockValue(SensorType::Tps1, 7);
engine->periodicSlowCallback();
eth.fireTriggerEvents2(/* count */ 4, 25 /* ms */);
ASSERT_EQ( 1200, Sensor::getOrZero(SensorType::Rpm)) << "RPM";
int expectedInvocationCounter = 1;
ASSERT_EQ(expectedInvocationCounter, engine->module<TpsAccelEnrichment>()->onUpdateInvocationCounter);
Sensor::setMockValue(SensorType::Tps1, 70);
eth.fireTriggerEvents2(/* count */ 1, 25 /* ms */);
float expectedAEValue = 7;
// it does not matter how many times we invoke 'getTpsEnrichment' - state does not change
for (int i = 0; i < 20; i++) {
ASSERT_NEAR(expectedAEValue, engine->module<TpsAccelEnrichment>()->getTpsEnrichment(), EPS4D);
}
expectedInvocationCounter++;
ASSERT_EQ(expectedInvocationCounter, engine->module<TpsAccelEnrichment>()->onUpdateInvocationCounter);
eth.engine.periodicFastCallback();
eth.engine.periodicFastCallback();
eth.engine.periodicFastCallback();
ASSERT_EQ(expectedInvocationCounter, engine->module<TpsAccelEnrichment>()->onUpdateInvocationCounter);
}
static void doFractionalTpsIteration(int period, int divisor, int numCycles, std::vector<floatms_t> &tpsEnrich) {
// every cycle
engineConfiguration->tpsAccelFractionPeriod = period;
// split into 2 portions
engineConfiguration->tpsAccelFractionDivisor = divisor;
engine->module<TpsAccelEnrichment>()->resetAE();
engine->module<TpsAccelEnrichment>()->onNewValue(0);
for (int i = 0; i < numCycles; i++) {
engine->module<TpsAccelEnrichment>()->onNewValue(10);
engine->module<TpsAccelEnrichment>()->onEngineCycleTps();
tpsEnrich[i] = engine->module<TpsAccelEnrichment>()->getTpsEnrichment();
}
}
TEST(fuel, testAccelEnrichmentFractionalTps) {
printf("====================================================================================== testAccelEnrichmentFractionalTps\r\n");
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
// setup
engineConfiguration->tpsAccelEnrichmentThreshold = 5;
engineConfiguration->tpsAccelLookback = 2;
// fill tps2tps map (todo: there should be a better way?)
static const float tpsTpsConst = 1.0f;
for (int loadIndex = 0; loadIndex < TPS_TPS_ACCEL_TABLE; loadIndex++) {
for (int rpmIndex = 0; rpmIndex < TPS_TPS_ACCEL_TABLE; rpmIndex++) {
config->tpsTpsAccelTable[loadIndex][rpmIndex] = tpsTpsConst;
}
}
initAccelEnrichment();
engine->rpmCalculator.setRpmValue(600);
engine->periodicFastCallback();
engine->module<TpsAccelEnrichment>()->setLength(2);
const int numCycles = 4;
std::vector<floatms_t> tpsEnrich(numCycles);
// first, test the default behavior without fractional division
doFractionalTpsIteration(1, 1, numCycles, tpsEnrich);
// the portion for the first cycle is full-enriched and there's no enrichment for next cycles
EXPECT_THAT(tpsEnrich, testing::ElementsAre(1.0f, 0.0f, 0.0f, 0.0f)) << "fractionalTps#1";
// divide into 2 each cycle
doFractionalTpsIteration(1, 2, numCycles, tpsEnrich);
// we have half-portion for the first cycle, then 1/4-th and 1/8th and so on...
EXPECT_THAT(tpsEnrich, testing::ElementsAre(0.5f, 0.25f, 0.125f, 0.0625f)) << "fractionalTps#2";
// split every portion into 3 sub-portions (so the whole enrichment takes longer)
doFractionalTpsIteration(3, 1, numCycles, tpsEnrich);
// we have 1/3rd-portion for the first three cycles
const float th = (1.0f / 3.0f);
EXPECT_THAT(tpsEnrich, testing::ElementsAre(testing::FloatEq(th), testing::FloatEq(th), testing::FloatEq(th), 0.0f)) << "fractionalTps#3";
// split every divided portion into 2 sub-portions (so the whole enrichment takes longer)
doFractionalTpsIteration(2, 2, numCycles, tpsEnrich);
// we have half-portion for the first two cycles, and 1/4-th portion for the next 2 cycles, and so on...
EXPECT_THAT(tpsEnrich, testing::ElementsAre(0.25f, 0.25f, 0.125f, 0.125f)) << "fractionalTps#4";
}
TEST(fuel, testTpsAccelEnrichment) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
engineConfiguration->accelEnrichmentMode = AE_MODE_PREDICTIVE_MAP;
// should return 0 if we are using predictive map
EXPECT_EQ(0, engine->module<TpsAccelEnrichment>()->getTpsEnrichment());
}
TEST(fuel, tpsAccelFlexFuelCompensation) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
engineConfiguration->tpsAccelEnrichmentThreshold = 5;
engineConfiguration->tpsAccelLookback = 2;
// non-fractional so the raw enrichment is the table value directly
engineConfiguration->tpsAccelFractionPeriod = 1;
engineConfiguration->tpsAccelFractionDivisor = 1;
// Constant AE table (1.0) and flat RPM correction so the base enrichment is a known 1.0
setTable(config->tpsTpsAccelTable, 1.0f);
setRpmTableBin(config->tpsTspCorrValuesBins);
setLinearCurve(config->tpsTspCorrValues, 1, 1);
// Flex transient AE table = 2.0 everywhere
setLinearCurve(config->flexTransientCltBins, -40, 100, 1);
setLinearCurve(config->flexTransientEthanolBins, 0, 100, 1);
setTable(config->flexAeMult, 2.0f);
engineConfiguration->flexFuelTransientComp = true;
Sensor::setMockValue(SensorType::Clt, 20);
initAccelEnrichment();
engine->rpmCalculator.setRpmValue(600);
engine->periodicFastCallback();
auto ae = engine->module<TpsAccelEnrichment>();
ae->setLength(2);
auto triggerAccel = [&]() {
ae->resetAE();
ae->onNewValue(0);
ae->onNewValue(10); // delta 10 > threshold 5 -> table value 1.0
return ae->getTpsEnrichment();
};
// No flex sensor -> compensation neutral, enrichment = base 1.0
Sensor::resetMockValue(SensorType::FuelEthanolPercent);
EXPECT_NEAR(1.0f, triggerAccel(), EPS4D);
// E100 with compensation enabled -> enrichment doubles
Sensor::setMockValue(SensorType::FuelEthanolPercent, 100);
EXPECT_NEAR(2.0f, triggerAccel(), EPS4D);
// Disable flag -> back to neutral even with a flex sensor present
engineConfiguration->flexFuelTransientComp = false;
EXPECT_NEAR(1.0f, triggerAccel(), EPS4D);
}