PDA

View Full Version : I am confuse



timseven
- 14th October 2009, 23:27
Hi, I am trying to use the 16f88 ability for read analog voltages. I need to use analog inputs RA0-RA3. My initial settings are as follows:

ANSEL = %00001111 'set RA0-RA3 as analog inputs
ADCON1 = %10000000 'Right Justifies 10-bit value
OSCCON = $60 'Sets the internal oscillator to 4 Mhz
DEFINE ADC_BITS 10 ' Sets the number of bits in the result to 10

ti var byte
ti = 50 '50 MILLISECONDS DELAY'
A var word ‘ A,B,C and D as variables
B var word
C var word
D var word

TRISA = %00001111
TRISB = 0 ‘Turn PORT B as outputs

I am using RA5 as my communication out to the LCD. (Internal clock). I am using also the 8 pins Portb for controlling two steps motors. Problem here is that if I ground the input pins (just for testing) I should get zero voltages and I don’t. I am using a 1K resistor to ground. For sure I am missing something here. Please advice.

mackrackit
- 15th October 2009, 01:05
With out seeing your code try setting the ADC for 8 bits and see what happens.

Acetronics2
- 15th October 2009, 08:29
Hi,

Set comparators OFF ...
ADCON0 = ?

Alain

mackrackit
- 15th October 2009, 12:40
I think this chip has the comparators off on reset. I need to double check.

Thinking more along the lines of not reading both the high and low bytes of the 10 bit setup might be the problem???

Acetronics2
- 15th October 2009, 14:44
Hi, Dave

you're right ... I never trust in defaults ... ( overhead, yes ... but sleeping nights ...)

what about this one :



TRISA = %00001111



RA5/MCLR/VPP bit 5 ST Input, Master Clear (Reset) or programming voltage input.




I am using RA5 as my communication out to the LCD


...

Alain

mackrackit
- 15th October 2009, 15:15
Alan,

That would make the display act funny :p

timseven
- 15th October 2009, 16:33
Well, first I did was to change the out pin to the LCD (Sorry I was using RA6 not RA5) to PortB.1 as for the test only. Second, I changed ADC to 8 bits and it went to zero but refuse to read any change voltage so I set it to back to 10. I wonder how can I set the AD comparators off using ADCON0. I read the 16F88 spec sheet page 114 and I don’t find a way to turn those comparators off. Please advice.

mackrackit
- 15th October 2009, 16:40
http://www.picbasic.co.uk/forum/showthread.php?t=561
Worth reading.

mackrackit
- 16th October 2009, 08:16
I picked up the below method of reading the ADC here
http://www.rentron.com/PICX2.htm
I like it much better than ADCIN.

The below code is an example for reading ADC channel 0. Look at the example on the above link to add other channels.

It looks like a lot of stuff to do to read the ADC, pretty much what ADCIN does behind the scenes. This way you have control.
The "READ_AD" part is only needed once no matter how many channels you are reading (reusable).

Use your LCD or SERIAL to see what is happening. I have this running at 2400 baud. Works OK with the internal OSC for testing.



[color=#000080]'16F88 ADC TEST FOR CHANNEL 0
DEFINE OSC 4
OSCCON = %01100000
@ __config _CONFIG1, _INTRC_IO & _WDT_OFF & _LVP_OFF & _MCLR_OFF &_CP_OFF
ANSEL = %00001111
TRISA = %11111111
CHAN0 VAR WORD 'VAR TO HOLD ADC0 READING
START:
HIGH PORTB.3 'HEART BEAT
PAUSE 250
LOW PORTB.3
PAUSE 250
'BELOW WILL SHOW WHAT THE ADRESH AND ADRESL REGISTER HOLDS
SEROUT2 PORTB.2, 16780, ["ADRESH ",DEC ADRESH," ADRESL ",DEC ADRESL,$a,$d]
PAUSE 50
'BELOW SHOWS THE 10 BIT READING OF ADC0 IN VAR CHAN0
SEROUT2 PORTB.2, 16780, ["CHAN0 ",DEC CHAN0,$a,$d]
GOSUB ADC_0 'STARTS THE READING OF ADC CHANNEL 0
GOTO START

ADC_0: 'READ AN0
ADCON1 = %10000000 'SET FOR 10 BIT
ADCON0 = %00000001 'TURNS ADC ON
GOSUB READ_AD
CHAN0.HighByte = ADRESH 'PLACES THE HIGH AND LOW BYTE
CHAN0.LowByte = ADRESL 'INTO VAR CHAN0
RETURN

READ_AD: 'DOES THE ADC CONVERSION
PAUSE 50
ADCON0.2 = 1
PAUSE 50
RETURN

Melanie
- 16th October 2009, 11:06
You can actually improve on that Dave...

Instead of...

ADCON0.2=1
PAUSE 50
RETURN

... which makes the assumption that your ADC reading will complete in 50mS... well - suppose it didn't? And suppose it only took only 50uS then you've wasted a shed load of time!

So, rather than a hit or miss approach, nail it properly...

ADCON0.2=1
WHILE ADCON0.2=1:WEND
RETURN

To find out why I've done this, read the Datasheet description for pin ADCON0.2

Acetronics2
- 16th October 2009, 12:31
A2D8.bas example program, in the SAMPLES Folder ...

While ... Wend did not exist in those prehistoric times this example was written ...


Still no code available from tim ???

Alain

mackrackit
- 16th October 2009, 13:48
COOL!!!

This is what I have said. You learn by trying to help.
Been using something like I posted all along and of course I have read that part about that bit but it never clicked...

Maybe that is why it is called GO/DONE :p

Prehistoric??? Maybe there is another message here. :eek:

Melanie
- 16th October 2009, 16:41
Well even in prehistoric times IF was available to you...



ADCON0.2=1
ADCTIMEOUT:
IF ADCON0.2=1 THEN ADCTIMEOUT
RETURN

Acetronics2
- 16th October 2009, 17:12
Hi, Mel

my prehistorics datings ( 14 Carbide ...) are V2.21 ...



mainloop: ADCON0.2 = 1 ' Start Conversion

notdone: Pause 5
If ADCON0.2 = 1 Then notdone ' Wait for low on bit-2 of ADCON0, conversion finished

adval = ADRESH ' Move high byte of result to adval


of course it's impossible you knew it, may be your grand'dad ...

I suspect " Pause 5 " here for 10,000 microns handcarved silicium "1650" processor ( PIC's ancester )...

Regards
Alain

timseven
- 20th October 2009, 03:03
Well after reading all of your posts and did some research on the 16f88 datasheet I applied some changes to my own program that looks it has improved. With all channels 0 to 3 straight to ground I got channels 2 and 3 to 0 and channels 0 and 1 to some value of 14. I am adding the program listing for your evaluation. Thank you in advance.


@ __config _CONFIG1, _INTRC_IO & _WDT_ON & _LVP_OFF & _CP_OFF

INCLUDE "modedefs.bas"
ANSEL = %00001111 'set RA0-RA3 as analog inputs
ADCON1 = %10000000 'Right Justifies 10-bit value
OSCCON = $60 'Sets the internal oscillator to 4 Mhz
CMCON = 7 'Comparators off

DEFINE ADC_BITS 10 ' Sets the number of bits in the result to 10

ti var byte
ti = 50 '20 MILLISECONDS DELAY'
A VAR word
B VAR word
C VAR word
D VAR word
TRISA = %00001111
TRISB = 0 'TURN PORT B as outputs but RB1 WHEN USE ICD FOR COMMUNICATION

'* * * * * MAIN PROGRAM START HERE * * * * * * * *

PAUSE 1000
Serout PORTB.1, 0, [254,1]
Serout PORTB.1, 0, [254,2]
PAUSE 20

READSENSORS:

ADCON0 = %00000001 'Turn ON CHAN 0
GOSUB ADCON
A.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, ["Ch 0= ",# A.LOWBYTE]
pause 20

ADCON0 = %00001001 'Turn ON CHAN 1
GOSUB ADCON
B.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, [" Ch 1= ",# B.LOWBYTE]
PAUSE 20

SEROUT PORTB.1,0,[$FE,$C0]

ADCON0 = %00010001 'Turn ON CHAN 2
GOSUB ADCON
C.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, ["Ch 2= ",# C.LOWBYTE]
PAUSE 20

ADCON0 = %00011001 'Turn ON CHAN 3
GOSUB ADCON
D.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, [" Ch 3= ",# D.LOWBYTE]
PAUSE 1000

Serout PORTB.1, 0, [254,1]

GOTO READSENSORS ' PROVISIONAL LOOP TO CHECK THE A/D CONVERTION.

'* * * * * * * * * SELECTING THE MOTOR MOVEMENT * * * * * * * *

IF A =0 and D =0 or C =0 and b =0 THEN GOTO READSENSORS 'IT IS DARK
IF ABS (A-D)<10 OR ABS (B-C)<10 THEN GOTO READSENSORS 'IT IS ALIGNED

If (B>D) OR (A>C) Then gosub Front
IF (A>B) OR (C>D) THEN GOsub Left
IF (C>A) OR (D>B) THEN GOsub Back
IF (D>C) OR (B>A) THEN GOsub Right

GOTO READSENSORS 'STAY FOR EVER LOOPING

'* * * * * * * * * MOTOR'S MOVEMENTS SUBRUTINES * * * * * * * *

Front:
Serout PORTA.6, 0, ["FRONT ",# ABS (B-D)," ",# ABS (A-C)]
SEROUT PORTA.6, 0, [$FE,$C0]
PORTB = 1 'GOING FRONT
PAUSE TI
PORTB = 2
PAUSE TI
PORTB = 4
PAUSE TI
PORTB = 8
PAUSE TI
Return
LEFT:
Serout PORTA.6, 0, ["LEFT ",# ABS (a-b)," ",# ABS (C-D)]
SEROUT PORTA.6, 0, [$FE,$C0]
PORTB = 128 'GOING LEFT
PAUSE TI
PORTB = 64
PAUSE TI
PORTB = 32
PAUSE TI
PORTB = 16
PAUSE TI
Return

Back:
Serout PORTA.6, 0, ["BACK ",# ABS(C-A)," ",# ABS(D-B)]
SEROUT PORTA.6, 0, [$FE,$C0]
PORTB = 8 'GOING BACK
PAUSE TI
PORTB = 4
PAUSE TI
PORTB = 2
PAUSE TI
PORTB = 1
PAUSE TI
Return
RIGHT:
Serout PORTA.6, 0, ["RIGHT ",# ABS(D-C)," ",# ABS(B-A)]
SEROUT PORTA.6, 0, [$FE,$C0]
PORTB = 16 'GOING RIGHT
PAUSE TI
PORTB = 32
PAUSE TI
PORTB = 64
PAUSE TI
PORTB = 128
PAUSE TI
Return

ADCON:
ADCON1 = %10000000 'SET FOR 10 BITS
ADCON0.2 = 1 'IT'S ONE TILL IT READS
WHILE ADCON0.2 = 1 : WEND
RETURN

END

mackrackit
- 20th October 2009, 07:52
I am probably missing something but give this a shot.


@ __config _CONFIG1, _INTRC_IO & _WDT_ON & _LVP_OFF & _CP_OFF

INCLUDE "modedefs.bas"
ANSEL = %00001111 'set RA0-RA3 as analog inputs
OSCCON = $60 'Sets the internal oscillator to 4 Mhz
CMCON = 7 'Comparators off

ti var byte
ti = 50 '20 MILLISECONDS DELAY'
A VAR word
B VAR word
C VAR word
D VAR word
TRISA = %00001111
TRISB = 0 'TURN PORT B as outputs but RB1 WHEN USE ICD FOR COMMUNICATION

'* * * * * MAIN PROGRAM START HERE * * * * * * * *

PAUSE 1000
Serout PORTB.1, 0, [254,1]
Serout PORTB.1, 0, [254,2]
PAUSE 20

READSENSORS:
ADCON1 = %10000000 'SET FOR 10 BITS
ADCON0 = %00000001 'Turn ON CHAN 0
GOSUB ADCON
A.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, ["Ch 0= ",# A.LOWBYTE]
pause 20
ADCON1 = %10000000 'SET FOR 10 BITS
ADCON0 = %00001001 'Turn ON CHAN 1
GOSUB ADCON
B.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, [" Ch 1= ",# B.LOWBYTE]
PAUSE 20
SEROUT PORTB.1,0,[$FE,$C0]
ADCON1 = %10000000 'SET FOR 10 BITS
ADCON0 = %00010001 'Turn ON CHAN 2
GOSUB ADCON
C.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, ["Ch 2= ",# C.LOWBYTE]
PAUSE 20
ADCON1 = %10000000 'SET FOR 10 BITS
ADCON0 = %00011001 'Turn ON CHAN 3
GOSUB ADCON
D.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR
SEROUT PORTB.1 , 0, [" Ch 3= ",# D.LOWBYTE]
PAUSE 1000
Serout PORTB.1, 0, [254,1]
GOTO READSENSORS ' PROVISIONAL LOOP TO CHECK THE A/D CONVERTION.
'* * * * * * * * * SELECTING THE MOTOR MOVEMENT * * * * * * * *

'* * * * * * * * * MOTOR'S MOVEMENTS SUBRUTINES * * * * * * * *
ADCON:
ADCON0.2 = 1 'IT'S ONE TILL IT READS
WHILE ADCON0.2 = 1 : WEND
RETURN
END
This is what I am basing the sequence on. From the data sheet.

1. Configure the A/D module:
• Configure analog/digital I/O (ANSEL)
• Configure voltage reference (ADCON1)
• Select A/D input channel (ADCON0)
• Select A/D conversion clock (ADCON0)
• Turn on A/D module (ADCON0)
I am pretty sure this sequence needs to be followed. I am not at the shop so I can not test your code now.

Acetronics2
- 20th October 2009, 08:59
Hi, Dave and Tim

I had a look to the TEST section of this program ... It gave that, with a " classic " PBP use. :



'Config

@ __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB3 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_ON & _INTRC_IO

@ __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF



'@ __config _CONFIG1, _INTRC_IO & _WDT_ON & _LVP_OFF & _CP_OFF

DEFINE ADC_BITS 10 ' Sets the number of bits in the result to 10


ANSEL = %00001111 'set RA0-RA3 as analog inputs

'ADCON1 = %10000000 'Right Justifies 10-bit value

'OSCCON = $60 'Sets the internal oscillator to 4 Mhz

OSCCON = %01101110 'Internal RC w/ I/Os

INTCON = 0
PIE1 = 0
PIE2 = 0
CMCON = 7 'Comparators off
CVRCON = 0

INCLUDE "modedefs.bas"

ti var byte
ti = 50 '20 MILLISECONDS DELAY'

A VAR word
B VAR word
C VAR word
D VAR word

_A CON 0
_B CON 1
_C CON 2
_D CON 3

TRISA = %00001111
TRISB = 0 'TURN PORT B as outputs but RB1 WHEN USE ICD FOR COMMUNICATION

'* * * * * MAIN PROGRAM START HERE * * * * * * * *

PAUSE 1000
Serout PORTB.1, 0, [254,1]
Serout PORTB.1, 0, [254,2]
PAUSE 20

READSENSORS:

'ADCON0 = %00000001 'Turn ON CHAN 0
'GOSUB ADCON

ADCIN _A, A

'A.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR

SEROUT PORTB.1 , 0, ["Ch 0= ",# A.LOWBYTE]
pause 20

'ADCON0 = %00001001 'Turn ON CHAN 1
'GOSUB ADCON

ADCIN _B, B

'B.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR

SEROUT PORTB.1 , 0, [" Ch 1= ",# B.LOWBYTE]
PAUSE 20

SEROUT PORTB.1,0,[$FE,$C0]

'ADCON0 = %00010001 'Turn ON CHAN 2
'GOSUB ADCON

ADCIN _C, C

'C.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR

SEROUT PORTB.1 , 0, ["Ch 2= ",# C.LOWBYTE]
PAUSE 20

'ADCON0 = %00011001 'Turn ON CHAN 3
'GOSUB ADCON

ADCIN _D, D

'D.LOWBYTE = ADRESL 'PLACES THE LOW BYTE INTO VAR

SEROUT PORTB.1 , 0, [" Ch 3= ",# D.LOWBYTE]


PAUSE 1000
Serout PORTB.1, 0, [254,1]

GOTO READSENSORS ' PROVISIONAL LOOP TO CHECK THE A/D CONVERTION.



I just commented out original lines for comparison ...

Hope it Helps

Alain

timseven
- 21st October 2009, 19:47
I did the two editing of my program as Acetronics and as Mackrackit subjected. I ran both versions and ran with the same faulty results. I can’t understood how three persons could be wrong so I started again a check of my hardware. I found the problem on the breadboard. At the two power lines that runs on the outside of the board (-,+) the + line had 50 ohms! from one end to the other. I found a fault connection and restored it with a new line, problem goes. Now every input goes to zero. I want to thanks all of you including Melanie. Every time I come across an obstacle there is a reason to learn. Thanks.

mackrackit
- 22nd October 2009, 01:59
COOL!!!
At least now you have a couple different ways to read the ADC.

Have FUN!!!

timseven
- 23rd October 2009, 15:49
Thank you. Yes I had a lot of fun with every project. I had to unassembled the breadboard and run a soldered copper line under all around it to ensure a good contact. That’s part of the fun also. Thanks.