Problem with smoothing values while using attachInterrupt

Hi All,

I was hoping that someone could help me out with a problem I’m having with attachInterrupt and trying to smooth values that it is creating. This code is for a heart rate monitor that works through an IR LED sensor and phototransistor. When I run it, the sensor reads the time between pulses well using attachInterrupt and millis().

The problem is that I want to smooth the values, as they are pretty aperiodic. If it could smooth somewhere between 5 and 10 values, that would be great. The thing is that since the function that is called by the interrupt has to be void, I can’t return a value (BPM in this case). Can someone help me out?

int heartBeatIn = 2; // Digital pin 2 selected for input
byte HRbpm = 0;  // Declare this as a byte if the count is always less than 255
		     // so you don't have to disable interrupts when using in loop
long lastFire = 0;
long currentTime = 0;
int BPM;

void setup() 
  {
  Serial.begin(9600); //Configure serial output
  
  pinMode(heartBeatIn, INPUT); //Pin 2 declared as an input
  digitalWrite(heartBeatIn, HIGH);  // Turn on pullup resistor
  
  attachInterrupt(0, count, RISING); // Call function "count" when pin 2 goes high
  
  lastFire = millis(); // lastFire = the time (in ms) since the program started running
  currentTime = millis(); // currentTime = the time (in ms) since the program started running
  
  }

void loop()
  {
   HRbpm= 0;

   byte HRcount = HRbpm;  // Get a snapshot of the count   
  }

void count()
  {
   HRbpm++;
   currentTime = millis(); // Value of currentTime becomes whatever the
                           // the time is since the program started running
   
   float temp = (60.0/((currentTime-lastFire)/1000.0)); // (60 seconds / frequency)= BPM
   
   if (temp < 220 && temp > 40)// Default outlying values to previous BPM
      BPM = temp;
      
   Serial.println(BPM); // Print the BPM
   
   lastFire=millis(); // Value of lastFire becomes time program has been running
  }

If the interrupt fires every time there is a heartbeat, it is not necessary to compute beats per minute in the interrupt handler. You should do there periodically in loop - every pass, every 100 milliseconds, whatever.

Interrupt handlers are supposed to be very fast. Serial.print() is not. It, therefore, does not belong in an ISR.

Variables that are referenced by an ISR and by code other than an ISR should be declared volatile. Yours are not.

I think you need to seriously rework your ISR.

I actually do not need to print the value, that was just to check and make sure I was getting the correct values, so that can/will be removed.

Will declaring the ISR as volatile let me return the value of "BPM"?

Will declaring the ISR as volatile let me return the value of "BPM"?

No. You don't need to return anything from the ISR, since the only thing that the ISR should be being is counting beats. The "per minute" nature is supposed to be handled outside the ISR.

If it could smooth somewhere between 5 and 10 values, that would be great

Have a look at the runningAverage class - http://arduino.cc/playground/Main/RunningAverage - it just does that

Sorry if I'm not following, but if nothing is being returned from the ISR, then how can I smooth the values?

Fix the problems with your ISR. Then, see if smoothing is still required. Your ISR should look like this:

void count()
{
   HRbpm++;
}