# How to find peaks & eliminate flat tops

I am very stuck here, I am using a pulse sensor and I need to find all peak points of the heartbeat. I am saving 256 points of data of the heartbeat to an array. I can find the top max point but I need to also find the 2nd, 3rd, 4th… max point if present… at times the max repeats to where the data in the array looks like [345,380,420,455,455,455,455,455,365,397,385,399] It’s very obvious 455 is the local max but its also a flat top and it prints the result as many times as 455 shows up. I just need it to show it once, along with its index in the array. I will post my code, I hope to get some feedback, as basic as possible please I am still learning code.

``````int inp;

void setup()
{
Serial.begin(9600);  // for debugging
}
void loop()
{
float dt = 0.01;
int ind1, mult;
float x, val1, val2, ind2;
val1 = -1.2;
int i;

for (i = 0 ; i < 256 ; i ++) // save 256 samples
{
//Serial.println((String)inp[i]+" index at - "+i);
delay(10);
} // close for

int max_i = 0;
int max_v = 0;

for (int i = 0; i < 256; i++)
{
if ( inp[i] > max_v )
{
max_v = inp[i];
max_i = i;
}
}
Serial.println((String)"\nGlobal Max is " + max_v + " at index " + max_i +"\n");
//Serial.println(max_v);

int N = 10;   // loc max neighborhood size
int cnt1 = 0;  // count number of local maxima
int cnt2 = 0;  // count number of distinct local maxima

for (int i = N-1; i < 255-N; i++)
{
bool loc = true;
for (int j = 1; j < N; j++) // look N-1 back and N-1 ahead
{
if (inp[i] > inp[i-j] && inp[i] > inp[i+j]) loc = false;
}
if (loc == true)
{
cnt1 = cnt1 + 1;
val1[cnt1] = x[i];
ind1[cnt1] = i;
if (x[i] != val1[cnt1-1])
{
cnt2 = cnt2 + 1;
mult[cnt2] = 1;
}
else
{
mult[cnt2] = mult[cnt2] + 1;
}
}

} // end for i

int cnt3 = 0;
Serial.println("Max value and time");
for (int i=1; i<=cnt2; i++)
{
int mid = 0;
for (int j=1; j<=mult[i]; j++)
{
mid = mid + ind1[cnt3 + j];
}
val2[i] = val1[cnt3 + mult[i]];
ind2[i] = dt*mid/mult[i];
Serial.print(val2[i]);
Serial.print("  ");
Serial.println(ind2[i]);
cnt3 = cnt3 + mult[i];
}

Serial.println("----------------------------------");

} // close main loop
`````` This appears to be a continuation of a previous thread of yours:

Are you now simply looking now for transitions from rising to falling values ? If so, the example you have given would be:

``````345,380,420,455,455,455,455,455,365,397,385,399
R   R   R   R   R   R   R   R   F   R   F   R
!!!     !!!

F = less than previous value ie falling
R = rising ie not falling
!!! = transition R->F detected ie next value smaller than current.
``````

You'll still have a problem though if your "flat top" has very slight "dents" in it. So you may have to apply some "smoothing" :

``````345,380,420,455,454,455,454,455,365,397,385,399
R   R   R   R   F   R   F   R   F   R   F   R
!!!     !!!     !!!     !!!

F = less than previous value ie falling
R = rising ie not falling
!!! = transition R->F detected
``````

Peak detection in data streams is a very common problem and there are several general purpose algorithms to find peaks.

Save yourself from reinventing the wheel and Google "peak detection algorithms" or "peak finding 1d" for lots of leads.

Is it possible for anyone to look through my code and fix any imperfections, I'm stumped..

rogernm001:
Is it possible for anyone to look through my code and fix any imperfections, I'm stumped..

yes, In my code if you look closely I use an algorithm for finding peak points. Thats not my issue... the flat tops are my issue, where they repeat and print each repeated value as a peak point which is false.. every example I observe does not contain flat tops so of course results are successful.

rogernm001:
yes, In my code if you look closely I use an algorithm for finding peak points. Thats not my issue… the flat tops are my issue, where they repeat and print each repeated value as a peak point which is false… every example I observe does not contain flat tops so of course results are successful.

No… your algorithm is the issue, since it is the one that is generating these ‘flat tops’, right?

This means ----- you need some other kind of algorithm.

You probably need to provide a file (eg. text file) that contains the raw data … ie. value versus time. And plot these values versus time, so that you can look at the raw measurements. And then everyone can get an idea about what your algorithm has done to the raw data.

rogernm001:
where they repeat and print each repeated value as a peak point which is false

Write down on paper step by step your thought process, ie. what decisions you make, to determine what constitutes a 'flat top' and why repeated peaks are incorrect. That's the germ of your algorithm.

You have developed (or found) a complex program for peak detection which apparently does not work as desired.
Have you either a link for this or can you explain in words the technique you are attempting to use to do the peak detection.

I agree with the idea already expressed that a ready developed algorithm would be the easiest approach, but this denies you the learning effect of the selection of an appropriate method and coding it.

As a base line, this very simple sketch (untested) detects peaks and would work with the sample data you have given. It makes no attempt to determine a trend in the input stream so may yield false peaks.

``````// peak detection without filtering/smoothing

void setup()
{
Serial.begin(9600);  // for debugging
}

void loop() {
static int sampleLast = 0 ;
int sampleCurrent = analogRead( A0 ) ;
if ( sampleCurrent < sampleLast ) {
Serial.print( millis() ) ;
Serial.print( "   " ) ;
Serial.println( sampleLast ) ;
}
sampleLast = sampleCurrent ;
delay(10) ;
}
``````