Serial Printing in Conditional Doesn't Work When I Remove Else Statement

Background: I am writing code that processes and identifies the QRS complex (R peak) in an ECG waveform for the 2nd lead.

Board Used: Arduino Uno Rev3

Issue: At the bottom of my code, I have a conditional that should print that the R peak was detected. I have confirmed that the code works as intended in the current version (what's posted below). When I remove the else statement, nothing prints anymore.

Attempts to Solve: I have stripped the code to try and identify where the issue is. When I have only the Serial.print("No"); in the else statement, the same issue occurs where nothing is detected apparently. Background research on other similar questions has not yielded much help.

** This code requires an input signal from a function generator using a 2.2Vpp 1Hz 0.6VDC offset ECG signal **

////// Library declarations
#include <stdio.h>

////// Input pin declarations
int lead2 = A0; // ECG

////// Variable declarations
float L2, L5;
float data_L2[5][5];    // by columns:
// time, input, filter, 1st derv, 2nd derv
float qrs[5][2];        // by columns:
// time, detected qrs input value
float trends[1000][2];  // by columns:
// time, rr_int
////// Data variables
// Data calculations
float tim, derv1, derv2, sum = 0;
// Flags
int flag1 = 0, flag2 = 0, flag3 = 0, flag4 = 0;
// ECG variables
float rr_int, qrs_time, qrs_data;
float gain;
// Internal detection flags
bool qrs_detect = false;
int tmp = 0; 

///////////////////////////// SETUP /////////////////////////////////
void setup() {
  // Beging serial monitor communication
  Serial.begin(9600);

  // Declaring pin modes for analog inputs
  pinMode(lead2, INPUT);
}

///////////////////////////// LOOP //////////////////////////////////
void loop() {
  // Reading input values
  L2 = analogRead(lead2);
  tim = millis(); // micros(); // use micros() if need greater precision. returns microseconds since startup

  //
  ////// Smoothing input data //////
  //
  // Assigning data to arrays for time and input
  for (int i = 4; i > -1; i--) {
    if (i != 0) {
      // Time data
      data_L2[i][0] = data_L2[i - 1][0];

      // Analog Values
      data_L2[i][1] = data_L2[i - 1][1];
    }
    else {// if i=0
      // Time data
      data_L2[i][0] = tim;

      // Analog values
      data_L2[i][1] = L2;
    }
  }

  //// ECG
  // Smoothing data
  sum =   data_L2[1][1] + data_L2[0][1];
  // Shifting data back
  data_L2[4][2] = data_L2[3][2];
  data_L2[3][2] = data_L2[2][2];
  data_L2[2][2] = data_L2[1][2];
  data_L2[1][2] = data_L2[0][2];
  data_L2[0][2] = sum / 2;

  //
  ////// First & Second Derivative
  //
  //// ECG Data
  // Calculating first and second derivative
  derv1 = data_L2[2][2] - data_L2[4][2];                     // First Derv
  derv2 = data_L2[2][2] - 2 * data_L2[3][2] + data_L2[4][2]; // Second Derv

  // Shifting derivative values down
  for (int i = 4; i > -1; i--) {
    if (i != 0) {
      data_L2[i][3] = data_L2[i - 1][3]; // first derv
      data_L2[i][4] = data_L2[i - 1][4]; // second derv
    }
    else {
      data_L2[i][3] = derv1; // first derv
      data_L2[i][4] = derv2; // second derv
    }
  }

  //
  ////// ECG Detection Scheme
  //
  // Looking at 5 values of derivatives
  for (int i = 1; i < 4; i++) {
    // First derv should be decreasing and have very large margins between previous and nex point (+/- 150)
    if ((data_L2[i + 1][3] > 0) && (data_L2[i - 1][3] < 0)) { // Trying to find zero crossing
      flag1++;
    }
    if(data_L2[i][4] < -300) {
      flag2++;
    }

    // Checking flag for qrs detection
    if (flag1 == 1 && data_L2[i][0] > qrs_time + 300 && flag2 == 1) {
      // Saving time point for qrs
      qrs_time = data_L2[i][0]; // saving time location

      // Internal flag detection
      qrs_detect = true;

      // Breaks out of code so you don't have multiple detections on single QRS
      break;
    }
    tmp = i; 
  }

  // Resetting ECG flags
  flag1 = 0;
  flag2 = 0;

///////////////////////////
// Issue Area Below Pls Help
///////////////////////////
  
  // Conditional that prints out data every new detection for ECG or BP
  if (qrs_detect == true) {
    // Setting internal ECG flag back to no detect
    qrs_detect = false;

    // Printing data
    Serial.print("Detection");
    Serial.print(",");
    Serial.print(qrs_time/1000);
    Serial.print(",");
    Serial.println(tmp);
    delay(1);
  }
  else {
    Serial.print("No");
    Serial.print(",");
    Serial.println(data_L2[0][3]);
  }
}

I'm not sure why I require this else statement and the Serial.print statements that are in it for my detection code to properly print out a positive detection. I also attached two images knowing that most people can't run this code to simulate my problem. The first image is of the Serial Monitor with the else statement included. At 12:04:50:459, a positive detection is recorded. The second image is where I removed

    Serial.print(",");
    Serial.println(data_L2[0][3]);

in the else statement. There should be a detection at the highlighted area, but there is not.

Please help :slight_smile: Much thanks

I don't know if I understood the problem, so when u take out the else statment the previous if (qrs_detect == true) doesnt print anything?

That is correct; removing the else statement for if(qrs_detect==true) prints nothing when I expect something to print.

You've got a crazy mix of data types.
analogRead does not return a float.
You should not assign a float to a bool.

And a Uno doesn't have enough RAM.

I don't know why you're moving so much data around.
Don't move data, move indices.
It's quicker.

The only thing I can think of is that your serial is set to 9600 baud. Each character you print to the serial will require about 1ms to transmit. Your serial output in the else statement will require about 9ms each time through loop. Without the else your analogs are being read much faster.

Try putting a 10ms delay in the else rather than printing to serial and see what happens.

Not withstanding your data typing and memory issues pointed out by AWOL.

float trends[1000][2]; ...and get real.

TheMemberFormerlyKnownAsAWOL:
float trends[1000][2];  ...and get real.

float is about as "real" as it gets :slight_smile: Well...maybe not...there's always double.

Without knowing the frequency of your input signal it is hard for me to know if timing is the issue but I suspect it is.

Any recommendations on moving the indices of data vs. shifting the data itself? Didn't realize I could do that.

There's also other parts of this code that I took out which is why I had trends[][]...

I implemented a 10ms delay and that fixed this issue. Thanks!