Pulse ln Function Time Out Problem

Hi all members,

If the frequency is greater than zero, no problem. Working normal.

But, When the frequency is zero, The loop is waiting 1600ms, then, working normal.

Again, frequency is greater than zero, no problem. Working normal.

Why it is waiting 1600ms?

Please check it code.

// time, low_time, high_time etc... is unsigned long


 if (low_time > 0)
  {
    high_time = pulseIn(3 , HIGH);
    low_time = pulseIn(3 , LOW );

    time = high_time + low_time;

    if (time > 0) freq = 1000000 / high_time;
  }
  else
  {
    high_time = pulseIn(3 , HIGH, 3000);
    low_time = pulseIn(3 , LOW, 3000);
    freq = 0;
  }

Why it is waiting 1600ms?

Because that is what pulseIn() does. There is an optional argument to define how long it waits for a pulse. RTFM.

Because the OP only posted a portion of the source code, I can only guess at the question and the answer.

There is a delay because that is what pulseIn does. However...

In the "else" branch of the "if" the delay is specified as 3000 microseconds twice, so I would have expected a delay of 6 milliseconds not 1600, but of course I cannot see the rest of the code.

The other branch of the "if" does not specify the delay time. The default unspecified delay time is one second (1000 milliseconds) so I would have expected 2000 milliseconds for doing this twice, but of course I cannot see the rest of the code.

I do not know whether the OP was questioning why a delay, or the amount of the delay. I do not see a loop.

How to change default delay time?

That's all the codes. I'm just measuring frequency. and i measuring the loop time.

If you do not use timeout, when the frequency is zero, always loop is waiting 1600ms.

Google "arduino pulseIn()" and see what happens.

BulldogLowell:
Google "arduino pulseIn()" and see what happens.

The problem is, it is not what be function. Problem is timeout.

I want, when the frequency is zero, not delay time in the loop.

It's a paradox.

You can't know that Frequency is zero without checking, you can't use pulseIn() without blocking.

Read the web page description of the function or use a non blocking method.

What is blocking method?

Any function or particular chunk of code that prevents the program from proceeding. Like for example: delay() or pulseIn() or a while or for loop.

Is your Google down?

BulldogLowell:
Any function or particular chunk of code that prevents the program from proceeding. Like for example: delay() or pulseIn() or a while or for loop.

Is your Google down?

But progress of the program should not be blocked. Loop time should be minimum. Are you ignorant?

Cloud_Blue:
Are you ignorant?

No, you are.

pulseIn works like that. If you do not want the delay, analyse the source code a write your own based on that. There is also the newping library that might be useful.

sterretje:
No, you are.

pulseIn works like that. If you do not want the delay, analyse the source code a write your own based on that. There is also the newping library that might be useful.

Which library my friend?

I see no setup() function, nor do I see a loop() function, so this cannot be all of the code for the Arduino IDE.

I do not know how to change the default timeout except by using the three argument version of the function.

vaj4088:
I see no setup() function, nor do I see a loop() function, so this cannot be all of the code for the Arduino IDE.

I do not know how to change the default timeout except by using the three argument version of the function.

Hi my friend,

Please check it my codes.

if freq zero or 10hz or etc, i want loop time (z2-z1) must be minimum.

unsigned long z1, z2, f1_h_time, f1_l_time, f2_h_time, f2_l_time, f1_time, f2_time, f1_freq, f2_freq;

#define f1_p 2
#define f2_p 3

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  z1 = millis();

////////////////////////////////////////

  if (f1_l_time > 0)
  {
    f1_h_time = pulseIn(f1_p , HIGH);
    f1_l_time = pulseIn(f1_p , LOW );
    f1_time = f1_h_time + f1_l_time;
    if (f1_time > 0) f1_freq = 1000000 / f1_time;
  }
  else
  {
    f1_l_time = pulseIn(f1_p , LOW, 64000);
    f1_freq = 0;
  }

////////////////////////////////////////

  if (f2_l_time > 0)
  {
    f2_h_time = pulseIn(f2_p , HIGH);
    f2_l_time = pulseIn(f2_p , LOW );
    f2_time = f2_h_time + f2_l_time;
    if (f2_time > 0) f2_freq = 1000000 / f2_time;
  }
  else
  {
    f2_l_time = pulseIn(f2_p , LOW, 10000);
    f2_freq = 0;
  }

////////////////////////////////////////

  z2 = millis();

  Serial.print(f1_freq); Serial.print("   ");
  Serial.print(f2_freq); Serial.print("   ");

  Serial.println(zl2 - zl1);
}

Once you tell us how you are going to detect that the frequency is zero without waiting for some period of time to see if a pulse arrives I'm sure we can help with the rest.

Read https://www.arduino.cc/en/Reference/PulseIn and then explain it to us.

Steve

Cloud_Blue:
But progress of the program should not be blocked. Loop time should be minimum. Are you ignorant?

even though you insulted me, i'll show you a method (using interrupts) to detect frequency. No pulseIn() used:

// CLASS DEFINITION

class FanSpeed {
  
  public:
    void 
      setup(uint8_t irq_pin, void (*ISR_callback)(void), int value),
      handleInterrupt(void);
    double
      getSpeed(),
      getHertz();

  private:
    double
      _timeConstant = 60000000.0;
    uint32_t
      _lastMicros = 0UL,
      _interval = 60000000UL;
    void(*ISR_callback)();
};

void FanSpeed::setup(uint8_t irq_pin, void (*ISR_callback)(void), int value)
{
  attachInterrupt(digitalPinToInterrupt(irq_pin), ISR_callback, value);
}

inline void FanSpeed::handleInterrupt(void)
{
  uint32_t nowMicros = micros();
  _interval = nowMicros - _lastMicros;
  _lastMicros = nowMicros;
}

double FanSpeed::getSpeed()
{
  if (micros() - _lastMicros < 1000000UL) // has rotated in the last second
  {
    return _timeConstant / _interval;
  }
  else
  {
    return 0;
  }   
}

double FanSpeed::getHertz()
{
  if (micros() - _lastMicros < 1000000UL) // has rotated in the last second
  {
    return getSpeed() * 60.0;
  }
  else
  {
    return 0;
  }   
}

// PROGRAM START

FanSpeed* fan1;
uint8_t fan1pin = 2;

void setup()
{
  Serial.begin(9600);
  pinMode(fan1pin, INPUT_PULLUP);
  fan1 = new FanSpeed();
  fan1->setup(fan1pin, []{fan1->handleInterrupt();}, FALLING);
}

void loop()
{
  static uint32_t lastMillis = 0;
  if (millis() - lastMillis > 1000UL)
  {
    char message[64] = "";
    sprintf(message, "Fan Speed:%4d RPM\t%4d Hz", uint32_t(floor(fan1->getSpeed() + 0.5)), uint32_t(floor(fan1->getHertz() + 0.5)));
    Serial.println(message);
    lastMillis = millis();
  }
}

BulldogLowell:
even though you insulted me, i'll show you a method (using interrupts) to detect frequency. No pulseIn() used:

// CLASS DEFINITION

class FanSpeed {
 
 public:
   void
     setup(uint8_t irq_pin, void (*ISR_callback)(void), int value),
     handleInterrupt(void);
   double
     getSpeed(),
     getHertz();

private:
   double
     _timeConstant = 60000000.0;
   uint32_t
     _lastMicros = 0UL,
     _interval = 60000000UL;
   void(*ISR_callback)();
};

void FanSpeed::setup(uint8_t irq_pin, void (*ISR_callback)(void), int value)
{
 attachInterrupt(digitalPinToInterrupt(irq_pin), ISR_callback, value);
}

inline void FanSpeed::handleInterrupt(void)
{
 uint32_t nowMicros = micros();
 _interval = nowMicros - _lastMicros;
 _lastMicros = nowMicros;
}

double FanSpeed::getSpeed()
{
 if (micros() - _lastMicros < 1000000UL) // has rotated in the last second
 {
   return _timeConstant / _interval;
 }
 else
 {
   return 0;
 }  
}

double FanSpeed::getHertz()
{
 if (micros() - _lastMicros < 1000000UL) // has rotated in the last second
 {
   return getSpeed() * 60.0;
 }
 else
 {
   return 0;
 }  
}

// PROGRAM START

FanSpeed* fan1;
uint8_t fan1pin = 2;

void setup()
{
 Serial.begin(9600);
 pinMode(fan1pin, INPUT_PULLUP);
 fan1 = new FanSpeed();
 fan1->setup(fan1pin, []{fan1->handleInterrupt();}, FALLING);
}

void loop()
{
 static uint32_t lastMillis = 0;
 if (millis() - lastMillis > 1000UL)
 {
   char message[64] = "";
   sprintf(message, "Fan Speed:%4d RPM\t%4d Hz", uint32_t(floor(fan1->getSpeed() + 0.5)), uint32_t(floor(fan1->getHertz() + 0.5)));
   Serial.println(message);
   lastMillis = millis();
 }
}

This is an excellent tachometer script. Thanks!
I'm Saving this one in my collection.
I Love the use of Lambda to allow the class function to be used in the callback.
I have a similar script for tachometers that uses an encoder for forward (+) and reverse speed (-) with distance:

#define ClockPin 2 << must be 2 or 3 on the uno
#define DataPin 9 << can be any pin
      // My Encoder has 400 Clock pulses per revolution
      // note that 150000.0 = (60 seonds * 1000000 microseconds)microseconds in a minute / 400 pulses in 1 revolution)
#define Multiplier 150000.0 // don't forget a decimal place to make this number a floating point number
volatile long EncoderCounter = 0;
volatile float SpeedInRPM = 0;

void onPin2CHANGECallBackFunction(uint32_t Time, uint32_t PinsChanged, uint32_t Pins){
    uint32_t cTime; // Current Time
    cTime = micros();
    int32_t dTime; // Delta in time
    static uint32_t lTime; // Saved Last Time of Last Pulse
    bool DataPinVal = digitalRead(DataPin);
    EncoderCounter += (DataPinVal) ? 1 : -1;
    dTime = cTime - lTime; 
    lTime = cTime;
    SpeedInRPM = Multiplier / ((DataPinVal) ? dTime: (-1 * dTime));
}

void setup() {
  Serial.begin(115200); //115200
  // put your setup code here, to run once:
  pinMode(ClockPin, INPUT);
  pinMode(DataPin, INPUT);
  attachInterrupt(0,onPin2CHANGECallBackFunction,RISING);
}

void loop() {
  static unsigned long SpamTimer;
  if ( (unsigned long)(millis() - SpamTimer) >= (100)) {
    SpamTimer = millis();
    Serial.print(EncoderCounter);
    Serial.print("\t");
    Serial.print(SpeedInRPM, 3);
    Serial.print(" RPM");
    Serial.println();
    SpeedInRPM = 0; // if no pulses occure in the next 100 miliseconds then we must assume that the motor has stopped
  }
}

Z