I'm using some code that i found here somewhere (thanks to whoever wrote this) for reading rpm on an input. It seems to be working fine except when i remove the input the output in the serial monitor doesn't drop to zero.
Am i missing something obvious?
The input signal is generated using tone from another arduino
int rpm = 0;
const int DispSampleTime = 200; //[millisec] //= 0.1sec
volatile unsigned long lastTime;
volatile unsigned long thisTime;
volatile unsigned long duration;
unsigned long disp_timeold = 0UL;
unsigned long timetemp = 0UL;
volatile uint32_t rev; // Revolution Count
unsigned long measureTime = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(0, rpm_interrupt, FALLING);
}
void loop() {
// DISPLAY RPM
timetemp = millis() - disp_timeold;
if( timetemp >= DispSampleTime)
{
disp_timeold += timetemp;
rpm = 60e6/duration; // 60.000.000 micros / duration in micros
}
Serial.print("RPM"); // prints RPM value
Serial.println(rpm);
}
void rpm_interrupt()
{
lastTime = thisTime;
thisTime = micros();
duration = thisTime-lastTime;
}
Edit: There is a pullup through a 10k resistor on the input
Obviously you are using interrupt at pin0. If you disconnect the input, the interrupt function rpm_interrupt() is not called, the value of duration is not changed.
On the other hand, how do you want to get zero if rpm = 60e6/duration? What duration need to be to get rpm = 0?
You can add one more check: if the timetemp is longer than for example 1 second, simply print 0.
Hello
the sketch is doing exately what it be. The variable duration contains the last time measured.
I did made some mods to your sketch wrt the mentioned variable. Test it. It´s untestet and uncompiled.
int rpm = 0;
const int DispSampleTime = 200; //[millisec] //= 0.1sec
volatile unsigned long lastTime;
volatile unsigned long thisTime;
volatile unsigned long duration;
unsigned long disp_timeold = 0UL;
unsigned long timetemp = 0UL;
volatile uint32_t rev; // Revolution Count
unsigned long measureTime = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(0, rpm_interrupt, FALLING);
}
void loop() {
// DISPLAY RPM
timetemp = millis() - disp_timeold;
if ( timetemp >= DispSampleTime)
{
disp_timeold += timetemp;
if (!duration) {
rpm = 60e6 / duration; // 60.000.000 micros / duration in micros
duration = 0;
} else rpm = 0;
}
Serial.print("RPM"); // prints RPM value
Serial.println(rpm);
}
void rpm_interrupt()
{
lastTime = thisTime;
thisTime = micros();
duration = thisTime - lastTime;
}
I have no idea how to quote with this new forum. Should have mentioned in the first post it was a nano, so interrupt 0 is pin 2.
The solution was what paulpaulson posted, with 'if (duration)' as pointed out by alto777.
Here's the working code. Gives a clean output with minimal accuracy loss and no massively long delays.
int rpm = 0;
const int DispSampleTime = 200; //[millisec] //= 0.1sec
volatile unsigned long lastTime;
volatile unsigned long thisTime;
volatile unsigned long duration;
unsigned long disp_timeold = 0UL;
unsigned long timetemp = 0UL;
volatile uint32_t rev; // Revolution Count
unsigned long measureTime = 0;
void setup() {
Serial.begin(9600);
attachInterrupt(0, rpm_interrupt, FALLING);
}
void loop() {
// DISPLAY RPM
timetemp = millis() - disp_timeold;
if ( timetemp >= DispSampleTime)
{
disp_timeold += timetemp;
if (duration) {
rpm = 60e6 / duration; // 60.000.000 micros / duration in micros
duration = 0;
} else rpm = 0;
}
Serial.print("RPM"); // prints RPM value
Serial.println(rpm);
}
void rpm_interrupt()
{
lastTime = thisTime;
thisTime = micros();
duration = thisTime - lastTime;
}