int pulseDuration = 5; // 1/2 cycle in Microseconds
float period = float(pulseDuration * 2) / 1000000; // 1 cycle in Seconds
unsigned int frequency = 1 / period;
int duration = 2734 * period * 1000; // Milliseconds
But I am getting incorrect for frequency.
Kindly spare a few moments and correct me where I am wrong.
Yes, I printed the results on the serial monitor.
Only the value of the calculated Frequency is incorrect. I guess, there is something wrong while calculations with different data type.
The 100kHz (100000) does not fit in a 16-bit integers as is used in a Arduino Uno.
A calculation with one or two floating point numbers can be done best with all float variables. Using integers half-way in the calculation is not good in my opinion. If you want a integer at the end, then convert the result to a integer at the end.
If you use all float, then there is no fuzz. When the compiler sees a "5" in the code, then it assumes that it is a integer, when the compiler sees a "5.0" then it is a floating point number. Therefor I prefer to write all the constants as floating pointer number as well.
Here you can see three different options:
void setup()
{
Serial.begin(115200);
original();
allFloat();
largerIntegersBadExample();
}
void loop() {}
void original()
{
Serial.println( "Original Code");
int pulseDuration = 5; // 1/2 cycle in Microseconds
float period = float(pulseDuration * 2) / 1000000; // 1 cycle in Seconds
unsigned int frequency = 1 / period;
int duration = 2734 * period * 1000; // Milliseconds
Serial.print( " frequency = ");
Serial.println( frequency);
Serial.print( " duration = ");
Serial.println( duration);
}
void allFloat()
{
Serial.println( "All Float");
float pulseDuration = 5.0; // 1/2 cycle in Microseconds
float period = (pulseDuration * 2.0) / 1000000.0; // 1 cycle in Seconds
float frequency = 1.0 / period;
float duration = 2734.0 * period * 1000.0; // Milliseconds
Serial.print( " frequency = ");
Serial.println( frequency, 10);
Serial.print( " duration = ");
Serial.println( duration, 10);
}
void largerIntegersBadExample()
{
Serial.println( "Larger Integers");
long pulseDuration = 5L; // 1/2 cycle in Microseconds
float period = float(pulseDuration * 2) / 1000000L; // 1 cycle in Seconds
long frequency = 1L / period;
long duration = 2734L * period * 1000L; // Milliseconds
Serial.print( " frequency = ");
Serial.println( frequency);
Serial.print( " duration = ");
Serial.println( duration);
}
Try the sketch in the Wokwi simulator:
Result:
Original Code
frequency = 65535
duration = 27
All Float
frequency = 100000.0000000000
duration = 27.3399982452
Larger Integers
frequency = 100000
duration = 27
Note to others: I called the mix of float and long a bad example. When float and integers are mixed, then I have to crunch my brain and check every line if using integers at that point is valid and I'm too lazy to crunch my brains. Number crunching is the job of the compiler and the processor.
Actually, it doesn't. Try a calculator to calculate each step and follow what the compiler is doing.
When the compiler sees "1 / period", it sees "integer divided by float". Variable "period" is a float. The compiler will use a floating point calculation for that, since at least one of the variables is a float. Since "period" is much smaller than 1, the result will be 100000, which will be converted to be put in the variable "frequency". That does not fit in a 16-bit variable, so the compiler scratches its head and tries to make the best out of the bad situation.
Division by a very large or small value is always dangerous loss of precision.
I would rewrite the calculations like this:
float period = (float)(pulseDuration * 2) / 1000000; // <=== are you really need it?
unsigned long frequency = 1000000 / (pulseDuration * 2);
int duration = 2734 * 1000UL / frequency;
We got a little carried away but sometimes it is interesting and important to know what is going on.
There is more to it. The calculation is done by the compiler and not runtime by the microcontroller. The compiler recognizes the constants and the calculations and calculates the result for you.
For example this sketch:
void setup()
{
Serial.begin(115200);
int pulseDuration = 5; // 1/2 cycle in Microseconds
float period = float(pulseDuration * 2) / 1000000; // 1 cycle in Seconds
unsigned int frequency = 1 / period;
int duration = 2734 * period * 1000; // Milliseconds
Serial.println( frequency);
Serial.println( duration);
}
void loop() {}
Do you recognize the 255, 255, that is the integer of 65535 which is put on the stack as a constant value. It is not runtime calculated. And the 27 is also put on the stack.
I got this assembly by putting the sketch in Wokwi. Run it. Stop it. Right click on source code, click "Command Palette" and search for "assembly", click that. A new tab "sketch.lst" shows the assembly code.