read a 1-60hz signal

Hey Everyone,

Im sure Im missing something obvious here but I need to read a 1-60hz signal ie. from 1 pulse per second to 60 pulses per second on a pin.

pulseIn reads the duration of the pulse which I dont care about, I need to know how many pulse per second, can some point me in the right direction please

It's pretty simple.

  • wait for it to be LOW
  • wait for it to be HIGH, take note of the time with millis()
  • wait for it to be LOW again
  • wait for it to be HIGH again, take note of the time with millis()
  • subtract earlier time from later time

That's the wavelength. The frequency is 1 second / wavelength. Since you're measuring in milliseconds, that's 1000 milliseconds / wavelength.

pulseIn reads the duration of the pulse which I dont care about, I need to know how many pulse per second

As Halley says you can calculate the frequency from the period, which is what you get using the above or the pluseIn. However, do you want to count how many pulses you get in one second as opposed to how many of the measured pulse you would get in a second if they all came in at the same rate.
If so make a note of the time in 1 seconds time using:-
endTime =millis() + 1000
Then enter a loop counting the falling edges of the signal until the time given by:-
millis() > than endTime
has expired.

By comparison, the pulseIn() function works* like this:

  • wait for it to be LOW
  • wait for it to be HIGH, take note of the time with millis()
  • wait for it to be LOW again, take note of the time with millis()
    * wait for it to be HIGH again
  • subtract earlier time from later time

It measures one portion of the cycle, not the whole cycle or wavelength. Well, (*) works is relative. First, there's a bug in 0012 or earlier, described in other threads, that it doesn't always wait for it to be LOW first. I think mellis said 0013 will specifically wait for the counter-condition first as I am indicating here. Second, you can ask for it to measure the LOW portion of the cycle, flipping all the logic above. Third, unlike my summary, you can ask for it to time out if the signal doesn't change within a specified time.

Hi Halley,
I have never herd of a waveform's period being described as it's wavelength. Normally a wavelength is measured in units of distance and is used to refer to electromagnetic waves.

However, it is logically consistent to say you are measuring length as a unit of time where length means "length of time".
Is this something that is taught in the U.S. only, as I say, I have never come across it before.

Hm, you're probably right, Grumpy. It's probably more common to refer to the "period" if talking about time instead of distance. It's been a long time since my formal education on this stuff, and as I reawaken old memories, I'm grasping for the right terms sometimes. (I recall you reminded me of the unit Henrys for inductance.) Also, I was never into the HAM or other radio stuff, so I probably don't even think of distance as being relevant at all to electronics most of the time. :slight_smile: I commented only because it looked like you were implying pulseIn() was essentially the same as finding the total period, which it doesn't.

Thanks Everyone, I think I understand enough to start tinkering :-?

I cant test this right now, and bear in mind this is my first program....
How does this look? I am concerned about the (input=HIGH) statement kicking it out of the (input=LOW) conditional statement

int input = 7;
int endtime;
int state;
int count;
unsigned long duration;

void setup()
{
  pinMode(input, INPUT);
}
void loop()
{
  if (millis() > endtime)
  {
    // calculate speed and send to display
    count = 0; // zero the counter
  }
  else
  {
    // reset endtime and begin counting pulses  
    endtime =millis() + 1000;
    state = digitalRead(input);
    if (state=LOW)
    {
      // watch for state to go high
      if (state=HIGH)
      count = count + 1;
    }
  }
}

Hi mfaust--

Here are a few observations:

  1. First, the "else" clause will never trigger, because endtime is 0 to start, so millis() will always be greater than endtime. You probably should set endtime = millis() + 1000 in setup().
  2. The two comparisons should use the C "equals" operator == and NOT the assignment operator =.
if (state == LOW)
  1. It's more C-like to increment numbers with the ++ operator like this:
count++;
  1. The increment will never happen because if state is LOW, then state cannot also be HIGH
if (state == LOW)
{
  if (state == HIGH) // this cannot ever be true

Following Halley's suggestion, I would suggest perhaps something like this:

void WaitForPin(int pin, int state) // Wait for pin to reach a certain state
{
  while (millis() < endtime && digitalRead(pin) != state);
}

void loop()
{
  ...
  WaitForPin(input, LOW); // * wait for it to be LOW
  WaitForPin(input, HIGH); // * wait for it to be HIGH
  start = millis(); // take note of the time with millis()
  WaitForPin(input, LOW); // * wait for it to be LOW again
  WaitForPin(input, HIGH); // * wait for it to be HIGH again
  end = millis(); // * take note of the time with millis()
  if (end < endtime)
  {
    duration = end - start; //* subtract earlier time from later time
  }
  else
  {
    .. timeout message
  }
}

I added the "millis() < endtime" clause to defend against hangs. If you were sure that the pin was pulsing you could simply the code considerably by removing this.

Mikal

Excellent, Thank you for the suggestions. It will greatly help me learn the language.

WaitForPin does not seem to be a valid command
:error "WaitForPin" was not declared in this scope

how can a track Low-High transitions?

ahh, got it
I didnt add the declaration! :-[