Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Averaging ADC results.

Status
Not open for further replies.

swapan

Member
Friends,
I like to get ADC result of a supply which is not pure DC. It is a rectified DC of a step down transformer. Since the rectified DC is some what pulsating, I apprehend that the ADC result will be unstable. I am using PIC 16F676. I think this problem could be eliminated by averaging multiple ADC results. I shall be very grateful if any of my friends give me an small example of asm. code for averaging the ADC.

Thanks in advance.

swapan
 
Hi,

I wrote this code for my temperature sensor project. It results in a stable display of temperature on an lcd. Don't know if it will work for your project, it may depend on the magnitude of the individual sample values, adding 32 times may result in too big a number. I use 10bit A/D

Code:
A2D       
start_sampling    
    bsf     ADCON0,1                    ;start conversion    
    btfsc   ADCON0,1                       
    goto    $-2
    incf    Avg_cnt ;sample counter
    
;add 32 samples
    movf    ADRESL,w
    addwf   read1_low,f
    btfsc   STATUS,C
    incf    read1_high
    movf    ADRESH,w
    addwf   read1_high,f
        
    movlw   .32
    subwf   Avg_cnt,w
    btfss   STATUS,Z
    goto    start_sampling
    clrf    Avg_cnt
    
;divide by 32
    bcf     STATUS,C
    rrcf    read1_high      
    rrcf    read1_low   ;/2
    
    bcf     STATUS,C
    rrcf    read1_high      
    rrcf    read1_low   ;/4
    
    bcf     STATUS,C
    rrcf    read1_high      
    rrcf    read1_low   ;/8
    
    bcf     STATUS,C
    rrcf    read1_high      
    rrcf    read1_low   ;/16          
    
    bcf     STATUS,C
    rrcf    read1_high      
    rrcf    read1_low   ;/32
 
Well, you've got to be sure that the register in which you accumulate the number before dividing cannot overflow.

Averaging MAY improve the results, or it may simply make noise somewhat less likely.
Proper filtering can only be done by making sure the sample rate satisfies the Nyquist criteria for the signal and use an FIR on the samples. It's a lot for a PIC16 coder to figure out, but it'll do the job perfectly.
 
hi
how about moving average filtering it may eliminate the noise
 
Thanks Mr. Angry Badger for your cooperation. Being a newbie, the averaging technique was beyond my knowledge. Your post helped me a lot. Here, one point is not clear to me. After each addition of LSB of ADC result into read1_low, bit C of the STATUS register is tested. In case the bit C is set, read1_high (MSB of ADC value) is incremented. I could not understand why it is incremented. Would you kindly extend your hand here?

With regards.

swapan
 
Thanks Mr. Angry Badger for your cooperation. Being a newbie, the averaging technique was beyond my knowledge. Your post helped me a lot. Here, one point is not clear to me. After each addition of LSB of ADC result into read1_low, bit C of the STATUS register is tested. In case the bit C is set, read1_high (MSB of ADC value) is incremented. I could not understand why it is incremented. Would you kindly extend your hand here?

With regards.

swapan

Hello,

erm, often don't understand my own code after I've written it, I really should be doing something else. Stamp collecting perhaps, or fishing.

Anyway, I think it's like this; if you add two or more successive low parts (ADRESL) of the sample and the result is more than 255 you have to carry (increment) the high part (ADRESH), even before you have added the two succesive high parts. It's like adding 5 + 5? You get ten so you have to carry the 1(ten) over. Sorry if I sound like I'm telling you how to suck eggs.

Does that make any sense? Probably not. Anyway, my code is probably a poor way to acheive the result that both you and I desire. I'm a newbie at this too. One of the smart ones' around here will surely provide a neater solution if you persist.

Good luck.
 
Or place a small capacitor on the feedback line to help eliminate the ripple.
 
Firstly, you do have to deal with a carry bit from the least significant bit before you add the most significant bit.

Secondly, here is how I filter ADC results:-

Using a timer, I only read the ADC something like 16 times a second.

I have an accumulator for the result, usually 24 bits, so 3 registers on an 8 bit PIC.

Each time the ADC is read, I add the result into the accumulator. Then I subtract 1/256 of the accumulator value from the accumulator.

That is easy in an 8 bit PIC, as you just subtract one the middle register from the bottom register, and the top register from the middle register, dealing with carry bits at each stage.

Then the top and middle registers are a smoothed version of the ADC value, with a time constant of 256/16 = 16 seconds.

Obviously, you can change the sampling rate or the divide factor to give other time constants. I would suggest keeping powers of 2 as the divide factor or the maths takes a lot of code.
 
Mr. Diver,
I am thankful to you as well as Mr. Angry Badger for detailing my query. Now it is clear to me as to why MSB is incremented on every setting of C bit of STATUS register caused by addition of successive LSBs. The above code of Mr. Angry Badger shows that the successive ADRESH is added in read1_high register. In a 8 bit Microcontroller the accamulated result will not be accomodated in a register. In that case what is the process of accamulation and right rotating to gate the average result of ADC?

Swapan
 
Mr. Diver,
I am thankful to you as well as Mr. Angry Badger for detailing my query. Now it is clear to me as to why MSB is incremented on every setting of C bit of STATUS register caused by addition of successive LSBs. The above code of Mr. Angry Badger shows that the successive ADRESH is added in read1_high register. In a 8 bit Microcontroller the accamulated result will not be accomodated in a register. In that case what is the process of accamulation and right rotating to gate the average result of ADC?

Swapan

Hi,

It's not neccessary to use 10 bit A/D of course. You could use 8 bit, add the results using a temporary register to hold the high byte until you do the division. You'll end up with the result as an 8 bit number.

It depends on what you want to do with the result. If using 10 bit maybe you could use a 10 bit to BCD routine and end up with the result in three registers (Hundreds, tens and units) for sending to an lcd display. I use this method in my program.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top