Talked a lot about how motors worked, and gave some of the mechanisms for making a motor work, but it still seems like the motor isn’t going to actually run. There seems to be quite a bit missing still. The truth in fact is very much of what is needed to have the motor run has been presented. What is missing are the exception conditions. Startup and shutoff, and acceleration (both up and down, second being deceleration).
What is missing are the exception conditions. Startup and shutoff, and acceleration (both up and down, second being deceleration). Exceptions are detected through the use of measurements. Measurements of pressure, and temperature provide the best operational information. Collection of sensor information is a discipline that is portable to mostly all embedded operations, and techniques are many and varied. The method presented here is done for speed with a good level of accuracy, which are two of the requirements for engine management. First item discussed was method of detecting the sensor information which is done with an Analog to Digital (A/D) converter. The A/D converts an analog voltage to a digital count proportional to the voltage level. The value of counts is easily converted:
Count Voltage
------------- = ---------------
MAX_VAL REF_VOLT
Where MAX_VAL is the max count of the A/D. (i.e. 10 bit = 1024, 12 bit = 4096), and REF_VOLT is the reference voltage provided in the circuit. Depending on who is makes the circuit, and what was available, the value can be 1v, 3.3v, 5v, or 12v. Need to check the circuit for this information. Sensors then provide a value of conversion, which is done as either a series of steps in a table, where a particular voltage represents a particular reading, or a conversion formula (usually linear y=mx+b). If the count represents a voltage, and the voltage represents a sensor value, why can’t the count represent a sensor value, without an intermediate conversion? Sounds like a great way to reduce the work on the processor and speed up operation. True if the conversion does not prove to be too complex, meaning, the single conversion is significantly more involved, than the two conversions.
The method presented here eliminates any complex runtime calculations, because they are done before operation. It also takes advantage of a feature used in integration. Calculus goes through explanation of how to obtain accuracy through successive approximation, and use of limits as values approach either zero or infinity. The premise of the operation used here is, a curve of undetermined value has points defined as y=f(x), where for each x there is a single value f(x) that lies on the line. The method used in calculus is the change in x relates to a change in y and as the value of delta X (difference in x) decreases, the approximation of the area under the curve is made more accurate. Also the approximation can be taken as a height of X0 or X1 or as the area of the trapezoid using the line between (X0,Y0) and (X1,Y1). First giving a low estimate, second giving a high estimate, then the last providing a generally accurate reading. The other feature is by reducing delta X the accuracy increases, so the more points used, the more accurate the result.
For speed of operation, it is often better to maintain calculations in integer form as well, but some values need to have fractional parts to preserve accuracy, so an agreed fixed point is used in those cases. The system described here uses 16 bit integer base for all numbers and calculations, which provides a satisfactory level of accuracy, as well as maintaining an integer operation for equations the system used is:
Angles are in binary radians where 360 degrees = 32768
Ratios are all *1024 100% = 1024
Temperature is maintained in degrees K * 100 unsigned (27315 = 0 degrees C)
Pressure is maintained in absolute kPa (1000 N/m^2) * 100
Voltage is maintained in mV (V * 1000)
Limits of accuracy for equations are imposed based on 16 bit values
angles (error +/- 0.0109 degrees)
ratios < 6399.9% for unsigned or 3199.9% for signed (error +/- 0.098%)
temperature < 655.35 degrees K or 382.20 degrees C (error +/- 0.01 degree C)
pressure < 655.35 kPa or 6.47 atm (error +/- 10Pa)
voltage +/- 32.767v (usually 5v reference)
The conversion for sensors is now managed as a single array with values equally spaced for values of A/D counts. Here is an example for a sensor converted from a 10 bit A/D using 8 cells for the table, and a non-linear conversion.
X | 0 | 128 | 256 | 384 | 512 | 640 | 768 | 896 |
Y | 2.1 | 2.2 | 2.8 | 3.6 | 4.5 | 5.1 | 5.7 | 6.1 |
For each value of the A/D a corresponding value exists in the table with the exception of the high end. A linear extension is performed to create a “phantom” cell for the last position. The table then is interpolated between any two cells to obtain the resulting value. So an A/D reading of 400 means a value between 384 and 512 taken as a percentage. The equation becomes a simple ratio interpolation:
Y1 – Y0 Y1 – Val (X4 – Count)(Y4 – Y3) 112 * (Y4 – Y3)
---------- = --------------- => Val = Y4 - -------------------------- => Val = Y4 - ------------------
X1 – X0 X1 – Count (X4 – X3) 128
Giving a final answer 3.71 after substitution. If more accuracy is needed (closer following the curve) more points can be added. Remembering, you cannot exceed the number of points equivalent to the A/D count. Which brings up the issue of significant digits. The temptations of floating point operations is the lure of perceived precision. Precision is limited by the measuring instrument, so it is necessary to maintain that item in the background. As such, all measurements need to have the error included as part of the answer. Many times, by including the error, the number of significant digits becomes very evident. Providing a solution 3.9999999 +/- 0.001 should be evident the last four or five digits are insignificant and should be ignored. Too many times I have seen systems where the conversion from a 5v 10 bit A/D is maintained in a double precision floating point, then wondering why equates don’t seem to work because the compare is outside the significance.
I need to provide one more formulaic method, to perform the same functionality with two variables. Often with engine management, two variables act on the same value, the most common case being timing advance, which is affected by engine speed, and manifold pressure. How much air is getting in, and how fast it is moving. For this, using similar logic of incremental elements, there is a formula for interpolation in two dimensions (planar). Using an array, of values with x and y components, for any value dx and dy, the result will lie at a point bounded by the four corners. This is an extension of the two points in the linear form from before. The four corners have coordinates (Xa, Ya), (Xb, Ya), (Xa, Yb), and (Xb, Yb). The formula for determining the interpolated value is:
Z0(Xb-dx)(Yb-dy) + Z1(dx-Xa)(Yb-dy) + Z2(Xb-dx)(dy-Ya) + Z3(dx-Xa)(dy-Ya)
-------------------------------------------------------------------------------------------
(Xb-Xa)(Yb-Ya)
Where the Z values are the cell values in each cell, and the values dx and dy are the values like “Count” in the previous linear example. The equation is available in most math table books. This table form will be used extensively, so it is good to get comfortable with the method of the equation, and brings about our first table. As stated before, two inputs for engine speed (RPM) and Manifold Air Pressure (MAP) are used as the axis lines RPM => X and MAP => Y the cells will hold a value named base advance and is retrieved whenever it is needed for calculating spark advance providing a base value for the equation.
The other item to address in this installment is getting the motor started. The steady state provides for when the motor is already running, but does not take care of getting the motor to that state. Again an exception, in this case, the crank, capture, accelerate to run, sequence. Looking at the system, there are the two event captures for cam and crank. Starting from an unknown position, it is not wise to schedule a spark as damage can occur, so determining position is the critical operation. In the simple system being used, there is a single cam pulse, and a single pulse at each cylinder TDC. The system has a retained value for cam to TDC. Engines have a device, called a starter. The starter cranks the engine at a generally constant rate until the motor is able to run on its own. Calculations from before provide a means for determining how fast the engine is turning during crank. In order to command a spark (at the proper time), identification of cam angle is required. This requires waiting until the cam signal is detected. Once the cam signal is detected, the very next cylinder spark event can be scheduled using the cam to TDC equation provided earlier. The values for the scheduling are provided based on current engine speed, and angle. Pseudo code for the operations are as follows:
// Global variables
camToTdc = 0;
toothAfterTdc = 0;
cylTdc[] = {0, 16384, 32768, 49152};
lastTime = 0;
lastDiff = 0;
camDetected = false;
sparkOk = false;
// Event managers with local variables
CrankEvent() {
currentTime = getEventTime(); // grab the current event time from the timer (measured in tics)
currentDiff = currentTime – lastTime; // calculate the delta to get speed
lastTime = currentTime; // current becomes previous, for next event
lastDiff = currentDiff; // record how fast we’re going
toothAfterCam++; // increment the tooth counter
if (camDetected == true) { // did we have a cam event???
toothAfterCam = camToTdc; // now we know for sure where we are, so…
sparkOk = true; // we can activate our spark
camDetected = false; // clear the flag, so we can track it again
}
}
CamEvent() {
camDetected = true; // we have a cam signal, so set the flag.
}
The toothAfterCam value holds the most recent tooth, and the value lastTime holds the timer value of when that tooth was detected. So taking lastTime + lastDiff will give a pretty good approximation of the time when the next event will occur. Using 2x lastDiff will give the tooth following, 3x the next, etc. etc. etc. Using the angle to time conversion from before, it is now possible to schedule when the start of dwell, and the spark event will need to occur. By repeating the process for each cylinder and each event, we get varoom!
Jack