I have a question regarding filtering to remove a DC offset bias. Specifically, I wonder whether the approach of the open energy monitor project is overly complex assuming the front end hardware (i.e. the analog inputs) has been designed with easy DC offset bias removal in mind. You can read about the theory / details behind their approach over at Page not found | Archived Forum but the basic approach is to take a varying AC signal (from a AC-AC transformer, for example) and then to use a voltage divider + capacitor as a DC offset source to make the signal all-positive for the arduino to read.
My approach to the hardware side was slightly different. A small linear voltage regulator creates a reference voltage for the arduino (i.e. AREF = 1.25V). Two 1k resistors (with a 1% tolerance) are used for the offset bias voltage divider. That way, the DC bias offset should always be equal to 1/2 the reference voltage. Measurements of the voltage and current inputs without external inputs attached confirm that the numeric ADC values are 511-512, just as one would expect.
The OpenEnergyMonitor group came up with a nifty way on the software side to remove bias, regardless of how the DC-bias voltage divider was set up. I suppose this is a great / better approach if the DC offset is not known, or drifts, etc. The snippet of their code below shows their approach to removing offsets as part of their measurement loops.
lastSampleV=sampleV; //Used for digital high pass filter
lastSampleI=sampleI; //Used for digital high pass filter
lastFilteredV = filteredV; //Used for offset removal
lastFilteredI = filteredI; //Used for offset removal
//-----------------------------------------------------------------------------
// A) Read in raw voltage and current samples
//-----------------------------------------------------------------------------
sampleV = analogRead(inPinV); //Read in raw voltage signal
sampleI = analogRead(inPinI); //Read in raw current signal
//-----------------------------------------------------------------------------
// B) Apply digital high pass filters to remove 2.5V DC offset (centered on 0V).
//-----------------------------------------------------------------------------
filteredV = 0.996*(lastFilteredV+sampleV-lastSampleV);
filteredI = 0.996*(lastFilteredI+sampleI-lastSampleI);
In the interest of speed (and simpler code), I would like to just use simple subtraction for the filtering. i.e.
filteredV = analogRead(inPinV)-512; //Read in raw voltage signal and subtract DC offset
filteredI = analogRead(inPinI)-512; //Read in raw current signal and subtract DC offset
Is there something I should be considering when doing this (that lead the openenergymon group down their particular path)? Also, any idea where/why they are applying the 0.996 multiplier?
Any suggestions are welcome and thanks to Grumpy Mike for posting his thoughts on how to protect the inputs of an Arduino using a BAV99, a cap, and a resistor.