PDA

View Full Version : A/D converter fails?



egberttheone
- 7th February 2006, 20:34
I'm building a system to monitor a few powerlines it works well but some times the conversion results into a 0; i took the data sheet of the pic i use (16f88) read the whole chapter about it over and over and i finished up changing my code(snippets; of course the enable bit and so are set) from this:


'GO/DONE: A/D Conversion Status bit
'If ADON = 1:
'1 = A/D conversion in progress (setting this bit starts the A/D conversion)
'0 = A/D conversion not in progress (this bit is automatically cleared by hardware when the A/D
'conversion is complete)
symbol AD_Progress = ADCON0.2


ADCON0.5 = 0
ADCON0.4 = 0
ADCON0.3 = 0
AD_Progress = 1
while AD_Progress = 1: wend
Sound_Level.lowbyte = ADRESL
Sound_Level.highbyte = ADRESH


to this:



'GO/DONE: A/D Conversion Status bit
'If ADON = 1:
'1 = A/D conversion in progress (setting this bit starts the A/D conversion)
'0 = A/D conversion not in progress (this bit is automatically cleared by hardware when the A/D
'conversion is complete)
symbol AD_Progress = ADCON0.2

ADCON0.5 = 0
ADCON0.4 = 0
ADCON0.3 = 0
pause 50
AD_Progress = 1
while AD_Progress = 1: wend
Sound_Level.lowbyte = ADRESL
Sound_Level.highbyte = ADRESH


as I understood of the manual: if I change the input port from the a/d converter I need to wait a minimum of time before recalling a new a/d conversion. So far so good but what happens is it stucks @ "while AD_Progress = 1: wend" because it simply does not clear any more the code above without the pause 50 does work! so if I remove that line "pause 50" the code runs but some times I get a 0 in the result of the a/d conversion :S I don;t get it do you?

Bruce
- 7th February 2006, 23:32
ADCON0.0 = 1 ' <-- Turn ON A/D module

egberttheone
- 8th February 2006, 19:22
ADCON0.0 = 1 ' <-- Turn ON A/D module

please read before replying; i told that all these bits are set AND i sad that it works without the pause command or do you want to say that beacause i added the command line "pause 50" that the a/d conversion module shuts off?

Bruce
- 8th February 2006, 21:05
Sorry. It's hard to "guess" how you're configuring things if you don't show it in your code.

I'm sure this isn't what the rest of your own application is doing, but it works fine with the
pause 50 in there;


@ DEVICE HS_OSC, WDT_ON, LVP_OFF, PROTECT_OFF
DEFINE OSC 20

SYMBOL AD_Progress = ADCON0.2
SYMBOL ADON = ADCON0.0
SYMBOL LED = PORTB.0

Sound_Level VAR WORD

TRISA.0 = 1 ' A/D input
PORTB.0 = 1 ' LED on at boot
TRISB.0 = 0 ' LED output

ADCON0 = 128 ' A/D clock Fosc/32, RA0/AN0, A/D disabled
ANSEL = 1 ' RA0 analog
ADCON1.7 = 1 ' right justify for 10-bit

Main:
ADON = 1 ' turn on A/D module
PAUSE 50 ' wait
AD_Progress = 1 ' start conversion

WHILE AD_Progress = 1 : WEND
Sound_Level.lowbyte = ADRESL
Sound_Level.highbyte = ADRESH
LED = LED ^ 1 ' toggle LED for visual
GOTO Main

END
I left the WDT enabled just to be sure PBP was handling it during the pause periods.

egberttheone
- 8th February 2006, 21:09
this code works but if you change the input port of the a/d convertor and then add a pause in the line between changing and a/d conversions start then it stucks.

example:



'retrieve sound level
ADCON0.5 = 0
ADCON0.4 = 0
ADCON0.3 = 0
pause 50
AD_Progress = 1
while AD_Progress = 1: wend
Sound_Level.lowbyte = ADRESL
Sound_Level.highbyte = ADRESH

'retrieve negative level
ADCON0.5 = 0
ADCON0.4 = 0
ADCON0.3 = 1
pause 50
AD_Progress = 1
while AD_Progress = 1: wend
Negative_Voltage.lowbyte = ADRESL
Negative_Voltage.highbyte = ADRESH

'retrieve positieve level
ADCON0.5 = 0
ADCON0.4 = 1
ADCON0.3 = 0
pause 50
AD_Progress = 1
while AD_Progress = 1: wend
Positive_Voltage.lowbyte = ADRESL
Positive_Voltage.highbyte = ADRESH

Bruce
- 8th February 2006, 21:42
That's odd. It works for me without getting stuck.

I modified your version to include 3 LED's in the last section of each channel read routine,
and all 3 LED's blink right along.

It doesn't appear to be getting getting stuck at any point.


@ DEVICE HS_OSC, WDT_ON, LVP_OFF, PROTECT_OFF
DEFINE OSC 20

SYMBOL AD_Progress = ADCON0.2
SYMBOL ADON = ADCON0.0
SYMBOL LED1 = PORTB.0
SYMBOL LED2 = PORTB.1
SYMBOL LED3 = PORTB.2

Sound_Level VAR WORD
Negative_Voltage VAR WORD
Positive_Voltage VAR WORD

TRISA.0 = 1 ' A/D input
PORTB = %00000111 ' LED's on at boot
TRISB = 0 ' LED outputs

ADCON0 = 128 ' A/D clock Fosc/32, RA0/AN0, A/D disabled
ANSEL = 1 ' RA0 analog
ADCON1.7 = 1 ' right justify for 10-bit

Main:
ADON = 1 ' turn on A/D module
PAUSE 50 ' wait
AD_Progress = 1 ' start conversion
WHILE AD_Progress = 1: WEND
Sound_Level.lowbyte = ADRESL
Sound_Level.highbyte = ADRESH
LED1 = LED1 ^ 1 ' toggle LED for visual

'retrieve negative level
ADCON0.5 = 0
ADCON0.4 = 0
ADCON0.3 = 1
PAUSE 50
AD_Progress = 1
WHILE AD_Progress = 1: WEND
Negative_Voltage.lowbyte = ADRESL
Negative_Voltage.highbyte = ADRESH
LED2 = LED2 ^ 1 ' toggle LED for visual

'retrieve positieve level
ADCON0.5 = 0
ADCON0.4 = 1
ADCON0.3 = 0
PAUSE 50
AD_Progress = 1
WHILE AD_Progress = 1: WEND
Positive_Voltage.lowbyte = ADRESL
Positive_Voltage.highbyte = ADRESH
LED3 = LED3 ^ 1 ' toggle LED for visual
GOTO Main

END
Are you reading 0-5 VDC voltage levels?

egberttheone
- 9th February 2006, 18:13
yes, i'm reading voltage's between 0-5VDC. i found out that it doesn't mather where i place the pause command(in the interrupt routine); it instant freez the pic forever. The AD routine is placed in a interrupt routine is it not possible to place a pause periode into a interrupt handel?

note: timer0, timer1 and serial interrupt are activated.

egberttheone
- 13th February 2006, 17:08
any one ? :(

Bruce
- 13th February 2006, 17:19
Are you using BASIC or assembler interrupts?

Can you post the code you're having problems with?

egberttheone
- 13th February 2006, 17:53
i do not want to post the code; but i can email it to you. i'm using the basic interrupt routine (on interrupt goto handel)

Bruce
- 13th February 2006, 18:06
Are you clearing "all" interrupt flags before exiting your interrupt handler?

egberttheone
- 13th February 2006, 18:09
Yes, but can i use a pause command in the interupt?




Disable ' interrupt handler
Handle:

if RCIF = 1 then ' serial intterupt
RCIF = 0 ' clearing interrupt flags
IF OERR THEN ' Clear over-runs if OERR set
CREN = 0 ' Disable USART receive
CREN = 1 ' Re-enable USART receive
ENDIF
'Serial commands.
endif


IF TMR0IF = 1 THEN 'RECEIVE all A/D value's
TMR0IF = 0
gosub CoversionsAD
gosub saftycontrol 'check al received value's
ENDIF

if TMR1IF = 1 then
TMR1IF = 0
gosub PacketSend
endif

TimeOut:
resume
enable

Bruce
- 13th February 2006, 18:28
You can use all the pause statements you want inside a BASIC interrupt, however, I don't recommend you place gosubs in your interrupt handler.

This exits the interrupt handler, and if it lands in a sub routine where you are not disabling PBP's auto-insertion of interrupt checking stubs, then it's going to go totally nuts on you.

Place all of your routines inside the interrupt handler, or set/clear some type of flags to indicate the interrupt source, then return, then act on the other sub routines as needed.

Also note that RCIF can NOT be cleared with RCIF = 0. The only way to clear RCIF is to read the fifo USART buffer until it's empty. Trying to clear this flag like you are, you're leaving it set, and never clearing the USART interrupt flag bit.

egberttheone
- 13th February 2006, 18:45
ah! the gosubs seems to be the problem :) ! but now I have the problem that the a/d conversion some times fluctuates(value's are not the same every querying + 1000 some times). Where can I begin to debug? Thx !

Bruce
- 13th February 2006, 18:57
A/D readings will pretty much always fluctuate. A small RC filter on each A/D input may help. If not, you might consider putting the PIC to sleep prior to A/D readings to reduce in-circuit noise from the oscillator & internal switching.

If you think "code" may be causing the fluctuations, then simply strip down the program to nothing but reading & displaying A/D values. If it works smoothly, then take a hard look at the rest of your code.