PDA

View Full Version : help setting up 16F886 for ADC



keithv
- 11th July 2016, 20:37
I'm trying to use adcin to read two different pots to get 8 bit results and I'm having trouble. I'm using the internal oscillator (there is no external oscillator). The pots are connected to AN0 and AN1

' Define ADCIN parameters ********************************
Define ADC_BITS 8 ' Set number of bits in result
Define ADC_SAMPLEUS 50 ' Set sampling time in uS
'Define ADC_CLOCK 3 ' This define is inoperative on 16F88x
ADCON0 = %11000000 ' Set ADC_CLOCK to RC (DEFINE ACD_CLOCK inoperative on the 16F88x)
ADCON1 = %00000000 ' Left-Justify result in ADRESH:ADRESL registers
ANSEL = %00000011 ' Set AN0, AN1 to analog, others digital
ANSELH = %00000000 ' Set AN8 and higher channels to digital operation
'************************************************* *********

I just copied the code from the LAB-X1 "adcin3x" sample program for the 16F887. I figured it would work the same for the 16F886 since it's basically a 28 pin version of the 16F887, but it doesn't seem to be working. I figured the problem was that the LAB-X1 uses a 4MHz external oscillator, but I've tried different setting on ADCON0 and it doesn't seem to change anything.

mark_s
- 11th July 2016, 23:32
I think that the code "adcin3x" is for the old pic16F877, not a pic16f887. The adc in the newer chips have more registers. I have found the adcin command does not always work. So I use a manual set and read routine. Below is an example for 10bit, I think the 8bit result will be in the ADC_AN0.HIGHBYTE when the adc is set to left shift?



ADC_AN0 var WORD '10bit result
ADC_AN1 var WORD '10bit result

'Read AN0
'--------------------------------------------------------------------------
ADCON0 = %11000011 'Set adc channel = AN0

WHILE ADCON0.1 = 1 'WAIT FOR CONVERSION

WEND
ADC_AN0.HIGHBYTE = ADRESH
ADC_AN0.LOWBYTE = ADRESL

'Read AN1
'--------------------------------------------------------------------------

ADCON0 = %11000111 'Set adc channel = AN1

While ADCON0.1 = 1 'WAIT FOR CONVERSION

WEND


ADC_AN1.HIGHBYTE = ADRESH
ADC_AN1.LOWBYTE = ADRESL
'---------------------------------------------------------------------------

midali
- 10th February 2018, 09:08
Hi to all,

I have troubles with reading 10 bit on AN0 , too .
Can somebody give me some ideas, please ?


'************************************************* ***************
'* Name : UNTITLED.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 10/2/2018 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
'PIC16F886
#config
__CONFIG _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG _CONFIG2, _WRT_OFF & _BOR21V
#endconfig

define osc 4
include "lcd886.bas"
CM1CON0 = 0 'Comparator Off
CM2CON0 = 0 'Comparator Off

Define ADC_BITS 10 'Set number of bits in result (10)
Define ADC_CLOCK 3 'Set clock source (3=rc)
Define ADC_SAMPLEUS 50 'Set sampling time in microseconds (50us)

TRISA = %00000001 'Set PORTA.0 as input
TRISB = %00000000 'Set PORTB as outputs
TRISC = %00000000 'Set PORTC as outputs

ANSEL = %00000001 'Set PORTA.0 as analog
ANSELH = %00000000 'The rest ports are digital
'ADCON0 = %11000011 'Set adc channel = AN0
'ADCON1 = %10000000 'SETUP ADC RIGHT JUSTIFY SET REFV to VDD & VSS

PORTA = 0
PORTB = 0
PORTC = 0

light var PORTA.3
tc var word

'--------light is ON and initialize the LCD ---------
pause 300
high light
gosub lcdrst
lcdout $fe, $80,"TEST"
gosub lcdrst

'---------------------PROGRAM------------------------
MAIN:
ADCON0 = %11000011
gosub read_tc

lcdout $fe, $80, #tc
pause 200
goto main
end

'---------------------Read AN0------------------------
read_tc:
WHILE ADCON0.1 = 1:WEND 'WAIT FOR CONVERSION
tc.HIGHBYTE = ADRESH
tc.LOWBYTE = ADRESL
return
'--------------------lcd reset------------------------
lcdrst:
lcdout, $fe, 1
pause 10
return

Ioannis
- 10th February 2018, 19:56
Is it on a F886?

You MUST NOT set the GO/DONE bit at the same time you enable the ADC converter (Data Sheet page 106, Note in the box).

Also you do not setup the ADCON1. It is commented.

Try this:



'************************************************* ***************
'* Name : UNTITLED.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 10/2/2018 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
'PIC16F886
#config
__CONFIG _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_ON & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG _CONFIG2, _WRT_OFF & _BOR21V
#endconfig

define osc 4
include "lcd886.bas"
CM1CON0 = 0 'Comparator Off
CM2CON0 = 0 'Comparator Off

Define ADC_BITS 10 'Set number of bits in result (10)
Define ADC_CLOCK 3 'Set clock source (3=rc)
Define ADC_SAMPLEUS 50 'Set sampling time in microseconds (50us)

TRISA = %00000001 'Set PORTA.0 as input
TRISB = %00000000 'Set PORTB as outputs
TRISC = %00000000 'Set PORTC as outputs

ANSEL = %00000001 'Set PORTA.0 as analog
ANSELH = %00000000 'The rest ports are digital
ADCON0 = %11000001 'Set adc channel = AN0
ADCON1 = %10000000 'SETUP ADC RIGHT JUSTIFY SET REFV to VDD & VSS

PORTA = 0
PORTB = 0
PORTC = 0

light var PORTA.3
tc var word

'--------light is ON and initialize the LCD ---------
pause 300
high light
gosub lcdrst
lcdout $fe, $80,"TEST"
gosub lcdrst

'---------------------PROGRAM------------------------
MAIN:
ADCON0.1=1
gosub read_tc

lcdout $fe, $80, #tc," " ' I put some space here when you go from large result to 1 digit result.
pause 200
goto main
end

'---------------------Read AN0------------------------
read_tc:
WHILE ADCON0.1 = 1:WEND 'WAIT FOR CONVERSION
tc.HIGHBYTE = ADRESH
tc.LOWBYTE = ADRESL
return
'--------------------lcd reset------------------------
lcdrst:
lcdout, $fe, 1
pause 10
return



Ioannis

midali
- 10th February 2018, 20:56
Thank you for your fast reply !

I tried your version, but don't work. The readed adc values oscilating from 10x to 22x.....

midali
- 10th February 2018, 21:08
Now I readed the some value on AN2 with succes, but AN0 is the same.

Ioannis
- 10th February 2018, 22:14
If you read on AN2 then we are getting somewhere.

Did you remember to change the channel to 0 after testing on AN2?

Does AN0 work on ADCIN 0,tc ?

Ioannis

midali
- 11th February 2018, 19:23
Thank you Ioannis for your effort ! .. you spend a time for me. The problem is solved, I don't understand what happened really.

So, on AN0 I had a TC1047 ( analog temperature sensor ) with a 100nF capacitor to ground. The voltage measured on AN0 was 726 mV , also I verified with a osciloscop and I had a "clean" voltage. After I removed the capacitor, AN0 work well .

Ioannis
- 12th February 2018, 06:45
this may lead you to these two things:

1. Your cap is shorted, or

2. if you use breadboard, it is faulty.

Ioannis

midali
- 13th February 2018, 09:02
I work on proffesional PCB, I changed the capacitor, but the same problem. So, nevermind, without 100nF capacitance the AN0 is ok. Anyway is strange whats what happen there.

On AN0 I read the voltage from a linear sensor temperature (TC1047). The temperature slope is fixed at 10 mV/°C and the output voltage at 0°C is 500 mV (according with page4 from datasheet).
My ideea to extract the °C isn't ok because the maximum reading read on the input is 1024 ((1024-500) / 10 = 52.4 degrees) and the number of read bits is read in step 5, so only 256 bits.

The problem with me is that I do not read correctly the milivolts on 10 bit. Any ideea is apreciated, thank you !


'---------------------PROGRAM------------------------
MAIN:
gosub read_tc 'read analog value
gosub calc_voltage 'calculate the mVolts
gosub conv_temp 'conversion to degrees

lcdout $fe, $80, #tc 'displat TC and mVolt only for info
lcdout $fe, $C0, #mvolt , " Temp= " , #grd
pause 100

goto main
end

'---------------------Read AN0------------------------
read_tc:
z=0
for i = 1 to 100 ' average to 100 reads
ADCON0.1=1
WHILE ADCON0.1 = 1:pause1:WEND 'WAIT FOR CONVERSION
tc.HIGHBYTE = ADRESH
tc.LOWBYTE = ADRESL
z = tc + z
next i
tc = z/100
return
'--------------------Calc Voltage----------------------
calc_voltage:
mvolt = (tc * 5//1024)
return
'-------------------Convert Temp----------------------
conv_temp:
grd = (mvolt - 500)/10 'readed mVolt value - 500 (according with TC1047 datasheet)
lcdout $fe, $C0+4, " Temp= " , #grd
return
'--------------------lcd reset------------------------
lcdrst:
lcdout, $fe, 1
pause 10
return

8593

richard
- 13th February 2018, 10:55
mvolt = (tc * 5//1024)

really

try


mvolt = (tc * 5/1024)

richard
- 13th February 2018, 12:37
also 100 iterations of this has every chance of overflowing a word var
z = tc + z
ie 100*921 = 92100 , word max val 65535



every count of tc = 5000/1024 mv


40 deg = 4500 mv would be a 921 count


the most accurate calc for pbp

would be mvolt = tc */ 1249

result for 921 = 4493



ps I assume ADFM set correctly

midali
- 13th February 2018, 20:54
Thank you very much Richard !

Now I see that 100 iterations overflowing a word var, so I'll use 10 iteration or DT Average routine, but nevermind right now.

I know it's unpleasant to ask beginners an advanced but you can explain me how its made middle 16 bits of multiplication calculation, please ? ( mvolt = tc */ 1249 )

Also I'm confused about "40 deg = 4500 mv would be a 921 count" , the maximum scale what I need is 1750 mV, 40 deg = 900mv ( 40 deg = 400mV + 500mV = 900mV) .

Please do not mind that I ask so many aberrations, but for me there are things I could not understand ...I'm old man and also beginner in programming.

richard
- 13th February 2018, 22:35
Also I'm confused about "40 deg = 4500 mv would be a 921 count" , the maximum scale what I need is 1750 mV, 40 deg = 900mv ( 40 deg = 400mV + 500mV = 900mV)

I must have up past my bedtime , managed to multiply 40 * 10 mv and got 4000


(
mvolt = tc */ 1249 )

@5v vcc each adc count is 4.88 mV
4.88*256=1249
pbp divides/multiplies have internal 32 bit results there are various commands the allow convenient
access to this result in useful ways

@40 deg tc would be about 184 counts


so our calc is (184*4.88*256)/256
since pbp can't do real numbers

we do the 4.88*256 =1249

and 184*/1249 does the rest ie 184*1249/256

midali
- 14th February 2018, 09:12
Now its clear for me.

Thank you very much for your patience and explanation !!

richard
- 14th February 2018, 11:14
this might interest you
http://www.picbasic.co.uk/forum/showthread.php?t=20469

midali
- 14th February 2018, 12:02
Sometimes I read this topic but when I needed it I did not find it ...I dug after him a few hours, so thousands thanks to all for help !