View previous topic :: View next topic |
Author |
Message |
iso9001
Joined: 02 Dec 2003 Posts: 262
|
ADC giving me wrong readings when switching channels |
Posted: Sat Feb 12, 2005 4:48 pm |
|
|
I dont quiet understand it.
But I'm still having problems when switching channels... Using 3 chans, 2 are fine, and 1 is pretty eratic. Here is some sample like code:
Code: |
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(AN0_AN1_AN3);
...
#INT_TIMER1
void isr_adc2() {
set_adc_channel(2);
delay_us(80);
value = read_adc();
}
set_adc_channel(3);
delay_us(80);
value = read_adc();
{
...
}
set_adc_channel(1);
delay_us(80);
value = read_adc();
{
...
}
|
Notice I use DIV_32 because when using Internal the readings are a erratic on all channels and not just 1.
I tried increasing the delay after switching chans to 200us, no change.
Its not noisy, I can see its prefect with a scope.
My code is shown pretty rough, but you can get the jist of it.
16F872 | 10MHz
Code: | #include <16F872.h>
#device ADC=10
#fuses HS,LVP,WDT,NOPROTECT, PUT, NOBROWNOUT
#use delay(clock=10000000) |
Anyone have any ideas ??? |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Sun Feb 13, 2005 2:21 pm |
|
|
No one ?
... I think one of my signals is right around 10k, but might be closer to 15k... which should still work I'de just need to give it a little more time then the recommended 12Tads which I'm already using 80us...
Perhaps ? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Feb 13, 2005 4:56 pm |
|
|
You didn't mention your CCS version and your program is not complete!
How did you declare the variable 'value'?
You say 2 channels are working fine, but one is erratic. Which one?
You are configuring AN0_AN1_AN3, but in your code you are using 1,2 and 3. Is this channel 2 the channel working erratic? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 13, 2005 6:02 pm |
|
|
Also in this thread, you didn't really answer a lot of questions that
I and Bluetooth raised.
http://www.ccsinfo.com/forum/viewtopic.php?t=21756
I had a question about the impedance of the voltage source that's
driving A/D channel 1. ie., What exactly is driving that pin, and
what is the size of the external series resistor, if any, and what is
the internal series resistance of the voltage source ?
Bluetooth had questions about what are your data types for the
variables "dummy" and "dummy_read", etc.
You need to answer these questions. |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Sun Feb 13, 2005 6:33 pm |
|
|
value is a long / int16
CCS: 2.315
You're right that should be 0 1 and 3, i summerized the code wrong. I cant post the whole thing, but its really nothing special, no crazy things going on there.
With the erratic pin (Chan 0) I am measuring a voltage divider with an unknown pullup and a max resistance of 8k to ground (other end of the divider)
PCM Progammer: Um.... Yea, Thats not me. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 13, 2005 6:42 pm |
|
|
Sorry. Just sounded like a very similar problem. |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Sun Feb 13, 2005 6:51 pm |
|
|
Yea, I read that one too. Makes me think there is somthing similar with his problem.
But I cant figure out what. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Feb 14, 2005 3:31 am |
|
|
Quote: | With the erratic pin (Chan 0) I am measuring a voltage divider with an unknown pullup and a max resistance of 8k to ground (other end of the divider) | Very likely in a voltage divider the unknown pullup resistor is equal to several times larger than the pulldown resistor. This means your input impedance is very likely larger than the recommended 10k maximum. Your acquisition time will be 30us or larger.
It could be an anti-aliasing problem. What is the frequency of the signal you are trying to meassure? Without knowing the exact hardware details, with this input impedance you can forget anything above 15kHz. |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Mon Feb 14, 2005 3:46 pm |
|
|
Or several times smaller ?
Either way, i'm using 80us, so I dont think it should be that.
Its a DC signal from a switch. I guess the freq could be however fast someone could press it. But this whole erratic problem happends when the switch is using its 'idle' resistor (no button pressed) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 14, 2005 4:15 pm |
|
|
Suggestion:
Temporarily remove the switch device and install a push-button
switch with a 1K pullup. Manually push the button and release
it to simulate your other switch. See if the problem goes away.
Or,
Insert a single-supply rail-to-rail opamp in voltage-follower configuration
between your switch and the PIC. This will buffer the switch signal
and provide low-impedance to the PIC's A/D input. See if this cures
the problem. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Feb 14, 2005 4:34 pm |
|
|
Quote: | Or several times smaller ? | Yes, possible. You tell me, it's your circuit....
Anyway, if you are just sampling a switch in the open position, you should get stable readings.
Do you mean v3.215?
I don't have that version, so can you compile the code below and post the list file? I want to have a close look at the assembly code for the setup_adc_ports function. To make the version below complete, add your #fuses and '#use delay' lines. Please copy these lines from your original source with copy/paste, don't type them manually (I have another idea about a possible error...).
Code: | #include <16F872.h>
// Add your #fuses and '#use delay' lines here
void main()
{
int16 value;
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(AN0_AN1_AN3);
set_adc_channel(0);
delay_us(80);
value = read_adc();
set_adc_channel(1);
set_adc_channel(3);
} |
|
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Tue Feb 15, 2005 7:23 pm |
|
|
I cant see the pullup resistor as its inside another system.
Quote: | Anyway, if you are just sampling a switch in the open position, you should get stable readings. |
Yea, thats the part thats confusing me. If all 3 signals were jumping around like crazy I'de almost expect a problem.
Here is that code you wanted me to compile. Oh, but it seems this was 3.212, my mistake.
Quote: | Insert a single-supply rail-to-rail opamp in voltage-follower configuration between your switch and the PIC. This will buffer the switch signal and provide low-impedance to the PIC's A/D input. See if this cures
the problem. |
I like that idea. I'll try that, although I beleive that my chan 2 signal is just as 'weak' as my first channel. But that one reads very stable.
Code: |
0000: MOVLW 00
0001: MOVWF 0A
0002: GOTO 004
0003: NOP
.................... #include <16F872.h>
.................... //////// Standard Header file for the PIC16F872 device ////////////////
.................... #device PIC16F872
.................... #list
....................
.................... #device ADC=10
.................... #fuses HS,LVP,WDT,NOPROTECT, PUT, NOBROWNOUT
.................... #use delay(clock=10000000)
....................
.................... void main()
.................... {
0004: CLRF 04
0005: MOVLW 1F
0006: ANDWF 03,F
0007: BSF 03.5
0008: BSF 1F.0
0009: BSF 1F.1
000A: BSF 1F.2
000B: BCF 1F.3
.................... int16 value;
....................
.................... setup_adc(ADC_CLOCK_DIV_32);
000C: BCF 03.5
000D: BCF 1F.6
000E: BSF 1F.7
000F: BSF 03.5
0010: BSF 1F.7
0011: BCF 03.5
0012: BSF 1F.0
.................... setup_adc_ports(AN0_AN1_AN3);
0013: BSF 03.5
0014: BCF 1F.0
0015: BCF 1F.1
0016: BSF 1F.2
0017: BCF 1F.3
....................
.................... set_adc_channel(0);
0018: MOVLW 00
0019: BCF 03.5
001A: MOVWF 21
001B: MOVF 1F,W
001C: ANDLW C7
001D: IORWF 21,W
001E: MOVWF 1F
.................... delay_us(80);
001F: MOVLW 42
0020: MOVWF 20
0021: DECFSZ 20,F
0022: GOTO 021
0023: NOP
.................... value = read_adc();
0024: BSF 1F.2
0025: BTFSC 1F.2
0026: GOTO 025
0027: BSF 03.5
0028: MOVF 1E,W
0029: BCF 03.5
002A: MOVWF 26
002B: MOVF 1E,W
002C: MOVWF 27
....................
.................... set_adc_channel(1);
002D: MOVLW 08
002E: MOVWF 21
002F: MOVF 1F,W
0030: ANDLW C7
0031: IORWF 21,W
0032: MOVWF 1F
.................... set_adc_channel(3);
0033: MOVLW 18
0034: MOVWF 21
0035: MOVF 1F,W
0036: ANDLW C7
0037: IORWF 21,W
0038: MOVWF 1F
.................... }
....................
0039: SLEEP |
Also, Iwas goofing around with the code and found this, i'm sure this has helped with 95% of the problem:
Code: |
set_adc_channel(0);
delay_us(80);
read_adc(ADC_START_ONLY);
set_adc_channel(0);
delay_us(80);
value = read_adc();
|
I bet I could lower the Tadc, and I'm not sure why this works, but it does. |
|
|
|