Sensing the signal and put delay based on RPM and then OUTPUT

thanks a lot . its really appreciating. i also have a code would you take a look at that, it include smoothing as well.

///////////////
// Calibration:
///////////////

const byte PulsesPerRevolution = 2; // Set how many pulses there are on each revolution. Default: 2.

// If the period between pulses is too high, or even if the pulses stopped, then we would get stuck showing the
// last value instead of a 0. Because of this we are going to set a limit for the maximum period allowed.
// If the period is above this value, the RPM will show as 0.
// The higher the set value, the longer lag/delay will have to sense that pulses stopped, but it will allow readings
// at very low RPM.
// Setting a low value is going to allow the detection of stop situations faster, but it will prevent having low RPM readings.
// The unit is in microseconds.
const unsigned long ZeroTimeout = 100000; // For high response time, a good value would be 100000.
// For reading very low RPM, a good value would be 300000.

// Calibration for smoothing RPM:
const byte numReadings = 2; // Number of samples for smoothing. The higher, the more smoothing, but it's going to
// react slower to changes. 1 = no smoothing. Default: 2.

/////////////
// Variables:
/////////////

volatile unsigned long LastTimeWeMeasured; // Stores the last time we measured a pulse so we can calculate the period.
volatile unsigned long PeriodBetweenPulses = ZeroTimeout+1000; // Stores the period between pulses in microseconds.
// It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
volatile unsigned long PeriodAverage = ZeroTimeout+1000; // Stores the period between pulses in microseconds in total, if we are taking multiple pulses.
// It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
unsigned long FrequencyRaw; // Calculated frequency, based on the period. This has a lot of extra decimals without the decimal point.
unsigned long FrequencyReal; // Frequency without decimals.
unsigned long RPM; // Raw RPM without any processing.
unsigned int PulseCounter = 1; // Counts the amount of pulse readings we took so we can average multiple pulses before calculating the period.

unsigned long PeriodSum; // Stores the summation of all the periods to do the average.

unsigned long LastTimeCycleMeasure = LastTimeWeMeasured; // Stores the last time we measure a pulse in that cycle.
// We need a variable with a value that is not going to be affected by the interrupt
// because we are going to do math and functions that are going to mess up if the values
// changes in the middle of the cycle.
unsigned long CurrentMicros = micros(); // Stores the micros in that cycle.
// We need a variable with a value that is not going to be affected by the interrupt
// because we are going to do math and functions that are going to mess up if the values
// changes in the middle of the cycle.

// We get the RPM by measuring the time between 2 or more pulses so the following will set how many pulses to
// take before calculating the RPM. 1 would be the minimum giving a result every pulse, which would feel very responsive
// even at very low speeds but also is going to be less accurate at higher speeds.
// With a value around 10 you will get a very accurate result at high speeds, but readings at lower speeds are going to be
// farther from eachother making it less "real time" at those speeds.
// There's a function that will set the value depending on the speed so this is done automatically.
unsigned int AmountOfReadings = 1;

unsigned int ZeroDebouncingExtra; // Stores the extra value added to the ZeroTimeout to debounce it.
// The ZeroTimeout needs debouncing so when the value is close to the threshold it
// doesn't jump from 0 to the value. This extra value changes the threshold a little
// when we show a 0.

// Variables for smoothing tachometer:
unsigned long readings[numReadings]; // The input.
unsigned long readIndex; // The index of the current reading.
unsigned long total; // The running total.
unsigned long average; // The RPM value after applying the smoothing.

void setup() // Start of setup:
{

Serial.begin(9600); // Begin serial communication.
attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING); // Enable interruption pin 2 when going from LOW to HIGH.

delay(1000); // We sometimes take several readings of the period to average. Since we don't have any readings
// stored we need a high enough value in micros() so if divided is not going to give negative values.
// The delay allows the micros() to be high enough for the first few cycles.

} // End of setup.

void loop() // Start of loop:
{

// The following is going to store the two values that might change in the middle of the cycle.
// We are going to do math and functions with those values and they can create glitches if they change in the
// middle of the cycle.
LastTimeCycleMeasure = LastTimeWeMeasured; // Store the LastTimeWeMeasured in a variable.
CurrentMicros = micros(); // Store the micros() in a variable.

// CurrentMicros should always be higher than LastTimeWeMeasured, but in rare occasions that's not true.
// I'm not sure why this happens, but my solution is to compare both and if CurrentMicros is lower than
// LastTimeCycleMeasure I set it as the CurrentMicros.
// The need of fixing this is that we later use this information to see if pulses stopped.
if(CurrentMicros < LastTimeCycleMeasure)
{
LastTimeCycleMeasure = CurrentMicros;
}

// Calculate the frequency:
FrequencyRaw = 10000000000 / PeriodAverage; // Calculate the frequency using the period between pulses.

// Detect if pulses stopped or frequency is too low, so we can show 0 Frequency:
if(PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
{ // If the pulses are too far apart that we reached the timeout for zero:
FrequencyRaw = 0; // Set frequency as 0.
ZeroDebouncingExtra = 2000; // Change the threshold a little so it doesn't bounce.
}
else
{
ZeroDebouncingExtra = 0; // Reset the threshold to the normal value so it doesn't bounce.
}

FrequencyReal = FrequencyRaw / 10000; // Get frequency without decimals.
// This is not used to calculate RPM but we remove the decimals just in case
// you want to print it.

// Calculate the RPM:
RPM = FrequencyRaw / PulsesPerRevolution * 60; // Frequency divided by amount of pulses per revolution multiply by
// 60 seconds to get minutes.
RPM = RPM / 10000; // Remove the decimals.

// Smoothing RPM:
total = total - readings[readIndex]; // Advance to the next position in the array.
readings[readIndex] = RPM; // Takes the value that we are going to smooth.
total = total + readings[readIndex]; // Add the reading to the total.
readIndex = readIndex + 1; // Advance to the next position in the array.

if (readIndex >= numReadings) // If we're at the end of the array:
{
readIndex = 0; // Reset array index.
}

// Calculate the average:
average = total / numReadings; // The average value it's the smoothed result.

// Print information on the serial monitor:
// Comment this section if you have a display and you don't need to monitor the values on the serial monitor.
// This is because disabling this section would make the loop run faster.
Serial.print("Period: ");
Serial.print(PeriodBetweenPulses);
Serial.print("\tReadings: ");
Serial.print(AmountOfReadings);
Serial.print("\tFrequency: ");
Serial.print(FrequencyReal);
Serial.print("\tRPM: ");
Serial.print(RPM);
Serial.print("\tTachometer: ");
Serial.println(average);

} // End of loop.

void Pulse_Event() // The interrupt runs this to calculate the period between pulses:
{

PeriodBetweenPulses = micros() - LastTimeWeMeasured; // Current "micros" minus the old "micros" when the last pulse happens.
// This will result with the period (microseconds) between both pulses.
// The way is made, the overflow of the "micros" is not going to cause any issue.

LastTimeWeMeasured = micros(); // Stores the current micros so the next time we have a pulse we would have something to compare with.

if(PulseCounter >= AmountOfReadings) // If counter for amount of readings reach the set limit:
{
PeriodAverage = PeriodSum / AmountOfReadings; // Calculate the final period dividing the sum of all readings by the
// amount of readings to get the average.
PulseCounter = 1; // Reset the counter to start over. The reset value is 1 because its the minimum setting allowed (1 reading).
PeriodSum = PeriodBetweenPulses; // Reset PeriodSum to start a new averaging operation.

// Change the amount of readings depending on the period between pulses.
// To be very responsive, ideally we should read every pulse. The problem is that at higher speeds the period gets
// too low decreasing the accuracy. To get more accurate readings at higher speeds we should get multiple pulses and
// average the period, but if we do that at lower speeds then we would have readings too far apart (laggy or sluggish).
// To have both advantages at different speeds, we will change the amount of readings depending on the period between pulses.
// Remap period to the amount of readings:
int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);  // Remap the period range to the reading range.
// 1st value is what are we going to remap. In this case is the PeriodBetweenPulses.
// 2nd value is the period value when we are going to have only 1 reading. The higher it is, the lower RPM has to be to reach 1 reading.
// 3rd value is the period value when we are going to have 10 readings. The higher it is, the lower RPM has to be to reach 10 readings.
// 4th and 5th values are the amount of readings range.
RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);  // Constrain the value so it doesn't go below or above the limits.
AmountOfReadings = RemapedAmountOfReadings;  // Set amount of readings as the remaped value.

}
else
{
PulseCounter++; // Increase the counter for amount of readings by 1.
PeriodSum = PeriodSum + PeriodBetweenPulses; // Add the periods so later we can average.
}

} // End of Pulse_Event.

Not wishing to seem unkind, but I'm not going to read all that, especially as you still haven't formatted it as code for the forum.

However, you have everything you need now to make a start on your RPM counter. Do please let us know how you get on - it's helpful for other people, especially beginners.

1 Like

T

o make short, on an interop input, calculate the time since the last one and apply this formula (y = 0.0084x - 38.756) while micro sec. see the graph.
LFRED

I have done rpm counter coding. Code is mentioned above. Its gives accurate reading from 500 - 13000rpm . My bike idle at 1200rpm. So numbers below 1200rpm dosent effect. So all i have to do convert that rpm number in such a way so it will reflect numbers from 0- 5000. Because my max dealy is 5000uS(5mS). Anybody have idea how to do that

@kassiano742: I can't believe you are asking this question! This is well within your capability - it is trivial mathematically and just requires a bit of thought. I'm worried that you are coming here for help without making any effort first.

Anyway, having said that, take a look at the map() function. I think it will do what you want.

Hopefully i have done that also using the same map() function . But now the real game. How to give trigger to igntion coil igbt with input pulse by applying delay acc to the rpm.
If rpm is this
(Delay ....)
If i put delay like this then the whole program get effected. How to do this thing im tryin my best . But im getting depressed after failures. Its way complicated for a beginner

Topics on the same subject merged

Cross-posting is against the rules of the forum. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend 15 minutes (or more) writing a detailed answer on this topic, without knowing that someone else already did the same in the other topic.

Repeated cross-posting will result in a timeout from the forum.

In the future, please take some time to pick the forum board that best suits the topic of your question and then only post once to that forum board. This is basic forum etiquette, as explained in the sticky "How to use this forum - please read." post you will find at the top of every forum board. It contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

There are circumstances where it's OK to use delay(), even though it blocks program execution. Yours might be such an example; if all your program does is monitor an input, and then trigger an output after a certain delay, then goes back to waiting for another input, using delay() should be OK because you never want to do anything else during that delay period.

So, I suggest you try it with delay() first, at least to get it going. I say that because it's often good to start simple to reassure yourself and build confidence, and then migrate to a better and more elegant solution.

There is an issue you maybe haven't considered. All ignition systems require two events to trigger them. The second event is the rising (or falling) edge which triggers the actual spark. Let's assume it's triggered by a rising edge; obviously you need a falling edge some time ahead of it in order to detect the rising edge:

image

You need to know the minimum dwell time required before the rising edge. If it's an electronic module - especially capacitor discharge (CDI) - these systems pre-charge a capacitor, and when triggered the charge is dumped across a transformer, the secondary of which produces the spark voltage. Importantly, they automatically recharge the capacitor after making the spark, and can often work with a very short dwell time - sometimes much less than a millisecond.

If it is a basic inductive system, a bit like the points-based system of old and you are simply replacing the points with a switching transistor (driven by an output from your Arduino) then you need to switch on the current in the coil first, wait for the current to build up (which takes time due to the inductance of the coil), and then switch off the current to initiate the spark. In other words, you initiate the charging of the magnetic field inside the coil, rather than it happening automatically after the previous spark. The coil charges during the dwell time of your control signal, which means that the dwell time often needs to be longer than for a CDI unit.

With both types of ignition system, the dwell needs to happen before the trigger. This makes your life a bit more complicated: how can you perform an event before you know when it is required? With an engine it's easy because they operate in a repeating cycle. You time the start of the dwell from the previous spark.

Let's pretend:

1/ your engine is running at such a speed that it needs a spark every 10ms

2/ you've calculated the spark needs to be 2ms after the trigger input

3/ the coil requires 5ms of current flow to charge its internal magnetic field

I've tried to show how the timing diagram would look:

The idea is that you would calculate the value for period (1) and period (4) based on your RPM calculation.

The charge time for the coil I've shown at 5ms just for the sake of the explanation. In both cases (CDI or inductive) you need to find out the minimum dwell period required in order to a/ trigger the CDI, or b/ fully charge the coil's magnetic field.

Not all of them. There was this thread from February which looks remarkably similar. However, merging that in as well would create a huge mess. ADVANCE RETARD IGNITION USING ARDUINO. NEED HELP!!!!!!!!

Im working with CDI system which i made earlier. It actually create spark only when i put a trigger to the igbt. The dwell time is basically a time for charging the capacitor(in cdi module) or charging the induction coil in tci module. Hopefully capacitor charge faster appx in 1mS. As per you saying if i try with delay then i would have to assign delay to every frequency 217times, this could be possible. A raw example

If (signalinput, HIGH && freq == 10hz);
Delay(5 or 0.005 or what) /* i dont know how to write in uS*/
Digitawrite(triggeroutput, HIGH);
else()
Digitalwrite(triggeroutput, LOW);

If (signalinput, HIGH && freq == 100hz);
Delay(1 or 0.001 or what) /* i dont know how to write in uS*/
Digitawrite(triggeroutput, HIGH);
else()
Digitalwrite(triggeroutput, LOW);
Would this work?

But my mind saying it is not a good idea13000 = 217Hz (4.6mS for completing rotation at 13000rpm) . crank rotation time and max delay time is quite close. A small error cause malfunction. Mine engine has also has a 0mS delay signal pulse(signal occur when piston is at top). When i trigger spark with this signal the rpm does not go beyond 5000RPM. Cause engine producing spark when the piston coming down. But the signal pulse with which im working is a 5ms advance. Petrol burning time is fixedin nature so At higher rpm the fuel take some time to burn so it burn earlier to precise the timing and power. But if i try to start my engine with 5mS advance pulse then it cause very hard to kickstart or slefstart. Because fuel burns a before the piston reaches to the top and try to push back in the same direction it comes. So it was very difficult for me to solve the whole engine working specially those advance and retard pulse wires without and oscilloscope. If i stops here due to coding stuff then my effrots are gonna waste. So please help if anyone can. RPM counter coding is done and working well now the remaining is assining delay values/frequency.

The photo you have explained is basically a TCI transistor controlled ignition. Im not using because coil charging time is 5mS or above. Coil dependent

Clearly you are fully familiar with the timing requirements for CDI and inductive ignition systems, so my diagram was unnecessary, but that's good - you've got a good understanding of all the issues.

There is something I am unclear about: where in the cycle does the pulse from the crankshaft position sensor get generated? I mean, how many degrees before top dead centre? And can you move the sensor to give yourself more time for processing?

This next part is confusing:

Obviously triggering the spark at top dead centre (TDC) is no good for higher engine speeds because, as you say, the fuel is burning during the power stroke. That is why, as the engine runs faster, you must start the burn some time before TDC. So we agree on this.

This is the confusing part: the signal pulse must surely be a certain number of degrees before TDC, not a certain number of milliseconds. Can you explain exactly how the signal pulse is generated? We need to understand that first.

Would this work? Probably, but I need to understand the nature and phasing of the signal input first. What is this about not knowing how to write the delay() function? Just look it up here: https://www.arduino.cc/reference/en/

@kassiano742 I have only just read this from @6v6gt. I am FURIOUS!!! I had no idea you have already asked all these questions. I realise now that I've spent ages explaining stuff that someone else has already explained, and stuff that you already know. The answers I want about the ignition pickup are already there in that other thread, but I didn't know about it! Why didn't you mention that other thread when you started this one??? This whole conversation has been a colossal waste of my time, and I feel like a fool for walking you through stuff which you already know and understand perfectly well.

This is such a silly comment. If you'd spent half as long researching and experimenting the problem as you have asking others to write your code for you, you'd have it up and running by now. What you are trying to do is not trivial (it's towards the limits of what I'd use an Arduino for), but it is perfectly possible. I recently developed a fuel injection system for an engine using an Arduino, which is a similar problem.

Bearing in mind your impressive achievements so far, you are perfectly capable of working out for yourself how to calculate the ignition delay values according to engine speed. It's not hard - I don't understand why you want someone else to do it for you when all you require is basic arithmetic and the functions on the reference page I linked earlier.

I'm such an idiot for letting myself get strung along, simply because I didn't know you'd already run the whole conversation back in February.

@kassiano742, I'm done!

@kassiano742

If you have decided, as it appears, that you cannot, or will not, do any of this yourself and want someone to do the whole project for you, that is deliver the complete software and support to solve this problem, then it is best to use this section of the forum: Jobs and Paid Consultancy - Arduino Forum

Make sure you give all the necessary information, which would include links to your various posts here and request offers. Be prepared to be asked how much you are willing to pay (although you don't have to answer because you are inviting offers)

This whole topic can be moved to Gigs and Collaborations, If you would like that then click on the flag icon below and choose the Something else option and ask for it to be moved

thanks for reading my whole passage. you asked about how the input pulse is generated. there is basically a magnet on the crank wheel and a PULSER coil (fixed on engine casing) which create advance positive spike when initially it gets contact with magnet(45degree advance before top dead centre) and when the magnet completely pass the pulsar coil then a negative spike generated which is at the top dead centre. there is no use of negative pulse because we want positive pulse(45deg adv) for our major reference. we are making delays by considering advance signal pulse and RPM based. i hope you can do something. ive spent so much time on its functioning so if there anything concerns you about the info then im here but please help me with the remaining code

No. Like I said, I'm done.

Forums like this are for people who try and fail, and just need someone to pick them up and point them in the right direction. They aren't for people who won't try, and expect others to do their work for them.

I apologyse that i made conversations earlier but im here now because i did not get any soild answers before. And you guys thinkin that im not doing any efforts and i want a fully written code from here. This is not true im doings my efforts or you guys can't understand how difficult that is for a beginner to make that code. You asked me about the how's the behaviour of input pulse and i explained well .

If you want to continue in this section of the forum, I suggest you provide the following in a single post:

  1. A short outline description of the project
    Integrating a home made CDI ignition system with a 160cc four stroke single cylinder motor or what ever, including the main features such as a variable advance/retard timing based on engine speed. Why you are doing it etc.

  2. A schematic diagram showing all the electrical components. This can be hand drawn.
    It should include all components Arduino, pickup coils, design of the CDI system, display, how it is powered etc.

  3. The software that you have currently developed, nicely formatted, in code tags. That code, incidentally, which you have included in post #22 does not appear to be configured for the motor you have described.

  4. A testing concept.
    How are you going to show that it is working and demonstrate that the advance/retard changes as required. Are you going to set up a work bench prototype? What testing equipment are you going to use for this ? etc. etc.

ADVANCE RETARD IGNITION of 160CC SC 4 STROKE bike engine
carburated (No fuel injection)
Engine idle 1200RPM
Engine max RPM 13000RPM ( stock 11700 witch TCI system(include advance retard system), with Coustom CDI 13000rpm(not have Advance Retard system))
SUPERCHARGED @ 2.2PSI (COUSTOM SETUP) + BHP enough to blow the engine.

Coding for measure RPM

const byte PulsesPerRevolution = 2;  // Set how many pulses there are on each revolution.
const unsigned long ZeroTimeout = 100000;  // For high response time, a good value would be 100000.
                                           // For reading very low RPM, a good value would be 300000.


// Calibration for smoothing RPM:
const byte numReadings = 2;  // Number of samples for smoothing. The higher, the more smoothing, but it's going to
                             // react slower to changes. 1 = no smoothing. Default: 2.
// Variables:
volatile unsigned long LastTimeWeMeasured;  // Stores the last time we measured a pulse so we can calculate the period.
volatile unsigned long PeriodBetweenPulses = ZeroTimeout+1000;  // Stores the period between pulses in microseconds.
                       // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
volatile unsigned long PeriodAverage = ZeroTimeout+1000;  // Stores the period between pulses in microseconds in total, if we are taking multiple pulses.
                       // It has a big number so it doesn't start with 0 which would be interpreted as a high frequency.
unsigned long FrequencyRaw;  // Calculated frequency, based on the period. This has a lot of extra decimals without the decimal point.
unsigned long FrequencyReal;  // Frequency without decimals.
unsigned long RPM;  // Raw RPM without any processing.
unsigned int PulseCounter = 1;  // Counts the amount of pulse readings we took so we can average multiple pulses before calculating the period.

unsigned long PeriodSum; // Stores the summation of all the periods to do the average.

unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;  // Stores the last time we measure a pulse in that cycle.
                                    // We need a variable with a value that is not going to be affected by the interrupt
                                    // because we are going to do math and functions that are going to mess up if the values
                                    // changes in the middle of the cycle.
unsigned long CurrentMicros = micros();  // Stores the micros in that cycle.
                                         // We need a variable with a value that is not going to be affected by the interrupt
                                         // because we are going to do math and functions that are going to mess up if the values
                                         // changes in the middle of the cycle.
unsigned int AmountOfReadings = 1;

unsigned int ZeroDebouncingExtra;  // Stores the extra value added to the ZeroTimeout to debounce it.
                                   // The ZeroTimeout needs debouncing so when the value is close to the threshold it
                                   // doesn't jump from 0 to the value. This extra value changes the threshold a little
                                   // when we show a 0.

// Variables for smoothing tachometer:
unsigned long readings[numReadings];  // The input.
unsigned long readIndex;  // The index of the current reading.
unsigned long total;  // The running total.
unsigned long average;  // The RPM value after applying the smoothing.
void setup()  // Start of setup:
{

  Serial.begin(9600);  // Begin serial communication.
  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING);  // Enable interruption pin 2 when going from LOW to HIGH.

  delay(1000);  // We sometimes take several readings of the period to average. Since we don't have any readings
                // stored we need a high enough value in micros() so if divided is not going to give negative values.
                // The delay allows the micros() to be high enough for the first few cycles.

}  // End of setup.

void loop()  // Start of loop:
{

  // The following is going to store the two values that might change in the middle of the cycle.
  // We are going to do math and functions with those values and they can create glitches if they change in the
  // middle of the cycle.
  LastTimeCycleMeasure = LastTimeWeMeasured;  // Store the LastTimeWeMeasured in a variable.
  CurrentMicros = micros();  // Store the micros() in a variable.
if(CurrentMicros < LastTimeCycleMeasure)
  {
    LastTimeCycleMeasure = CurrentMicros;
  }

// Calculate the frequency:
  FrequencyRaw = 10000000000 / PeriodAverage;  // Calculate the frequency using the period between pulses.


  

  
  // Detect if pulses stopped or frequency is too low, so we can show 0 Frequency:
  if(PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
  {  // If the pulses are too far apart that we reached the timeout for zero:
    FrequencyRaw = 0;  // Set frequency as 0.
    ZeroDebouncingExtra = 2000;  // Change the threshold a little so it doesn't bounce.
  }
  else
  {
    ZeroDebouncingExtra = 0;  // Reset the threshold to the normal value so it doesn't bounce.
  }
FrequencyReal = FrequencyRaw / 10000;  // Get frequency without decimals.
                                          // This is not used to calculate RPM but we remove the decimals just in case
                                          // you want to print it.


  int ignitiondel= map(FrequencyReal,0,217,5000,0);
                                          


  // Calculate the RPM:
  RPM = FrequencyRaw * 2 / PulsesPerRevolution * 60;  // Frequency divided by amount of pulses per revolution multiply by
                                                  // 60 seconds to get minutes.
  RPM = RPM / 10000;  // Remove the decimals.
// Smoothing RPM:
  total = total - readings[readIndex];  // Advance to the next position in the array.
  readings[readIndex] = RPM;  // Takes the value that we are going to smooth.
  total = total + readings[readIndex];  // Add the reading to the total.
  readIndex = readIndex + 1;  // Advance to the next position in the array.

  if (readIndex >= numReadings)  // If we're at the end of the array:
  {
    readIndex = 0;  // Reset array index.
  }
  
  // Calculate the average:
  average = total / numReadings;  // The average value it's the smoothed result.

Serial.print("Period: ");
  Serial.print(PeriodBetweenPulses);
  Serial.print("\tReadings: ");
  Serial.print(AmountOfReadings);
  Serial.print("\tFrequency: ");
  Serial.print(FrequencyReal);
  Serial.print("\tRPM: ");
  Serial.print(RPM);
  Serial.print("\tTachometer: ");
  Serial.print(average);
  Serial.print("\tignitiondelay: ");
  Serial.println(ignitiondel);

}  // End of loop.

void Pulse_Event()  // The interrupt runs this to calculate the period between pulses:
{

  PeriodBetweenPulses = micros() - LastTimeWeMeasured;  // Current "micros" minus the old "micros" when the last pulse happens.
                                                        // This will result with the period (microseconds) between both pulses.
                                                        // The way is made, the overflow of the "micros" is not going to cause any issue.

  LastTimeWeMeasured = micros();  // Stores the current micros so the next time we have a pulse we would have something to compare with.

if(PulseCounter >= AmountOfReadings)  // If counter for amount of readings reach the set limit:
  {
    PeriodAverage = PeriodSum / AmountOfReadings;  // Calculate the final period dividing the sum of all readings by the
                                                   // amount of readings to get the average.
    PulseCounter = 1;  // Reset the counter to start over. The reset value is 1 because its the minimum setting allowed (1 reading).
    PeriodSum = PeriodBetweenPulses;  // Reset PeriodSum to start a new averaging operation.
int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);  // Remap the period range to the reading range.

 RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);  // Constrain the value so it doesn't go below or above the limits.
    AmountOfReadings = RemapedAmountOfReadings;  // Set amount of readings as the remaped value.
  }
  else
  {
    PulseCounter++;  // Increase the counter for amount of readings by 1.
    PeriodSum = PeriodSum + PeriodBetweenPulses;  // Add the periods so later we can average.
  }

}  // End of Pulse_Event.gfdg

OUTPUT OF THE CODE ( the ignitiondelay is in microsecond. it is 47uS this time because i was unable to adjust rpm to exact 13000 with 555 timer ic

at 5000 RPM it is around 3mS delay. i used map function to assign frequency/delay so now it is working in linear way. this delay is quite a lot for 5000RPM. but initially for understanding it can be compromisable. this is what ive could done