Hello! I'm trying to calculate the percentage of something in Arduino. More specifically, I have a fan that I'm reading the RPM from. I know it's maximum RPM, so I would like to be able to display both its RPM and its % speed (0%-100%). I have no problem reading the RPM, but for some reason, I can't get the % to calculate!
Is there something I'm missing? Full code below:
//Calculate RPM from fan tachometer:
int fanRPM= 0;
int maxfanRPM= 1380;
float fanRPM_percentage= 0;
unsigned long lastmillis= 0;
int half_revolutions= 0;
//--------------------------------------------------------------------------------------
void RPM_fan() // this code will be executed every time the interrupt 0 (pin 2) gets low.
{
half_revolutions= half_revolutions + 1;
}
//--------------------------------------------------------------------------------------
void setup()
{
Serial.begin(9600);
attachInterrupt(0, RPM_fan, FALLING);
}
//--------------------------------------------------------------------------------------
void loop()
{
if (millis() - lastmillis == 1000) //Update every second
{
detachInterrupt(0); //Disable interrupt when calculating
fanRPM= half_revolutions * 30; //Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use half_revolutions * 30.
fanRPM_percentage= (fanRPM / maxfanRPM) * 100;
Serial.print("Fan Speed: ");
Serial.print(fanRPM);
Serial.print(" (");
Serial.print(fanRPM_percentage);
Serial.println("%)");
half_revolutions = 0;
fanRPM= 0;
fanRPM_percentage= 0;
lastmillis = millis();
attachInterrupt(0, RPM_fan, FALLING); //Enable interrupt
}
}
//--------------------------------END OF PROGRAM------------------------------------------
That's because all your variables are integers, and integer division is truncated for results less than a whole number.
So 99/100 == 0. 100/100 = 1.
If you use a bit of algebra (even though no one ever uses algebra past their school years; they should just stop teaching it. :-; ), and rearrange your equation like so, you should get much more satisfactory results (without the expense of using floating point, BTW. fanRPM_percentage doesn't need to be float, either.):
@westfw, your code didn't exactly work.. it did change to nonzero, but the math was off. I think BulldogLowell's fix is the most accurate. I added in (int) to the whole thing to get a nice round number
if (millis() - lastmillis == 1000) //Update every second
millis() can skip values. It would be safer to do:
if (millis() - lastmillis >= 1000) //Update every second
(Notice the greater-than sign in place of an equal sign).
For most cases, this will be the same as what you had. In cases where millis() skips a value, this will catch it whereas what you had could miss.