Program freezing after constant number of iterations

I’m working on a program to calculate and display SpO2 via the MAX30102 sensor, the Feather M4 Express uController, and an LCD. The sketch is setup to run when the MAX triggers an interrupt, and it performs the SpO2 calculation every other interrupt (to allow data to fill the FIFO queue I’ve written). For some reason, the output (confirmed using both serial monitor and the LCD) freezes after exactly 23 iterations of the calculation and display cycle. I use the FIFO queue that I wrote to pass around data, and I suspect there is a memory leak problem somewhere. I have deleted all dynamically allocated arrays (I think!) using delete once they are no longer needed. There is quite a bit of code that I’ve written, but I’ve included the relevant functions that get called for the calculation. I am confident that it is not a problem with the class that I wrote to communicate with the registers on the MAX30102, because that has ran fine in the past over extended periods.

I have attached the sketch and the .cpp file where the algorithm is contained. Is there a memory issue I’m missing, or something else? Thank you for your time!

SpO2AlgorithmFIFO.cpp (9.3 KB)

TestFIFOAlgorithm.ino (2.07 KB)

CircularFIFO.cpp (3.58 KB)

Can you post the CircularFIFO class code directly in the forum? Can’t read .ino on mobile

I also see some dynamic instanciations of smoothed and average CircularFIFO which possibly poke holes into your heap.

I've attached the CircularFIFO class to the original post. Here's the sketch (case 128 is what is triggered by the sensor):

#include "SpO2AlgorithmFIFO.h"
#include "MAX30102.h"
#include "CircularFIFO.h"
#include "LCDdisplay.h"

MAX30102 sensor;
LCDdisplay screen;

volatile bool intFlag = false;
volatile int k = 0;

void setup() {
//  Serial.begin(115200);
//  while(!Serial);



  pinMode(10, INPUT);
  attachInterrupt(digitalPinToInterrupt(10), interruptRoutine, FALLING);


void loop() {

  if (intFlag) {
      switch(sensor.readFromRegister(0x00)) {
        case 0: // Temperature reading ready
        case 1: // Initial power up ready
        case 32: // Ambient light cancellation overwhelmed
        case 64: // FIFO has at least one data element
        case 128: // FIFO is almost full
          if (++k >= 2) {
            displaySpO2(calculateSpO2(*(sensor.getRedFIFO()), *(sensor.getIRFIFO()), 50), calculateHR(*(sensor.getRedFIFO()), 50, 6));
            k = 0;
      intFlag = false;


void interruptRoutine() {
  intFlag = true;

void displaySpO2(uint8_t SpO2, uint8_t HR) {

As far as the dynamic instantiations, I think the only things which are dynamically instantiated are the peaks and valleys arrays. The other object instantiations don't use the "new" keyword, and I think have lifetimes limited to their scopes (the functions they are created in, or the functions which call functions which create them). Is that incorrect?

I see the constructor where you allocate the array

CircularFIFO::CircularFIFO(uint16_t size) {
	write = read = -1;
	arr = new uint32_t[size];
	this->size = size;
	itemCount = 0;

I think you need a destructor where you free up (call delete) the arr array

The standard behavior of the implicit destructor is to destroy all data members and base classes. However, deleting a raw pointer (which I assume arr is) simply removes the pointer, not what it points to.

(new creates and initializes objects with dynamic storage duration, that is, objects whose lifetime is not necessarily limited by the scope in which they were created)

That's it! After adding a destructor to free the array memory, everything works great.

Thanks for your help!