Peak detection find algorithm - Page 1
Forum section: electronics / general

author: rvalente
author_rank: Frequent Contributor
timestamp: October 20, 2021, 04:03:55 pm
content: Hello Mates,I'm looking for a better way to detect peaks in a signal sampleThe signal is a sinusoidal from VR sensor and tone ring wheel with 40 to 140 teeth, the output frequency is from 40 to 200Hz, this signal is then rectified (80 to 400Hz) and sampled in the uC ADC, 12bits, 0 to 5V.The sample rate is adjusted so 1.2 revolutions of the tone ring can be captured. Usually the tone ring has 100 teeth and the algorithm finds 239 to 240 Peaks, which is correctThe current algorithm is pretty simple it basically looks for a number of consecutive signal samples which are bigger than the previous, if not the increments the "fall" counter, when the fall counter is a given number (8 by now) is the peak is saved to a array. As the sample rate is now 20 times the non rectified frequency the number 8 for the fall counter works just fine.The thing is: this works but, I feel I need to make it better, I'd like to have this fall number self adjusted or to find a better and proven peak detection algorithmAnyway, I'd like some suggestions from you guysCode:///////// SEARCH FOR SIGNAL PEAKS /////////for(point=0; point<samples; point++){if(buffer > buffer[point-1]){fall = 0;pointBuffer = point;}else{fall++;if(fall == FALLS) //This FALLS constant is set to 8, I'd like it to be adjustable{if (peaks < expectedPeaks && firstPeak){//Make sure the array wont be overwrittenpeakArray = buffer; //Salva posição do picotimeArray = pointBuffer; //Salva tempo do pico na posiçãopeaks++;}firstPeak = 1; //Set first peak has passed already, save later peaksif (peaks >= expectedPeaks){//Check for excessive readingseturn(EXCESSIVE_PEAKS);}}}}

author: ledtester
author_rank: Super Contributor
timestamp: October 20, 2021, 04:31:51 pm
content: The algorithm you use might depend on the kind of data you expect to collect.This one might be worth trying out:https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 20, 2021, 05:32:32 pm
content: As I see it, the algorithm you're using is more or less equivalent to low-pass filtering the signal and then determining a local maximum from the numeric derivative's sign change.Of course the approach to use all depends on your requirements. One issue with the one you use is that, while trying to avoid local peaks from noise, it's also less time-accurate.There's a bunch of articles on peak detection out there. Probably more than you'll have time to read.One way I know of smoothing data while not having the drawbacks of simple low-pass filtering (/moving averages/...) is to use Savitzky–Golay filters.https://en.wikipedia.org/wiki/Savitzky%E2%80%93Golay_filterI've used that successfully.There are more efficient approaches as well. Probably you should first determine what exactly your requirements are:- what you consider a valid 'peak' in the signals you're dealing with;- what kind of noise you're expecting;- what you expect in terms of time accuracy for peak detection.

author: rvalente
author_rank: Frequent Contributor
timestamp: October 20, 2021, 06:55:58 pm
content: Hello mates,you've given a buch of useful information, I'm already studying.Would you have some code to share?

author: DavidAlfa
author_rank: Super Contributor
timestamp: October 20, 2021, 07:04:38 pm
content: Edit: I wrote this thinking you wanted to get rid of the spikes.But it can be useful too. o exactky this to have a clean, spikes-less signal.Apply new readings to the EMA filtering, then compare the reading with the updated EMA value.Now you can apply any threshold/percentage you want to consider the reading a spike or not.You can make a simple EMA fitering, you'll get some delay but much cleaner signal.https://www.norwegiancreations.com/2016/08/double-exponential-moving-average-filter-speeding-up-the-ema/The basic EMA code implementation is:Code:#define k 0.5f // coefficient. 0=use 0% of new, 100% of old(won't update) . 1=100% of new, 0% of old(no filtering).// Play with the coefficient to find the best value.static float stored_ema; // Stored averagevoid reset_ema(uint32_t new_read){stored_ema = new_read; // Some times you'll need this to avoid the initial delay, as the average needs to build up (ex. first ADC reading).}uint32_t ema(unt32_t new_read){stored_ema= (1.0-k)*stored_ema+ k*new_read;return stored_ema;}Also, you can apply a pre-filter. As I see in your waveforms, there're quite a lot of spikes. If you don't want them, simply use a threshold a window.You know the signal is supossed to change progressively, so any reading that exceeds ex. 10% of last reading could be ignored.That and a small EMA filtering for the high frequency changes will clean the signal a lot.

author: rvalente
author_rank: Frequent Contributor
timestamp: October 20, 2021, 07:14:59 pm
content: Quote from: DavidAlfa on October 20, 2021, 07:04:38 pmI need to read the high spikes, they're the defect I'm want to detect (a teeth defect in the tone ring).

author: DavidAlfa
author_rank: Super Contributor
timestamp: October 20, 2021, 08:19:13 pm
content: Following my post: I took an excel sheet I made long time ago for my T12 firmware.It lets you see how the EMA/DEMA and filtering works, apply random noise, change the filter constant... not reinventing the wheel here but could help.This looks interesting: If you split the signal into low and high frequencies, you'll get your peak noise:https://stackoverflow.com/questions/7105962/how-do-i-run-a-high-pass-or-low-pass-filter-on-data-points-in-rDigital filtering is not my field...

author: rvalente
author_rank: Frequent Contributor
timestamp: October 21, 2021, 09:55:43 am
content: Quote from: DavidAlfa on October 20, 2021, 08:19:13 pmThe signal is not really noisy, not that it seems to bother. What I really wanna improve is the peakArray detection algorithm. any tips on that?

author: JOEBOBSICLE
author_rank: Regular Contributor
timestamp: October 21, 2021, 04:02:50 pm
content: Sounds like you could label up some data and use it to train a LSTM neural network. Sometimes this is easier than figuring out a classical algorithm

author: profdc9
author_rank: Frequent Contributor
timestamp: October 21, 2021, 09:27:58 pm
content: If you have the processing power, you can run a running median filter over the time series to get rid of outliers, decimate the sequence, and keep the samples as peaks where a sample is greater than its two neighbors.