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 multiple samples of ADC result.

Status
Not open for further replies.

swapan

Member
Friends,
With the tips of my friends and esteemed seniors of our forum I took up the experiment to average multiple samples of ADC. But unfortunately my code does not respond. Please see the code and suggest how to set the code right. Please note that if single ADC is compared, the code is OK. When I take multiple sample and average it, the code fails.

Regards,

swapan

Code:
list      p=16F676           ; list directive to define processor
    #include <p16F676.inc>        ; processor specific variable definitions

    errorlevel  -302              ; suppress message 302 from list file

    __CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT 

; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.

;***** VARIABLE DEFINITIONS (examples)

; example of using Shared Uninitialized Data Section
CBLOCK		0x20
COUNT		
HIGH_BIT
COUNT1
ENDC

;**********************************************************************
RESET_VECTOR    CODE    0x0000       ; processor reset vector
        goto    start                ; go to beginning of program


INT_VECTOR      CODE    0x0004       ; interrupt vector location



        
MAIN_PROG       CODE

; these first 4 instructions are not required if the internal oscillator is not used
start
        call    0x3FF             ; retrieve factory calibration value
        bsf     STATUS,RP0        ; set file register bank to 1 
        movwf   OSCCAL            ; update register with factory cal value 
        bcf     STATUS,RP0        ; set file register bank to 0

; remaining code goes here

	
		BSF		STATUS, RP0
		MOVLW	b'00000001'		
		MOVWF	TRISA
		
		MOVLW	b'00000001'
                MOVWF	ANSEL
		MOVLW	b'01010000'         ;  16 T osc.
		MOVWF	ADCON1
	
		BCF		STATUS, RP0
		MOVLW	0X07
		MOVWF	CMCON
BEGIN:
		CALL	ADC
		MOVLW	D'128'
		SUBWF	HIGH_BIT,0
		BTFSC	STATUS,C    ; compare with a pre-loaded value.
		GOTO	RLY_ON       ;  If average ADC is higher than the value, held
		GOTO	RLY_OFF      ;  PORTA,1 high, otherwise clear it.

RLY_ON:
		MOVLW	b'00000010'
		MOVWF	PORTA
		GOTO	BEGIN

RLY_OFF:
		CLRF	        PORTA
		GOTO	BEGIN


ADC:
		CLRF	        HIGH_BIT
		MOVLW	b'00000001'
		MOVWF	ADCON0
		CALL	        DLY_20
SAMPL:	BSF		ADCON0,GO
		BTFSC	ADCON0,GO
		GOTO	$-1
		

		INCF	        COUNT
	
		MOVF	ADRESH,W
		ADDWF	HIGH_BIT,1

		MOVLW	D'32'
		SUBWF	COUNT,W
		BTFSS	STATUS,Z
		GOTO	SAMPL
		CLRF	   COUNT

		BCF		STATUS,C
		RRF		HIGH_BIT		; devide by 2

		BCF		STATUS,C
		RRF		HIGH_BIT		;devide by 4


		BCF		STATUS,C
		RRF		HIGH_BIT		; devide by 8


		BCF		STATUS,C
		RRF		HIGH_BIT		; devide by 16


		BCF		STATUS,C
		RRF		HIGH_BIT		; devide by 32

		RETURN

DLY_20	
		MOVLW	D'20'
		MOVWF	COUNT1
		DECFSZ	COUNT1,1
		GOTO	$-1
		RETURN		

; initialize eeprom locations



        END                       ; directive 'end of program'
 
Code:
Do_ADC		clrf	Total_L
		clrf	Total_H
		movlw	.8
		movwf	Read_Count
Set_ADC		movlw	b'00000001'
		movwf	ADCON0
		call	DLY_20
Read_ADC	bsf	ADCON0,GO
Wait_ADC	btfsc	ADCON0,GO
		goto	Wait_ADC
		movf	ADRESH,W
		addwf	Total_L,F
		btfsc	STATUS,C
		incf	Total_H,F
		decfsz	Read_Count,F
		goto	Read_ADC
Do_Average	bcf	STATUS,C
		rrf	Total_H,F
		rrf	Total_L,F
		bcf	STATUS,C
		rrf	Total_H,F
		rrf	Total_L,F
		bcf	STATUS,C
		rrf	Total_H,F
		rrf	Total_L,F
		return
 
w

If you want a lot of averaging, you can get the effect of a huge RC filter like this.

Each time you sample, you add the result of the ADC to a 3-byte register. You also subtract 1/256 th of the 3 byte register from the 3 byte register. The effect is a time constant of 256 times the sample time.

Code:
      movf     av_mid, w
      subwf    av_bot, f
      movf     av_top, w
      btfss     status, c
      incfsz    av_top, w
      subwf   av_mid, f
      btss      status, c
      decf      av_top, f     ;this subtracts 1/256 th of av_top:av_mid:av_bot from av_top:av_mid:av_bot

      movf    adresl, w
      addwf   av_bot, f
      mov     adresh, w
      btfsc     status, c
      incfsz    adresh, w
      addwf   av_mid, f
      btsc      status, c
      incf       av_top, f  ;This adds ADRESH:ADRESL to the three registers.

The total in av_top:av_mid tends to the same value as ADRESH:ADRESL if the readings are steady.

You do have to make sure that this routine is called at regular intervals or you time constant will keep changing.
 
Code:
Do_ADC		clrf	Total_L
		clrf	Total_H
		movlw	.8
		movwf	Read_Count
Set_ADC		movlw	b'00000001'
		movwf	ADCON0
		call	DLY_20
Read_ADC	bsf	ADCON0,GO
Wait_ADC	btfsc	ADCON0,GO
		goto	Wait_ADC
		movf	ADRESH,W
		addwf	Total_L,F
		btfsc	STATUS,C
		incf	Total_H,F
		decfsz	Read_Count,F
		goto	Read_ADC
Do_Average	bcf	STATUS,C
		rrf	Total_H,F
		rrf	Total_L,F
		bcf	STATUS,C
		rrf	Total_H,F
		rrf	Total_L,F
		bcf	STATUS,C
		rrf	Total_H,F
		rrf	Total_L,F
		return


Thanks Mr. Soyza,
First I apologize for not attending to your post timely. Actually I was pre-occupied with some assignments and had to be out of city. That's why I could not access the forum. However, I again thank you for your guidance. I have already tested such averaging with arbitrary figures and seen the result using OSHONSOFT simulator which yielded fruitful result.

regards,

swapan
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top