I've built a circuit to measure an unknown resistance (over a large range) which is basically the following:


simulate this circuit – Schematic created using CircuitLab

Range_Select_1 and Range_Select_2 can be set to GND or High-Impedance by a microcontroller. When set to GND, they effectively short circuit the voltage divider and remove resistors below the node. So In the circuit above.

  • Range_Select_1 = GND => Low Side Resistance = 1 kOhm
  • Range_Select_1 = Z, Range_Select_2 = GND => Low Side Resistance = 11 kOhm
  • Range_Select_1 = Z, Range_Select_2 = Z => Low Side Resistance = 111 kOhm

Is there an optimal way to select the Range_Select_1 and Range_Select_2 settings to get the best results in measuring Rx?

I figure I will get 3 ADC readings (one for each range selection) and choose one of them as my best choice. How do I choose which one without knowing the true value of Rx ahead of time (which would defeat the purpose of doing the measurement in the first place).

  • \$\begingroup\$ Be aware that a logic '0' output isn't exactly 0 volts if it has to sink any current. This will make your readings very inaccurate on a low resistance scale, where a logic 0 might be 0.5 volt or so. \$\endgroup\$ – Joe Hass Apr 16 '13 at 11:11
  • \$\begingroup\$ @JoeHass good point, I don't expect to sink more than a milli-amp or so \$\endgroup\$ – vicatcu Apr 16 '13 at 13:57

The question is a little ambiguous, so I will try my best to interpret your question correctly.

The term "optimal" needs a bit more clarification. Given that you've made three readings of an \$R_x\$ value that does not change between readings, the question is now how to deduce what the value of \$R_x\$ is. Though you could pick one of the three that is closest to the true value, this is not the only way.

Doing an ADC conversion cuts off the lower portions of the digits from an analog read. As I'm sure you already know, the equation to find \$R_x\$ is as follows:

$$ A = \lfloor 2^n \frac{R_L}{R_x + R_L} \rfloor $$

Where \$A\$ is the \$n\$ bit analog read (10 bits, say) and the \$\lfloor \cdot \rfloor\$ is the floor function (that is, rounding down). The problem arises with the rounding down. Since the analog read throws away the lower order bits, any value of \$R_x\$ is admissible that will produce the same rounded down value of \$A\$.

The range of values for which \$R_x\$ will produce the same \$A\$ value is as (by a simple rearrangment of terms):

$$ R_{x \text{ lower}} = ( \frac{2^n}{A+1} - 1 ) R_L $$ $$ R_{x \text{ upper}} = ( \frac{2^n}{A} - 1 ) R_L $$

where the true value of \$R_x\$ can be anywhere within the range of \$R_{x \text{ lower}}\$ to \$R_{x \text{ upper}}\$. If you were doing one analog read of \$n\$ bits and assumed a uniform distribution on \$R_x\$ within the range of \$R_{x \text{ lower}}\$ to \$R_{x \text{ upper}}\$, you would just pick the midpoint and be done.

But we don't have one read, we have three. In this case, each analog read gives us a range of values for \$R_x\$. The intersection of all three of these gives a restricted range for an admissible value of \$R_x\$. If we assume again a uniform distribution of \$R_x\$ values within this range of values, the best pick would then just be the midpoint of the restricted range.

To me, this is the definition of optimal: Pick the midpoint value of \$R_x\$ from the restricted range. This will minimize error assuming the \$R_x\$ value is uniform within the restricted range.

As an example, consider doing three read values on a true value of \$R_x = 4424\$. This would result in (assuming the number of bits \$n = 10\$):

$$ A_{1k} = 188 $$ $$ A_{11k} = 730 $$ $$ A_{111k} = 984 $$

Which corresponds to calculated ranges of \$R_x\$ for each lower resistance value:

$$ R_{x \text{ 1k lower}} = 4417.99\dots $$ $$ R_{x \text{ 1k upper}} = 4446.81\dots $$

$$ R_{x \text{ 11k lower}} = 4409.03\dots $$ $$ R_{x \text{ 11k upper}} = 4430.13\dots $$

$$ R_{x \text{ 111k lower}} = 4394.92\dots $$ $$ R_{x \text{ 111k upper}} = 4512.20\dots $$

Picking the lower bound and upper bounds to find the smallest range of values gives us a choice of \$R_{x \text{ 1k lower}}\$ and \$R_{x \text{ 11k upper}}\$ respectively. Choosing the midpoint from this restricted range gives us:

$$ \frac{ R_{x \text{ 11k upper}} - R_{x \text{ 1k lower}} } { 2 } + R_{x \text{ 1k lower }} = 4424.06 $$

Picking the midpoints for the individual ranges would give \$R_{x \text{ 1k}} = 4461.37\dots\$, \$R_{x \text{ 11k}} = 4453.56\dots\$ and \$R_{x \text{ 111k}} = 4419.58\dots\$ respectively. Please note that I cherry picked the 4424 value to illustrate this example.

In the end, you're only getting 1.5 more bits of information and maybe doing this type of fine grained analysis isn't worth it, especially if this calculation is required to be done on an embedded system with limited resources.

One alternative, which is perhaps more along the lines of what you wanted in the first place, is to choose one of ADC readings based on what the average absolute error is.

If we take \$R_{x \text{ lower}}\$ and \$R_{x \text{ upper}}\$ as above, then one way to measure the error for a measured value relative to the true value is:

$$ M = \frac{ R_{x \text{ upper}} - R_{x \text{ lower}} }{2} + R_{x \text{ lower}} $$ $$ \text{Error} = \int_{R_{x \text{ lower}}}^{ M } (M - x) dx + \int_{ M }^{R_{x \text{ upper}}} (x - M) dx $$

That is, measure the absolute (and unscaled) error from the midpoint of the range.

Using this, you can get a closed form solution for each range of values and calculate absolute error for each resistor combination. I have done this and used GNUPLOT to generate a pretty picture (ADC conversion assumed to be 10 bit):

enter image description here

Note that this is plotted on a log-log scale. Looking at the graph, it looks like picking 3316 and 34943 are suitable cross-over points.

I picked absolute unscaled error as the definition of "optimal" in this case and this may not be appropriate. Once you define what optimal is for your needs, then you should be able to pick suitable values of cross over points if you wanted use this method.

Please let me know if I've done any of the analysis in error.

  • \$\begingroup\$ this is incredibly thorough, thanks very much! I think picking the ADC value that gets me closest to mid-scale ADC is adequate for my purposes, but this is still a fantastic answer \$\endgroup\$ – vicatcu Apr 17 '13 at 14:10

The reading will be right on the edge of the scale for the wrong ranges. In the wrong scale, a resistance that is too small gives a nearly 5V reading, and one that is too large pulls the reading down to near 0V.

For instance, a 500 ohm resistor next to 111K is not very significant, and so the divider will put out nearly 5V. Or, a 200K Rx next to 1K will swamp the 1K. The reading will be nearly 0V.

Pick the range in which the reading is closest to the middle 2.5V. The reading is exactly 2.5V when the range resistance is equal to Rx, which is ideal.

By the way, I sense that you're reinventing a digital pot. You could replace R1, R2 and R3 with a digital pot that goes from 0 to 100K in 256 steps, using it as a rheostat. To discover an Rx which is in the range of around, say 500 ohms to 100K, you could simply step the digital pot (in reverse, in case Rx is shorted!) until you get about a 2.5V reading (the rheostat is approximately 1:1 with the resistor). Rx is then directly obtained from the value of the rheostat. Some additional logic could deal with outlying cases, within reasonable limits. For instance if Rx is a megohm, then the voltage when the pot is set to the full 100K is only 0.455V. At that point, you stop and conclude that Rx is ten times greater.

  • \$\begingroup\$ I'm not reinventing a digital pot, but I see what you mean, i've basically made a two tap non-linear digital pot lol... ironically I actually do have a real digital potentiometer elsewhre in my circuit \$\endgroup\$ – vicatcu Apr 16 '13 at 4:56
  • \$\begingroup\$ Wouldn't this cause issues with any Rx value under right about 1000Ω? And that's only for absolute maximum, pulse current, when the digital pot taps are close to 0 (50mA). Most digital pots have a significantly low max recommended current through the wiper and high/low end of the pot, like 2 to 10mA! Any significantly low (under ~800Ω) Rx resistor will fry a digital pot. \$\endgroup\$ – Passerby Apr 16 '13 at 5:14

Essentially, you are implementing the same thing a Auto-Ranging Multimeter does.

You need to decide how high or low value resistor you want to measure, and then divide that into a few ranges. Then decide what each range represents at the ADC, like a truth table.

If Rx / RangeX gives a adc value under 1V, then switch to the next lower range. If it still does, then switch to the next lower range. Repeat until the ADC range is something useful that you can work with.

From the question:

They use a resistor ladder, like for instance 9 M + 900 k + 90 k + 10 k. That gives you a total of 10 M, and taps at 1:10, 1:100 and 1:1000. These exist in single component networks, with tight relative tolerances (more important than absolute tolerance).

Only thing I would suggest, is to make sure you use an accurate ohm meter to test your chosen resistors, and choose one that is closer to your chosen value. Because of tolerances, a 100kΩ 10% resistor might be up to 10kΩ off in either direction. So you need to accurately measure and note what it actually is.

See the answer to How does autoranging work in a multimeter? What is the circuit? for more details.


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.