FreqMeasure Zero handling advice needed

Hello all,

I am new to the arduino scene and have come to a grinding halt on my project. I am using the library FreqMeasure and am trying to detect 0 (zero) when there is no signal. Reading from the PJRC website it says"Zero Handling

Because FreqMeasure works on a per-cycle time frame, it is impossible to directly measure zero frequency. When displaying frequency, such as the LCD_Output example, if the input frequency stops, the most recent measurement will remain on the display.
To detect zero, a timeout must be implemented. On simple approach would be to record the millis() time when FreqMeasure.available() returns true. When it returns false, check if too much time as elapsed and update the output to show zero."

With that in mind I have been playing around with the millis(). With no luck yet.

/* FreqCount - Example with serial output
 * http://www.pjrc.com/teensy/td_libs_FreqCount.html
 *
 * This example code is in the public domain.
 */
unsigned long currentMillis;
unsigned long previousMillis = 0;

const long interval = 1000;

#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  FreqMeasure.begin();
}

double sum = 0;
int count = 0;

void loop() {

  if (FreqMeasure.available() == 0) {
    currentMillis = millis();
  }
  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    Serial.println("0");

  }
  else if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 30) {
      float frequency = FreqMeasure.countToFrequency(sum / count);
      Serial.println(frequency);
      sum = 0;
      count = 0;
    }
  }
}

As you can see this is how its not done. I am trying to understand how to implement the use of the millis() If anyone could shed some light for me would be awesome. Thank you. Ray

  if (FreqMeasure.available() == 0) {
    currentMillis = millis();
  }
  if (currentMillis - previousMillis >= interval) {

Why are you comparing time and taking action regardless of whether FreqMeasure is available, or not?

Hi PaulS, I was waiting for a comment from you, to be honest Paul I'm not to sure how to make use of the millis() I've been basically staring at the Blink without delay example getting nowhere. If you could please elaborate more on the situation would be great. Cheers

I've been basically staring at the Blink without delay example getting nowhere.

I can't really understand this. The example is quite simple. What it does is ask "Is it time to do something?". The answer to that question depends on what time it is now, what time something happened in the past, and how long it is to be between now and then before something else happens.

What time it is now is what millis() returns. What time something happened in the past is easy to see. When the event happened, now (as returned by millis()) is stored in an appropriately named variable. The interval between events is constant in the example, but could be a variable if you wanted, for instance, the off time and the on time to be different.

If you could please elaborate more on the situation would be great.

Suppose we were trying to calculate RPM, instead of frequency. Suppose that no revolutions have been counted (for some period of time). How would you determine RPM, when revolutions come a long time apart?

At some point, you say "if the interval between pulses (revolutions or frequency spikes) is excessive, set the output (RPM or frequency) to 0".

So, look at your code. When data is not available (presumably because the interval between pulses has exceeded some threshold), you record when that happens. But, then you have an if/else if statement that deals with two completely different topic.

What (I think) you should have is:

if(FreqMeasure.available())
{
    // Do something with the frequency data that is available
}
else
{
   // There is no data. How long has there been no data?
}

The question "how long has there been no data" is not a simple answer. You need to record when the available() method return value changed from "yes, there is data" to "no, there is no data". The simple fact that now there is no data is not enough information.

The last time that there WAS data is one time point. Now, when there is no data is another.

So, you need to record the time every time that there IS data. previousMillis is a crappy name for the variable to store the last time there was frequency data.

Then, when there is no data, compare now (a much better name than currentMillis, and easier to type, too) to then (when there last was data), to see if there has been no data for long enough to be able to state that the frequency is infinite (not zero).

Thank you Paul for clearing that up for me. I've been going around in circles with this for some time. This is what I have come up with so far.

/* FreqCount - Example with serial output
   http://www.pjrc.com/teensy/td_libs_FreqCount.html

   This example code is in the public domain.
*/
unsigned long data_unavailable = 0;
unsigned long data_available = 0;


const long interval = 1000;

#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  FreqMeasure.begin();

}

double sum = 0;
int count = 0;

void loop() {




  if (FreqMeasure.available()) {
    sum = sum + FreqMeasure.read();
    count = count + 1;
    // average several reading together
    if (count > 30) {
      float frequency = FreqMeasure.countToFrequency(sum / count);
      Serial.println(frequency);
      data_available = millis();
      sum = 0;
      count = 0;
    }
  }

  data_unavailable = millis();

  if (data_unavailable - data_available >= interval) {
    Serial.println("0");
  }
}

As the code stands, it displays many 0's when 1 second has passed with no signal. Look forward to your feedback.

After deleting the useless white space in your program, and putting every { on a new line, where they belong, and using Tools + Auto Format, your code looks like this:

/* FreqCount - Example with serial output
   http://www.pjrc.com/teensy/td_libs_FreqCount.html

   This example code is in the public domain.
*/
unsigned long data_unavailable = 0;
unsigned long data_available = 0;

const long interval = 1000;

#include <FreqMeasure.h>

void setup()
{
  Serial.begin(57600);
  FreqMeasure.begin();
}

double sum = 0;
int count = 0;

void loop()
{
  if (FreqMeasure.available())
  {
    sum = sum + FreqMeasure.read();
    count = count + 1;
    // average several reading together
    if (count > 30)
    {
      float frequency = FreqMeasure.countToFrequency(sum / count);
      Serial.println(frequency);
      data_available = millis();
      sum = 0;
      count = 0;
    }
  }
  data_unavailable = millis();

  if (data_unavailable - data_available >= interval)
  {
    Serial.println("0");
  }
}

Now, it is perfectly obvious that you set data_unavailable to now on every pass through loop() regardless of whether there is data, or not. Why?