rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
engine2.cpp
Go to the documentation of this file.
1/*
2 * engine2.cpp
3 *
4 * @date Jan 5, 2019
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8// todo: move this code to more proper locations
9
10#include "pch.h"
11
12
13#include "speed_density.h"
14#include "fuel_math.h"
15#include "advance_map.h"
16#include "aux_valves.h"
17#include "closed_loop_fuel.h"
18#include "launch_control.h"
19#include "injector_model.h"
20#include "tunerstudio.h"
21
22#include "rusefi/efistring.h"
23
24#if ! EFI_UNIT_TEST
25#include "status_loop.h"
26#endif
27
31
37
41
42 warning_t* existing = recentWarnings.find(code);
43 if (!existing) {
44 chibios_rt::CriticalSectionLocker csl;
45
46 // Add the code to the list
47 existing = recentWarnings.add(warning_t(code));
48 }
49
50 if (existing) {
51 // Reset the timer on the code to now
52 existing->LastTriggered.reset();
53
54 // no pending message? lets try to add this
55 if ((m_msgWarning == nullptr) && (text)) {
56 strlncpy(m_msg, text, sizeof(m_msg));
57 m_msgWarning = existing;
58 }
59 }
60
61 // Reset the "any warning" timer too
63}
64
67 const int period = maxI(3, engineConfiguration->warningPeriod);
68
69 // TODO: do we neet this sticky warning code?
71 tsOutputChannels->lastErrorCode = static_cast<uint16_t>(engine->engineState.warnings.lastErrorCode);
72
73 // TODO: fix OBD codes "jumping" between positions when one of codes disapears
74
75 size_t i = 0;
76 for (size_t j = 0; j < recentWarnings.getCount(); j++) {
77 warning_t& warn = recentWarnings.get(j);
78 if (warn.Code != ObdCode::None) {
79 if (!warn.LastTriggered.hasElapsedSec(period)) {
80 if (i < efi::size(tsOutputChannels->recentErrorCode)) {
81 tsOutputChannels->recentErrorCode[i] = static_cast<uint16_t>(warn.Code);
82 i++;
83 }
84 } else {
85 // warning message is outdated, stop showing to TS
86 if (m_msgWarning == &warn) {
87 m_msg[0] = 0;
88 m_msgWarning = nullptr;
89 }
90 // TODO:
91 // reset warning as it is outdated
92 }
93 }
94 }
95
96 // reset rest
97 for ( ; i < efi::size(tsOutputChannels->recentErrorCode); i++) {
98 tsOutputChannels->recentErrorCode[i] = 0;
99 }
100}
101
103 // Do we have any error code to show as text?
104 return (m_msgWarning != nullptr);
105}
106
108 return m_msg;
109}
110
111/**
112 * @param forIndicator if we want to retrieving value for TS indicator, this case a minimal period is applued
113 */
116
117 return !timeSinceLastWarning.hasElapsedSec(period);
118}
119
120// Check whether a particular warning is active
123
124 // No warning found at all
125 if (!warn) {
126 return false;
127 }
128
129 // If the warning is old, it is not active
130 return !warn->LastTriggered.hasElapsedSec(maxI(3, engineConfiguration->warningPeriod));
131}
132
136
138#if EFI_LAUNCH_CONTROL
143 /*
144 * We are applying launch controller spark skip ratio only for hard skip limiter (see
145 * https://github.com/rusefi/rusefi/issues/6566#issuecomment-2153149902).
146 */
148 );
149#endif // EFI_LAUNCH_CONTROL
150}
151
152#define MAKE_HUMAN_READABLE_ADVANCE(advance) (advance > getEngineState()->engineCycle / 2 ? advance - getEngineState()->engineCycle : advance)
153
156
157#if EFI_SHAFT_POSITION_INPUT
159 warning(ObdCode::CUSTOM_SLOW_NOT_INVOKED, "Slow not invoked yet");
160 }
161
162 efitick_t nowNt = getTimeNowNt();
163 bool isCranking = engine->rpmCalculator.isCranking();
165
166 if (isCranking) {
167 crankingTimer.reset(nowNt);
168 }
169
171
172#if EFI_AUX_VALVES
174#endif //EFI_AUX_VALVES
175
176 engine->ignitionState.updateDwell(rpm, isCranking);
177
178 // todo: move this into slow callback, no reason for IAT corr to be here
180 // todo: move this into slow callback, no reason for CLT corr to be here
182
183 engine->module<DfcoController>()->update();
184 // should be called before getInjectionMass() and getLimitingTimingRetard()
186
188
190
191 auto tps = Sensor::get(SensorType::Tps1);
192 updateTChargeK(rpm, tps.value_or(0));
193
194 float untrimmedInjectionMass = getInjectionMass(rpm) * engine->engineState.lua.fuelMult + engine->engineState.lua.fuelAdd;
195 float fuelLoad = getFuelingLoad();
196
197 auto clResult = engine->module<ShortTermFuelTrim>()->getCorrection(rpm, fuelLoad);
198
199 engine->module<LongTermFuelTrim>()->learn(clResult, rpm, fuelLoad);
200
201 auto ltftResult = engine->module<LongTermFuelTrim>()->getTrims(rpm, fuelLoad);
202
204 float stage2InjectionMass = untrimmedInjectionMass * injectionStage2Fraction;
205 float stage1InjectionMass = untrimmedInjectionMass - stage2InjectionMass;
206
207 // Store the pre-wall wetting injection duration for scheduling purposes only, not the actual injection duration
208 engine->engineState.injectionDuration = engine->module<InjectorModelPrimary>()->getInjectionDuration(stage1InjectionMass);
211 ? engine->module<InjectorModelSecondary>()->getInjectionDuration(stage2InjectionMass)
212 : 0;
213
214 injectionOffset = getInjectionOffset(rpm, fuelLoad);
215 engine->lambdaMonitor.update(rpm, fuelLoad);
216
217#if EFI_LAUNCH_CONTROL
220#endif //EFI_LAUNCH_CONTROL
221
222 float l_ignitionLoad = getIgnitionLoad();
224 float baseAdvance = engine->ignitionState.getWrappedAdvance(rpm, l_ignitionLoad);
225 float corrections = engineConfiguration->timingMode == TM_DYNAMIC ?
226 // Pull any extra timing for knock retard
227 - engine->module<KnockController>()->getKnockRetard()
228 // Degrees of timing REMOVED from actual timing during soft RPM limit window
230 0;
231 float correctedIgnitionAdvance = baseAdvance + corrections;
232 // these fields are scaled_channel so let's only use for observability, with a local variables holding value while it matters locally
233 engine->ignitionState.baseIgnitionAdvance = MAKE_HUMAN_READABLE_ADVANCE(baseAdvance);
235
236 // compute per-bank fueling
237 for (size_t bankIndex = 0; bankIndex < FT_BANK_COUNT; bankIndex++) {
238 engine->engineState.stftCorrection[bankIndex] = clResult.banks[bankIndex];
239 }
240
241 // Now apply that to per-cylinder fueling and timing
242 for (size_t cylinderIndex = 0; cylinderIndex < engineConfiguration->cylindersCount; cylinderIndex++) {
243 uint8_t bankIndex = engineConfiguration->cylinderBankSelect[cylinderIndex];
244 /* TODO: add LTFT trims when ready */
245 auto bankTrim = clResult.banks[bankIndex] * ltftResult.banks[bankIndex];
246 auto cylinderTrim = getCylinderFuelTrim(cylinderIndex, rpm, fuelLoad);
247 auto knockTrim = engine->module<KnockController>()->getFuelTrimMultiplier();
248
249 // Apply both per-bank and per-cylinder trims
250 engine->engineState.injectionMass[cylinderIndex] = untrimmedInjectionMass * bankTrim * cylinderTrim * knockTrim;
251
252 angle_t cylinderIgnitionAdvance = correctedIgnitionAdvance
253 + getCylinderIgnitionTrim(cylinderIndex, rpm, l_ignitionLoad)
254 // spark hardware latency correction, for implementation details see:
255 // https://github.com/rusefi/rusefi/issues/6832:
257 wrapAngle(cylinderIgnitionAdvance, "EngineState::periodicFastCallback", ObdCode::CUSTOM_ERR_ADCANCE_CALC_ANGLE);
258 // todo: is it OK to apply cylinder trim with FIXED timing?
259 timingAdvance[cylinderIndex] = cylinderIgnitionAdvance;
260 }
261
263
265
267
268#if EFI_ANTILAG_SYSTEM
270#endif //EFI_ANTILAG_SYSTEM
271#endif // EFI_SHAFT_POSITION_INPUT
272}
273
274#if EFI_ENGINE_CONTROL
275void EngineState::updateTChargeK(float rpm, float tps) {
276 float newTCharge = engine->fuelComputer.getTCharge(rpm, tps);
277 if (!std::isnan(newTCharge)) {
278 // control the rate of change or just fill with the initial value
279 efitick_t nowNt = getTimeNowNt();
280 float secsPassed = timeSinceLastTChargeK.getElapsedSeconds(nowNt);
282 sd.tChargeK = convertCelsiusToKelvin(sd.tCharge);
283 timeSinceLastTChargeK.reset(nowNt);
284 }
285}
286#endif
287
292
296
300
302 // Convert from VVT type to trigger_config_s
304}
305
309
312 bool isLocked = lock > 0;
313 if (isLocked) {
314 criticalError("Tune is password protected. Please use console to unlock tune.");
315 }
316 return isLocked;
317}
318
319void unlockEcu(int password) {
320 if (password != engineConfiguration->tuneHidingKey) {
321 efiPrintf("Nope rebooting...");
322#if EFI_PROD_CODE
324#endif // EFI_PROD_CODE
325 } else {
326 efiPrintf("Unlocked! Burning...");
328 requestBurn();
329 }
330}
size_t getMultiSparkCount(float rpm)
angle_t getCylinderIgnitionTrim(size_t cylinderNumber, float rpm, float ignitionLoad)
void recalculateAuxValveTiming()
uint8_t code
Definition bluetooth.cpp:40
beuint32_t period
FuelComputer fuelComputer
Definition engine.h:139
SoftSparkLimiter softSparkLimiter
Definition engine.h:222
IgnitionState ignitionState
Definition engine.h:239
bool slowCallBackWasInvoked
Definition engine.h:304
LaunchControlBase launchController
Definition engine.h:220
EngineState engineState
Definition engine.h:344
RpmCalculator rpmCalculator
Definition engine.h:306
AntilagSystemBase antilagController
Definition engine.h:228
LambdaMonitor lambdaMonitor
Definition engine.h:236
TunerStudioOutputChannels outputChannels
Definition engine.h:109
SoftSparkLimiter hardSparkLimiter
Definition engine.h:224
constexpr auto & module()
Definition engine.h:200
ShiftTorqueReductionController shiftTorqueReductionController
Definition engine.h:221
angle_t injectionOffset
Timer crankingTimer
Timer timeSinceLastTChargeK
void periodicFastCallback()
Definition engine2.cpp:154
bool shouldUpdateInjectionTiming
void updateSparkSkip()
Definition engine2.cpp:137
WarningCodeState warnings
void updateTChargeK(float rpm, float tps)
Definition engine2.cpp:275
floatms_t injectionDuration
floatms_t injectionDurationStage2
float injectionStage2Fraction
multispark_state multispark
angle_t timingAdvance[MAX_CYLINDER_COUNT]
void updateAdvanceCorrections(float engineLoad)
angle_t getTrailingSparkAngle(const float rpm, const float engineLoad)
angle_t getWrappedAdvance(const float rpm, const float engineLoad)
angle_t getSparkHardwareLatencyCorrection()
void updateDwell(float rpm, bool isCranking)
float getSparkSkipRatio() const
void updateRevLimit(float rpm)
angle_t getLimitingTimingRetard() const
trigger_config_s getType() const override
Definition engine2.cpp:293
bool isVerboseTriggerSynchDetails() const override
Definition engine2.cpp:297
bool isCranking() const override
virtual SensorResult get() const =0
static float getOrZero(SensorType type)
Definition sensor.h:83
void updateTargetSkipRatio(float luaSoftSparkSkip, float tractionControlSparkSkip, float launchOrShiftTorqueReductionControllerSparkSkipRatio=0.0f)
virtual bool isVerboseTriggerSynchDetails() const =0
trigger_config_s TriggerType
virtual trigger_config_s getType() const =0
trigger_config_s getType() const override
Definition engine2.cpp:301
bool isVerboseTriggerSynchDetails() const override
Definition engine2.cpp:306
warningBuffer_t recentWarnings
ObdCode lastErrorCode
warning_t * m_msgWarning
critical_msg_t m_msg
const char * getWarningMessage()
Definition engine2.cpp:107
bool hasWarningMessage()
Definition engine2.cpp:102
void addWarningCode(ObdCode code, const char *text=nullptr)
Definition engine2.cpp:38
bool isWarningNow() const
Definition engine2.cpp:114
Timer timeSinceLastWarning
float limitRateOfChange(float newValue, float oldValue, float incrLimitPerSec, float decrLimitPerSec, float secsPassed)
Definition efilib.cpp:170
efitick_t getTimeNowNt()
Definition efitime.cpp:19
void unlockEcu(int password)
Definition engine2.cpp:319
bool isLockedFromUser()
Definition engine2.cpp:310
LimpManager * getLimpManager()
Definition engine.cpp:596
trigger_type_e getVvtTriggerType(vvt_mode_e vvtMode)
Definition engine.cpp:72
void scheduleReboot()
Definition rusefi.cpp:158
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
float getFuelingLoad()
float getIgnitionLoad()
bool warning(ObdCode code, const char *fmt,...)
float getStage2InjectionFraction(float rpm, float load)
float getPostCrankingFuelCorrection()
angle_t getInjectionOffset(float rpm, float load)
float getIatFuelCorrection()
float getBaroCorrection()
float getCltFuelCorrection()
Engine warm-up fuel correction.
PUBLIC_API_WEAK_SOMETHING_WEIRD float getCylinderFuelTrim(size_t cylinderNumber, float rpm, float fuelLoad)
float getInjectionMass(float rpm)
percent_t getInjectorDutyCycle(float rpm)
static bool isLocked
Definition flash_int.cpp:22
ObdCode
@ CUSTOM_SLOW_NOT_INVOKED
@ CUSTOM_ERR_ADCANCE_CALC_ANGLE
@ EngineStatePeriodicFastCallback
correctedIgnitionAdvance("Timing: ignition", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 962, 0.02, 0.0, 0.0, "deg")
temperature_t getTCharge(float rpm, float tps)
void update(float rpm, float load)
float stftCorrection[FT_BANK_COUNT]
float injectionMass[MAX_CYLINDER_COUNT]
scaled_channel< uint16_t, 100, 1 > afrTableYAxis
scaled_channel< int16_t, 100, 1 > trailingSparkAngle
scaled_channel< int16_t, 50, 1 > baseIgnitionAdvance
scaled_channel< int16_t, 50, 1 > correctedIgnitionAdvance
scaled_channel< int16_t, 100, 1 > tCharge
T & get(size_t i)
T * add(const T &value)
T * find(const TSearch &search) const
size_t getCount() const
ObdCode Code
Timer LastTriggered
void wrapAngle(angle_t &angle, const char *msg, ObdCode code)
void requestBurn()