PIC Peak Detection Routine

Discussion in 'The Projects Forum' started by mojo_risin, Feb 7, 2014.

  1. mojo_risin

    Thread Starter Member

    Jul 3, 2013
    35
    0
    [​IMG]Hello all

    I am working on my project that is blood pressure monitor, and I need to devise an algorithm that would detect the peaks of the signal that is fed to the ADC. A little background:
    - I am feeding the pressure signal to one ADC (16 bit), and I am using 16 sample moving average filter (not weighted) to smooth it out. It works good enough for me.
    - The pulse oscillation signal is read by the second ADC (12 bit).
    - I am sampling at 500 Hz, and for debugging purposes I am sending the values of the ADCs through UART with baud rate of 56K. It is not fast enough, but I am using the internal 8 MHz oscillator and that's the best I can get. It doesn't really matter, though, because I won't be using UART functions in the final project. The point is that some of the samples get lost in the process of sending, but still I have enough to produce a good chart of what the ADCs are reading. Here it is:
    [​IMG]
    The orange graph is the pressure signal, and the red is the pulse oscillation. Now, in order to get this thing working, I must detect the pulse peaks of the oscillation signal, and record their value plus the value of the pressure at that time, and also the absolute time (I would use a timer for this). I can't use any threshold above the DC bias value of the signal, which is about 0.7 volts, because each person's pulse would produce different voltage oscillations.

    I've been searching for an algorithm for peak detection, but unfortunately what I found was way above mu current abilities... So I would be happy to get some suggestions from more experienced users. It appears that this problem would be the biggest in my project, and it calls for a lot of expertise, which right now I don't have.

    What I was thinking is an algorithm to detect the slope of the pulse (you can see that is is pretty sharp), record its peak, than wait a certain amount of time to avoid false triggering, and repeat.

    Thanks a lot!
     
  2. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    You haven't given a blown-up image of a single pulse, but assuming that you have a number of rising samples before the peak, then a number of falling ones, I'd have the processor examine each sample versus the previous one. Then if you detect a rising waveform, increment a counter. If the waveform switches from rising to falling, store the peak value and the present time, and change over to counting falling samples. After enough samples to be sure that you have a falling waveform, say "That was a peak" and do whatever you do when peaks occur.

    Issues to beware of: what happens if there is a little glitch in the incoming samples which causes a small local peak? Are you quite sure this will never happen, or if it does, can you reliably reject it? And does the proposed algorithm also reject minor variations that occur between peaks? What you have to do in a situation like this is be sure that you know what you're looking for and also what the likely sources of error are.

    Edited to say, your data looks complete enough that you could quite easily write a program on the computer to analyze it based on a stored file, which would let you work the bugs out of your algorithm without the hassle of generating real data for every time you want to run the program. I've done that before, where I couldn't resist drawing the graph on the screen with little colored marks to indicate rising and falling and peaks and changes of slope, and then I had to force myself to quit doing that and get it working on the processor.
     
    Last edited: Feb 7, 2014
  3. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    I like that idea.

    Since the data is so very slow, you could do the same on the PIC.

    Just sample into a circular buffer and a simple software algortihm could easily detect the "peaks" and also derive any other data you might need from it. :)
     
  4. mojo_risin

    Thread Starter Member

    Jul 3, 2013
    35
    0
    @John P: That's my initial idea... I am going to calculate the slope of the pulse waveform to a certain limits (just to be sure I am detecting a pulse and not a glitch), and the compare values until I detect the peak. At this point, I am going to record the value of the pressure plus the value of a running timer. You can see how the pulse is way sharper that other parts of the signal. After a peak is detected, I would pause sampling for a certain amount of time (300 ms for example) and the try to detect rising slope again. There's nothing in the falling slope that I am going to use, so I won't sample it. This of course depends on whether or not I would be able do devise reliable slope constant within certain limits, and would limit the pulse detection to certain frequency, but I don't think I would have the opportunity to test this on someone with pulse of about 200 bpm.

    And yes, I am going to analyze the program on my computer, I don't have to do it on the PIC :) I'll do it in Code Blocks, my favorite C editor. I would be easy to port it to XC16 later, I guess, provided that I make a working program, of course.

    Doing this on the MCU would take a lot of time, and PC debugging is easier :)

    I just faced a temporary PWM problem (I would have to start another topic, unfortunately), and this would delay a little bit my working on the software. As soon as I am done with it, I would try to tackle it and I would update the thread.

    Thanks a lot for the great answers :)
     
  5. John P

    AAC Fanatic!

    Oct 14, 2008
    1,632
    224
    You'd count the falling samples so that once you've seen several in succession, you know that "we just passed a peak". So if you've stored the present level and timestamp when you see a rising sample (but not for falling samples) as soon as you decide that you've passed the peak, you can process those values. I don't see the need for a circular buffer; it looks as if all you need is "this sample" and "previous sample" and counts of consecutive rising samples and consecutive falling samples, and the "peak height so far" and matching timestamp.
     
  6. THE_RB

    AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    I would do it a different way, using a buffer and finding the average voltage, and the peaks detected by amplitude compared to the running average, nothing needs to be slope related.

    My way would be more like a classic analogue peak detector or bit slicer.

    Doing it by slope and not amplitude would give potential issues because the bottom of the waveform also has short duration high-slope content. :)
     
  7. donpetru

    Active Member

    Nov 14, 2008
    186
    25
    1. By the way, what type of PIC microcontroller used in this application?
    2. You have calculated how much time is between two successive shots from the same ADC channel ? For example, how many us?
    3. You measure which was the lowest pulse (time) peaks of the oscillation signal ?

    Depending on the answers to these questions, you may end up in a situation to change the MCU. I don't know if you using a dsPIC but a powerful ARM I think it's doing much better. But before that, I'd like to see some answers to the questions above.
     
  8. mojo_risin

    Thread Starter Member

    Jul 3, 2013
    35
    0
    1.I am using PIC24FJ128GC006. It has 2 ADCs. I am using the internal clock at 8 MHz, and Tcy is 4 MHz.

    2. I am scanning the input analog channels at 500 Hz, and I am not multiplexing since I am using both ADCs. The time between two successive scans would be 0.002s + The time for the conversion + Function Call Overhead. I haven't estimated the precise conversion time, but I guess it would be pretty low, since results are accurate. ADC source impedance is under 2.5 kΩ on both channels input. I can calculate the time between conversions by outputting the value of a timer at each scan - I'll do that later and post the results.

    3. The lowest possible oscillation frequency (I mean the pulse frequency) would be equal to the lowest possible human pulse that I would measure... I think it won't be below 50, for obvious reasons :)

    I've chosen this particular PIC because of on Microchip's app note, which is using the same for BP monitor. I like it a lot, it's definitely worth checking out.

    Update: The time for the oscillation AD conversion is 1.5 uS + the function overhead, because the conversion is done by calling a function. The acquisition time works OK - I compared the results of my current acquisition time and the results when increasing it by 20.
     
    Last edited: Feb 9, 2014
Loading...