Controlling an ignition coil with arduino

Hello, I am new to programming and need help with a code that controls the pulse of an ignition coil. What happens is this: I have a signal in pulses coming from the rotation of the engine that activates and deactivates the coil with a frequency varying between 10Hz and 100Hz. This signal has a duty cycle close to 50%, so the coil charging time varies with engine speed. The lower the rotation of the motor, the longer the coil charging time and vice versa, because the time that the signal stays high has a variation in function of the frequency, thus varying the coil charging time. This recharge time is very high, it even heats up the coil. I need to create a code that the arduino nano reads this signal and generates another signal with a dwell time always fixed at about 4ms and that the output signal has the falling edge happening at the same time as the input signal. Any ideas where to start? In terms of hardware I know that an arduino can't pulse a coil so I have looked into a schematic diagram of an IGBT that can use the pulse from the arduino to control the pulsing of the coil. For me this part is not the problem. The problem is the code.

Why not use an NE555?

I am betting the coil in the original circuit had a resistor in series with the coil. ALL 12 volt automotive ignition systems had a resistor that was only shorted out while the engine was being started. After that the resistor always limited the current.

This is probably a lot more complex than you first thought.

In order to generate a fixed width pulse of 4ms you need to be able to predict when the pulse is going to end, before you know when to start the pulse.

1 Like

No, as pointed out the problem is being able to predict when the pulse will end.

Can you draw out the waveforms you have and want. With identification of the triggers?

How fast does the frequency vary?

If the frequency varies slowly enough, you might be able to trigger off of the previous pulse.

Look into the Change Detection example,

...and drop out the delay(50) because bouncing will likely not be a problem.

If you record the time when the signal changes, and the time between changes, you'll have enough information to predict the next change and 4ms before it. Then do a little "Multitasking the Arduino" to blink a light/signal at those times.

Any suggestions on how I could use it?

Explaining why I want to do such a project:
Here where I live it is difficult to find the original parts of this vehicle: coil and resistor. I want to adapt the coil from another vehicle that works with a Dwell close to 4ms. The ignition is very good with this coil, since it generates a much higher voltage at the spark plug electrode. As I mentioned the resistance is difficult to find and even so I do not find it interesting to use it, since it decreases the strength of the voltage that the coil generates, the vehicle I am wanting to adapt this coil has no pre-resistance. The current is controlled only via dwell that always stays with a fixed value, or close to 4ms.

Yes. The older cars had them. Today it is no longer necessary since the recharging time is controlled via Dwell.

The pulse always goes LOW on the falling edge of the signal from the motor sensor. The problem is to create a code that sets the output to HIGH at the right time to keep the dwell at 4ms.

Between 10Hz and 100Hz.

I believe that with logic and mathematics I could create a code that works reasonably well, but as I said I am a beginner and I can't implement it yet. It works as follows: I measure the distance between the rising edge and the falling edge in milliseconds from the last detected pulse. Based on this information I make the following calculation: (delay of next pulse) = (width of last pulse) - (Dwell time). This will be the delay in ms that the arduino will need to wait before setting the output signal to HIGH when it detects a new rising edge from the pulse coming from the motor sensor. Once the signal is set to HIGH the arduino needs to enter a wait mode, where it must wait for the falling edge of the input signal. Once the falling edge is detected it needs to set the output to LOW. Even though the engine RPM is varying, which directly affects the width of the last detected pulse, I believe that this variation does not significantly affect the coil's performance. It could easily work with Dwell varying between 3.5 ms and 4.5 ms (or more) during these RPM oscillations.

image

Yellow = Motor sensor
Green = Pulse going to coil

I even tried to implement a code with the help of chatGPT but it doesn't work properly. If the frequency drops below 25Hz Dwell goes up to 20ms. If I change the duty cycle the dwell changes too.

const int coilPin = 3;
const unsigned long dwellTime = 4000;
volatile unsigned long lastPulseTime = 0;
volatile int contactState = LOW;

void setup() {

pinMode(coilPin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), handleContactInterrupt, CHANGE);

}

void loop() {
}

void handleContactInterrupt() {

int currentState = digitalRead(2);

unsigned long pulseTime = micros();

unsigned long waitTime = (pulseTime - lastPulseTime) - dwellTime;

if (currentState == HIGH && contactState == LOW) {
digitalWrite(coilPin, LOW);
    delayMicroseconds(waitTime);

    digitalWrite(coilPin, HIGH);
}

else if (currentState == LOW && contactState == HIGH) {
   digitalWrite(coilPin, LOW);
}

contactState = currentState;

lastPulseTime = pulseTime;

}

So when you turn the engine over to start it you want to monitor an input pin and start a timer when it changes from high to low the first time and then when it changes from high to low again you want to store that time in a variable Previous_Time zero that timer and restart it.
Then enter a loop where you calculate Previous_Time - 4ms and start a second timer that counts down from this calculated time and triggers an output pin at the end of that time. Then when the next transition from high to low occurs you want to save the first counter’s value in Previous_Time, restart that timer and toggle the output state.
The output level you control will depend on the ignition circuitry.

Upon startup what would have been the first ignition event in a conventional system will be missed and will be of no consequence.

Is that the logic you are trying to program?

2 Likes

There will be an RPM e.g. 5000 RPM for an 8 cylinder engine when the dwell time is equal to the time between ignition events. At that RPM the effective dwell time will start to decrease.

First, forget ChatGPT. It is hard to lead it to a valid solution when you 100 percent know where it must go…

Is it possible for you to delay the yellow signal in #10?

That is to say, hijack the yellow signal, and pass it on delayed by 4 milliseconds.

Now you can more easily create the green signal.

Otherwise you need to predict the future, and use some clever way of accommodating the varying frequency, which will necessarily mean slight and maybe not so slight deviations of the 4 ms requirement.

Call it the man in the middle method.

a7

The yellow signal trailing edge is the ignition event so if you move it into the future you retard the timing.

Some....not all.
Voltage would be clearly marked on the coil body as 8V if a balast resistor was required.

Again, not all, however, not the reason for the balast arrangement.
The reason was it put 12v (or lower depending on what the cranking did) on an 8v coil and hence hotter spark at startup.

Yes. Now where do I begin the code? kkkkk

I don't think it will be a problem. It's a four-cylinder engine and it won't go over 5000 ~ 6000 rpm. Even in the future I want to see if I can implement an RPM limitation

Okay, for a 4 cylinder engine, at that rPM it will not be an issue. You could think about what you would do in the case of more cylinders when it would be an issue when you construct your program.