Part of my project is to build heart rate monitor from Nano and a PulseSensor. I am having trouble working with the Fast Fourier Transform part of the code.
This code here is from a library (arduinofft) that can be found in the arduino IDE. When testing the arduino the serial printer returns values of about 51 bpm, which is far to low, compared to other devices of about 70bpm.
What i have done:
- changed the sampling frequency to 5.6Hz to get the range of 0 to 2.8Hz range for the hate rate
- edited the library to only take the last 25 to 128 samples (only when computing the max peak), to off-set the DC. Previously getting readings of 5 BPM
What i don't understand:
the sampling period, if the samples are taken and put into an array every second what does the period do.
Also if samples are taken every second is this enough to get a good reading on a heart rate shouldn't the sample be maybe of 15-30 seconds?
If this is so, should i put another array at the bottom. To capture the results every second upto 15 or 30, print the average then first in first out the array of new values?
#include "arduinoFFT.h"
arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
#define CHANNEL A0
const uint16_t samples = 128; //This value MUST ALWAYS be a power of 2
const double samplingFrequency = 5.6; //Hz, must be less than 10000 due to ADC
unsigned int sampling_period_us;
unsigned long microseconds;
double vReal[samples];
double vImag[samples];
#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02
#define SCL_PLOT 0x03
void setup()
{
sampling_period_us = round(1000000*(1/samplingFrequency));
Serial.begin(115200);
Serial.println("Ready");
}
void loop()
{
/*SAMPLING*/
for(int i=0; i<samples; i++)
{
microseconds = micros(); //Overflows after around 70 minutes!
vReal[i] = analogRead(CHANNEL);
vImag[i] = 0;
while(micros() < (microseconds + sampling_period_us)){
}
}
FFT.Windowing(vReal, samples, FFT_WIN_TYP_RECTANGLE, FFT_FORWARD); /* Weigh data */
FFT.Compute(vReal, vImag, samples, FFT_FORWARD); /* Compute FFT */
FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */
double x = FFT.MajorPeak(vReal, samples, samplingFrequency); /* Compute largest peak*/
double y = round((60/(1/x)));
Serial.println(y); //print bpm
delay(2000); /* Repeat after delay */
}
Thanks for any help