Build your own ohmmeter!

Check out this ohmmeter built and coded from scratch using an Arduino, 8 precision resistors, a multiplexer, and an OLED display! It can measure resistance from 0Ohm to 1Gohm with fairly high accuracy and it’s even auto-ranging!

We’ve provided all the code, a parts list, and a schematic diagram linked in the description – so you can easily build this on your own as well.

We have our own Steve Stefanidis, one of Programming Electronics Academy’s technical writers, to thank for designing this great project.

Check out this project build, and watch us test it against an off the shelf multimeter we got from amazon.

Arduino ohmmeter on breadboard

Ohmmeter Schematic
Arduino ohmmeter schematic

Parts List

The parts required for this project are:

Ohmmeter Code

// ---------------------------------------------------------------------------
// ArduinOhmmeter
//
// Precision auto-ranging Ohmmeter using the Arduino to measure resistances
// in the range of 0 Ohms to 1 GOhms.
//
// Parts (refer to the schematic):
//    Arduino Pro Mini, MAX4617CPE 8:1 Analog Multiplexer, eight 1% tolerance 
//    reference resistors, SSD 1306 OLED display, 220uF 16V capacitor.
//
// The design and operation is described in detail in a separate document, 
// which also contains the full schematic diagram.
// 
// By Steve S. (C) Feb, 2021
//
// Current code is designed to use a SSD 1306 OLED display (128x64 resolution)
// ---------------------------------------------------------------------------
 
#include <U8glib.h>

#define NUM_REF_RESISTORS 8
#define NUM_SELECT_PINS   3
#define MAX_ANALOG_VALUE  1023
#define SWITCH_RESISTANCE 4.5

// Note that the MAX4617 8:1 Mutiplexer routes signals from X0, x1, ...x7 to X.
// It uses 3 select lines A, B and C to choose one of the signals.
// X0 is the least significant (ABC=0b000), while X7 is most significant (ABC=0b111)

// Reference Resistor values      x0    x1   x2     x3     x4       x5       x6       x7
float rRef[NUM_REF_RESISTORS] = {49.9, 100, 1000, 10000, 100000, 1000000, 4990000, 10000000};

// Multiplexer select pins              A  B  C
const byte rSelPins[NUM_SELECT_PINS] = {5, 4, 3};

const byte enableMux = 6; // 1 = no connection, 0 = one of eight signals connected

int screenWidth, screenHeight;

// Enable the display type to be used. We use SPI for now, but can also use I2C.
U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9, 12); // SW SPI: SCK/D0 = 13, MOSI/D1 = 11, CS = 10, A0/DC = 9, RESET = 12


void setup()
{
  pinMode(enableMux, OUTPUT);
  digitalWrite(enableMux, HIGH);      // disable all switches
  
  for (int i = 0; i < NUM_SELECT_PINS; i++)
  {
    pinMode(rSelPins[i], OUTPUT);     // Mux select pins configured as outputs
    digitalWrite(rSelPins[i], HIGH);  // select the highest Rref
  }

  screenWidth = u8g.getWidth();
  screenHeight = u8g.getHeight();
  DisplayIntroScreen();

  Serial.begin(9600);
  Serial.println("\nStarting ArduinOhmmeter...");
}

// This function scales the resistor value, so that it
// can be expressed in Ohms, KOhms, MOhms or GOhms.
// It then ensures that 3 digits of precision are 
// present in the final result.
char ScaleToMetricUnits(float *prVal, char fStr[])
{
  char unit;

  if (*prVal < 1000)
  {
    unit = ' ';
  }
  else if (*prVal >= 1000 && *prVal < 1000000)
  {
    *prVal /= 1000;
    unit = 'K';
  }
  else if (*prVal >= 1000000 && *prVal < 1000000000)
  {
    *prVal /= 1000000;
    unit = 'M';
  }
  else
  {
    *prVal /= 1000000000;
    unit = 'G';
  }

  // Cycle the decimal number in prVal until its whole number is 0.
  // Note that counter 'k' is decremented from 2 to 0 (inclusive),
  // which gives us the 3-digit precision we're looking for.
  for (int k=2, s=10; k >= 0; k--, s*=10)
  {
    if ((int)(*prVal) / s == 0)
    {
      dtostrf(*prVal, 4, k, fStr); // convert the float result to a string
      break;
    }
  }

  return unit;
}

// Central routine to display the image on the SSD 1306.
// 'xTop' and 'xBot' are the x-coordinates of the two words that can
// be moved horizontally (during intro) or kept in place (when measuring).
// 'unit' is a 1-byte character for unit: ' ', 'K', 'M' or 'G'. 0 if no reading.
// 'fStr' is the string representation of the 3-digit decimal value to display.
void DisplayResultsOnLEDScreen(int xTop, int xBot, char unit, char fStr[])
{
  u8g.firstPage();
  do {
      char myStr[8];
      u8g.setFont(u8g_font_profont12r);     // use small font for letters
      u8g.drawStr(xTop, 9, "ArduinO");
      u8g.drawStr(xBot, 16, "Ohmmeter");
      u8g.drawRFrame(0, 16, screenWidth-1, screenHeight-16, 3);
      u8g.drawLine(0, 0, 0, 15);
      u8g.drawLine(90, 0, 90, 15);
      u8g.drawLine(screenWidth-1, 0, screenWidth-1, 15);

      u8g.setFont(u8g_font_fur30r);         // switch to large font for numbers
      if (unit != 0)
      {
        sprintf(myStr, "%6s", fStr);
        u8g.drawStr(0, 56, myStr);
        sprintf(myStr, "%c%c", unit, 'W');  // 'W' stands for Greek 'Omega'
        u8g.setFont(u8g_font_symb14r);      // switch to symbol font for unit
        u8g.drawStr(95, 16, myStr);
      }
      else
      {
        strcpy(myStr, "- - -");
        u8g.drawStr((screenWidth-u8g.getStrPixelWidth(myStr))/2, 48, myStr);
      }
   } while (u8g.nextPage());
}

// Routine to display the animated introductory screen
void DisplayIntroScreen(void)
{
  for (int xTop = 40, xBot = 4; xTop >= 4; xTop--, xBot++)
  {
    DisplayResultsOnLEDScreen(xTop, xBot, 0, 0);
    if (xTop == 40) delay(500);
  }
}

void loop()
{
  int cOut;
  float delta, deltaBest1 = MAX_ANALOG_VALUE, deltaBest2 = MAX_ANALOG_VALUE;
  float rBest1 = -1, rBest2 = -1, rR, rX;
  char unit = 0, fStr[16];

  for (byte count = 0; count < NUM_REF_RESISTORS; count++)
  {
    // Set the Mux select pins to switch in one Rref at a time.
    // count=0: Rref0 (49.9 ohms), count=1: Rref1 (100 ohms), etc...
    digitalWrite(rSelPins[0], count & 1); // C: least significant bit
    digitalWrite(rSelPins[1], count & 2); // B:
    digitalWrite(rSelPins[2], count & 4); // A: most significant bit
    
    digitalWrite(enableMux, LOW);       // enable the selected reference resistor
    delay(count + 1);                   // delay 1ms for Rref0, 2ms for Ref1, etc...
    cOut = analogRead(A0);              // convert analog voltage Vx to a digital value
    digitalWrite(enableMux, HIGH);      // disable the selected reference resistor
    delay(NUM_REF_RESISTORS - count);   // delay 8ms for Rref0, 7ms for Ref1, etc...

    // Work only with valid digitized values
    if (cOut < MAX_ANALOG_VALUE)
    {
      // Identify the Rref value being used and compute Rx based on formula #2.
      // Note how Mux's internal switch resistance is added to Rref. 
      rR = rRef[count] + SWITCH_RESISTANCE; 
      rX = (rR * cOut) / (MAX_ANALOG_VALUE - cOut);

      // Compute the delta and track the top two best delta and Rx values
      delta = (MAX_ANALOG_VALUE / 2.0 - cOut);
      if (fabs(delta) < fabs(deltaBest1))
      {
        deltaBest2 = deltaBest1;
        rBest2 = rBest1;
        deltaBest1 = delta;
        rBest1 = rX;
      }
      else if (fabs(deltaBest2) > fabs(delta))
      {
        deltaBest2 = delta;
        rBest2 = rX;
      }
    }
  }

  // Make sure there are at least two good samples to work with
  if (rBest1 >= 0 && rBest2 >= 0)
  {
    // Check to see if need to interpolate between the two data points.
    // Refer to the documentation for details regarding this.
    if (deltaBest1 * deltaBest2 < 0)
    {
      rX = rBest1 - deltaBest1 * (rBest2 - rBest1) / (deltaBest2 - deltaBest1); // Yes
    }
    else
    {
      rX = rBest1;  // No. Just use the best value
    }

    // Convert the scaled float result to string and extract the units
    unit = ScaleToMetricUnits(&rX, fStr);
  }

  DisplayResultsOnLEDScreen(4, 40, unit, fStr);

  delay(250);
}

Theory of Operation

OK – so how does this thing actually work? Here’s the basics…

You may have heard of this thing called Ohm’s law, I think it was discovered by a monk, you know like “ohmmmmmm”?

Anyway, if we create a voltage divider circuit like this one shown:

voltage divider equation and circuit

Where…

  • Rref is the reference resistor, whose value is known
  • Rx is the resistor under test (unknown resistance that is being determined)
  • Vcc is the voltage applied to the circuit
  • Vx is the voltage measured at the junction

By Ohm’s law, we can create this voltage divider equation – and if we solve for Vx, that is, if we can determine what the voltage is between the known Rref value and Rx the unknown resistance value, then we can calculate Rx.

Lucky for us, the Arduino has an Analog to Digital Convertor that we can use to measure the voltage at Vx!  The error of this voltage measurement grows as the difference between our reference resistor and unknown resistance grows – the bigger the difference – the greater the error. So we need to pick a reference resistor as close to the unknown resistance value as possible – but wait a sec – we don’t know the value reference resistor – how can we possibly know which reference resistor to choose?

This is where the mux and the 8 precision resistors come in. In our code, we make 8 separate measurements of Vx switching between each of the different reference resistors.  Basically a mux allows you to select one of many different signals.  Since this is an 8 channel mux, we are able to choose between 8 different signals.

multiplexer, mux diagram

Then we cherry pick from that list the measurement which shows the Rx and Rref to be closest.

Now, it’s a little more detailed than that – but not too much. If you’d like us to dive further into the theory, operation and code of this ohmmeter let us know in the comments!

AppLab Bricks open in background with actual brick

Arduino AppLab Bricks → Marketing Garbage or New Powerful Interface?

Arduino Ventuno single board computer - top side

New Ventuno Q Dual Brain Single Board Computer

AppLab Pip Install

How to Add Python Packages in Arduino AppLab (No pip install needed)

Arduino Power Section Schematic

Kit-on-a-Shield Schematic Review

Just how random is the ESP32 random number generator?

Just how random is the ESP32 random number generator?

68 Comments

  1. Maurice Porter on September 24, 2021 at 4:50 pm

    I have a problem with the code line 31
    float rRef = {49.9, 100, 1000, 10000, 100000, 1000000, 4990000, 10000000};

    // Multiplexer select pins A B C
    const byte rSelPins = {5, 4, 3};

    OHM_Meter_sep24a:31:7: error: scalar object ‘rRef’ requires one element in initializer
    float rRef = {49.9, 100, 1000, 10000, 100000, 1000000, 4990000, 10000000};
    OHM_Meter_sep24a:34:12: error: scalar object ‘rSelPins’ requires one element in initializer
    const byte rSelPins = {5, 4, 3};
    ^~~~~~~~
    exit status 1
    scalar object ‘rRef’ requires one element in initializer
    Any ideas?

    • Michael James on September 24, 2021 at 5:54 pm

      Sorry about that Maurice! The brackets in the code were not showing correctly – issue fixed!

  2. Stephen Tripoli on September 25, 2021 at 11:53 am

    Thanks for a great tutorial. I appreciate the effort you put into this. I am going to build this. Again thanks.

  3. Mike G on September 25, 2021 at 1:28 pm

    The font of the labels in the picture is too small to easily read. If I print it to a .pdf file, then zoom in, then the test is way too blury.

  4. Avi Khalid on September 27, 2021 at 6:44 pm

    Hi, I am very new to Arduino programing. I copied the Ohmmeter to the Arduino IDE I am getting this error message #include I need your help.
    SKETCH_SEP27A:19:20: FATAL ERROR: U8GLIB.H: NO SUCH FILE OR DIRECTORY
    COMPILATION TERMINATED.
    EXIT STATUS 1
    U8GLIB.H: NO SUCH FILE OR DIRECTORY

    • Michael James on September 27, 2021 at 8:09 pm

      Hi Avi – great question. You’ll need to install the U8GLIB.H library. You can do that in the Arduino IDE under Tools > Manage Libraries … then search for U8GLIB and click the install button.

  5. Siva Low on November 8, 2021 at 5:57 pm

    Hi. I have to design a resistor tester like this one that can be controlled via MATLAB GUI, can you please assist me. will be highly appreciated. thanks in advance

  6. Ravi N on November 23, 2021 at 9:19 pm

    Hi,

    Really a great Tutorial.
    How to send the value to serial Port instead of SSD 1306 OLED.
    Awaiting your Reply.
    Thanks in advance.
    Ravi

    • Michael James on November 23, 2021 at 10:10 pm

      Hi Ravi,

      On line 215, where they print to the display, I believe you just use a couple serial prints to print the unit and the fstr.

      • Ravi N on November 24, 2021 at 12:30 am

        Yes. I Tried That . Thanks for the Quick reply.

        • Camilla on October 31, 2022 at 9:23 am

          Hi, do you remeber what you changed? I can’t seam to get it working, and i need my output on the serial monitor. Thanks in advance.

  7. Siva Low on November 24, 2021 at 11:15 am

    hello. i would like to use this design to be implemented on a MATLAB GUI. if you could possibly assist. would really appreciate that. you can email my email id.
    also is there an alternative for the MAX4617CPE my local store says its discontinued and ordering from mouser/digikey will take forever to come.
    thanks in advance

    • Michael James on April 23, 2022 at 9:38 pm

      Sounds neat Siva! Unfortunately, I don’t have the expertise in MATLAB to help you out on this – sorry I could be of more help!

      I think any 8 to 1 Low Resistance Analog Multiplexer should work OK in place of the MAX4617CPE.

  8. mark stoeger on April 19, 2022 at 1:36 pm

    I was only able to get the Geekcreit 0.96 inch 4 pin white I2C OLED where I live, it has 4 wires, two power and SCL and SDA. what is needed to be done to change this over?

    BTW had the Geekcreit working on a hello world program.

    Thank you,
    Mark

    • mark stoeger on April 19, 2022 at 3:56 pm

      this is Mark, btw changed lines 41, 55 and 56 but still no go

    • Michael James on April 23, 2022 at 9:23 pm

      Hi Mark! OK, sounds like you have already downloaded the U8GLIB library and checked out the example sketch “HelloWorld” – and you had it working…

      Are you getting any thing on the screen – or just total blank?

      • mark stoeger on April 25, 2022 at 11:36 am

        Hi Michael,

        Cool, you are still on. I am sure it is my programing, I know very little about programing, which is why I am interested in your course. For hello world I use pins A4 and A5 but this code call for D pins 9-13, line 41. The display is blank for this, but worked for hello world just fine. Also a side note, your wiring diagram is missing A0, or at least I believe it is A0 above. If it isn’t A0 that might also be the issue.
        I look forward to your reply and to learning Ardunio.
        Thank you,
        Mark

        • Michael James on April 25, 2022 at 6:02 pm

          Hi Mark, I think you should be able to go with pins A4 and A5 as you had it connected before.

          I think line 41 would look like this:
          U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);

          Thanks for the heads up on A0 in the diagram – yes, that is what is used!

  9. Matthew on May 9, 2022 at 12:02 am

    Hello, This is Matt and I was wondering how you would change the code to view a 16×2 LCD display?

    Thanks for your help in advance. Great video!

    • Michael James on May 11, 2022 at 3:25 pm

      Hi Matt – Great question! You’d want to switch out from using the U8G display library to an LCD library, maybe the LiquidCrystal one.
      https://www.arduino.cc/reference/en/libraries/liquidcrystal/

      You’d have to look at all the display code currently, and then figure out how to rework it with those other library functions. I hope this helps some!

  10. Tarçın on August 14, 2022 at 7:09 am

    Hi,
    Great project. I want to use this in my project. I have a material and I want to measure its resistance in four different points. There are four wires fixed to the system. I want to switch ohmmeter’s probes between these four points. Let’s say these points are a, b, c, d. I should measure resistance between a and b, then a and c, then a and d. Do you have any idea how to do that? Thanks in advance.

    • Michael James on August 19, 2022 at 5:58 pm

      Neat project… I think you ad 3 more analog “probes”, and connect one to each corner. When you do an analog reading at a specific corner, write all the other pins LOW. Then just do this in turn with the others. Just a thought!

  11. Claude Belfer on September 1, 2022 at 8:40 pm

    Hello Michael
    I would like to build this auto range ohmmeter that you’ve designed, But I cannot get a Multiplexer MAX4617CPE I can however get a MAX 4618CPE comparing the data sheet they look similar. Can I use this one instead?
    Thank you

    • Michael James on September 2, 2022 at 3:19 pm

      I am not sure the 4618 model would be a simple component swap. But I am thinking it may be able to be handled in code…

      The (MAX4618) has two 4-channel multiplexers, Where the one used here (MAX4617) is an 8-channel multiplexer.

      I believe, if you can find a different 8 channel multiplexer, you’d be good to go.

  12. EDZEL on October 2, 2022 at 10:03 pm

    Hi! I’m planning on making this. Can I use 5 of the 8 pins on the multiplexer or is it required to have 8? and may I ask if this can measure low resistance up to 5 ohms?

    • Michael James on October 7, 2022 at 4:17 pm

      I think you could use 5 of the pins, but you would have to adjust the code accordingly.

  13. Giovanni on November 30, 2022 at 4:19 pm

    Hi Michael,

    Can you please provide some assistance. I compiled the code and uploaded the program with no errors. However, with no resistor connected (open) my display is fluctuating random numbers displayed ex. 25ohm, 518ohm… When I short the output the screen does not display short, again just random numbers. Any feedback?

    • Michael James on November 30, 2022 at 4:32 pm

      When you connect a resistor, are you getting a value in the ball park?

      • Ruben on January 22, 2023 at 10:26 am

        Hello Michael, great build. I got it working and reading resistances, I am having the same issue as the above poster Giovanni. The readings are on point but when no resistor is attached the screen is jumping all over the place. Any idea as to what might be causing this and is there a solution?

        • Ruben on February 1, 2023 at 5:55 am

          I noticed that while the arduino ohmmeter is getting power via USB, the screen will jump all over the place when no resistor is attached but while hooked up to 4 series AAA batteries the ohmmeter acts accordingly. Not sure why this would happen but issue resolved for what my needs. Thanks again for a great build.

          • Steve Stefanidis on October 26, 2023 at 12:40 pm

            When there’s no resistor under test, then the A0 input is floating. This means that it will pick up any random noise and effects due to moisture, stray capacitance, etc. If the tool detects resistances greater than 1Gohms, or isn’t able to perform a measurement, it will display “—“.
            One quick fix is to put a large (say 50Mohms resistor) between A0 and Gnd, so as to alleviate the external stray effects.



  14. Agastya on December 2, 2022 at 1:51 pm

    rX = (rR * cOut) / (MAX_ANALOG_VALUE – cOut);

    what exactly is this line doing? could you please explain the delta calculations?

    • Steve Stefanidis on October 26, 2023 at 12:12 pm

      Equation 1 is already shown above:
      Vx = [Rx / (Rx + Rref)] × Vcc (eqn 1)

      Now, cOut is the output count value produced by the A/D (ranges from 0 to 1023):
      cOut = [Rx / (Rx + Rref)] × 1023

      Doing some simple algebra…
      cOut × (Rx + Rref) = 1023 × Rx
      cOut × Rx + cOut × Rref = 1023 × Rx
      cOut × Rref = 1023 × Rx – cOut × Rx
      cOut × Rref = (1023 – cOut) × Rx
      Rx = cOut × Rref / (1023 – cOut) (eqn 2)

  15. Ruben Bustamante on January 16, 2023 at 9:01 pm

    Hello Michael.
    Im having a hard time reading the diagram, specifically the MAX3617CPE X Inputs. I was also reading in the first bit of the arduino code “The design and operation is described in detail in a separate document,
    // which also contains the full schematic diagram.” and was wondering if you’d be able to share the document that might elaborate on Multiplexor inputs or if you could elaborate a bit more on those. Thank you, I appreciate your time and effort.

    • Ruben Bustamante on January 16, 2023 at 9:14 pm

      Watching the Video I understand now, thank you for the great tutorial.

  16. Donald on January 27, 2023 at 1:20 pm

    How about digging a little deeper, the theory, code, etc. then the next project is to use this as voltmeter, then a current meter?

    • Michael James on January 30, 2023 at 4:32 pm

      Thanks for the recommendation Donald!

  17. Timmy G on March 31, 2023 at 8:12 pm

    I just got my parts from Digikey and am breadboarding it as I’m typing this
    FYI I also used the I2C 1306 OLED Displays from Amazon. I’m using the U8G2 Library from Oliver Kraus (V2.33.15)
    You’ll have to do a fair amount of adjusting to use I2C. Here are the Library’s I have
    #include
    #include
    #include

    Here is the connector that works for me (Arduino Pro Micro)
    U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

    I wanted to ask, How can I get the Fonts to work? that’s where it errors now.
    u8g_font_profont12r Works but the others:

    u8g_font_fur30r
    u8g_font_symb14r

    Kick errors back.
    How can I fix that?
    Thanks in advanced

    • Michael James on April 5, 2023 at 7:05 am

      Hey Timmy – cool! What kind of errors are you getting back? Can you post them here?

    • Matt D on November 21, 2024 at 11:54 am

      It is a simple change to get the I2C display to work. Here is the modification;

      // Enable the display type to be used. We use SPI for now, but can also use I2C.
      // U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9, 12); // SW SPI: SCK/D0 = 13, MOSI/D1 = 11, CS = 10, A0/DC = 9, RESET = 12

      //Initialize display.
      U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);

  18. Justin on April 13, 2023 at 1:52 pm

    Is it possible to get this to work with a 3.3v Arduino? Have a few extra lying around..

    • Steve Stefanidis on October 26, 2023 at 12:20 pm

      There’s no reason why it wouldn’t work with lower-voltage microcontrollers like ESP32.
      But it should be noted that the ADC on those parts could be different than the 10-bit ADC that’s used on the Arduino UNO/Nano/Micro, etc.
      So, depending on the ADC’s resolution (10bits, 11bits, 12bits…), you’ll need to update this line of the code:

      #define MAX_ANALOG_VALUE 1023

  19. Jonathan Festus on April 14, 2023 at 7:02 am

    Hello sir can this project measure the insulation resistance of a motor.

  20. Tim on May 22, 2023 at 7:08 pm

    I understand that X is connected to the unknown resistor but is x also connected to D6 of the ardiuno?

    • Michael James on May 22, 2023 at 7:30 pm

      My apologies for this oversight Tim. X is also connected to pin A0 – which is missing in that circuit diagram.

  21. David W on June 18, 2023 at 3:54 pm

    What is the point of the delays?

    delay(count + 1); // delay 1ms for Rref0, 2ms for Ref1, etc…
    delay(NUM_REF_RESISTORS – count); // delay 8ms for Rref0, 7ms for Ref1, etc…

    • Michael James on June 19, 2023 at 6:26 pm

      The idea is to enable the reference resistor for a short amount of time and then disable it, so as to comply with the Mux’s duty
      cycle and supported current and power dissipation specs.

      • TimBanjo on March 7, 2025 at 3:39 pm

        This interests my too. I don’t understand why the delay time depends on which switch is being activated. The data sheet does not seem to say anything about that. What do you think?

  22. David S. on August 12, 2023 at 7:40 pm

    Interesting project – but mostly about coding the Arduino. a few enhancements would make it an excellent ohm meter: First, I would suggest a calibration routine to adjust the gain of the A2D and the offset errors for each reference resistor. Second, some type of circuit protection just in case the user accidentally connects the input to a voltage source.

  23. Sam on October 25, 2023 at 9:03 am

    Hi, I need to simulate this project on PROTEUS 8.16 but the MAX4617CPE+ is not available for VSM simulation. Do you suggest another MUX ?
    Thanks

    • Steve Stefanidis on October 26, 2023 at 12:10 pm

      Here are some alternates for MAX4617CPE :
      – Maxim MAX4617CPE+ (direct replacement)
      – Maxim MAX4581
      – Vishay DG508B
      – Analog Devices ADG608BNZ
      – SN74HC4851N

      But note that some of these will have a higher switch resistance (in the 100s of ohms), which could impact the low-resistance measurement of the tool.
      It is advised that one refers to the spec sheet and use the actual switch resistance value in the code. so if the chosen multiplexor’s switch resistance is 150 ohms, then one will need to update this line to:
      #define SWITCH_RESISTANCE 150

  24. Steve Stefanidis on October 26, 2023 at 12:07 pm

    AFAIK, the MAX4617CPE has been replaced by MAX4617CPE+, which is a direct drop-in part for the MAX4617CPE !

  25. Vinay on December 4, 2023 at 5:12 am

    Hi can you please explain the code bit more I am using LCD display and I wanted to know how are you picking the reference resistor based on the Rx value?

  26. Nefzi Arbi on February 29, 2024 at 4:58 pm

    I can’t understand this part sir.!!!
    delta = (MAX_ANALOG_VALUE / 2.0 – cOut);
    if (fabs(delta) fabs(delta))
    {
    deltaBest2 = delta;
    rBest2 = rX;
    }
    }
    }
    // Make sure there are at least two good samples to work with
    if (rBest1 >= 0 && rBest2 >= 0)
    {
    // Check to see if need to interpolate between the two data points.
    // Refer to the documentation for details regarding this.
    if (deltaBest1 * deltaBest2 < 0)
    {
    rX = rBest1 – deltaBest1 * (rBest2 – rBest1) / (deltaBest2 – deltaBest1); // Yes
    }
    else
    {
    rX = rBest1; // No. Just use the best value

    • Steve S. on February 16, 2025 at 3:57 pm

      Ideally, it’s best to have a delta value of 0, which means that the supply voltage Vcc is divided exactly in half at the junction of the two resistors (Rref and Rx).
      This gives us the maximum fidelity, and hence, accuracy in measurement of voltage Vx. As delta gets closer to its limit of -511.5 and 511.5, the measurement accuracy progressively degrades, so it’s in our best interests to keep the delta to a minimum.
      The code selects the two best measurements, as it cycles though each of the 8 reference resistors and then interpolates (i.e. takes the average) between these two best readings.

  27. David on May 15, 2024 at 7:06 pm

    Hi! Where is the PDF with the full explanation to download?

  28. Steve on June 16, 2024 at 5:51 pm

    I’ve just came across this cool little nifty project, so I thought I’d try it with and ESP32, changed the adc part from 1023 to 4095 and the pins that control the mux but unfortunately the eps32 just keeps restarting/resetting complies and uploads ok..
    Not sure what’s the difference or what’s gone wrong ?

  29. Christoph on July 29, 2024 at 6:29 am

    Hello, I am currently working on a project where I need to measure resistances between 0 and 200 ohms as accurately as possible (sensor, water level measurement by a swimmer). What is the best way for me to do this? Can I adapt your design and how?

    • Steve S. on February 16, 2025 at 3:21 pm

      If you follow all of the design step accurately and use the 1% precision resistors are shown, you will be able to accurately measure resistances < 200ohms. In fact, one can even use a short (i.e. plain wire) instead of a resistor and the device will safely measure the resistance of that wire stub!

  30. Vishwajeet on August 12, 2024 at 3:14 am

    Hello, respected sir,

    The current ohmmeter code is a great development. However, at 16 MHz, it is not very sensitive and fast; it becomes stuck when I add the Modbus library. Can you suggest ways to optimize it? My requirements are Modbus master functionality and OLED display updates.

    Thank you.

    • Steve S. on February 16, 2025 at 3:23 pm

      There’s a strong possibility that after adding the Modbus library to the code, you may be using up more of the system RAM. On most Arduinos the RAM size is 2KB, so if your code tends to exceed that, strange and unexpected side-effects may occur. It’s always a good idea to monitor the RAM usage to avoid such complications. One quick experiment would be to use the Arduino MEGA, which has 8KB of RAM and see if the issues go away.

  31. Vivek on January 16, 2025 at 4:12 pm

    Hi Michael,

    Thank you for sharing this project—it’s fascinating! I’ve been working on it and have observed a change in resistance as expected. However, I’ve encountered two issues that I’d like to discuss:

    Resistance Measurement Discrepancy:
    When measuring resistance above 1 MΩ and using the lower ground on the breadboard, I notice the measured resistance is approximately half the expected value. For resistances below 1 MΩ, the readings are accurate.
    Conversely, when using the upper ground of the breadboard, I get accurate readings for resistances above 1 MΩ, but the values below 1 MΩ appear doubled.
    Could this be related to grounding issues, and how might I resolve it to ensure consistent and accurate measurements across all resistance ranges?

    Measuring Semiconductor Resistance with Applied Voltage:
    I would like to measure the resistance of a semiconductor material, which is expected to behave like a variable resistance. Additionally, I want to apply a fixed voltage, say 1V, across the semiconductor during measurement.
    What modifications should I make to the circuit to accommodate this setup while ensuring accurate resistance measurement?

    I appreciate your insights on these points and look forward to your advice.

    • Steve S. on February 16, 2025 at 3:26 pm

      This sounds like some sort of a connection/continuity issue. Also, if one of the IC’s pins isn’t connected, that pin may be floating and picking up random noises from outside. I’d recheck all the wiring and ensure that the grounds are all in place.
      Wrt measuring resistance with live voltage being applied: this is strictly not recommended. One should refer to the note in this article which explains the methodology of resistance measurement in this project. The design is geared for measuring the resistance only of passive components (i.e. standalone resistors) and not active ones.

  32. user1337 on October 13, 2025 at 1:35 pm

    Why do you use interpolation when the deltas are opposite signs?
    Just use the R (rBest1) corresponding to the smallest delta.
    The larger delta is just going to introduce more error into your estimation.

  33. Monte Meredith on January 10, 2026 at 3:44 pm

    Can someone please explain the code in more detail. I find that all the arduino videos don’t go into the detail on the code, just breeze over it, but will spend 3/4 of the video on how to wire a breadboard .

    • Michael Cheich on January 10, 2026 at 4:38 pm

      Hi Monte! I’ll see if we can make a video explaining the code better.

Leave a Comment