PDA

View Full Version : 16F88 + 2 Analog inputs



ruijc
- 4th June 2010, 21:27
Hi all,

I'm having some issues reading 2 analog voltages with Pic 16F88.

I have successfully make it work with only AN0, but when using 2 or more ports just doesn't want to work. Something is missing and i cant see it.

The hardware is simple:

Pic has only 3 connections ( output to RS232 and 2 analog inputs ). I have a 330K resistor from VDD to AN0 and a 47K resistor from VDD to AN1.

Measuring voltage on these 2 pins i have AN0 = 1.19V and AN1=4.82V
If my math is correct i should have readings like AN0= 244 and AN1=986 ( 10Bits calculation ).

Instead i have AN0= 1011 and AN1=1014 ( most of the times both reading are the same ).

Here's the code:

[code]

'****************************************
'DEFINEs

@ DEVICE PIC16F88, INTRC_OSC_NOCLKOUT
@ DEVICE PIC16F88, MCLR_OFF
@ DEVICE PIC16F88, PROTECT_OFF

DEFINE OSC 8

@ DEVICE PIC16F88, CPD_OFF
@ DEVICE PIC16F88, LVP_OFF
@ DEVICE PIC16F88, BOD_OFF
@ DEVICE PIC16F88, PWRT_OFF
@ DEVICE PIC16F88, WDT_OFF
@ DEVICE PIC16F88, CCPMX_OFF

@ DEVICE PIC16F88, FCMEN_OFF
@ DEVICE PIC16F88, IESO_OFF

@ DEVICE PIC16F88, DEBUG_OFF
@ DEVICE PIC16F88, LVP_OFF

'***************************************

OSCTUNE=0

OSCCON = %01111110
INTCON = 0
PIE1 = 0
PIE2 = 0
CMCON = %00001111 'comparators off
CVRCON = 0
CCP1CON = 0

'*******************************************
'ADC

DEFINE ADC_BITS 10 ' Set number of bits in result ( 8 or 10 bits )
DEFINE ADC_CLOCK 3 ' Set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in uS

'******************************************
'ADC parameters

ADCON0 = %11000000 ' clock source
ANSEL =%00000011 ' Porta.1 and .2 used by ADC
ADCON1 =%10000011 ' Right justify

'***************************************

INCLUDE "modedefs.bas"
DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 6
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 1

'*************************************
' variables

loop VAR WORD
som VAR WORD
luz VAR WORD

vals VAR WORD
vall VAR WORD

A VAR word
B VAR word

'****************************************

PORTA=0
PORTB=0
TRISA=%10110111
TRISB=%11000100

'***************************************

'PINS

Si var PORTA.0 'input1
Li var PORTA.1 'input2
a2 var PORTA.2 'nc
com var PORTA.3 'RS232
A4 var PORTA.4 'nc
MCLR var PORTA.5 'MCLR
A6 var PORTA.6 'nc
A7 var PORTA.7 'nc
B0 var PORTB.0 'nc
b1 var PORTB.1 'nc
But var PORTB.2 'Button
B3 var PORTB.3 'nc
b4 var PORTB.4 'nc
Led var PORTB.5 'Led
PGC var PORTB.6 'PGC
PGD var PORTB.7 'PGD

'***************************************
clear
'***************************************
INIT:

high led
pause 50

debug "Starting...",13,10


debug $0D, $0A
PAUSE 50

for loop=0 to 7
toggle led
next

pause 1500


'**********************************************
start:

gosub s1

gosub s2

gosub out

goto start

'*******************************************
S2:

ADCON0 = %11001000
luz=0
vall=0
for loop=0 to 15
adcin PORTA.1,vall
pause 80
luz=luz+vall
next
luz=luz/16

return

'*********************************************
S1:

ADCON0 = %11000000
som=0
vals=0
for loop=0 to 15
adcin PORTA.0,vals
pause 80
som=som+vals
next
som=som/16

return

'*********************************************
out:

debug 13,10
debug "AN0 = ",dec som,13,10
debug 13,10
debug "AN1 = ",dec luz,13,10
debug 13,10
debug 13,10
debug 13,10

return

'******************************************

end
[\code]

Any help would be appreciated

tenaja
- 4th June 2010, 21:42
adcin PORTA.1,vall

This is a syntax error that compiles.

You need to use the analog CHANNEL number, NOT the port PIN number.

The hex value of PORTA is $05. Setting the bit to .0, .1, or .3 might set it to 0 or 1, but no matter what Port pin you use, you will never get a port number greater than 1 if you are using a bit value.

The hex value of analog channel 0 (AN0) is 0, and that's what you need to be using. It may have helped to read the HELP file:

ADCIN 0, B0 ' Read channel 0 to B0


So the hex values are valid to compile, but when they are placed into the ANSEL register, you don't get the results you were expecting.

Bottom line: Use the channel number, which is the "x" value of the ANx number on the pin diagrams. This is pretty simple had you looked at the HELP file.
ADCIN 0, B0 ' Read channel 0 to B0


Have fun!

ruijc
- 4th June 2010, 22:46
Hi tenaja,

Actually i use always the name given in the pinout definition:

Si var PORTA.0 'input1
Li var PORTA.1 'input2

My code has changed alot after some experiments and some reading.

Unfortunately changing to ADCin 0 or ADCin Si does not change the readings.

Still not working :(

Bruce
- 4th June 2010, 23:37
Using an alias to a port + pin is fine for some operations, but what tenaja told you is 100% correct. You cannot use anything except ADCIN 0,VAR - or ADCIN 1,VAR, etc.

The 0,1,2,3,4, etc immediately after the ADCIN command is a constant. Not an alias to a PORT + PIN. This should be fairly clear by simply reading the manual, and looking at the example provided - or searching this forum for ADCIN examples.

tenaja
- 4th June 2010, 23:46
You are still using the incorrect syntax. You need to use numbers 0 through 6 (since your pic has 7 channels), or symbols representing those numbers, not PORT numbers. If it works with a Portx, then it's just coincidence and this bad practice will come back to bite you. You could easily be reading some pin other than the one you want. READ THE MANUAL.

Second, I just read about your resistor connections:

Pic has only 3 connections ( output to RS232 and 2 analog inputs ). I have a 330K resistor from VDD to AN0 and a 47K resistor from VDD to AN1.

Measuring voltage on these 2 pins i have AN0 = 1.19V and AN1=4.82V
If my math is correct i should have readings like AN0= 244 and AN1=986 ( 10Bits calculation ).

This is the reason you are getting high values instead of low values. Either you misrepresented your circuit, or you do not understand resistor networks.

For starters, the datasheet says you need 10k max to ground--see section 12.1 of the datasheet--it's in BOLD in the first paragraph! You don't mention any R's to ground, and the values you do mention are way out of spec. If that's he case & you don't have a resistor going to ground, then you should theoretically have VDD volts at both a/d ports--and that explains your readings near 1024. If you do have an R to ground in a similar high K range, you could easily be getting an unreliable value due to the high impedance.

Toss in those extra two resistors, fix your channel numbers, and you are good to go.

ruijc
- 5th June 2010, 00:24
Hi Tenaja and Bruce

Thanks for your support.

About the pin calling its noted ;)

But Tenaja was also right about the input impedance.

The circuit was missing the pulldown resistors.
I checked the datasheet and it's confusing for me that in bold it states the max impedance for analog sources is 2.5K and at the bottom square states the max impedance for analog sources is 10K. Which should we follow ?

tenaja
- 5th June 2010, 04:26
Page 117 it states 10k in two places; text and notes. Page 190 says 2.5 with a NOTE, that says 10k is allowable with an increased acquisition time. That basically means extra time to charge the sampling cap. If you plug your numbers into equation 12-1 on pg. 117 you will get the appropriate time required. IIRC, the fastest it can go is around 30-35kHz, so with a 10k R, you'll have to slow it down to be reliable.

However, if you don't need 10bit accuracy, it probably doesn't matter.

ruijc
- 5th June 2010, 14:43
Got it ;)

Thanks Tenaja

tekart
- 6th July 2010, 23:17
I had been struggling with the AD in the 16F88 recently and the answers you gave straightened me out. There's only so much documentation one person can digest and it is really wonderful to have this forum where we can learn from each other.

Thanks Tenaja