Custom ECG using FFT

I am almost done with my ECG but I am running into a problem where I get a negative frequency when im using FFT to find my heart rate. I want to use FFT to get amp, freq and phase so I can graph a waveform of my heart beat. What am I missing or doing wrong? I am using an ESP32 Heltec LoRa and ThinkSpeak to store the data and display the waveform

#include <WiFi.h>
#include <Wire.h>
#include "heltec.h"
#include "arduinoFFT.h"
#include "ThingSpeak.h"
#include <math.h>
// connect the signal to the pin 13 of heltec LoRa ESP32

arduinoFFT fft = arduinoFFT();
WiFiClient client_1;


// ************* Variables and WiFi SSID/PWD setup
const char* SSID_1 = "SSID"; 
const char* PWD_1 = "PWD";
 
unsigned long myChannelNumber2 =   Ch2;         //Collects Amplitude
const char * myWriteAPIKey2 = WriteAPI2";

unsigned long myChannelNumber3 = Ch3;           //Collects Frequency
const char * myWriteAPIKey3 = "WriteAPI3";

unsigned long myChannelNumber4 = Ch4;           // Collects Phase
const char * myWriteAPIKey4 = "WriteAPI4";

int status = WL_IDLE_STATUS;

const int FFT_size = 256;
const int Sampling_freq = 20; 
const int Heart_Read = 13;
const int N = 6;
//float Signal;
double vReal[FFT_size];
double vImag[FFT_size];
double vPhase[FFT_size];
double x = 0;
double v = 0;
double peaks[N];
double phases[N];
double freq[N];
// *******************************************************************
void setupOLED()
{
  pinMode(RST_OLED, OUTPUT);
  digitalWrite(RST_OLED, LOW);        // turn D16 low to reset OLED
  delay(50);
  digitalWrite(RST_OLED, HIGH);       // while OLED is running, must set D16 in high
  Heltec.display->init();
  Heltec.display->flipScreenVertically();           
  Heltec.display->setFont(ArialMT_Plain_10);         
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); 
}

//********************************************************************

void setupWIFI()
{
  WiFi.disconnect(true);
  delay(1000);
  
  WiFi.mode(WIFI_STA);  
  WiFi.setAutoConnect(true);      
  WiFi.setAutoReconnect(true);    
  WiFi.begin(SSID_1, PWD_1);
  //ThingSpeak.begin(client_1);
/*
  Heltec.display->clear();
  if(WiFi.status() == WL_CONNECTED)
    Heltec.display->drawString(0, 0, "WiFi Connected"); 
  else
    Heltec.display->drawString(0, 0, "WiFi Connection Failed");
  Heltec.display->display();
*/  
}

//*****************************************************

void setup() 
{
  Serial.begin(115200);
  ThingSpeak.begin(client_1);
    
  Heltec.begin(true, false, true);
  pinMode(25, OUTPUT);
  digitalWrite(25,HIGH);
  pinMode(Heart_Read, INPUT);

  Heltec.display->init();
  Heltec.display->flipScreenVertically();           
  //Heltec.display->setFont(ArialMT_Plain_10);         
  Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT);  
}

// ******************************************************
void loop() 
{   
  delay(5000);
  for (int k = 0; k < FFT_size; k++)
     {
      vReal[k] = (double)analogRead(Heart_Read);
      //Serial.println(vReal[k]);      
      vImag[k] = 0;
      delay(50);    //Delay = 1000/Sampling_freq
     }
  delay(100);

  fft.Windowing(vReal, FFT_size, FFT_WIN_TYP_RECTANGLE, FFT_FORWARD);
  fft.Compute(vReal, vImag, FFT_size, FFT_FORWARD);
  for (int k = 0; k < FFT_size; k++)
     vPhase[k] = atan2(vImag[k], vReal[k]);
  fft.ComplexToMagnitude(vReal, vImag, FFT_size);
  fft.MajorPeak(vReal, FFT_size, Sampling_freq,&x,&v);
  int Heart_rate = (int) (x * 60);
  //Serial.println(x);
  //Serial.println(v);
  int n_peak = (int)((double)x * (double)FFT_size/(double)Sampling_freq);
  //Serial.println(n_peak);
  delay(1000);
  
  for (int cnt = 0; cnt < FFT_size/2; cnt++)
     {
      if (vReal[cnt] < 0.1 * v)
        vReal[cnt] = 0;  
     }
  
  int knt,cnt = 0;
  double temp;
  for(knt = 1; knt <= FFT_size/2; knt++)
    {
     temp = vReal[knt];
     if ((temp > vReal[knt+1]) && (temp > vReal[knt-1]) && (cnt < N))
       {
        peaks[cnt] = (double) vReal[knt]/(double)FFT_size;
        phases[cnt] = (double) vPhase[knt]; // * 180.0 / 3.141592;
        freq[cnt] = (double)(knt * Sampling_freq)/(double)FFT_size;
        cnt++;
       }
    }     
/*    
  for (cnt = 0; cnt < N; cnt++)
     {     
      Serial.print(freq[cnt]);
      Serial.print("     ");
      Serial.print(phases[cnt]);        
      Serial.print("     ");
      Serial.println(peaks[cnt]);
     } 
*/  
  delay(100);
  setupOLED();
  Heltec.display->clear();
  Heltec.display->setFont(ArialMT_Plain_16);
  String BPM = String("BPM: " +String(Heart_rate));
  Heltec.display->drawString(0,10,BPM);
  Heltec.display->display();
  delay(5000);
  Heltec.display->clear();
  Heltec.display->display(); 
  digitalWrite(RST_OLED, LOW);        // turn D16 low to reset OLED
  delay(50);
  digitalWrite(RST_OLED, HIGH);       // while OLED is running, must set D16 in high
    
  delay(100);
  setupWIFI();
  
  for(cnt = 0; cnt < N; cnt++)
     {
      ThingSpeak.setField(cnt+1, (float)peaks[cnt]);
      ThingSpeak.writeFields(myChannelNumber2, myWriteAPIKey2);   
      delay(15000);  
     }
     
  ThingSpeak.setField(7, Heart_rate);
  ThingSpeak.writeFields(myChannelNumber2, myWriteAPIKey2);   
  Serial.println("The heart-rate was sent to ThingSpeak");
  delay(15000); 
       
  for(cnt = 0; cnt < N; cnt++)
     {
      ThingSpeak.setField(cnt+1, (float)freq[cnt]);
      ThingSpeak.writeFields(myChannelNumber3, myWriteAPIKey3);   
      delay(15000);  
     }    
  for(cnt = 0; cnt < N; cnt++)
     {
      ThingSpeak.setField(cnt+1, (float)phases[cnt]);
      ThingSpeak.writeFields(myChannelNumber4, myWriteAPIKey4);   
      delay(15000);  
     } 

  delay(500);
  delay(300000);
  
  //WiFi.disconnect();
  WiFi.mode( WIFI_MODE_NULL );
    
}

Show us the output.

Error compiling for board Arduino Uno.

I doubt that is the complete listing... post the entire message. Don't paraphrase, copy and paste.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.