Understanding the ADC Offset

Hi all,

Can anyone explain the relevance of this line of code from the EmonLib.cpp:

offsetI = offsetI + ((sampleI-offsetI)/1024);

It’s within the main measurement loop, line 113. I understand it’s purpose is to remove the DC bias from the raw values, but what’s wrong with just using an offset of 512 each time?

It isn’t 512. Component tolerances will make it different on each input on each device, so that line is actually a low pass filter to get the true value.

Thanks for the instant response!

I understand that the offset is different for each device, but I don’t get why it needs to change for each iteration of analogread(). I can see how it acts as a digital low pass filter, applying a weighted moving average to give a smoothing effect. But why is this necessary, is there something inherent in the ADC that causes a shift away from the “true” value?

I had the same reaction when I first saw how this works, and those are good questions. There is nothing inherent in the ADCs that cause the bias to drift, and it works fine if you can use the ADC value corresponding to the DC bias. That is the technique used in IotaWatt and it is reevaluated once after each sampling and adjusted within a narrow range if anything changes.

I had other issues with this code though:

If I recall correctly, they keep the offset as a floating point number and develop the sample value as a floating point number. Doing all that floating point math in an 8bit Arduino is slow, and accounts for a lot of the relatively low sample rates the code produces.

More of an issue to me is the actual function itself. If you plot the function against a sine wave, you will discover that the offset value becomes a low amplitude sine wave that is about 90 degrees out of phase with the original signal. The amplitude of the offset wave is not trivial and contributes much more inaccuracy than any advantage of using floating point math. A year or so ago when I was still playing with Arduinos I recoded that algorithm to use an adjusted fixed offset and do integer math. As I recall it was a lot faster and seemed to be more accurate.

IotaWatt is a 32 bit processor that does floating point very fast. Nevertheless I encorporate those techniques there and achieve sample rates (with faster ADCs) above 600 samples per AC cycle.

Does that actually improve the accuracy by much?

I believe so.