|
|
View previous topic :: View next topic |
Author |
Message |
iso9001
Joined: 02 Dec 2003 Posts: 262
|
Erratic ADC Readings (revisited, still stuck) |
Posted: Sat Apr 09, 2005 6:08 pm |
|
|
Hi.
I had a post awhile back about my wrong ADC readings. I'm using A0_A1_A3 and have tried all different ADC timing flags (DIV_BY_X, Internal etc etc) but I think I've narrowed it down.
Here is my code sample:
Code: |
#include <16F872.h>
#device ADC=10
#fuses HS,LVP,NOWDT,NOPROTECT, PUT, NOBROWNOUT
#use delay(clock=10000000)
#Define SLEEP PIN_B1
short y=TRUE;
int x;
int16 value=0;
void ADC0_Ctrl() {
set_adc_channel(0);
delay_us(80);
value = read_adc();
//Do Stuff
}
void ADC1_Ctrl() {
set_adc_channel(1);
delay_us(80);
value = read_adc();
//Do Stuff
}
void ADC3_Ctrl() {
set_adc_channel(3);
delay_us(80);
value = read_adc();
//Do More Stuff
}
#INT_TIMER1
void isr_timer1() {
x++;
y=!y;
if (y)
ADC0_Ctrl();
if (x>=20) {
ADC1_Ctrl();
x=0;
}
}
#INT_TIMER2
void isr_timer2() {
ADC3_Ctrl();
}
void main() {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //.208s
setup_timer_2 (T2_DIV_BY_4, 0xc0, 2); //~1ms
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
setup_adc(ADC_CLOCK_DIV_2);
setup_adc_ports(AN0_AN1_AN3);
output_high(SLEEP); //Wake Up an Interface IC (~20ma ON | ~40ua SLEEPING)
while(1) {
output_low(SLEEP);
}
} //eom
|
I ruled out noise as a possible problem in my last post. Hooked a scope up and everything was pretty clean. Now I think the problem may have somthing to do w/ my interface IC, or at least sending it power.
The whole cicuit is automotive and there is a 5V supply that runs all over the car. I tapped into that for power. I think maybe when I turn on and off my interface and the car is running and this 5V wire is being pulled on, I am getting a poor reference for my adc ?
It seems unlikely but I honestly can not figure out whats wrong w/ this thing !
So,
What values should I be using for the caps on the supply and ground ?
Would adding caps to my incoming ADC wires help or would they adversely effect the sensors they are connected to (I'm tapping into sensors that the ECU is reading too)
What exaclty does the ADC_Clock do ? Should I be using a high or low value for more accurate readings ? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Sat Apr 09, 2005 8:18 pm |
|
|
I guess that this is a partial code.
1)Are you using LVP?
2)It seems that you do not average in the sampled analog voltage.
3)Do not call a subroutine inside the interrupt service code space.
Quote: |
What values should I be using for the caps on the supply and ground ?
|
We dont know your hardware. How do you suposse we will know the right
cap it will need?
Quote: |
Would adding caps to my incoming ADC wires help or would they
adversely effect the sensors they are connected to (I'm tapping into
sensors that the ECU is reading too)
|
Adding caps to the incoming ADC wires all you will get is to slow down the
whole response. If you can slow the response, why use such high ADC
convertion rate ~1000 per second ?
To fight against noise the are two different task:
1) Hardware architecture: the power supply impedance, the PCB
paths, external wiring criteria, shielding weak signals, grounding
technique, front-end analog signal design, etc.
2) Software technique: like averaging or smooting and validating the
sampled ADC value before processing.
Quote: |
What exaclty does the ADC_Clock do ? Should I be using a high or low
value for more accurate readings ?
|
ADC clock has direct effect in the conversion speed, not with the accuracy.
Humberto |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Apr 10, 2005 3:08 pm |
|
|
I notice that each time you post this problem, you give us a little more
information that you kept secret in the previous posts.
This time, you let us know that you're running off a +5v bus that's inside
the car.
My suggestion is this:
1. Get it running in your lab first. Use a +5v bench power supply.
Make it all work perfectly.
Also, the program that you posted is incredibly complicated for a test
program. At this point you're still having basic problems, and you
should be using a very simple program until they are solved.
2. Move the board out to your car. Also bring along the bench power
supply. Use an extension cord. Now, just connect one of the car's
analog voltages to Channel 0, and also connect ground between
the car and your board.
In this test, the only variable that's changed from the lab will be
the analog source. You still have a clean +5v reference from your
bench supply, because it's out there with your board, sitting on your
car seat.
So, it should work. If it doesn't, then it may be that the analog
signal from the car is in fact, erratic. Or, it the signal source may
be high impedance, and you may need to add a voltage-follower
op-amp to buffer it before it goes to the PIC.
The key here is to get it working in the lab, and then change just ONE
thing and see if it works. If not, fix that problem, and then move on
to the next change.
------------------------
Another test that could be done is to take your board out to the car,
and keep the analog test signal that you were using in the lab.
This might be a trimpot or something like that. Then remove the
bench power supply from the board, and use the car's +5v supply
instead. See if it works. If not, there's problem with the car's +5v,
or with your power supply filtering.
By doing very simple tests like this, you can track down the problem. |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Mon Apr 11, 2005 7:00 pm |
|
|
I'm not being secretive at all, I just posted my problem nothing more.
I am using LVP. I can not bench test it. It requires the car to work at all. It would be VERY complicated to bench test. The car is my bench, I have lots of test cars/benches. It does need to be fast an averaging is going to do me no good since its specific point in time I am interested in.
I guess I can try using a voltage follower / buffer of some sorts. The source signal are either voltage drop switches or normal resistance type sensors. However I think the voltage drop switch is ~20k on its pullup and at most 20k on the ground side. Maybe this is too weak of a signal to be getting in reliably ?
The problem is now that it seems this is erratic. By that last night I had everything working fine, but this morning it acted up again.
The only difference was the ambient temp. Either the car's signals are chaging enough to mess up the pics ADC or ther ADC itself is being screwed up.
I just dont understand it, even if I set the ADC to wait 400us, it still gets screwy readings. If it were an impediance problem, just giving it more time should help it no ?
Is there some huge No No about calling subroutines inside interup space? If there is I can fix that easy enough,
I looked through the datasheets and saw nothing about recommends power supply caps. Is there a formula I could use to determine this ? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Mon Apr 11, 2005 7:28 pm |
|
|
First, putting a resistive type sensor, by itself, directly into a pic shouldn't be that big of a problem. However, since the sensor's resistance is quite large, you really need a low impedance drive between it and the pic because it's possible that the pic's a/d input is loading the signal. If that's happening, all bets are off. I think that the biggest side effect of high impedance drive circuits hooked up to the a/d input would be a greatly reduced response time. Like on the order of seconds, not milliseconds. Unless the signal you want is slow, you need a buffer.
I don't know if you have any single supply op amps available, but if not, I really like the TI TLV237x family. Rail-to-rail input and output, and quite robust too. I should also mention relatively cheap.
You also have to be careful of the standard vehicle things that can really mess with a signal. Like ignition noise. As a bare minimum, I'd make sure that there was a simple LPF on the signal - incorporate it with the low impedance driver that you'll need. I'd also throw a ferrite bead on the input too, just to be safe. Do the same for the supply & ground.
What about ESD? Are your input lines protected? An MOV on the supply lines would help to protect against surges/spikes, and anything else that a car's electrical system can throw at you.
The PIC should have a .1uF cap between supply and ground, placed physically close to each supply pin. A good sized electrolytic (maybe 22 - 47 uF or more) should also be placed on the supply.
If you have a programming header on the board, watch the length of the trace going to the VPP (/MCLR) pin on the pic. I once had a circuit that would reset - part of the problem was that line and some EMI that was coupling into it. Shortening it and re-routing it solved the problem.
Lastly, if all these suggestions are impossible right now, is it possible to at least power your board from a battery? If it works (or works better) when it's powered from a battery, then the car's power supply is at least part of the problem.
Just suggestions. It's hard to troubleshoot without actually getting my hands on it. Let me know if none of this works. |
|
|
JohnKennedy
Joined: 12 May 2004 Posts: 38
|
|
Posted: Tue Apr 12, 2005 1:44 am |
|
|
Have you checked the signal on an oscilloscope?
Is it noisy or not?
There should be no problems with a 20K resistance I use Thermistors all the time and only have erratic readings if the signal or the supply is noisy. Decouple both with appropiate caps (depends on the frequency) though the supply line I usually decouple with a 100nF and a 47uF as close to the PIC's supply pins as possible. You may also find that using a common mode choke on the DC supply line is neccesary to filter out spikes created by the cars electrical systems.
One other thing I have done in the past is to use the 12V vehicle supply and drop down to 5V using a standard 7805 3 terminal regulater, this eliminates a lot of noise as well. You will still need the two caps on the supply line though.
Don't now if this makes a difference but one part of your code was different to what I use this being when you set your A/D to 10bit resolution, I use Code: | #DEVICE *=16 ADC=10 | .
HTH
JFK |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Tue Apr 12, 2005 4:52 am |
|
|
(Newguy: THANKS! I will try all of that tomorrow. I dont think mouser carries the TLV, but they carry a quad railtorail microchip op amp that looks like it'll do the trick)
Thats just the thing. I looked on a scope and saw very little noise. This is all happening with the car OFF by the way.
I'm confused as to why I notice it a LOT more when its cold out (3x checked all solder joints on two test boards). The 5V supply should be able to handle 2 amps no problem, I'm drawing a total of 40ma. I doubt its in a cold weakened state or anything like that.
The impedience doesn't change drasticly with temp does it ?
I know 20k is not an extremely weak signal, that is the part that confuses me. The only thing I can think of it that since this is a splice maybe the ground side of the voltage drop (4 positions between 0.5k - 20k) is effecting this or maybe its the adc inside the factory processor taking all the signal from me ?
It doesnt make sense! I've given it ridiculously long delays and still get garbage reads. I've tried ADC_Read_Only and Start_Only, tried all different settings.
The only time I can get it to work correctly is when I take all but one of the signals away from the adc. Then I get one good reading. I've tried many different pics.
So if it were a buffering or noise problem, I would still have it with only one sinal no? Its acting like its trying to read without dumping the signal, or trying to read from two lines at the same time, etc. I'm stuck. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Tue Apr 12, 2005 9:23 am |
|
|
I can't believe I didn't catch this earlier..... What you said about the car being off triggered this.
ISO, have a look at the 16F872's data sheet, section 10.2. It's on page 85 if you're using adobe reader to look at it. At the bottom of the page is Table 10-1. It lists the maximum clock frequency the pic can have vs the A/D clock division choices.
For your setup (A/D clock is the system clock/2), the maximum crystal frequency is 1.25 MHz. Since your crystal is 10 MHz, you need the div/32 option.
In a nutshell, the pic's A/D needs a clock with a period of at least 1.6 us to work. Try changing it and see what happens. |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Tue Apr 12, 2005 11:34 pm |
|
|
Newguy: I read that yesturday too, but I think I skimmed over it not really understanding the words on the page. I'm kinda dumb but I really appreciate the help!
Ok. I moved it back to DIV32. The signal is still erratic. I'm going to wire up an op amp in and see if that helps.
I meant to do this today but it seems due to a coworker hooking up a wire in the wrong spot I've been feeding 12V to A2 now and then. I now have a few chips that have a nonresponsive adc and a few that have and adc that is extremely erratic. Does that sound like a likely cause and effect for failure ? (I would not have thought so, but I've destroyed more chips in the past day then I have in about a year, 5 total). I thought that the chips were sort of protected from this, clipped diodes or somthing like that.
Anyway, I found some chips that are still good and I'll hook the op amp up. Whats interesting to me is that some are reading a little more stable then others. And that I am having problems with all the adc pins. Not just the small signal one. I have another that is a 5V pull up with a 460ohm resistor down to another voltage drop switch.
Getting a poor reading from a weak signal should only effect that channel no? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Tue Apr 12, 2005 11:55 pm |
|
|
The 12V into the pic might hurt it - it all depends on whether there's any current limiting resistor in place or not. If there was no resistor, yeah, it would probably fry the input.
Microchip has an application note that deals with making a simple light dimmer with a low end pic (a 12F-something) and a triac. To detect the zero crossing on the mains, they simply wired it into one of the pic's pins, through a big resistor (like a megaohm or 1.5 Meg - big). In that case, the 120V isn't hooked directly to the input, and no damage.
I don't have an 872, but I do have an 877. Tomorrow I'm going to try your code, exactly as you gave it with a 10 MHz crystal, and see what it reads if I wire up 3 pots to those 3 A/D inputs (0,1, and 3). I'm beginning to suspect an issue with the code, and not just the hardware.
Almost forgot: you've learned why you should buffer any incoming analog signal with an op-amp: for the same reason a general doesn't fight on the front lines...... In other words, op-amps are cheaper than pics. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Wed Apr 13, 2005 10:14 am |
|
|
This is the code I tested. I had to change the LVP fuse to NOLVP, and I made some slight mods to determine if is working or not. I hate to tell you this, but it's stable. No erratic readings at all. I used 5k pots hooked up between Vcc and ground, with their wipers going into the analog inputs.
Anyway, here's what I tested:
Code: | #include <16F877.h>
#device ADC=10
#fuses HS,NOLVP,NOWDT,NOPROTECT, PUT, NOBROWNOUT
#use delay(clock=10000000)
#Define SLEEP PIN_B1
#include "i:\ELEN\LCD Task\lcd_driver.c"
int1 y = TRUE, got0 = FALSE, got1 = FALSE, got3 = FALSE;
int x;
int16 value0 = 0, value1 = 0, value3 = 0;
void ADC0_Ctrl() {
set_adc_channel(0);
delay_us(80);
value0 = read_adc();
got0 = TRUE;
//Do Stuff
}
void ADC1_Ctrl() {
set_adc_channel(1);
delay_us(80);
value1 = read_adc();
got1 = TRUE;
//Do Stuff
}
void ADC3_Ctrl() {
set_adc_channel(3);
delay_us(80);
value3 = read_adc();
got3 = TRUE;
//Do More Stuff
}
#INT_TIMER1
void isr_timer1() {
x++;
y=!y;
if (y)
ADC0_Ctrl();
if (x>=20) {
ADC1_Ctrl();
x=0;
}
}
#INT_TIMER2
void isr_timer2() {
ADC3_Ctrl();
}
void main() {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //.208s
setup_timer_2 (T2_DIV_BY_4, 0xc0, 2); //~1ms
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(AN0_AN1_AN3);
output_high(SLEEP); //Wake Up an Interface IC (~20ma ON | ~40ua SLEEPING)
set_tris_e(0x00); // needed for lcd
lcd_init();
lcd_putc("\f0: 1:\n3:");
while(1) {
output_low(SLEEP);
if (got0) {
got0 = FALSE;
lcd_gotoxy(4,1);
printf(lcd_putc,"%04lu",value0);
}
if (got1) {
got1 = FALSE;
lcd_gotoxy(12,1);
printf(lcd_putc,"%04lu",value1);
}
if (got3) {
got3 = FALSE;
lcd_gotoxy(4,2);
printf(lcd_putc,"%04lu",value3);
}
}
} //eom |
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Apr 13, 2005 11:56 am |
|
|
newguy wrote:
Quote: |
I had to change the LVP fuse to NOLVP
|
Can we conclude that it was the whole problem cause ?
Humberto |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Wed Apr 13, 2005 12:04 pm |
|
|
It depends on his circuit. With mine, I have no way of isolating that line (I use ME Labs' Lab-X1 board), and have to disable that fuse to make anything work in that board.
In my experience, if the LVP fuse is set, the application won't run at all, which isn't what he's seeing. |
|
|
iso9001
Joined: 02 Dec 2003 Posts: 262
|
|
Posted: Wed Apr 13, 2005 12:44 pm |
|
|
I would agree... kepp in mind that I am actually using Low Voltage Programming. I've been using a TrivialLVP (which if built right works well).
I just got a ICD40U (expect noob qestions with that ) So now I can test with high voltage (shouldn't effect anything I dont think). And I'll be able to put a watch on my ADC readings. Which I know are erratic, but then maybe I can hook up an op amp and whats going on.
Newguy, hey I dont suppose you have anything near a 20k pot you could test one line with no ? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Wed Apr 13, 2005 1:42 pm |
|
|
Sorry, since this is a pre-made board, I really can't hook on a 20k pot without warming up my soldering iron.
I know that I've simulated analog inputs with 10k pots (different board that allowed me to do this), and I think I've used a 20k pot too - no problems. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|