Electronic ignition advance

Hi everyone,
i have a big problem with my software: i'm making a programmable ignition advance system with arduino UNO and i want to read the RPM (the frequency) of the input square signal and select a delay value previously saved in a table, to apply as delay to my input signal.
The reading of the input freq is maked by the freq/counter interrupt routin on pin3 found in internet.
So what is the correct method to apply the delay on the output signal?

I tried with the micros() function but the trace of the output signal isn't stable on oscilloscope. it seems the delay is variable.

Please help me.

Thanks in advance!

All hands on the ouija board.


This will explain.

I'm not an expert of programming but i can understand the code.
Is an entire day that i try to modify the code and search in all the web the solution but i don't found nothing or only piecies.

I need an help from you!

In the link above, you should have found a part about posting your code. Without your code, we have to call to the spirits using a triangle and a board, to find your problem.

this is the code:

#include "FreqPeriodCounter.h"

#define PUIN 3
#define PUOUT 4

float m[6]={0, 0, 0, 0, 0, 0}; // y=m*x+q
float q[6]={0, 0, 0, 0, 0, 0}; 
int i=0;

unsigned long prec=0;
int delta_t; // in microseconds
int freq; // hertz

const byte counterPin=PUIN; 
const byte counterInterrupt=1;
FreqPeriodCounter counter(counterPin, micros, 0);

void setup()
  attachInterrupt(counterInterrupt, counterISR, CHANGE);

  pinMode(PUIN,INPUT); // input signal
  pinMode(PUOUT,OUTPUT); // output signal
  digitalWrite(PUOUT, LOW);

  //  configuration 2000rpm 0°, 4000rpm 3°, 6000rpm 5.5°, 8000rpm 7.5°, 10000rpm 10° 
    for(i=0; i<5; i++)
    for(i=0; i<5; i++)

void loop(void)
         if(counter.ready()) {freq=counter.hertz();}
          if(freq<freq_max[0]) //make the semi-lines in every frq range and y=m*x+q -> delta_t=m[]*freq+q[]
          if(freq>=freq_max[0] && freq<freq_max[1])
          if(freq>=freq_max[1] && freq<freq_max[2])
          if(freq>=freq_max[2] && freq<freq_max[3])
          if(freq>=freq_max[3] && freq<freq_max[4])
          if(freq>=freq_max[4] && freq<freq_max[5])
          if(micros()-prec>=(unsigned long)(delta_t)) //wait until the delay and then make the out signal

void counterISR() // for the freq counter

I must admit I'm too lazy to try to figure out all that arithmetic you're doing.

It looks rather more complex than I was expecting for something that basically just outputs a PWM signal phase-locked to an input square wave.

I thought you might handle the problem in several stages.

Count and time the pulses to maintain an average RPM value.
Regularly look at the current RPM and load and choose your required advance angle and dwell angle and from that work out the timing of your output pulse relative to the input pulse.

Have a very simple loop which detects the input transition marking the start of your timing cycle, determines when the next output event is relative to that, and performs the output event when it's due.

Since you're doing rather a lot of arithmetic every time round the loop, you're adding in a substantial delay before you can test whether it's time to output your pulse. I'd defer all that to a quiet time - for example after you have performed an output action and hence know that you won't need to perform another action for a while.