In the previous discussion, I presented a base system for engine management. The problem with what was created is, it only runs in steady state. Steady state for an engine is constant rpm and load, no acceleration, and no change to demand. The software components of the system have been intentionally designed to be independent of hardware processor. The specific platform is the Arduino Nano and the 328p processor. The choice was as an exercise to see if it could be done, and to force a level of discipline for the programming model. The other item of note from the previous discussion is, I am a software person primarily, with a working knowledge of electronic hardware. I am happy to admit to shortcomings in any circuits that I present, and encourage correction.
This second section will deal with making improvements to the basic software to manage the asynchronous events. Some items will make reference to the previous discussion, so please review for a full description. If something was left out, I am happy to fill in the detail. Jumping in to the first item which is a one time event. The engine start. When the engine is cranking, before ignition timing is captured, fuel is being input, and not burned. To correct the state, once the engine starts, the acceleration is raised temporarily to "burn off" the excess fuel. This is done by adjusting the advance, first increasing, then reducing back to steady state. Also, during crank (before ignition capture), the advance is reduced to almost zero. Because the advance goes from near zero to a large angle, a measured transition is needed. This is called the ramp in rate. Also, the recovery from the large angle to the steady state angle, is again a measured value. This is called the decay. The startup sequence then becomes a small state operation. Crank > Ramp to max > Decay to steady > Steady State. In each of the states a value is combined as part of the total advance.
The ramp in and decay are governed by the RPM of the motor, so a counter tied to the cam signal is implemented. The four states are monitored with a simple switch operation. The values for ramp in and decay are defined in calibration, as well as the values for max and minimum advance. The other part is to implement a counter of some sort that is updated during the cam signal detect (same place as setting cam detected flag). The sequence works sort of like this:
- Engine off - Retrieve from calibration values for min, max, ramp, and decay.
- Crank to start - Set advance to minimum until ignition is detected, also set counter to ramp in value when ignition is detected change state.
- Ramp in - Adjust advance from minimum to maximum with a slope = counter / ramp until max is reached then set counter to decay and change state
- Decay out - Adjust advance from max to steady state with a slope = counter / decay until steady state is reached then change state
- Steady State - watch for engine stop
SWord updateStartupTrim(SWord t) { static SWord ramp; static SWord min = 0; static SWord max = 0; static UByte stState = 0; switch(stState) { case 0: // engine off, crank to start min = getIgnStartupAdjustment() - t; ramp = getIgnStartupRampIn(); if (ramp == 0) { ramp = 1; } ignStTrim = getRpm() > 0 ? min : 0; if (getRpm() > getIgnRpmMinRun()) { camTrimCt = ramp; stState = 1; } break; case 1: // ramp in max = getIgnStartupTrim(); if (camTrimCt > 0) { ignStTrim = max - (SWord)((SLong)camTrimCt * (SLong)(max - min) / (SLong)ramp); } else { ignStTrim = max; ramp = getIgnStartupDecay(); if (ramp == 0) { ramp = 1; } camTrimCt = ramp; stState = 2; } break; case 2: // decay if (camTrimCt > 0) { ignStTrim = (SWord)((SLong)max * (SLong)camTrimCt / (SLong)ramp); } else { ignStTrim = 0; stState = 3; } break; default: // running ignStTrim = 0; if (isEngStopped()) { stState = 0; } break; } return ignStTrim; }
The variable camTrimCt is the counter which gets decremented on each cam.
Good news is, there are lots of exception and asynchronous activities to manage, so there will be lots offered here
Jack