Crankshaft Position Generator

I am building a crankshaft position generator to trick an ECU into believing that there is an engine attached and that the engine is running. I have an Arduino Mega that I have been able to successfully use to trick the ECU and RPM's show up downstream of the ECU on the proper tachometer.

I cannot use the Arduino Mega as a final board. I have an Adafruit Metro 328.

When I load the same code onto the Metro, that I successfully used on the Mega the ECU is no longer tricked and RPM's no longer show up on the tachometer.

I've searched online for reasons this isn't working but haven't been successful.

Here is the code; works with the Mega, but not the Metro.

Thanks for any help.


const byte CPS1 = 5;
const byte CPS2 = 6;

unsigned long TotalTeeth = 36;
unsigned long MissingTeeth = 2;
unsigned long TeethBetweenMissingTeeth = 0;
unsigned long RPM = 2796;

const unsigned long MicrosecondsPerMinute = 1000000ul * 60;


//===============================================================

void setup() {

  pinMode(CPS1, OUTPUT);
  pinMode(CPS2, OUTPUT);
}



//=================================================================
void loop() {

  unsigned long pulsesPerMinute = RPM * TotalTeeth;
  unsigned long microsecondsPerPulse = MicrosecondsPerMinute / pulsesPerMinute;
  unsigned long microsecondsPerHalfPulse = microsecondsPerPulse / 2;

  for (int i = 0; i < TotalTeeth - MissingTeeth - (TeethBetweenMissingTeeth * (MissingTeeth - 1)); i++)
  {
    Tooth(microsecondsPerHalfPulse);
  }

  for (int i = 0; i < MissingTeeth; i++)
  {
    ToothMissing(microsecondsPerHalfPulse);

    // Between pairs of missing teeth, insert this many teeth
    if (i < MissingTeeth - 1)
    {
      for (int j = 0; j < TeethBetweenMissingTeeth; j++)
      {
        Tooth(microsecondsPerHalfPulse);
      }
    }
  }
}




//======================================
void Tooth(int duration)
{
  digitalWrite(CPS1, HIGH);
  digitalWrite(CPS2, HIGH);
  delayMicroseconds(duration);
  digitalWrite(CPS1, LOW);
  digitalWrite(CPS2, LOW);
  delayMicroseconds(duration);
}

void ToothMissing(int duration)
{
  // two delays for both halves of a missing pulse
  delayMicroseconds(duration);
  delayMicroseconds(duration);

}




1 Like

Code looks fine. Did you remember to change the processor selection in the IDE?

Yes, I even have an O-scope connected to the output lines. I get the same pattern using the Mega or the Metro, but RPM's only show with the Mega. This image is from the Mega, I'll put the Metro in the next post for comparison.

Here is the image from the Metro. Definitely seeing some differences after looking more closely at the two images. Still not sure how to fix...

What differences?

My guess would be a one or more bad connections between the Arduino and the ECU.

1 Like

The only connections that change are moving the wires from the Mega to the Metro, the other side (ECU side and O-scope side) remains untouched. When I talk about differences, the Mega just appears to have a cleaner, crisper look to the lines, and the blue peaks seem bigger on the Metro. The resolutions on the images are are the same. I guess maybe not much difference that might affect anything....but I'm just searching for anything that is different.

Hi,
the only difference I saw is that the Metro
uses Atemga 328 and Mega uses Atmega 2560.

But I don't see where this might affect your project.

please answer

I did.

Read post #6.

your saying just your perception of the plot?

are the sequence of pulses different, the timing, the amplitude?

The second set of traces showed significantly more overshoot on the blue trace. By the way, what is the source of the yellow vs blue traces?

Thank you for seeing the differences I was talking about.

The probes for ch 1 and ch 2 are touching the connection between the

  1. Wires coming from the Ardunio and
  2. The wires going into the ECU harness

Can you turn on Vmax & Vmin on your scope so we can compare the voltage levels a little better? I can't see the screen divisions very well.

They look pretty much identical.

Are those scope traces on the ECU side or the MCU side? You should be probing at the ECU (signal input and ground at that end).

Other thing I would check: compare the drive capabilities of all the pins you are using (Mega and 328) on the datasheets and see if they are different. Could be that one processor can source more current than the other. Either way, those lines shouldn't have that much overshoot.

It shouldn't be a difference between the Mega and the Metro and maybe it is not a problem here but (a) you are passing a 32bit integer to function Tooth() which takes only a 16bit integer and (b) you are passing a 16bit integer to delayMicroseconds() which works reliably only up to 16383 us.

Edit
OK. From the oscilloscope picture, it is more or less clear that delayMicroseconds() is not exceeding the maximum value.

What type of sensor is the ECU expecting and is it still in the circuit or have you removed it ?
You appear to be using two parallel outputs from your Arduino, both HIGH or LOW together. Does the original sensor have two connections, neither of which are at ground level ?

is this a measurement issue rather than a coding problem?

do the scope probes need to be adjusted?

How about looking at the pulses a bit more expanded to see how the over/under shoot looks. Also what does the noise look like.

There seems to be quite a bit of "ringing" in the metro stream.

What I'm wondering is if you are getting ringing from the overshoot which is giving extra trigger pulses.

Crank position sensors nearly always used variable reluctance pickups, with a VERY wide output voltage range (5V->60V P-P is not unusual). Sensing is done with a true zero-crossing detector. The signal is clipped before doing zero crossing detection, so ringing on the signal peaks will make no difference whatsoever.

1 Like

I think the key word here is "used". Regardless, I think OP's circuit would be simulating the output of that zero crossing detector if in fact a variable reluctance pickup is been used.