Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | #include "pch.h" | |||
2 | ||||
3 | #include "closed_loop_fuel_cell.h" | |||
4 | ||||
5 | #if EFI_ENGINE_CONTROL | |||
6 | ||||
7 | constexpr float integrator_dt = FAST_CALLBACK_PERIOD_MS * 0.001f; | |||
8 | ||||
9 | 2 | void ClosedLoopFuelCellBase::update(float lambdaDeadband, bool ignoreErrorMagnitude) | ||
10 | { | |||
11 | // Compute how far off target we are | |||
12 | 2 | float lambdaError = getLambdaError(); | ||
13 | ||||
14 | // If we're within the deadband, make no adjustment. | |||
15 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 1 time.
|
2 | if (std::abs(lambdaError) < lambdaDeadband) { |
16 | 1 | return; | ||
17 | } | |||
18 | ||||
19 | // Fixed magnitude - runs in constant adjustment rate mode | |||
20 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 time.
|
1 | if (ignoreErrorMagnitude) { |
21 | ✗ | if (lambdaError > 0) { | ||
22 | ✗ | lambdaError = 0.1f; | ||
23 | } else { | |||
24 | ✗ | lambdaError = -0.1f; | ||
25 | } | |||
26 | } | |||
27 | ||||
28 | // Integrate | |||
29 | 1 | float adjust = getIntegratorGain() * lambdaError * integrator_dt | ||
30 | 1 | + m_adjustment; | ||
31 | ||||
32 | // Clamp to bounds and save | |||
33 | 1 | m_adjustment = clampF(getMinAdjustment(), adjust, getMaxAdjustment()); | ||
34 | } | |||
35 | ||||
36 | 2 | float ClosedLoopFuelCellBase::getAdjustment() const { | ||
37 | 2 | return 1.0f + m_adjustment; | ||
38 | } | |||
39 | ||||
40 | ✗ | float ClosedLoopFuelCellImpl::getLambdaError() const { | ||
41 | ✗ | auto lambda = Sensor::get(m_lambdaSensor); | ||
42 | ||||
43 | // Failed sensor -> no error | |||
44 | ✗ | if (!lambda) { | ||
45 | ✗ | return 0; | ||
46 | } | |||
47 | ||||
48 | ✗ | return lambda.Value - engine->fuelComputer.targetLambda; | ||
49 | } | |||
50 | ||||
51 | #define MAX_ADJ (0.25f) | |||
52 | ||||
53 | ✗ | float ClosedLoopFuelCellImpl::getMaxAdjustment() const { | ||
54 | ✗ | if (!m_config) { | ||
55 | // If no config, disallow adjustment. | |||
56 | ✗ | return 0; | ||
57 | } | |||
58 | ||||
59 | ✗ | float raw = 0.01 * m_config->maxAdd; | ||
60 | // Don't allow maximum less than 0, or more than maximum adjustment | |||
61 | ✗ | return clampF(0, raw, MAX_ADJ); | ||
62 | } | |||
63 | ||||
64 | ✗ | float ClosedLoopFuelCellImpl::getMinAdjustment() const { | ||
65 | ✗ | if (!m_config) { | ||
66 | // If no config, disallow adjustment. | |||
67 | ✗ | return 0; | ||
68 | } | |||
69 | ||||
70 | ✗ | float raw = -0.01f * m_config->maxRemove; | ||
71 | // Don't allow minimum more than 0, or more than maximum adjustment | |||
72 | ✗ | return clampF(-MAX_ADJ, raw, 0); | ||
73 | } | |||
74 | ||||
75 | ✗ | float ClosedLoopFuelCellImpl::getIntegratorGain() const { | ||
76 | ✗ | if (!m_config) { | ||
77 | // If no config, disallow adjustment. | |||
78 | ✗ | return 0.0f; | ||
79 | } | |||
80 | ||||
81 | // Clamp to reasonable limits - 100ms to 100s | |||
82 | ✗ | float timeConstant = clampF(0.1f, m_config->timeConstant, 100); | ||
83 | ||||
84 | ✗ | return 1 / timeConstant; | ||
85 | } | |||
86 | ||||
87 | #endif // EFI_ENGINE_CONTROL | |||
88 |