RPM measurement as a function with main delay


It’s my first post on this forum and I was inspired by this thread for my project :

Ref: RPM thread

I’m looking to log the RPM on a timer (0 here) for 1000 ms as a subfunction of my main code. The problem is that I have to wait for 2 sec in my main loop because another sensor need this break to capture an accurate value.

Here’s the code

declarations :
// RPM Function declarations
volatile int rpmcount = 0;
int rpm = 0;
unsigned long lastmillis = 0;

Main :
void loop() {
delay(2000); // Refresh rate (min. 2000 for TX23 readings)

void fnReadRPM(int x){
attachInterrupt(x, rpm_fan, RISING);//interrupt cero (0) is on pin two(2)
unsigned long trigger = (millis() + 1000);
while (millis() != trigger){ /Uptade every one second, this will be equal to reading frecuency (Hz)./
detachInterrupt(x); //Disable interrupt when calculating
rpm = rpmcount * 60; /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
Serial.print(“RPM =\t”); //print the word “RPM” and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word “Hz”.
Serial.println(rpmcount); /print revolutions per second or Hz. And print new line or enter./
rpmcount = 0; // Restart the RPM counter
lastmillis = millis();

void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/

This way, the returned RPM value is accurate but the entire arduino freeze

Any advice ??

Thanks !!

Using interrupts just so you can waste time in a delaying loop seems kind of crude. Perhaps you should tell us something about this "other sensor" and post your full code using code tags.

Nothing very fancy about the "other sensor", it's just a LaCrosse Anemometer I use to measure wind's speed & direction. The lib I'm using recommend having a 2000ms delay to be sure that the next read will not be corrupted.

The "crude" while loop I'm using it's to let the rpmcount value be updated for 1000ms without "stopping" the count and having a precise refresh rate in the main loop and having the same time a precise rpm count as x count in 1 sec. x 60 for the rpm value.

I've noticed the arduino not seems to be fully stalled, I'm using an "analogWrite(8,2)" in the main loop to generate a pulse catched by the timer. Maybe a conflict between them???? Sounds like something stacking in a registry, maybe only the one returning values to the serial monitor...

Thanks !!

sebviel: The lib I'm using recommend having a 2000ms delay to be sure that the next read will not be corrupted.

That doesn't mean you have to delay for two seconds doing nothing. Check out: https://forum.arduino.cc/index.php?topic=503368.0

Delaying the loop() code while your ISR gathers data totally defeats the whole purpose of interrupts. You need to rethink and restructure that. I'd have the ISR gather rpm counts until it has "enough" (either at least one second's worth or some minimum number of counts). Then set a flag for the loop() code to detect. This loop() code then gathers both the actual count and actual elapsed time (both of which could have increased since the flag was set). Copy these to local variables, reset timer, counter, and flag (all within noInterrupts() / interrupts() protection block because the operations won't be atomic). Finally, compute and print results. To do all this, you also need to read up on declaring variables volatile.

The above will keep loop() running continuously with no wasteful delay() functions or while() loops.