| 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 |