Simple problem with division

Hello, I’m having a problem with simple division. My board is an Arduino Mega 2560 R3. I am using the pulseIn function to measure periodic pulses from which I desire to derive the frequency of the pulses. I am calling the function as duration = pulseIn(sensorPin, HIGH); where duration is a float. Putting this in a loop with a test Serial.println(duration); properly shows the varying pulse width in microseconds. I then try to derive the frequency with the equation frequency = 1/(duration*1000000) where frequency is also defined as a float. But when I add Serial.println(frequency); after the earlier println, while the varying duration is still shown, the value for frequency is shown as zero. I know that for floating division, the arguments and the variable to which the results are assigned, must be floats, and they are.

I also added some test code, trying to use the variable “duration” in addition, multiplication, and division. Addition and multiplication work, and division works when duration is in the numerator, but not the denominator, even when I try casting the arguments as floats.

Any ideas? Thanks so much for any help!

Here is my code:

/* Test of pulseIn function and frequency derivation */

void setup() {
  #include <Wire.h>
  Serial.begin(9600);
}

void loop() {
  const int sensorPin = 42;
  float duration;
  float frequency;
  float addTest;
  float multiplyTest;
  float divideTest1;
  float divideTest2;
  float divideTest3;
  duration = pulseIn(sensorPin, HIGH);
  frequency = 1.0 / (duration * 1000000);
  addTest = duration + 3.0;
  multiplyTest = duration * 3.0;
  divideTest1 = duration / 3.0;
  divideTest2 = 3.0 / duration;
  divideTest3 = (float)3.0 / (float)duration;
  Serial.print("duration: ");Serial.println(duration);
  Serial.print("frequency: ");Serial.println(frequency);
  Serial.print("addTest: ");Serial.println(addTest);
  Serial.print("multiplyTest: ");Serial.println(multiplyTest);
  Serial.print("divideTest1: ");Serial.println(divideTest1);
  Serial.print("divideTest2: ");Serial.println(divideTest2);
  Serial.print("divideTest3: ");Serial.println(divideTest3);
  Serial.println("-------");
}

And here is some sample console output:

duration: 165834.00
frequency: 0.00
addTest: 165837.00
multiplyTest: 497502.00
divideTest1: 55278.00
divideTest2: 0.00
divideTest3: 0.00
-------
duration: 175372.00
frequency: 0.00
addTest: 175375.00
multiplyTest: 526116.00
divideTest1: 58457.33
divideTest2: 0.00
divideTest3: 0.00
-------
duration: 110803.00
frequency: 0.00
addTest: 110806.00
multiplyTest: 332409.00
divideTest1: 36934.33
divideTest2: 0.00
divideTest3: 0.00
-------

Thanks again!

Shouldn't the equation be frequency = 1/(duration/1000000) ?

david_2018:
Shouldn’t the equation be frequency = 1/(duration/1000000) ?

If duration is in us then yes.

Or more simply: frequency = 1000000 / duration;

void setup() {
  #include <Wire.h>
  Serial.begin(9600);
}

That is a really odd place for an #include

a.
as pcbbc posted

frequency = 1000000 / duration;

or frequency = 1/(duration/1000000)

the following is NOT correct

frequency = 1/(duration*1000000) . This makes result "too small" so ...

...b. note that displayed value is default 2 decimal places. See Serial.print for more.

wouldn’t the frequency of the “pulses” be related to the time between pulses?

if the pulse was periodic, wouldn’t the frequency be related to twice the pulse width?

Yes, it fails to take that into account, and also assumes an exactly 50% duty cycle.

To get the full duration of a cycle, add the HIGH duration and the LOW duration together. It is generally faster and more accurate to do math operations (except divide) in integers.

/* Test of pulseIn function and frequency derivation */
// #include <Wire.h>  // Not used?
const int sensorPin = 42;


void setup()
{
  Serial.begin(115200);  // Because 9600-baud is so late 90's.
  delay(100);
}


void loop()
{
  unsigned long duration = pulseIn(sensorPin, HIGH) + pulseIn(sensorPin, LOW);
  // unsigned long duration = millis();  // For testing if no input pulse is available
  float frequency = 1000000.0 / duration;
  unsigned long addTest = duration + 3;
  unsigned long multiplyTest = duration * 3;
  float divideTest1 = duration / 3.0;
  float divideTest2 = 3.0 / duration;
  float divideTest3 = (float)3.0 / (float)duration;
  
  Serial.print("duration: "); 
  Serial.println(duration);
  Serial.print("frequency: "); 
  Serial.println(frequency);
  Serial.print("addTest: "); 
  Serial.println(addTest);
  Serial.print("multiplyTest: "); 
  Serial.println(multiplyTest);
  Serial.print("divideTest1: "); 
  Serial.println(divideTest1, 7);
  Serial.print("divideTest2: "); 
  Serial.println(divideTest2, 7);
  Serial.print("divideTest3: "); 
  Serial.println(divideTest3, 7);
  Serial.println("-------");


  delay(1000);
}

@gcjr, aarg, johnwasser

yeap,
my miss that OP's duration is not the period, its only the HIGHpulse.

Thanks for everyone's help! The primary issue is that I was dividing by 1000000 instead of multiplying by 1000000. This resulted in a very small float number, and possibly an arithmetic underflow a number smaller than a float in this system can store. The secondary issue, is that when println displays floats, the default is two digits after the decimal point, so some numbers round down to zero. Increasing the number of digits to show has been helpful, in addition to multiplying by 1000000. Thanks to everyone!