Calculating Unknown Resistor with Arduino

Used a 10 ohm fixed resistor, a 6.8 ohm test resistor and this sketch.
Printed 6.7 ohm.

const byte measurePin = A0;
const float R_fixed = 10.0;
float R_unknown;
int rawValue;

void setup() {
  Serial.begin(9600);
}

void loop() {
  rawValue = analogRead(A0);
  rawValue = 1023 - rawValue; // invert if R_unknown is between pin and ground
  R_unknown = R_fixed * ((1024.0 / rawValue) - 1.0);
  Serial.print(R_unknown, 1);
  Serial.println(" Ω");
  delay (5000);
}
1 Like

I use (for known R on bottom (R2)):
unknown = known * 1024 / ADCval - known;
And for known on top (R1);
unknown = known * 1024 / (1024 - ADCval) - known;

i have my formula as
R_unknown = R_fixed * 1023 / rawValue - R_fixed;
because if it is shorted the rawValue is 1023 and the resistance should be 0.

Note the problem is already found and it is not the math. It is voltage drop in the wiring.

There is a lot of ways to fix this issue. Depends what HW modification is easiest for you. You may use one ADC channel to measure real supply of the resistors. You may use the supply of the resistors as supply for your Arduino converting to the ratiometric measurement. Your proposed SW fix will work only if the load is constant. I.e. when someone decides to measure only single resistor and keeps the other not connected you will overcompensate and get a large error.

Hi Julian - hope a fresh view will help.
I looked at your code in #1; I dont see a line choosing your reference for analog measurement eg
analogReference(EXTERNAL);

I dont know if this is relevant but I don't see you taking an analog reading eg

int var= analogRead(pin);

Here

// average a multiple of reads to filter noise
float sum = 0.0;
for (int n=0; n < 100; n++) {
// sum with correction according to http://www.skillbank.co.uk/arduino/readanalogvolts.ino
sum += ((float)analogRead(pin) + 0.5) / _stepsInRange * _inputVoltage;
}
sum /= 100.0;

I'd be happier seeing you aggregating the readings as integers  ( ok #6)

in #1 you show the 10 ohns connected to +5 (ok +5.15) but in #18 you show them connected to ground.

around #43 the input voltage needs to be within the range 0V to Vref. If you use a 1.1V ref that will not be the case.

#46 Thanks Julian!

I'd suggest you use the 5.15V to power the arduino then voltage reference will not be an issue.

Providing the wires never change you can do some simple tests to work out their resistance, then draw a circuit that shows their position in relation to psu and arduino inputs, and it should be easy to work out a correction.
Of course it would have been better to do it right at the beginning.

Hey John, great to see you again.

I didn't set one originally. I do have it now set to INTERNAL2V56. It appears to be more accurate than INTERNAL or DEFAULT; but I'm always open to being corrected.

I never even caught that! My bad. Thank you for pointing that out. The knowns are between VCC and the pin. #1 has the correct diagram.

I will wire this now and report back any changes. I would think 10A would be more than enough to power this entire thing.

Indeed. This absolutely would have been. But, as I stated above, I'm just trying to fix these issues from an already-made board. The original creator is no longer around, so it's down to me to fix it until we get another helper who is more knowledgeable.

I believe this will be the easiest fix. The other solution would require multiplexing the inputs (or adding another Arduino over I2C) to measure the supply of the resistors as all analog pins are currently used.

I will keep this in mind. They are all commonly powered via a single rail and commonly grounded. When the "switch" is thrown to test, they are all activated simultaneously. Without a massive rework, it would not be possible to complete individual testing.

Thank you all for your time and suggestions on this issue. I will report back the results as soon as I have them. :slight_smile:

So, just to confirm, the ratiometric equation is this:

R2 = (R1 * X) / (1024 - X)
Where R1 = known resistor (10 ohms) and X = the value from the ADC (0 - 1023).
(I use 1024 in the equation instead of 1023 according to Arduino data conversion - 1023 or 1024?)

This appears to match @JohnRob's equation in #30 and @er_name_not_found in #38 (among others I am forgetting to mention).

Okay, attempting that equation gives wildly inaccurate results.

For example (analogReference set to INTERVAL2V56):
-1.47, -1.78, -1.88, -1.98...

Or (analogReference set to DEFAULT):
2.02, 1.95, 1.93, 1.91...

@Wawa your equation in #61 produces equally inaccurate results. Except it is:
2.02, 1.95, 1.93, 1.91... and -21.49, -21.80, -21.88, -21.99... depending on which way rawValue is subtracted as you noted (inverting as you suggested produces the positive values). This was tried with analogReference set to INTERNAL2V56 and DEFAULT which had the same effect as noted above.

you should be using

  • EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference.

and make sure your external power is not more than 5 volts

Connecting the external 5volt supply to Aref could be dangerous.
Better leave Aref as it is (default), and power the Arduino from the external 5volt supply (on the 5volt pin).
Leo..

Thank you.
Leo..

From Arduino Foundations:
The ATmega datasheet also cautions against switching analog pins in close temporal proximity to making A/D readings (analogRead) on other analog pins. This can cause electrical noise and introduce jitter in the analog system. It may be desirable, after manipulating analog pins (in digital mode), to add a short delay before using analogRead() to read other analog pins.

The Atmel datasheet advised to read twice and keep the 2nd but did give a "settle time" shorter than a full read.

Do you measure each 10R resistor as exact 10.0?

Arduino has no FPU, the floats are 32-bit piles of sand so why not work with integers and small units? It'll run faster and hold precision.

Work in long microvolts and Ohms. You can lose 3 places in a divide and still have precise millivolts.

10R + 100R divider, 5VCC
Vout = (5000000uV * 100R) / (10R + 100R) = 4,545,454uV = 4545mV = 4.545V

Please ignore that its just wrong.

So the current flowing in all the resistor chains is all flowing through the thin supply wires (aka resistors). While I'm not saying its impossible my meories of working with Kirchoffs laws, Thevenin & Norton Thms are not up to working that one out.
There will be an (basically unknown) voltage drop across the ground, which you would need to compensate; and ALSO a voltage drop across the 5V supply that would change the reference voltage for your measurements.

Realistically you need to find a way to change the hardware to allow you to make a 4 terminal measurement.

Here is a suggestion. If you can break the connection between one of the resistor chains you can access the voltages you need to measure like this
ski

Rw1, Rw2 represent the connecting wires;
As "no" current is drawn by the arduino analog inputs you can connect MV1, MV2 and measure voltage V1, V2.
Alternatively you could use MV1 as arduino ground and MV2 as arduino supply, so taking fewer analog inputs.
Or if you cant have seperate grounds you can use the voltage drop across RW2 to estimate that across RW1.
Of course these approaches will ONLY be accurate if the "bus bar" connections shown thicker in the diagram are relatively low resistance.

Heh, I had a feeling I should. No worries :slight_smile:

Yeah, I was really hoping not to have to rehash this tester again. But, as 4-terminal testing has already been suggested, I suppose there is no way around it.

That is probably the easiest point to break the chain at. These wires are soldered into a daughter board (which the resistors are mounted to), so unsoldering them shouldn't be much of a challenge.

Connect these to 2 analog inputs you mean? I.e. A0 and A1 will be hooked to MV1 and MV2, and then A2+ will be connected to each subsequence resistor network as it is currently? If so, I'll need to find a way to multiplex then. All 16 analog inputs are currently being used with the current setup.

My current bus bar is quite robust as it is and is soldered directly to the PSU. It's only the wire leading into the resistor networks that are thin.

Of note, this morning, I have rewired the board to only use the master PSU (the 5.15V @ 10A powering the rails). Everything, including the Arduino, is running off this single PSU. Under full load, I am seeing the resistor networks consume, at most, 4-5A with no drop in the voltage from the PSU. I've seen marginal improvement to where I am now barely within my goal of +/- 0.5 ohms. But, I would still like to see this improve if at all possible.

I believe in one of my updated code pieces above, I am doing these suggestions. You can go back up and look to verify.

I am stealing this quote, it made me chuckle.. I didn't think about that. I haven't had an issue with precision as I am only going to 2 decimal places, but I will update the code to use integers wherever possible.

Okay, curveball question time: this Arduino is supposed to drive a W5500 ethernet shield and 16 Adafruit Neopixels (sometimes simultaneously, including during testing) for data collection. Because both are being driven off the 5V pin on the Mega, will this cause any additional errors I'll need to correct for?

It is possible for me to drive both off the 5.15V PSU directly instead of through the 5V pin on the Mega if you think I should.

Reply #2

I assumed you were just meaning as I was reading the analog value. Not the entire program, nor did you explain why it was a bad idea. Plus, as I stated above, I'm not having an issue with floating point precision, so I didn't think about it the implications of using floating points then. Tbh, it's not a priority of mine to change to use integers wherever possible at this time. Floating point precision isn't causing issues as seen between the readings on the Arduino and the fluke :confused:

I would worry more about the effect of the interrupts being disabled by the NeoPixel libraries for significant intervals, on the operation of the ethernet.