Greetings!
I am working on a project (prototype) where I am using hall effect sensors to read the RPM's from two computer fans. I have servo's that are working as "analog tachometers" and I want one of the servos to range between 0 and 2 in terms of positioning. Both fans are relatively similar in RPM (fan1 ~ 1200rpm and fan2 ~ 1700rpm), so I know I wouldn't go over a ratio of 2.
I have everything working fine and displaying on the serial monitor and everything, however, when it comes time to display the ratio, I get erratic numbers in the thousands jumping between negative and positive!
Here is my code:
#include <Servo.h>
unsigned int rpm1; // RPM value
unsigned int rpm2;
unsigned long oldTime1; // time value
unsigned long oldTime2;
unsigned long intTime1; // time intervals
unsigned long intTime2;
int servPos1; // servo positions
int servPos2;
int i; // counter for serial monitor display
int noAction; // counter for loops with nothing happening
float ratio; // used for ratio between RPM's
Servo rpmServo1; // initialize servos
Servo rpmServo2;
void setup()
{
Serial.begin(115200); // IMPORTANT for timing!
attachInterrupt(0,magnet1,RISING); // pin 2 = sensor1 input
attachInterrupt(1,magnet2,RISING); // pin 3 = sensor2 input
rpmServo1.attach(9); // pin 9 = servo1 ouput
rpmServo2.attach(10); // pin 10 = servo2 output
rpm1 = 0; // initialize rpm1 to 0
rpm2 = 0; // initialize rpm2 to 0
oldTime1 = 0; // start temp timer1
oldTime2 = 0; // start temp timer2
intTime1 = 60000; // initialize time1 interval
intTime2 = 60000; // initialize time2 interval
noAction = 0; // start counter
ratio = 1.0; // prevent division by zero on startup
}
void loop()
{
noAction++;
if(noAction > 10) // if 10 loops pass with no magnetic detection
{
rpm1 = 0; // reset servo positions to 0
rpm2 = 0;
noAction = 11; // prevent overflow of int
}
else
{
rpm1 = 60000/intTime1; // rev/min = (60s/1min)*(60000ms/60s)*(1rev/timeInt(ms))
rpm2 = 60000/intTime2;
}
//////////////////// Calculate Ratio /////////////////////////////
if(rpm2 == 0)
rpm2 = 1; // prevent division by zero
ratio = (float(rpm1)/float(rpm2)); // rpm1 = slower fan, rpm2 = faster fan
/////////////////// Print to Serial Monitor ////////////////////////
char buffer[50]; // create buffer to hold display char's
i = sprintf(buffer,"RPM1: %d - RPM2: %d - Ratio: %d", rpm1, rpm2, ratio); // create display phrase
for(int j=0;j<=i;j++) // cycle through each char
Serial.print(buffer[j]); // print each char
Serial.println(); // print new line
////////////////////////// Move Servos //////////////////////////////
servPos1 = map(ratio, 0, 2, 160, 0); // range = 0-2 for ratio (float)
servPos2 = map(rpm2, 100, 1800, 180, 20); // showing RPM of faster fan
rpmServo1.write(servPos1); // set Servo1 to adjusted position
rpmServo2.write(servPos2); // set Servo2 to adjusted position
delay(50); // refresh rate
//////////////////////////////////////////////////////////////////////
}
void magnet1() // when magnet is detected
{
intTime1 = millis() - oldTime1; // update time interval
oldTime1 = millis(); // update starting point for timer1
noAction = 0; // reset counter
}
void magnet2() // when magnet is detected
{
intTime2 = (millis() - oldTime2); // update time interval
oldTime2 = millis(); // update starting point for timer2
noAction = 0; // reset counter
}
The part causing the erratic behavior is in the "Calculate Ratio" and "Print to Serial Monitor" sections. Everything prior to adding anything regarding the ratio variable was working fine and that was the very last thing I did.
Here is the output:
[...]
RPM1: 1276 - RPM2: 1714 - Ratio: -27453
RPM1: 1304 - RPM2: 1764 - Ratio: 15901
RPM1: 1304 - RPM2: 1666 - Ratio: 24546
RPM1: 1276 - RPM2: 1714 - Ratio: -27453
RPM1: 1304 - RPM2: 1714 - Ratio: -15524
RPM1: 1304 - RPM2: 1764 - Ratio: 15901
RPM1: 1304 - RPM2: 1714 - Ratio: -15524
RPM1: 1276 - RPM2: 1714 - Ratio: -27453
RPM1: 1304 - RPM2: 1714 - Ratio: -15524
RPM1: 1276 - RPM2: 1714 - Ratio: -27453
[...]
While the RPM's of both fans are fairly constant, the ratio goes crazy, even though I simply have it dividing something like 1714/1276 which should give me 1.34.
I tried seeing if those numbers correlate to anything, but I couldn't find anything. I tried setting the float variable as "unsigned", but it wouldn't let me. I tried putting the variables as float(rpm1) and float(rpm2) and that's what I have so far and it's not displaying the correct answer.
I have read that some people have had issues with simple arithmetic division in the past, but those are posts from 2011 and I haven't found anything more recent and they were getting outputs with "?" instead of the numbers I'm getting. I got that problem already, but that's when I tried printing with the %f in the sprintf function instead of %d. Surprisingly, %d shows with something while %f shows up with nothing. Weird.
Any thoughts? Any help is greatly appreciated!