Hey guys,
I’m building an RPM counter for counting RPM of a fan at work. I'm using Arduino Duemillanove(Atmega328) and an optical sensor. The sensor senses light reflecting of a reflective sticker on one of the fan blades, it outputs a logical high(5V), and each time it shines on the sticker a logic low(0V). So my way of approaching the problem was to use interrupts to catch the logic low from the sensor. I found a lot of stuff on rpm counters using Arduino, but all of which seem to originate from this post:
http://playground.arduino.cc/Main/ReadingRPM I don’t like the idea to measure 20 or so revolutions and average them out to get a smooth number flow. I would rather measure a period of one cycle as precise as possible. So my way of tackling the problem is to measure time in interrupt routine using micros(). Each time interrupt occurs time is measured and previous time subtracted from it to get a period of one cycle. The problem is that the period time jumps from 20000us to 19500us and back at 3000RPM. This then relates to around 70RPM error. The code I wrote is below:
#define baudrate 115200
char PERCommand[] = "PER?";
char SerialCommand[10];
int SerialDelay;
byte cnt = 0;
unsigned long time[2] = {0,0};
volatile unsigned long per = 0;
void setup() {
Serial.begin(115200);
SerialDelay = (10000000/baudrate)+50;
attachInterrupt(0, handler, FALLING);
}
void loop() {
if(Serial.available() > 0) {
// detachInterrupt(0);
GetCommand();
CompareAndReturn();
// attachInterrupt(0, handler, FALLING);
}
}
void GetCommand() {
while(Serial.available() > 0 && cnt < 9) {
char c = Serial.read();
SerialCommand[cnt] = c;
SerialCommand[cnt+1] = '\0';
cnt++;
delayMicroseconds(SerialDelay);
}
cnt = 0;
}
int CompareAndReturn() {
if(strcmp(PERCommand, SerialCommand) == 0) {
Serial.print(per);
} else {
error();
}
}
int error() {
Serial.print(-1);
while(Serial.available() > 0){
Serial.read();
delayMicroseconds(SerialDelay);
}
return(0);
}
// ISR
void handler() {
time[1] = micros();
per = time[0] - time[1];
time[0] = time[1];
}
I tried to comment out GetCommand() and CompareAndReturn() functions and just putting there a Serial.print() function to return period(I was wondering if the serial communication could be the problem), I also tried detachInterrupt(), but it's just not working properly.
Is there another way to tackle the problem?
If anyone knows what the problem could be please do help.
Cheers,
Jure