RPM algorithm works, only if there is a serial.println in it?

Hi All,

Im scratching my head on this one, when I run the following code, it works.

void checkRPM() {

        interruptCount = 0;
        delay (100);
        Serial.print("\t");
        rpm = ((interruptCount)*(60))/(numpoles)*10;
        Serial.println("RPM : ");
        Serial.println(rpm);
        
   }

void interruptFired()
{
    interruptCount++;

}

But when I run this code, the rpm displays 0!!

void checkRPM() {

        interruptCount = 0;
        delay (100);
        //Serial.print("\t");
        rpm = ((interruptCount)*(60))/(numpoles)*10;
        Serial.println("RPM : ");
        Serial.println(rpm);
        
   }

void interruptFired()
{
    interruptCount++;

}

The Serial.print() before the rpm expression can say anything. Is this because I need to give more time to collect the interrupts? :(

Post ALL the code, so we can see how you declared variables.

For example, interruptCount must be declared volatile.

Sorry about that, here is the code:

// ---------------------------------------------------------------------------
#include <Servo.h>
// ---------------------------------------------------------------------------
// Customize here pulse lengths as needed
#define MIN_PULSE_LENGTH 1000 // Minimum pulse length in µs
#define LOW_PULSE_LENGTH 1250
#define MEDL_PULSE_LENGTH 1450
#define MEDH_PULSE_LENGTH 1650
#define MAX_PULSE_LENGTH 2000 // Maximum pulse length in µs
// ---------------------------------------------------------------------------
//SERVO VARIABLES
Servo motA;
char data;
int motorPin = 4; //Digital Pin 4

// -------------- VARIABLES ---------------

//RPM READING VARIABLES
#define INTERRUPT_PIN 0   // digital pin 2
volatile int interruptCount;
float rpm = 0;
float numpoles = 22;   //Change value to the number of magnets in the motor


void setup() {
    Serial.begin(9600);

    // RC MOTOR INIT
    motA.attach(motorPin, MIN_PULSE_LENGTH, MAX_PULSE_LENGTH);


    // RPM COUNTER INIT
     pinMode(INTERRUPT_PIN, INPUT);
     attachInterrupt(INTERRUPT_PIN, interruptFired, CHANGE);
      
    //DISPLAY SERIAL INSTRUCTIONS ON BOOT
    displayInstructions();
   
}


void loop() {
  
  //SERIAL MOTOR CONTROL INPUT FUNCTION
    if (Serial.available()) {
        

        switch (data) {
            // 0
            case 48 : Serial.println("Sending minimum throttle");
                      motA.writeMicroseconds(MIN_PULSE_LENGTH);

            break;

            // 1
            case 49 : Serial.println("Sending low throttle");
                      motA.writeMicroseconds(LOW_PULSE_LENGTH);
                      
            break;

            // 2
            case 50 : Serial.println("Sending medium low throttle");
                      motA.writeMicroseconds(MEDL_PULSE_LENGTH);

            break;

            // 3
            case 51 : Serial.println("Sending medium high throttle");
                      motA.writeMicroseconds(MEDH_PULSE_LENGTH);

            break;

            // 4
            case 52 : Serial.println("Sending maximum throttle");
                      motA.writeMicroseconds(MAX_PULSE_LENGTH);

            break;

            // 5
            case 53 : // RPM COUNTER FUNCTION 
                      checkRPM();
                     
           break;

        }
    }

// MAIN LOOP FUNCTIONS BELOW

// END MAIN LOOP

}

/// START RPM FUNCTIONS ///
  void checkRPM() {
    
        interruptCount = 0;
        delay (100);
        Serial.print("hi");
        rpm = ((interruptCount)*(60))/(numpoles)*10;
        Serial.println("RPM : ");
        Serial.println(rpm);
        
   }

void interruptFired()
{
    interruptCount++;

}

/// END RPM FUNCTIONS ///

You are not using a critical section to access the interruptCount variable, so it will get garbled every now and again.

You need:

  void checkRPM() {
        noInterrupts() ;
        interruptCount = 0;  // set variable in critical section
        interrupts() ;

        delay (100);
        noInterrupts() ;
        int my_copy = interruptCount ;  // read variable in critical section 
        interrupts() ;
        Serial.print("hi");
        rpm = ((my_copy)*(60))/(numpoles)*10;
        Serial.println("RPM : ");
        Serial.println(rpm);
       
   }

Thank you, this worked! it was my first time doing something of this sort so this really pointed me in the correct direction.

So, if I am not mistaken, in this code snippet:

void checkRPM() {
        noInterrupts() ;
        interruptCount = 0;  // set variable in critical section
        interrupts() ;
        delay (100);
        noInterrupts() ;
        int my_copy = interruptCount ;  // read variable in critical section 
        interrupts() ;
        rpm = ((my_copy)*(60))/(numpoles)*10;
        Serial.println("RPM : ");
        Serial.println(rpm);
       
   }

the noInterrupts() and interrupts() disables and enables interrupts. I needed to disable it in order to read/write to the interruptCount variable correctly. Would I be correct in assuming i would be able to just directly access the interruptCount variable without re-enabling interrupts and just reenable them at at the end of the function like so:

void checkRPM() {
        noInterrupts() ;
        interruptCount = 0;  // set variable in critical section
        interrupts() ;
        delay (100);
        noInterrupts() ;
        
        rpm = ((interruptCount)*(60))/(numpoles)*10;
        Serial.println("RPM : ");
        Serial.println(rpm);
        interrupts() ;
       
   }

I guess my question is would it be a more efficient way to do it this way rather than create another variable?

Turn off interrupts only when absolutely necessary. Functions like millis() and Serial print() require interrupts to be on.

drinnird: Would I be correct in assuming i would be able to just directly access the interruptCount variable without re-enabling interrupts and just reenable them at at the end of the function

No, completely incorrect, everything grinds to a halt if you do that. delay() busy-waits for interrupts so freezes forever if interrupts are disabled.

Thank you all for the insight into interrupts. I went ahead and tried it both ways and you are correct, when the interrupts are disabled everything just sort of locks up. Thanks for helping me to understand how interrupts work!