PDA

View Full Version : ADC problem with PIC16F917



eetech
- 6th March 2007, 21:11
I am having a problem using a 2.5 volt reference for adc conversions. The result has an offset error( which is consistent and correctable in software). The error does not exist if 5 volts is used as reference. I have duplicated the problem in a seperate test circuit. No inputs or outputs where left floating. I have even used different chips to insure it was not a bad chip. At this point I figure it has to be something I am doing in intial setup. I have included the test circuits code below. Any help, suggestions, or ideas would be appreciated. (and yes I fully expect it to be some kind of dumb mistake on my part so feel free to point it out that way)


'************************************************* ********
' Config Settings *
'************************************************* ********
@ DEVICE pic16F917,FCMEN_ON
@ DEVICE pic16F917,IESO_ON
@ DEVICE pic16F917,BOD_OFF
@ DEVICE pic16F917,MCLR_OFF
@ DEVICE pic16F917,CPD_OFF
@ DEVICE pic16F917,WDT_OFF
@ DEVICE pic16F917,PWRT_ON
@ DEVICE pic16F917,INTRC_OSC_NOCLKOUT


'************************************************* ********
' LCD Defines *
'************************************************* ********
define LCD_DREG PORTB 'PORTB is LCD output register
define LCD_RSREG PORTC 'PORTD will contain LCD control bits
define LCD_RSBIT 0 'RS (register select) is bit 1
define LCD_EREG PORTC
define LCD_EBIT 2 'E (enable) is bit 2
define LCD_BITS 8


'************************************************* ********
' Constants *
'************************************************* ********
Samples CON 25 'number of A2D samples to average for result


'************************************************* ********
' Variable Declarations *
'************************************************* ********
Delay1 var byte ' timing loop variable
Delay2 var byte ' timing loop variable
ADval var word ' holds result of A2D conversion
ADCHS var byte ' A2D Channel to convert
' 20 = AN5(pin 8), 24 =AN6(Pin 9)
' 28 =AN7(Pin 10)
' value OR'ed with ADCON0 to complete the setup

ALoop var byte 'conversion sampling loop count
TempAD var word 'holds A2D samples for averaging

GOTO START


'************************************************* ********
' MPU Setup - inline assembly block *
'************************************************* ********
INIMPU:
asm
Delay1 res 1
Delay2 res 1

bsf STATUS,RP0 ; Select Bank 1

movlw 0xEC ; set A<5:1:0> as digital I/O
movwf ANSEL ; A<3:2> and E<2:0> as analog

movlw 0Fh ; set A<3:0> as inputs
movwf TRISA ; (A<3:2> analog, A<1:0> digital)
;A<7:4> as outputs(digital)

movlw 10h
movwf ADCON1 ; set A2D Clock Fosc/8

movlw 00h
movwf TRISB ; set PORTB as outputs

movlw 08h ; set PORTC C<2:0> as outputs
movwf TRISC ;C<7:3> as inputs
; C<7:4> not used, will be reconfigured if needed

movlw 0xFF
movwf TRISD ; set PORTD as inputs

movlw 0Fh
movwf TRISE ; set PORTE as inputs

bcf STATUS,RP0 ; Select Bank 2
bsf STATUS,RP1 ;

clrf LCDCON ; Disable VLCD<3:1>
; inputs on RC<2:0>

bcf STATUS,RP0 ;Select Bank 0
bcf STATUS,RP1 ;

;clear all outputs
clrf PORTA
clrf PORTB
clrf PORTC ; RS and RW low
clrf PORTD
clrf PORTE

DelayLoop ;allow time for display to initialize
decfsz Delay1,f
goto DelayLoop
decfsz Delay2,f
goto DelayLoop

return
endasm


'************************************************* ********
' Main Program *
' continous loop to get and display A2D result *
'************************************************* ********
Start:
gosub INIMPU 'initialize MPU

DoConvert:
ADCHS = 20 ' ORed with ADCON0 in A2D to select channel
gosub A2D ' get conversion - stored in ADval variable

lcdout $FE,1, dec adval 'put ADC count on display
pause 1000 'wait one second before doing it again
Goto DoConvert


'************************************************* ********
' Analog to Digital Conversion *
' The AD Module is turned on with the first call to this routine *
' and stays on *
'************************************************* ********
A2D:
ADVal = 0 ' clear results from last conversion
TempAD = 0 '
ADCON0 = %11100001 | ADCHS ' Configure and turn on A/D Module

pauseus 25 ' settling time

For ALoop = 1 to Samples ' number of samples to do
ADCON0.1 = 1 ' start conversion
notdone:
If ADCON0.1 = 1 Then notdone ' wait until conversion is done
ADval.highbyte = ADRESH ' Move HIGH byte of result to ADval
ADval.lowbyte = ADRESL ' Move LOW byte of result to ADval
TempAD = TempAD + ADval
next ALoop

ADval = TempAD/Samples 'get conversion result

' The result has an offset error, the average slope of which is
' 0.772023. .772 is accurate within a couple counts and thus is
' acceptable for our use here. To keep from dealing with floating
' point math we will multiply by 772 and divide by 1000 and only
' concern ourselves with the whole number result.
' Uncomment these two lines to use the correction
'Dummy = ADval*772 'compensate for error offset
'Adval = div32 1000 '

return

Darrel Taylor
- 6th March 2007, 21:51
The VREF pins are multiplexed with the comparators.
You have to turn them off.

CMCON0 = 7

Also, you are setting both the VREF+ and VREF- to external pins.
What voltage do you have on VREF-
<br>

BigWumpus
- 6th March 2007, 21:54
OK,

you use 2,5V as VRef+, this is near the limit ! (see page 243 of the PIC16F917-manual).

You talk about an offset-error and use the formula *772/1000 to compensate it ... this seems to be a linearity-error, not an offset.

What voltages do you attach and what do you measure ?

eetech
- 6th March 2007, 23:30
Darrel,
You are right, the code I posted did not have the comparators turned off. I had noticed that and thought that mistake was fixed. It is now, thanks for catching it.
That unfortunetly did not correct the problem.

VREF+ and VREF- are both now set to external pins, I have tried it with VREF- set to VDD. VREF- is set to ground. For all practical purposes the same, but it was thought using a dedicated pin for VREF- was worth a try.

eetech
- 6th March 2007, 23:34
BigW,

I realize the 2.5 is near the limit, but it is the best choice for the project. The correction factor was computed by using several samples to compute the slope of the error. Calling it an offset is bad terminology on my part.

VSS = 5.0v
VREF+ = 2.58v
VREF- = gnd
measured voltages are in the range of 0.2v to 2.0v

eetech
- 7th March 2007, 21:22
As I said, I fully expected someone to point out a stupid mistake on my part.... and I get to be that someone. The problem was the reference itself, it was not stable.
Thanks to everyone who took the time to look at the problem and those who made sugesstions.


Lesson learned: check everything!