3
$\begingroup$

I am trying to get a useable wave from a pulse oximeter, but there is a pesky DC bias that keeps changing every now and then, so I cannot simply subtract the DC bias from it and get useable results for long. I also tried to take an appropriate sampled running average, and subtract that from my wave, and it gave me much better results than before.

However, I am told that a DSP high pass filter will work even better, and I am trying to implement that. I am not an electrical engineer and do not have much knowledge about filters, and absolutely no knowledge of DSP. I found this great website that lets me design a DSP filter and gives me a C++ library to use that filter in my code.

The problem is, I want to design a filter that cuts below 1Hz and lets through any frequencies above 1Hz or 1.3Hz max. My oximeter wave is 1.4Hz. But the design tool I mentioned above seems to indicate that it is not possible.

Any help in this would be highly appreciated.

[Edit]

I have finally managed to make it work a bit, but the DC bias is still there. (red line is the data filtered from the filter from that website, blue line is moving average subtracted from incoming signal) filtered data

And this is the frequency-gain graph of the filter filter

$\endgroup$
5
  • 3
    $\begingroup$ "I also tried to take an appropriate sample running average, and subtract that from my wave, and it gave me much better results than before." Congratulations, that is a DSP filter! You're by far not as inexperienced as you think you are. $\endgroup$ Mar 1, 2021 at 10:13
  • $\begingroup$ @MarcusMüller Woah. I honestly feel more confident now. :D $\endgroup$ Mar 1, 2021 at 10:30
  • 2
    $\begingroup$ Hi! What's your sampling frequency? $\endgroup$
    – Fat32
    Mar 1, 2021 at 11:40
  • $\begingroup$ @Fat32 I'm sampling at 200Hz $\endgroup$ Mar 2, 2021 at 7:02
  • $\begingroup$ I would look into "modulating"/pulsing the source at a high frequency and then demodulating back to the base band. This allows rejecting DC internal to the sensor. $\endgroup$
    – rrogers
    Mar 2, 2021 at 20:22

1 Answer 1

4
$\begingroup$

but there is a pesky DC bias that keeps changing every now and then

Fix that, if you can. If it changes suddenly, then any filter you have is going to have odd results after the change, until it settles again.

So this is the algorithm you want (note the pseudo-C pseudo code -- data types are up to you):

static state_t state = 0;
static const cutoff_frequency = 1.0;
static const state_t gain = cutoff_frequency / (2 * PI * sampling_rate);

input_t highpass(input_t input) {
    input_t retval = input - state;
    state += gain * retval;
    return retval;
}

state_t is up to you -- it's easiest to choose 64-bit or longer floating point; excepting issues with speed or space that's almost certain to work. Anything else and you'll need to worry about truncation. I assume that input_t is some integer type -- if it's unsigned, you'll need to do some casting so the first line of the function works.

What this is doing is making a highpass filter by making a 1st-order infinite-impulse response lowpass filter of the input data, with unity gain, and subtracting it from the input. As long as you have enough precision in your variables, the second line of the function insures that the output really is servoed to an average value of zero.

It's up to you to make sure that nothing overflows for extreme values of the input, and that state_t and gain fit together so that the second line of the function does not underflow (i.e., if the input changes by its smallest increment, state still "sees" the difference in retval after multiplied by gain.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.