rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
engine_math.cpp
Go to the documentation of this file.
1/**
2 * @file engine_math.cpp
3 * @brief
4 *
5 * @date Jul 13, 2013
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 *
8 * This file is part of rusEfi - see http://rusefi.com
9 *
10 * rusEfi is free software; you can redistribute it and/or modify it under the terms of
11 * the GNU General Public License as published by the Free Software Foundation; either
12 * version 3 of the License, or (at your option) any later version.
13 *
14 * rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
15 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along with this program.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "pch.h"
23
24#include "event_registry.h"
25#include "fuel_math.h"
26#include "advance_map.h"
28
29#if EFI_UNIT_TEST
30extern bool verboseMode;
31#endif /* EFI_UNIT_TEST */
32
36
37/**
38 * @return number of milliseconds in one crank shaft revolution
39 */
41 if (rpm == 0) {
42 return NAN;
43 }
44 return 360 * getOneDegreeTimeMs(rpm);
45}
46
49}
50
53}
54
55/**
56 * see also setConstantDwell
57 */
59 for (int i = 0; i < DWELL_CURVE_SIZE; i++) {
60 config->sparkDwellRpmBins[i] = (i + 1) * 50;
62 }
63
64 config->sparkDwellRpmBins[5] = 500;
66
67 config->sparkDwellRpmBins[6] = 4500;
69
70 config->sparkDwellRpmBins[7] = 12500;
72}
73
74/**
75 * @return IM_WASTED_SPARK if in SPINNING mode and IM_INDIVIDUAL_COILS setting
76 * @return engineConfiguration->ignitionMode otherwise
77 */
80#if EFI_SHAFT_POSITION_INPUT
81 // In spin-up cranking mode we don't have full phase sync info yet, so wasted spark mode is better
82 if (ignitionMode == IM_INDIVIDUAL_COILS) {
83 bool missingPhaseInfoForSequential =
85
86 if (engine->rpmCalculator.isSpinningUp() || missingPhaseInfoForSequential) {
87 ignitionMode = IM_WASTED_SPARK;
88 }
89 }
90#endif /* EFI_SHAFT_POSITION_INPUT */
91 return ignitionMode;
92}
93
94#if EFI_ENGINE_CONTROL
95
96/**
97 * This heavy method is only invoked in case of a configuration change or initialization.
98 */
100 auto operationMode = getEngineRotationState()->getOperationMode();
101 getEngineState()->engineCycle = getEngineCycle(operationMode);
102
103 bool isOddFire = false;
104 for (size_t i = 0; i < engineConfiguration->cylindersCount; i++) {
106 isOddFire = true;
107 break;
108 }
109 }
110
112
113 // Use odd fire wasted spark logic if not two stroke, and an odd fire or odd cylinder # engine
115 && (isOddFire | (engineConfiguration->cylindersCount % 2 == 1));
116
117#if EFI_UNIT_TEST
118 if (verboseMode) {
120 }
121#endif /* EFI_UNIT_TEST */
122
123#if EFI_SHAFT_POSITION_INPUT
125#endif // EFI_SHAFT_POSITION_INPUT
126
127 // Fuel schedule may now be completely wrong, force a reset
129}
130
131angle_t getPerCylinderFiringOrderOffset(uint8_t cylinderIndex, uint8_t cylinderNumber) {
132 // base = position of this cylinder in the firing order.
133 // We get a cylinder every n-th of an engine cycle where N is the number of cylinders
134 auto firingOrderOffset = engine->engineState.engineCycle * cylinderIndex / engineConfiguration->cylindersCount;
135
136 // Plus or minus any adjustment if this is an odd-fire engine
137 auto adjustment = engineConfiguration->timing_offset_cylinder[cylinderNumber];
138
139 auto result = firingOrderOffset + adjustment;
140
141 assertAngleRange(result, "getCylinderAngle", ObdCode::CUSTOM_ERR_CYL_ANGLE);
142
143 return result;
144}
145
146void setTimingRpmBin(float from, float to) {
147 setRpmBin(config->ignitionRpmBins, IGN_RPM_COUNT, from, to);
148}
149
150/**
151 * this method sets algorithm and ignition table scale
152 */
153void setAlgorithm(engine_load_mode_e algo) {
155}
156
160
161BlendResult calculateBlend(blend_table_s& cfg, float rpm, float load) {
162 // If set to 0, skip the math as its disabled
163 if (cfg.blendParameter == GPPWM_Zero) {
164 return { 0, 0, 0, 0 };
165 }
166
167 auto value = readGppwmChannel(cfg.blendParameter);
168
169 if (!value) {
170 return { 0, 0, 0, 0 };
171 }
172
173 // Override Y axis value (if necessary)
174 if (cfg.yAxisOverride != GPPWM_Zero) {
175 // TODO: is this value_or(0) correct or even reasonable?
176 load = readGppwmChannel(cfg.yAxisOverride).value_or(0);
177 }
178
179 float tableValue = interpolate3d(
180 cfg.table,
181 cfg.loadBins, load,
182 cfg.rpmBins, rpm
183 );
184
185 float blendFactor = interpolate2d(value.Value, cfg.blendBins, cfg.blendValues);
186
187 return { value.Value, blendFactor, 0.01f * blendFactor * tableValue, load };
188}
189
190#endif /* EFI_ENGINE_CONTROL */
const char * getIgnition_mode_e(ignition_mode_e value)
TriggerCentral triggerCentral
Definition engine.h:318
FuelSchedule injectionEvents
Definition engine.h:288
EngineState engineState
Definition engine.h:344
RpmCalculator rpmCalculator
Definition engine.h:306
virtual operation_mode_e getOperationMode() const =0
bool useOddFireWastedSpark
angle_t engineCycle
bool hasSynchronizedPhase() const
bool isSpinningUp() const
PrimaryTriggerDecoder triggerState
void prepareTriggerShape()
EngineRotationState * getEngineRotationState()
Definition engine.cpp:573
EngineState * getEngineState()
Definition engine.cpp:577
static EngineAccessor engine
Definition engine.h:413
static constexpr persistent_config_s * config
static constexpr engine_configuration_s * engineConfiguration
angle_t getPerCylinderFiringOrderOffset(uint8_t cylinderIndex, uint8_t cylinderNumber)
bool verboseMode
void setAlgorithm(engine_load_mode_e algo)
void setFlatInjectorLag(float value)
floatms_t getEngineCycleDuration(float rpm)
void setSingleCoilDwell()
float getFuelingLoad()
void prepareOutputSignals()
void setTimingRpmBin(float from, float to)
floatms_t getCrankshaftRevolutionTimeMs(float rpm)
BlendResult calculateBlend(blend_table_s &cfg, float rpm, float load)
ignition_mode_e getCurrentIgnitionMode()
float getIgnitionLoad()
expected< float > readGppwmChannel(gppwm_channel_e channel)
void updateCylinders(void)
@ CUSTOM_ERR_CYL_ANGLE
ignition_mode_e
@ TWO_STROKE
float floatms_t
float angle_t
scaled_channel< int16_t, 10, 1 > blendBins[BLEND_FACTOR_SIZE]
scaled_channel< uint8_t, 2, 1 > blendValues[BLEND_FACTOR_SIZE]
scaled_channel< int16_t, 10, 1 > table[BLEND_TABLE_COUNT][BLEND_TABLE_COUNT]
scaled_channel< int16_t, 100, 1 > battLagCorrTable[VBAT_INJECTOR_CURVE_PRESSURE_SIZE][VBAT_INJECTOR_CURVE_SIZE]
scaled_channel< uint16_t, 100, 1 > sparkDwellValues[DWELL_CURVE_SIZE]
constexpr void setTable(TElement(&dest)[N][M], const VElement value)
void setRpmBin(kType array[], int size, float idleRpm, float topRpm)
angle_t getEngineCycle(operation_mode_e operationMode)
printf("\n")