Analog to Digital Signal Rectification

facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Hello,

Often in my projects i need to detect the signal level and then feed it to an A/D Converter. Since Digital circuitry operate on a single rail power supply usually from 1.8V to 5V you cannot feed the analog signal to the ADC’s input referenced to digital ground because the negative polarity will be ignored or worse, could damage the ADC.

One way is to use an analog rectifier and convert this output to digital. This requires some extra components though and depending on maximum frequency of the signal can be expensive.

In audio domain I usually rectify it in software and I provide a DC offset on the ADC input in order to keep both positive and negative side of the signal within the ADC’s input range.

To have a symmetric voltage swing the offset is VDD/2. This of course gives a first limitation of peak input voltage of VDD/2 but it can be easily resolved by attenuating the signal first and keeping the attenuation level in mind in software side. This way we can scale the signal to fit our input requirements.

Digital Rectifier ADC Software signal rectifier

 

 

In the picture above (a) shows you the signal with a VDD/2 offset presented at the input of our A/D converter. We will sample this signal in time as shown on the x axis. and the black lines represent the result after sampling

(b) shows how to reconstruct the analog signal. You can see that for values above the VDD/2 line the green part exists in our sample value from (a) and for samples below VDD/2 line we need to add the green part.

Looking at our analog input signal and samples in (a) and looking at the green parts in (b) we can say that the signal value v(t) for each sample s[n] is:

v(t1) = s[1]-VDD/2

v(t2) = s[2]-VDD/2

v(t3) = s[3]-VDD/2

v(t4) = s[4]-VDD/2

v(t5) = s[5]-VDD/2

…..

What the above list describes are actually the green parts in (b). The problem that remains is that v(t3) and v(t4) (corresponding for the negative voltage swing in the input signal) are negative because sample 3 and 4 are lower in value than VDD/2.

What we did so far is eliminate the input offset and now in order to rectify it we need to make all the negative values positive. This is simply done this way:

v(t1) = s[1]-VDD/2

v(t2) = s[2]-VDD/2

v(t3) = VDD/2-s[3]

v(t4) = VDD/2-s[4]

v(t5) = s[5]-VDD/2

…..

Now the signal is rectified. v(t3) and v(t4) are positive and the list above describes now figure (c), the rectified output.

There are a couple of drawbacks in using this technique. First is the stability of the offset VDD/2. This voltage will need to be extremely stable for accurate result. If offset fluctuates then sample values will fluctuate too. If you can eliminate drift caused by temperature, load fluctuations etc then you can have a very accurate and fast rectifier.

There is a way to make this problem disappear by using a second A/D converter channel. And this is the second drawback if your number of channels is very limited. When using a microcontroller this isnt really a problem as usually there are a sufficient number of channels available.

I usually use the second solution and i always get the VDD/2 value from the second ADC channel and then get the input signal value. Lets look below at at example on how to do this;

/* we will use channel 0 for VDD/2 input and channel 1 for signal input */

int READ_ADC(int channel); //function prototype to read ADC value on channel 

int RECTIFY(void)

{

int INPUT_OFFSET, SAMPLE_VALUE;

INPUT_OFFSET = READ_ADC(0);

SAMPLE_VALUE = READ_ADC(1);

if(SAMPLE_VALUE >= INPUT_OFFSET)

  SAMPLE_VALUE = SAMPLE_VALUE – INPUT_OFFSET;

else

  SAMPLE_VALUE = INPUT_OFFSET – SAMPLE_VALUE;

return SAMPLE_VALUE;

}

 

Output of RECTIFY function can then be stored into a vector and perform various calculations to get your desired result. I usually average the values:

#define SUM_LENGTH 512 //how many samples you want to average

int AVERAGE(void)

{

double SUM=0; // depending on the ADC resolution choose the data type

int RESULT, i;

for(i=0;i<SUM_LENGTH;i++)

{

  RESULT = RECTIFY();

  SUM = SUM + RESULT;

}

RESULT = SUM/SUM_LENGTH;

return RESULT;

}

To choose the SUM_LENGTH you should consider the speed of the A/D conversion and the lowest frequency of the input signal so that you can capture an entire period. This, of course is application dependant but you can play around with the values and check the result.

Holding the RECTIFY value in a vector you can then get max value which is peak value or RMS, envelope and so many more things.

I hope this will be useful and if there is anything you want to ask go ahead and leave a comment.

Thank you for visiting.

Leave a Reply

Your email address will not be published. Required fields are marked *