How could I count number of pulses from analog signal

I'm trying to use an Arduino as a tachometer but I've been having a hard time with interrupts. When using the interrupt, it appears that when I set the interrupt using the "FALLING" mode, it executes the interrupt loop several times, which is giving me a false reading. I'm not sure if this is exactly what's happening, but I've gone over it several times and that's the only thing that it could be.

Basically I just want to count the number of pulses of an analog signal and divide that over the time that has passed between those pulses. The analog signal itself is most likely rough, due to the results received from the interrupt.

How would you do that? Would I need to buy some hardware to make it easier?

Thanks in advance.

I'm not sure if this is exactly what's happening

And we, without seeing your code, are supposed to?

Basically I just want to count the number of pulses of an analog signal

Interrupts are generated by a digital signal.

You need to provide a lot more details.

Yes I understand that my code would be useful but my question is not necessarily another "FIX MY CODE!!!!", but more of a "What other options do I have besides interrupts?"

And since my code consists only of interrupts, it's useless in this post.

I will provide as much information as I can but I'm new to this programming world and I don't yet know what information is required. I'm sorry about my ignorance but I will answer any questions if need be.

Here's as much info as I can provide:

I will be trying to hook up the Arduino to the negative side of an ignition coil on an engine. The voltage pulses every time it supplies spark to a spark plug. I will be using this pulse to determine the revolutions per minute of my engine and I want to plot it over time, for short 3 to 5 minute trials.

I don't know exactly how this signal looks if I plotted it in a graph but I am pretty sure it's erratic like in this picture: http://www.mr2.com/TEXT/DavidKucharczyk/spark.jpg

Using the interrupts, I have been getting the wrong readings, off by a factor of 10, which leads me to believe that the interrupt is being triggered multiple times per pulse. My code is posted here: http://arduino.cc/forum/index.php/topic,153826.0.html But I feel like I posted in the wrong place, so I posted here. Again, this is the code using an interrupt.

If there is any other information that is necessary, I'll do my best to supply it. I don't want to seem like another new person who just wants other people to solve their problems for them, but I have done a lot of research and still have not come up with a suitable solution.

Thank you.

I will be trying to hook up the Arduino to the negative side of an ignition coil on an engine. The voltage pulses every time it supplies spark to a spark plug.

So, how is this an analog signal? The voltage is either high to trigger the coil or low. Sounds digital to me. Now, there is a ramp up and a ramp down, but the signal is basically a square wave, not a sine wave.

I don't know exactly how this signal looks if I plotted it in a graph but I am pretty sure it's erratic like in this picture

True, but it's that spike that will trigger the interrupt, on either the RISING edge or the FALLING edge.

If you are getting more than one interrupt per spike, then you need to debounce the signal. That is, you ignore a second interrupt if it occurs too close after the previous one. To do that, you record when the interrupt is triggered, after copying the last time (which might be 0) to the previous time variable.

unsigned long currTime;
unsigned long lastTime;

void spark()
{
   lastTime = currTime;
   currTime = micros();

   if(currTime - lastTime > longEnough)
   {
      // Count this pulse
   }
}

lnz423:
I will be trying to hook up the Arduino to the negative side of an ignition coil on an engine. The voltage pulses every time it supplies spark to a spark plug. I will be using this pulse to determine the revolutions per minute of my engine and I want to plot it over time, for short 3 to 5 minute trials.

I don't know exactly how this signal looks if I plotted it in a graph but I am pretty sure it's erratic like in this picture: http://www.mr2.com/TEXT/DavidKucharczyk/spark.jpg

You should probably find out some details about that pulse before connecting it to your Arduino and/or developing a sensing algorithm. For example, what are the voltages going to be? If you look at the voltage scale of the picture you linked to (yes, I know it isn't your signal), you see that it goes to 15kV (that is 15,000V). A signal that large is guaranteed to let out the magic smoke somewhere on your Arduino.

Find a friendly shop or friend who can actually put some sort of scope on your engine to find out what the signal will look like. Design a circuit to safely get that signal (and possibly shape it or clean it up) to your Arduino, and then decide how to write a program to count the pulses. If the engine is modern enough, you might be able to actually get a TTL-style pulse out of the on-board computer, or even a decoded tach reading. (I'm not that familiar with OBD protocols so I can't help you beyond pointing you in that direction.)

What does your hardware connection look like? How are you conditioning the signal so that it will trigger the interrupt?

lnz423:
I will be trying to hook up the Arduino to the negative side of an ignition coil on an engine.

That's a recipe for a dead Arduino. There are all sorts of voltage transients coming off the coil LT circuit and you will need to buffer that signal down to TTL levels before it is safe to connect it to your Arduino. Having done that, a plain old digital read will be all you need to read it.

Thanks everyone for the help. I really appreciate it. I'll try to answer all the replies.

PaulS:
So, how is this an analog signal? The voltage is either high to trigger the coil or low. Sounds digital to me. Now, there is a ramp up and a ramp down, but the signal is basically a square wave, not a sine wave.

Well I could try treating it like a digital signal. I tried triggering the interrupt by LOW instead of FALLING, but it didn't work. It never gave me any output. When I changed it to FALLING, it worked, except for that extra triggers.

PaulS:
If you are getting more than one interrupt per spike, then you need to debounce the signal. That is, you ignore a second interrupt if it occurs too close after the previous one. To do that, you record when the interrupt is triggered, after copying the last time (which might be 0) to the previous time variable.

unsigned long currTime;

unsigned long lastTime;

void spark()
{
   lastTime = currTime;
   currTime = micros();

if(currTime - lastTime > longEnough)
   {
      // Count this pulse
   }
}

I could try that. I didn't know how to write it out. I think it should work if I work find a good amount of time that would be long enough to get rid of the extra interrupts, but short enough to not ignore actual pulses.

Sembazuru:
You should probably find out some details about that pulse before connecting it to your Arduino and/or developing a sensing algorithm. For example, what are the voltages going to be? If you look at the voltage scale of the picture you linked to (yes, I know it isn't your signal), you see that it goes to 15kV (that is 15,000V). A signal that large is guaranteed to let out the magic smoke somewhere on your Arduino.

Find a friendly shop or friend who can actually put some sort of scope on your engine to find out what the signal will look like. Design a circuit to safely get that signal (and possibly shape it or clean it up) to your Arduino, and then decide how to write a program to count the pulses. If the engine is modern enough, you might be able to actually get a TTL-style pulse out of the on-board computer, or even a decoded tach reading. (I'm not that familiar with OBD protocols so I can't help you beyond pointing you in that direction.)

Yeah I'm not hooking it up to a spark plug wire. My coil is actually supposed to output 45,000 volts to the spark plugs rather than 15,000. But I'm connecting it to the negative side of the coil. I measured it and it only has around 14 volts at any given time. I used a voltage divider circuit so that if I get 20 volts input, the Arduino will only see 5 volts max.

TanHadron:
What does your hardware connection look like? How are you conditioning the signal so that it will trigger the interrupt?

I'm just connecting a wire from the negative side of the coil to a voltage divider circuit to the Arduino.

PeterH:
That's a recipe for a dead Arduino. There are all sorts of voltage transients coming off the coil LT circuit and you will need to buffer that signal down to TTL levels before it is safe to connect it to your Arduino. Having done that, a plain old digital read will be all you need to read it.

Well I hope not. What do you mean by a digital read?

lnz423:
What do you mean by a digital read?

See here

I tried triggering the interrupt by LOW instead of FALLING, but it didn't work

A LOW interrupt happens over and over when the signal is LOW. Not likely what you want.

I think it should work if I work find a good amount of time that would be long enough to get rid of the extra interrupts, but short enough to not ignore actual pulses.

You have to know how long between real pulses. Then, ignore any extra pulses that are less than 10% of that interval. If the valid pulses are 50 milliseconds apart, ignore any pulse that arrives within 5 milliseconds of the last one.

PaulS:
You have to know how long between real pulses. Then, ignore any extra pulses that are less than 10% of that interval. If the valid pulses are 50 milliseconds apart, ignore any pulse that arrives within 5 milliseconds of the last one.

Ok at around 1000 rpm, which is about the max that I'll be testing, the time between pulses is 15 milliseconds. I tried writing some code that would do what you said, but I'm confused.

void rpmtrigger()
{
  oldtime = newtime;
  newtime = millis();

   if (newtime - oldtime > 12)
       {
        rpmcount++;
       }

}

This is the interrupt function. I initialized both oldtime and newtime as integers equal to 0 before the setup. So what I did was measure the time between pulses, and if the time between them is greater than 12 ms, then it will add 1 to rpmcount. But won't this just give me pulses equally spaced 12 ms apart? I think I did this wrong.

So what I did was measure the time between pulses, and if the time between them is greater than 12 ms, then it will add 1 to rpmcount.

Which looks right.

But won't this just give me pulses equally spaced 12 ms apart? I think I did this wrong.

No. Unless the interrupt trigger is LOW. If the interrupt trigger is RISING or FALLING, then there must be an interrupt to define newtime.

Think of it this way. The first time the interrupt fires, newtime is 0 and oldtime is 0. newtime is updated to match the clock (say 7), but oldtime is still 0.

15 milliseconds later, there is another interrupt. oldtime is set to 7, and newtime is set to 22 (15 + 7). 22 minus 7 is 15, which is greater than 12, so you count the pulse.

There is a problem, though. oldtime should be set to newtime only when you count a pulse.

So, there was a pulse at 7, but that is less than 12 after the Arduino started, so you'd ignore it. Then, there is another pulse at 22, which is far enough after oldtime (which is still 0), so you count the pulse AND set oldtime to 22. Another pulse at 38. 38 - 22 = 16, so you count the pulse and set oldtime to 38.

Now, suppose another pulse arrives at 40. 40 - 38 is 2, so you ignore the pulse AND leave oldtime alone.

Another pulse at 53. 53 - 38 is 15, so count it and update oldtime to 53.