How to Obtain an Accurate DC Value in an AC+DC Signal

filterlow passoperational-amplifiersignal

My goal is to use an Arduino with two proximity probe sensors to achieve some output.

It is worth mentioning that the output of the proximity probe has two components:

  1. DC output that determines the position or the GAP
  2. AC component on the top of that DC voltage to determine the vibration

I want to focus on the DC part.

The proximity probe sensor has a negative voltage output from 0 to -20 volt DC, as the Arduino accepts voltage only in the range of 0 to 5 volt, so I decided to use
a low-pass filter to remove the AC component and get just the DC component, as this DC component is in the range of 0 to -20 volt. I used an op-amp to invert and to scale down the voltage so instead of being in the range 0 to -20 V, it will be 0 to 5 V.

In this specific question my goal is to get the very accurate DC component. The circuit I implemented is very simple. Basically, it's a low-pass filter with a cut-off frequency of 1 Hz (assuming that my signal won't have a frequency component in the range of 0.00001 – 1 Hz) and then an inverting amplifier with a gain of 1/4 to invert and to scale down the DC voltage.

Here is the circuit:


The output is logical. I used a voltage source with AC and a DC component of -10 V DC offset to simulate the proximity probe signal, and here is the output:

Enter image description here

The green line is the DC component which is almost -10 volt, and the blue line is the output inverted and scaled down. Which is almost 2.5.

The problem is with the output. It's almost 2.5 V, and it's oscillating and changing. My application needs an accuracy of millivolt, so this won't be acceptable.
How do I get a more stable and accurate output?

Here is the picture of a zoomed-in output:

Enter image description here

Best Answer

Your output looks fine to me.
There is always a period at start up of a filter where its output is off, and it converges to the correct output in a time period related to the cutoff frequency - a lower cutoff for a low pass filter means it will take longer to converge to the true value. This explains the "changing" output of your filter.

Next, is the oscillation. That, too, looks correct. A filter doesn't remove everything out side of its passband, it merely reduces it. Since you are using a simple filter, the reduction isn't very strong. Your output has a much reduced 50Hz wave riding on the DC, which is about what you could expect from the given circuit and simulator settings (signal generator says -10V DC, 1 Volt AC at 50Hz.)

You will need a better filter to reduce the AC. Some other folks here are more capable of giving you tips on that.

You will probably have to live with the period at the beginning where the filter is converging to the proper DC level.

I missed the bit about "millivolt accuracy." Given the Arduino has a 10bit ADC, you will only get 1024 steps for voltages between 0 and 5 volts. That's a tad less than 5 millivolt resolution (4.88mVolt.) So, you aren't gong to get millivolt accuracy just using the ADC.

What you can do is to use a variant of the suggested moving average filter to improve the accuracy at the cost of time resolution. What you would do is use a low pass filter to remove (reduce, really) components above say 1Hz, then average all the ADC values for one second. You would get a value with more bits of accuracy, but only once per second. The ratio between the time period for the average and the real sampling rate tells you how many (theoretical) bits of accuracy you can gain. If you are sampling at 8000Hz, and average every two samples, you can gain one bit of accuracy but only have 4000 samples per second instead of 8000.

That will help with the DC, but not the AC. I don't know what you can do there or if you also need millivolt accuracy there as well.

In response to comments: I see you can do post processing in Matlab. This makes a BIG difference. Use a simple anti-aliasing filter appropriate to your sampling rate and expected signal. Store the sampled data to SD, then process in Matlab.

In Matlab, you can implement the resampling to improve the bit accuracy as mentioned above, as well as using better filters to remove the AC. Since you are working offline, you can use a non-causal filter to remove the AC - this will take care of the convergence problem mentioned above.

Filtering out the DC so that you can process just the AC will also be simpler - non-causal filters will also help here.