jump to navigation

(new) Engine Speed Measurement 2010/06/06

Posted by Michael in 2JZduino.
add a comment

I recently removed the cam signal processing from the design of 2JZduino on the grounds that it isn’t required to effect moderate ignition timing retard, and also because there remained an unsolved problem.

As a result I needed an alternate method to measure engine speed (originally I was using every third cam sensor signal to count 1 revolution).

I’ve taken a slightly different approach. The crank sensor provides a higher resolution measurement of total rotation. Rather than count the time for one revolution the new method calculates the total rotation for a fixed time interval. See relevant code below…

void setup()
  TCCR4B = B11000010;  // Input Capture Noise Canceler = ON, Input Capture Edge Select = RISING, Prescaler = clk/8
  TIMSK4 |= B00001000;  // enable Timer4 Output Compare Match C

ISR(TIMER4_COMPC_vect) { // Event every ~30ms for RPM calculation
  OCR4C += 59000; // next Interrupt in +29.5ms
  static byte iteration = 1;
  if (iteration >= 4) { // calculate engine speed every 29.5*4 = 118ms
    EngineHz = CrankSignalCounter >> 2; // Hz ~= RisingCrankSignals/4 (for a 118ms period)
    EngineHzIndex = constrain(EngineHz >> 2, 0, RPMIntervals_LookupTable-1);  // index: 0->30 = Hz: 0-120
    iteration = 1;
    CrankSignalCounter = 0;
  else iteration++;

In the above, the Timer4 Output Capture C register fires every 59000 counts or 29.5ms (prescaler = 8), and the engine Hz is calculated on every 4th iteration of the interrupt. Thus EngineHz is calculated every 118ms. A sufficiently long duration is used so that at idle at least one full revolution occurs between calculations to minimize the potential error attributed to the 2 absent signals in the crank wheel (34 teeth spaced 10 degrees apart + 2 missing teeth).

The number of rotations that occurred since the beginning of the 118ms interval is CrankSignalCounter/34. The frequency is then calculated as rotations/period. 34 * 0.118 simplifies to 4.0 and the result is the efficient calculation…
EngineHz = CrankSignalCounter / 4


0.1 Alpha (first public release) 2010/06/03

Posted by Michael in 2JZduino.

For a few months now I’ve been struggling with the cam sensor signal when the engine is at idle speeds (300 – 900 RPM). At low speed, the signal strength of the cam VR sensor is too low to be register as a digital input (it’s peaks are sometimes < 2v when the engine is turning at 600 RPM). The same thing happens with the crank sensor.

The solution I've implemented is to switch over to an ADC mode when the engine speed is below ENGINEHZ_ADCMODESWITCH. In this "ADC mode" the ADC samples the cam and crank signals and switches the digital outputs depending on the values.

This never worked reliably despite implementing a number of trigger and filter algorithms for the on/off events. My latest theory is that the cam output signal from the 2JZduino was settling too close to 0v between incoming pulses (i.e. the inductor had completely discharged), and electrical noise was causing false triggers at the input of the stock ECU.

For now, I've stripped out the cam sensor signal from 2JZduino (the sensor now connects directly to the stock ECU), so that it is no longer possible to delay it. More thought and research needs to go into the permanence of this decision, but I suspect this will hold. It will not have an affect on delayed ignition timing. It might have an effect on the operation of VVT-i, however this affect might be favourable for a forced induction application.

Nevertheless, after removing the cam signal DSP I've finally been able to operate my 2JZ-GE engine without issue between 300 and 5000 RPM. And so with one of my few readers requesting a preview of the full code package, I've decided finally to make an Alpha release (v0.1)…


The download package contains both the code for the Arduino environment (compiles for the Arduino Mega), and also the Windows-based .exe to write values to the 2JZduino EEPROM (for injector scaling and crank signal delay).

Features in this version include…
LCD display support
Support for Fuel Injector drivers
Support for Crank signal DSP
Engine simulator code for bench-testing

Not included: working code for oxygen sensors.

Obviously, as an Alpha release use this at your own risk. Documentation is incomplete and various sections of the code remain untested.