Searching \ for '[PIC]: multi-channel A/D trouble?' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/ios.htm?key=a%2Fd
Search entire site for: 'multi-channel A/D trouble?'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: multi-channel A/D trouble?'
2002\06\24@111149 by Guillermo Rodriguez Garcia

flavicon
face
Hi all,

I have an application running on a 16F872 @ 20 MHz that
(among other things) reads and converts data from three
analog channels connected to RA0, RA1, and RA3. The ADC
clock is selected as Fosc/32, so Tad = 1.6 us (Tad is
the bit conversion time).

Each channel is connected as follows:

                        50 Ohm
PIC's RAx ---------+---------/\/\/\/\----------- actual source
                   |
                   /
                   \ 10K
                   /
                   \
                   |
                  -+-
                  ///

So the impedance seen from the PIC should be somewhere between
50 Ohm and 10 K.


Software side of things:

1. I select the channel.

2. Then I am allow for an acquisition time of 22 us (the datasheet
   mentions 20 us for a 10 K source)

3. Then I start the conversion (set the 'GO' bit)

4. Once the conversion is over, I wait _at least_ 11 us (the
   datasheet also mentions that a delay of 2 x Tad needs to be
   honoured here)

5. Go back to step 1, but with the next channel.


Now my problem is the following: I just set one of the three channels
(let's say RA0) to a 4V source, and leave the other two (RA1 and RA3
in this example) unused (i.e. just connected to GND through the 10K
resistor). The first channel (4 V) is read OK, but for the next one
I read I get a non-zero value (about $008). Looks like the S & H
capacitor is not completely discharged.

I've checked the followin:

- Set RA1 to 4 V instead of RA0. In this case it is RA3 the one
  that reads a non-zero value.

- Replace the 10K resistor with a 1K resistor; in this case I
  measure about $004 instead of $008 in the 'next' channel.


Does someone have a clue? What's happening here?

Thanks in advance,
G.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spam_OUTlistservTakeThisOuTspammitvma.mit.edu with SET PICList DIGEST in the body


2002\06\24@112649 by Drew Vassallo

picon face
>1. I select the channel.
>
>2. Then I am allow for an acquisition time of 22 us (the datasheet
>    mentions 20 us for a 10 K source)
>
>3. Then I start the conversion (set the 'GO' bit)
>
>4. Once the conversion is over, I wait _at least_ 11 us (the
>    datasheet also mentions that a delay of 2 x Tad needs to be
>    honoured here)
>
>5. Go back to step 1, but with the next channel.

This sounds ok to me, except for the fact that there may be a problem with
your code, not your logic.

How about posting the A/D conversion section of your code?

--Andrew

_________________________________________________________________
Join the world s largest e-mail service with MSN Hotmail.
http://www.hotmail.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email .....listservKILLspamspam@spam@mitvma.mit.edu with SET PICList DIGEST in the body


2002\06\24@122946 by Olin Lathrop

face picon face
> 1. I select the channel.
>
> 2. Then I am allow for an acquisition time of 22 us (the datasheet
>     mentions 20 us for a 10 K source)
>
> 3. Then I start the conversion (set the 'GO' bit)
>
> 4. Once the conversion is over, I wait _at least_ 11 us (the
>     datasheet also mentions that a delay of 2 x Tad needs to be
>     honoured here)

There is no need to wait after the conversion is over, since it's over.  The
best way to wait for the conversion to complete is to monitor the GO/DONE
bit in ADCON0, or the ADIF flag in PIR1.  When reading multiple channels, I
usually switch to the next channel as soon as a conversion completes, then
get the ADRES values, etc.

{Quote hidden}

It seems like you are doing everything right.  Could the unused inputs be
picking up noise?  Are you really sure the 22uS wait is really 22uS?  It
seems very suspicious that you were still reading 4 with a 1K resistor.


*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspamKILLspammitvma.mit.edu with SET PICList DIGEST in the body


2002\06\24@123958 by Guillermo Rodriguez Garcia

flavicon
face
Hi Olin,

At 12:29 24/06/2002 -0400, Olin Lathrop wrote:
> > 1. I select the channel.
> >
> > 2. Then I am allow for an acquisition time of 22 us (the datasheet
> >     mentions 20 us for a 10 K source)
> >
> > 3. Then I start the conversion (set the 'GO' bit)
> >
> > 4. Once the conversion is over, I wait _at least_ 11 us (the
> >     datasheet also mentions that a delay of 2 x Tad needs to be
> >     honoured here)
>
>There is no need to wait after the conversion is over, since it's over.  The
>best way to wait for the conversion to complete is to monitor the GO/DONE
>bit in ADCON0, or the ADIF flag in PIR1.

That's what I do (I monitor ADIF in PIR1) but when I see ADIF=1 I still wait
an extra iteration. This is because in the mid-range reference manual I have
read that you must allow for at least 2 Tad extra between two consecutive
acquisitions (actually after finishing the conversion but before starting
the next acquisition). Isn't this correct?

>When reading multiple channels, I
>usually switch to the next channel as soon as a conversion completes, then
>get the ADRES values, etc.

Yep.


{Quote hidden}

But would it should this behaviour then? I mean, the unused inputs
seem to be somehow 'tracking' the channel that is set to 4 V. If I
set all three channels to unused (so all three are connected to GND
via 10K resistors) then I do measure zero on all of them...

>Are you really sure the 22uS wait is really 22uS?

Yes -- that's both calculated and checked (for debugging purposes)
by inspecting the timer value in each iteration. If any iteration
takes less than 11 us I turn on an 'error led'.

>It
>seems very suspicious that you were still reading 4 with a 1K resistor.

Indeed :-/

G.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email .....listservKILLspamspam.....mitvma.mit.edu with SET PICList DIGEST in the body


2002\06\24@124214 by Guillermo Rodriguez Garcia
flavicon
face
At 15:24 24/06/2002 +0000, Drew Vassallo wrote:
>>1. I select the channel.
>>
>>2. Then I am allow for an acquisition time of 22 us (the datasheet
>>    mentions 20 us for a 10 K source)
>>
>>3. Then I start the conversion (set the 'GO' bit)
>>
>>4. Once the conversion is over, I wait _at least_ 11 us (the
>>    datasheet also mentions that a delay of 2 x Tad needs to be
>>    honoured here)
>>
>>5. Go back to step 1, but with the next channel.
>
>This sounds ok to me, except for the fact that there may be a problem with
>your code, not your logic.

Of course :)


>How about posting the A/D conversion section of your code?

Sure. I didn't post it because the original message was already
long enough without any code, but here it is.

1. Variables and constants:

adc1_M:1
adc1_L:1
adc2_M:1
adc2_L:1
adc3_M:1
adc3_L:1
state:1


2. The initialisation section:

    bsf     STATUS, RP0                 ; Bank1
    bsf     TRISA, 0                    ; AN0 as input
    bsf     TRISA, 1                    ; AN1 as input
    bsf     TRISA, 3                    ; AN3 as input
    movlw   b'10000100'                 ; AN0, AN1, AN3, right justified
    movwf   ADCON1                      ; (RA5, RA2 = digital inputs)
    bcf     STATUS, RP0                 ; Bank0
    movlw   b'10000001'                 ; Fosc/32 (20 MHz clock)
    movwf   ADCON0

    clrf    state                       ; init vars
    clrf    adc1_M
    clrf    adc1_L
    clrf    adc2_M
    clrf    adc2_L
    clrf    adc3_M
    clrf    adc3_L


3. The A/D code from the main loop

The AD code is embedded in the main loop of the application. This
main loop takes 11 us minimum, 60 us maximum. I ensure that all delays
are honoured by implementing the A/D code as a state machine with
state transitions taking place on each iteration of the main loop.
I have defined the following states:

              Trigger       Action                  Next state
              ---------------------------------------------------
ADC_IDLE      -             Start acquisition       ADC_ACQ1
ADC_ACQ1      -             -                       ADC_ACQ2
ADC_ACQ2      -             Start conversion        ADC_RUNNING
ADC_RUNNING   ADIF=0        -                       ADC_RUNNING
ADC_RUNNING   ADIF=1        -                       ADC_IDLE

You can see that from "Start acquisition" from "Start conversion"
there are two state transitions, so two iterations of the main loop
(i.e. minimum 22 us for the acquisition). Also, after the conversion
is finished, there is one complete iteration before the next
acquisition starts (so that's again 11 us minimum).

The states are encoded in the three LSBs of the 'state' variable:

              state[2:0]
              ----------
ADC_IDLE         XX0          == ADC is idle
ADC_ACQ1         X01          == ADC in acquisition stage (1/2)
ADC_ACQ2         011          == ADC in acquisition stage (2/2)
ADC_RUNNING      111          == ADC in conversion stage



The actual code:


ADC
    ;
    ; Is ADC busy?
    ;
    btfsc   state, 0
     goto   _adc_busy

    ;
    ; ADC is idle, save the converted value in the corresponding vars
    ; and select the next channel (acquisition starts automatically)
    ;
    ; The configuration bits (ADCON0 register) are:
    ;
    ; Channel  CHS0    CHS1
    ;   1       0       0
    ;   2       0       1
    ;   3       1       1
    ;
    bcf     ADCON0, ADON                ; turn off ADC (to change config)
    btfss   ADCON0, CHS0
     goto   _adc1
    btfss   ADCON0, CHS1
     goto   _adc2
    bcf     ADCON0, CHS0                ; was channel 3: next one is 0
    bcf     ADCON0, CHS1
    movfw   ADRESH                      ; get the converted value
    movwf   adc3_M
    bsf     STATUS, RP0                 ; Bank1
    movfw   ADRESL
    bcf     STATUS, RP0                 ; Bank0
    movwf   adc3_L
    goto    _adc_restart
_adc1
    bsf     ADCON0, CHS0                ; was channel 1: next one is 2
    movfw   ADRESH                      ; get the converted value
    movwf   adc1_M
    bsf     STATUS, RP0                 ; Bank1
    movfw   ADRESL
    bcf     STATUS, RP0                 ; Bank0
    movwf   adc1_L
    goto    _adc_restart
_adc2
    bsf     ADCON0, CHS1                ; was channel 2: next one is 3
    movf    ADRESH, W                   ; get the converted value
    movwf   adc2_M
    bsf     STATUS, RP0                 ; Bank1
    movfw   ADRESL
    bcf     STATUS, RP0                 ; Bank0
    movwf   adc2_L
_adc_restart
    bsf     ADCON0, ADON                ; turn the ADC module on again
    bsf     state, 0

    goto _adc_end

    ;
    ; ADC is busy, is the acquisition in progress?
    ;
_adc_busy
    btfsc   state, 1
     goto   _adc_acqdone
    bsf     state, 1

    goto    _adc_end

    ;
    ; Acquisition is complete, should we start a new conversion?
    ;
_adc_acqdone
    btfsc   state, 2                    ; conversion started?
     goto   _adc_is_running             ; = YES, check conversion status

    bsf     ADCON0, GO                  ; = NO, start conversion
    bsf     state, 2                    ; change to ADC_RUNNING state
    goto    _adc_end                    ; end ADC processing

    ;
    ; Conversion already started, is it complete?
    ;
_adc_is_running
    btfss   PIR1, ADIF                  ; data ready?
     goto   _adc_end                    ; = NO
    bcf     PIR1, ADIF                  ; = YES, clear AD conversion flag
    clrf    state                       ; clear flags register

_adc_end



TIA,
G.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email EraseMElistservspam_OUTspamTakeThisOuTmitvma.mit.edu with SET PICList DIGEST in the body


2002\06\24@161335 by Olin Lathrop

face picon face
> That's what I do (I monitor ADIF in PIR1) but when I see ADIF=1 I still
wait
> an extra iteration. This is because in the mid-range reference manual I
have
> read that you must allow for at least 2 Tad extra between two consecutive
> acquisitions (actually after finishing the conversion but before starting
> the next acquisition). Isn't this correct?

Yes, but you're going to wait at least 22uS anyway as I understand it.  You
do need to wait before starting the next conversion, but not before reading
the results or switching the channel after a conversion.


*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservspamspam_OUTmitvma.mit.edu with SET PICList DIGEST in the body


2002\06\24@174038 by Guillermo Rodriguez Garcia

flavicon
face
At 16:12 24/06/2002 -0400, Olin Lathrop wrote:
> > That's what I do (I monitor ADIF in PIR1) but when I see ADIF=1 I still
>wait
> > an extra iteration. This is because in the mid-range reference manual I
>have
> > read that you must allow for at least 2 Tad extra between two consecutive
> > acquisitions (actually after finishing the conversion but before starting
> > the next acquisition). Isn't this correct?
>
>Yes, but you're going to wait at least 22uS anyway as I understand it.

For the acquisition, yes.

>You
>do need to wait before starting the next conversion, but not before reading
>the results or switching the channel after a conversion.

OK, then I have read the manual wrongly -- I understood it was a delay
before starting the new acquisition. Thanks for clarifying!

Regarding the actual problem, do you think that noise could be the
cause of the problem? If so, how would that translate to this $008 or
$004 reading?

Thanks!
G.

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email @spam@listservKILLspamspammitvma.mit.edu with SET PICList DIGEST in the body


2002\06\26@030517 by Guillermo Rodriguez Garcia

flavicon
face
At 15:24 24/06/2002 +0000, Drew Vassallo wrote:
>>1. I select the channel.
>>
>>2. Then I am allow for an acquisition time of 22 us (the datasheet
>>    mentions 20 us for a 10 K source)
>>
>>3. Then I start the conversion (set the 'GO' bit)
>>
>>4. Once the conversion is over, I wait _at least_ 11 us (the
>>    datasheet also mentions that a delay of 2 x Tad needs to be
>>    honoured here)
>>
>>5. Go back to step 1, but with the next channel.
>
>This sounds ok to me, except for the fact that there may be a problem with
>your code, not your logic.

Of course :)


>How about posting the A/D conversion section of your code?

Sure. I didn't post it because the original message was already
long enough without any code, but here it is.

1. Variables and constants:

adc1_M:1
adc1_L:1
adc2_M:1
adc2_L:1
adc3_M:1
adc3_L:1
state:1


2. The initialisation section:

    bsf     STATUS, RP0                 ; Bank1
    bsf     TRISA, 0                    ; AN0 as input
    bsf     TRISA, 1                    ; AN1 as input
    bsf     TRISA, 3                    ; AN3 as input
    movlw   b'10000100'                 ; AN0, AN1, AN3, right justified
    movwf   ADCON1                      ; (RA5, RA2 = digital inputs)
    bcf     STATUS, RP0                 ; Bank0
    movlw   b'10000001'                 ; Fosc/32 (20 MHz clock)
    movwf   ADCON0

    clrf    state                       ; init vars
    clrf    adc1_M
    clrf    adc1_L
    clrf    adc2_M
    clrf    adc2_L
    clrf    adc3_M
    clrf    adc3_L


3. The A/D code from the main loop

The AD code is embedded in the main loop of the application. This
main loop takes 11 us minimum, 60 us maximum. I ensure that all delays
are honoured by implementing the A/D code as a state machine with
state transitions taking place on each iteration of the main loop.
I have defined the following states:

              Trigger       Action                  Next state
              ---------------------------------------------------
ADC_IDLE      -             Start acquisition       ADC_ACQ1
ADC_ACQ1      -             -                       ADC_ACQ2
ADC_ACQ2      -             Start conversion        ADC_RUNNING
ADC_RUNNING   ADIF=0        -                       ADC_RUNNING
ADC_RUNNING   ADIF=1        -                       ADC_IDLE

You can see that from "Start acquisition" from "Start conversion"
there are two state transitions, so two iterations of the main loop
(i.e. minimum 22 us for the acquisition). Also, after the conversion
is finished, there is one complete iteration before the next
acquisition starts (so that's again 11 us minimum).

The states are encoded in the three LSBs of the 'state' variable:

              state[2:0]
              ----------
ADC_IDLE         XX0          == ADC is idle
ADC_ACQ1         X01          == ADC in acquisition stage (1/2)
ADC_ACQ2         011          == ADC in acquisition stage (2/2)
ADC_RUNNING      111          == ADC in conversion stage



The actual code:


ADC
    ;
    ; Is ADC busy?
    ;
    btfsc   state, 0
     goto   _adc_busy

    ;
    ; ADC is idle, save the converted value in the corresponding vars
    ; and select the next channel (acquisition starts automatically)
    ;
    ; The configuration bits (ADCON0 register) are:
    ;
    ; Channel  CHS0    CHS1
    ;   1       0       0
    ;   2       0       1
    ;   3       1       1
    ;
    bcf     ADCON0, ADON                ; turn off ADC (to change config)
    btfss   ADCON0, CHS0
     goto   _adc1
    btfss   ADCON0, CHS1
     goto   _adc2
    bcf     ADCON0, CHS0                ; was channel 3: next one is 0
    bcf     ADCON0, CHS1
    movfw   ADRESH                      ; get the converted value
    movwf   adc3_M
    bsf     STATUS, RP0                 ; Bank1
    movfw   ADRESL
    bcf     STATUS, RP0                 ; Bank0
    movwf   adc3_L
    goto    _adc_restart
_adc1
    bsf     ADCON0, CHS0                ; was channel 1: next one is 2
    movfw   ADRESH                      ; get the converted value
    movwf   adc1_M
    bsf     STATUS, RP0                 ; Bank1
    movfw   ADRESL
    bcf     STATUS, RP0                 ; Bank0
    movwf   adc1_L
    goto    _adc_restart
_adc2
    bsf     ADCON0, CHS1                ; was channel 2: next one is 3
    movf    ADRESH, W                   ; get the converted value
    movwf   adc2_M
    bsf     STATUS, RP0                 ; Bank1
    movfw   ADRESL
    bcf     STATUS, RP0                 ; Bank0
    movwf   adc2_L
_adc_restart
    bsf     ADCON0, ADON                ; turn the ADC module on again
    bsf     state, 0

    goto _adc_end

    ;
    ; ADC is busy, is the acquisition in progress?
    ;
_adc_busy
    btfsc   state, 1
     goto   _adc_acqdone
    bsf     state, 1

    goto    _adc_end

    ;
    ; Acquisition is complete, should we start a new conversion?
    ;
_adc_acqdone
    btfsc   state, 2                    ; conversion started?
     goto   _adc_is_running             ; = YES, check conversion status

    bsf     ADCON0, GO                  ; = NO, start conversion
    bsf     state, 2                    ; change to ADC_RUNNING state
    goto    _adc_end                    ; end ADC processing

    ;
    ; Conversion already started, is it complete?
    ;
_adc_is_running
    btfss   PIR1, ADIF                  ; data ready?
     goto   _adc_end                    ; = NO
    bcf     PIR1, ADIF                  ; = YES, clear AD conversion flag
    clrf    state                       ; clear flags register

_adc_end



TIA,
G.

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


More... (looser matching)
- Last day of these posts
- In 2002 , 2003 only
- Today
- New search...