3
\$\begingroup\$

edit: solution found with our new board revision; outside of careless mistakes, buffering the signal with an op amp seems to have resolved the issue (as suggested by Joshua below).

I am working with a custom PCB using the ARM LPC2148. I'm trying to measure the battery voltage, which can be up to 4.2V or so, by using a voltage divider. However, using different resistors causes huge changes in the accuracy of ADC readings. Why is this?

Details:

I set the power supply to 3.0 V and hooked it up to an ADC pin, and got a reading of 2.987V, which is accurate enough for our use and shows that everything is working.

Using the voltage divider we built into the PCB with 47K and 100K resistors, the readings from the ADC vary in a non-linear manner -- I mean, not by a simple scalar factor -- (data below).

I built a voltage divider using 5% 10K 1K and 100K resistors (divides by 11 101), and took a reading on the ADC. Software showed 0.029V, or 0.319V after being scaled according to the voltage divider. This is obviously wrong, but the reason we're using large resistor values is that it limits the current draw; the power supply is showing less than 1mA being used.

I built another voltage divider using much smaller 5% resistors, of values 4.7 and 8.2 (divides by 2.745), and took a reading on the ADC. Software showed a value of 1.071V, or 2.940V after being scaled according to the voltage divider. This is obviously much better than the other voltage divider, and we could probably use this. However, the current draw is 228mA, which is unacceptable. It seems that the path forward is to redesign the board to use smaller resistor values and to hook the divider up to a transistor to limit current draw.

ADC Vref is 2.5V.

My question: why the huge change in accuracy from the different resistors?

Data:

power supply: voltage coming from the power supply to the board
input voltage: voltage reading taken at the voltage divider
voltage after divider: the voltage reading taken at the output of the voltage divider
raw from ADC: value from the ADC; average of a few readings
scaled by divider: value obtained by taking the ADC reading and scaling by the voltage divider (the first row is 0.28/0.32, etc)
voltage divider: resistor values for the current data set
+---------------+---------------+-----------------------+--------------+-------------------+-----------------+
| using the voltage divider on the board (47K / 47K + 100K)                                                  |
|                                                                                                            |
| power supply  | input voltage | voltage after divider | raw from ADC | scaled by divider | voltage divider |
|         3.8   |         3.80  |                 1.22  |        0.28  |             0.87  |      47,150  Ω  |
|         3.7   |         3.70  |                 1.18  |        0.29  |             0.89  |     100,000  Ω  |
|         3.6   |         3.60  |                 1.15  |        0.30  |             0.92  |         0.320   |
|         3.5   |         3.50  |                 1.12  |        0.31  |             0.95  |                 |
|         3.4   |         3.40  |                 1.09  |        0.32  |             1.00  |                 |
|         3.3   |         3.30  |                 1.06  |        0.33  |             1.04  |                 |
|         3.2   |         3.20  |                 1.02  |        0.35  |             1.08  |                 |
|         3.1   |         3.10  |                 0.99  |        0.37  |             1.15  |                 |
|         3.0   |         3.00  |                 0.96  |        0.39  |             1.21  |                 |
+---------------+---------------+-----------------------+--------------+-------------------+-----------------+
| using an external voltage divider (4.7 / 4.7 + 8.2)                                                        |
|                                                                                                            |
| power supply  | input voltage | voltage after divider | raw from ADC | scaled by divider | voltage divider |
|         3.8   |         3.79  |                 1.39  |        1.37  |             3.76  |          4.7 Ω  |
|         3.7   |         3.69  |                 1.35  |        1.33  |             3.66  |          8.2 Ω  |
|         3.6   |         3.59  |                 1.31  |        1.30  |             3.56  |         0.364   |
|         3.5   |         3.50  |                 1.28  |        1.26  |             3.47  |                 |
|         3.4   |         3.40  |                 1.24  |        1.23  |             3.37  |                 |
|         3.3   |         3.30  |                 1.21  |        1.19  |             3.27  |                 |
|         3.2   |         3.20  |                 1.17  |        1.16  |             3.17  |                 |
|         3.1   |         3.10  |                 1.13  |        1.12  |             3.07  |                 |
|         3.0   |         3.00  |                 1.10  |        1.09  |             2.98  |                 |
+---------------+---------------+-----------------------+--------------+-------------------+-----------------+
| using an external voltage divider (10K / 10K + 100K)                                                       |
|                                                                                                            |
| power supply  | input voltage | voltage after divider | raw from ADC | scaled by divider | voltage divider |
|         3.8   |         3.80  |                 0.35  |        0.35  |             3.81  |       9,820  Ω  |
|         3.7   |         3.70  |                 0.34  |        0.34  |             3.71  |      98,400  Ω  |
|         3.6   |         3.60  |                 0.33  |        0.33  |             3.63  |         0.091   |
|         3.5   |         3.50  |                 0.33  |        0.32  |             3.53  |                 |
|         3.4   |         3.40  |                 0.32  |        0.31  |             3.43  |                 |
|         3.3   |         3.30  |                 0.31  |        0.30  |             3.33  |                 |
|         3.2   |         3.20  |                 0.30  |        0.29  |             3.23  |                 |
|         3.1   |         3.10  |                 0.29  |        0.28  |             3.13  |                 |
|         3.0   |         3.00  |                 0.28  |        0.28  |             3.04  |                 |
+---------------+---------------+-----------------------+--------------+-------------------+-----------------+
\$\endgroup\$
  • \$\begingroup\$ Try 1% resistors. \$\endgroup\$ – Leon Heller Dec 12 '11 at 20:26
  • \$\begingroup\$ What happens if you use two 10k resistors, or two 100k resistors? \$\endgroup\$ – W5VO Dec 12 '11 at 20:47
2
\$\begingroup\$

By your values, I have to assume that you are measuring off of the 10kOhm resistor on the bottom. I would hazard a guess that your 10kOhm resistor is a little high and the 100kOhm resistor is a little low. This would mean if your 10kOhm resistor is taking more of the voltage in the voltage division than expected.

There are a few problems at work here.

  1. The first is the resistor value error. Ohm's Law: V=I*R. So if there is 5% error in R, then for a constant I, there will be a %5 error in the expected value of V. The %error from resistor tolerances are the maximum +/- error. So in reality, there could be a resistor with +5% error and other with -5% error. So there is a much larger possible range in output voltages for a constant current.

    • This can be eliminated by either hard-coding the real resistances in software or adding a reference voltage that is more accurate than the resistor or A/D quantization error. This reference voltage would be used to get the real resistance values as the A/D sees them.
  2. A/Ds can have an offset error. This really has to be calibrated out. Some A/Ds have this built in.

  3. A/Ds also have quantization error. So if a voltage falls between two consecutive quantization levels, it will have to be rounded to one of those two, introducing error. There are ways of increasing the number of bits for an A/D by oversampling and averaging blocks of samples into one sample.

There are other errors that could be at work, but those three are the main ones I have run into. If the A/D is fairly linear, then measuring two accurate voltages with the A/D circuitry would let you build an affine linear equation to correct the data. This builds off of the problems in 1 and 2.

A/Ds can appear linear, but end up being very nonlinear at a particular range. I have heard of some implementations using a look-up table to correct the nonlinear behavior. But that is getting a little beyond your current problems.

Edit: One more item. It is a good idea to buffer your analog signals to the A/D. It does a few things, like add another device to protect the microcontroller, and limit any possible transient sampling behavior from the A/D go into the analog signal.

\$\endgroup\$
6
\$\begingroup\$

There are 3 main error contributions

LPC2148 datasheet here

(1) Your erroneous result of 0.029V is completely explained if you apparent 10k resistor is actually a 1k. so 3V/101 (rather than 3/11) = 0.0297 Volt.
Your ADC seems to have got it about right.

(2) If you use 5% resistors then notionally one may be Rnom+ 5% and the other may be Rnom - 5%, although this would be rare with modern metal film resistors which tend to cluster around the nominal values.

  • 1/(1+10) = 1/11 = 0.090909

  • (1+5%)/( (1+5%) + (10-5% ))
    = 1.05 / (1.05 + 9.5)
    = 1.05/10.55
    = 0.0995

    0.0995/0.090909 ~= +9.5% high !!!

  • Similarly, making the 1k maximum low and 10k maximum high also leads to an error approaching 10% low.

Using 5% components you can expect errors on the 2% - 5% range typically - could be less and could be more.

(3) You seem to be dividing by an much higher ration than is needed.
Vdd is presumably 3.3V and allowable ADC in max = VddA.(p32)
You are dividing the input voltage such that Vinmaxseen << Vibmaxallowed, so are wasting precision.

As Vbattery = 4.2v max (and will safely be hardly higher than this very worst case) you can allow say 4.4V max safely.

You don't say what reference voltage you are using for the ADCV .
You are allowed 2.5 <= Vref <= VddA. (p16)

Max "allowed" ADC input resistor = 40 k. (fig 9 page 34) and there is a 20k internal resistance (fig 9) which is ahead of the ADC sampler so it should not have any great effect.

If you had ADC Vin max = 3.3V and Vbattery max = 4.4 V (as above) then you need input resistors which drop 1.1:3.3V = 1:3 The ADC "sees" the parallel resistance of the input resistor divider.
So reffective = 1//3 1 x 3 / (1+3) = 0.75. ie the effective value of the whole divider = 0.75 x the upper resistor
so the upper resistor can be Reffective x 1/0.75.

A Rinmax allowed = 40k then Rupper can be 53.3k and R lower = 160k.
I supply = 4.2/(53.3k + 160k) =~ 20uA.

In practice you almost certainly can go to several times higher resistance than this and still get acceptable accuracy.

\$\endgroup\$
  • \$\begingroup\$ You are correct that I grabbed the wrong resistor :o and thanks for pointing out the data sheet. As near as I can tell my problem with the readings is using to-large value resistors even though the data sheet seems to show what I'm using is fine. \$\endgroup\$ – tolos Dec 16 '11 at 17:45
4
\$\begingroup\$

Check the maximum signal impedance spec for driving a A/D pin on that micro. These can be surprisingly low. The faster the A/D, the lower the required impedance.

The main reason for the low impedance is to charge up the internal sample and hold capacitor in time to finish the acquisition and then do the conversion within the fastest time specified for the A/D. Pin leakage is another reason, but that is usually a µA or less for a CMOS input.

Since you don't need high speed, one solution could be to extend the acquisition time so that the capacitor can fully stabalize when fed from the lower source impedance. I am not familiar with that micro to know whether that is possible, but it is on many other micros.

However, the overall "right" solution is to switch the battery test circuit on only when needed. In this case you will need a high side FET switch. If you were to switch the low side instead, the voltage on the A/D pin would be the battery voltage when the switch was off, which would be outside the allowable limits.

\$\endgroup\$
  • \$\begingroup\$ I can not find anything in the user manual other than a vague reference. "The APB clock (PCLK) is divided by (this value plus one) to produce the clock for the A/D converter, which should be less than or equal to 4.5 MHz. Typically, software should program the smallest value in this field that yields a clock of 4.5 MHz or slightly less, but in certain cases (such as a high-impedance analog source) a slower clock may be desirable." (page 288). Changing the clock divide value gave a reading of 0.341V for the 10K/100K. Probably going to go the FET route. \$\endgroup\$ – tolos Dec 12 '11 at 21:54
  • \$\begingroup\$ @tolos: I am not familiar with that micro, but have you checked the electrical specs section for the A/D? What you quoted sounds like it's from the general description section. \$\endgroup\$ – Olin Lathrop Dec 12 '11 at 22:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.