Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
f.w.mclennan
Published © LGPL

Auto-Ranging Ohmmeter

Arduino auto-ranging ohmmeter using Pro-Mini & Oled display. Live Test: 56K ohm resistor shown.

AdvancedShowcase (no instructions)1,653
Auto-Ranging Ohmmeter

Things used in this project

Hardware components

Arduino Pro Mini 328 - 5V/16MHz
SparkFun Arduino Pro Mini 328 - 5V/16MHz
×1
SH-1106 I2C OLED DISPLAY
×1
LM-2596 BUCK CONVERTER
Adjustable 9-12VDC to 5VDC Voltage Regulator board (MP184EN)
×1
9V 1A Switching Wall Power Supply
9V 1A Switching Wall Power Supply
A/C Wall Adapter Pack (120VAC to 9-12VDC.
×1
2N3906 PNP TRANSISTOR
- or equivalent
×5
100nF Ceramic Capacitors
×2
4k7k ohm resistors 1/4 watt
×5
1M ohm resistor (1/4 watt)
×1
100k ohm resistor (1/4 watt)
×1
10k ohm resistor (1/4 watt)
×1
1k ohm resistor (1/4 watt)
×1
100 ohm resistor (1/4 watt)
×1
Small Plastic Food Container
×1
Short Stainless Steel Bolts, Nuts and Washers
For mounting Oled Display, PC board & Test Terminals
×6
DC Power Chassis Jack
Size should match the Wall Power Pack.
×1
Hookup Wire
×1

Story

Read more

Custom parts and enclosures

VERO PC BOARDS & TOP DISPLAY HOOKUP

Interface wiring between pc boards and display.

VERO CIRCUIT BOARDS

Transistor voltage divider switcher and Pro-mini PC boards.

Schematics

Auto-range Ohmmeter #1 Prototype

I used this for my first protype circuit, using an Arduino UNO micro driving a 1602 LCD display. Additional accuracy will be gained by replacing the transistors with p-channel field-effect transistors.

Auto-range Ohmmeter #0 (Not Prototyped)

This was one of the first circuits I came across, which outlined how the ohmmeter was first configured. In later designs, PNP transistors were added for more accurate readings.

Auto-range Ohmmeter #3 Finished Project

My third and final design using Arduino Pro-Mini micro with SH1106 Oled display. I added a LM2596 Adjustable Buck Converter which regulates the 9-12VDC wall adapter voltage to 5VDC to power the ohmmeter circuits. It is soldered directly to the DC power jack.

Auto-range Ohmmeter #2 Prototype

My second Prototype using Arduino UNO R3 micro with SH1106 Oled display.

Code

Ohmmeter_Autoranging_SimpleCircuitcom.ino

Arduino
This easy to use Ohmmeter is made for electronic technicians and hobbyists who quickly want to find the resistance of resistors by just placing the component across two bolts. The accuracy is only about 10% but the exact value can be easily recognized.
// SKETCH: Ohmmeter_Autoranging_SimpleCircuitcom.ino
// Autoranging Ohmmeter with 128x64 Oled display with Arduino Pro-Mini
// SH1106 Oled display driven with I2C via A4=SDA & A5=SCK.
// Adaped from: https://simple-circuit.com/arduino-auto-ranging-ohmmeter-lcd/

#include <Arduino.h>
#include <U8g2lib.h>  // Oled library

// Define digital pins to enable pnp transistors through 4k7 ohm base resistor
#define CH0  12       // Q1 - 100 ohm range
#define CH1  11       // Q2 - 1k ohm range
#define CH2  10       // Q3 - 10k ohm range
#define CH3  9        // Q4 - 100k ohm range
#define CH4  8        // Q5 - 1 Meg ohm range

byte ch_number;
uint32_t res;
const uint32_t res_table[5] = {100, 1000, 10000, 100000ul, 1000000ul};  // resistor table array
char _buffer[11];

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

void setup(void) {
  // Serial.begin(9600);                         // initialize the Serial display
  
  // analogReference(EXTERNAL);  // I did not use AREF as Pro-Mini does not have it
  // ***Add this after wiring AREF to 5 volt, and before analogRead(A1)

  u8g2.begin();                               // initialize the I2C Oled display
  u8g2.clearDisplay();
  u8g2.setFont(u8g2_font_lubB14_tf);          // Set Lucida 14 font
  u8g2.drawStr(10, 20, " < OHM >");           // write to the internal memory
  u8g2.drawStr(10, 40, "< METER >");          // write to the internal memory
  u8g2.setFont(u8g2_font_luRS10_tf);          // Set Lucida 10 font
  u8g2.drawStr(0, 60, " by: f.w.mclennan");   // write to the internal memory
  u8g2.sendBuffer();                          // transfer internal memory to Oled
  // NOTE: Millis can only be used once per sketch like this:
  while (millis() < 4000) {                   // Hold Oled display 4 seconds
  }
  u8g2.clearDisplay();                        // clear the display
  u8g2.clearBuffer();                         // clear the internal memory

  // Set digital pins as outputs
  pinMode(CH0, OUTPUT);
  pinMode(CH1, OUTPUT);
  pinMode(CH2, OUTPUT);
  pinMode(CH3, OUTPUT);
  pinMode(CH4, OUTPUT);

  ch_number = 4;
  ch_select(ch_number);
}

void loop() {
  // Read ADC voltage across unknown resistor (digital value between 0 and 1023
  // uint16_t volt_image = analogRead(A1) + 1;
  uint16_t volt_image = analogRead(A1);  // Seems to work OK without the +1 (above)

  if (volt_image >= 550 && ch_number < 4) {
    ch_number++;
    ch_select(ch_number);  // Execute void ch_select (below)
    delay(50);
    return;
  }

  if (volt_image <= 90 && ch_number > 0) {
    ch_number--;
    ch_select(ch_number);  // Execute void ch_select (below)
    delay(50);
    return;
  }

  if (volt_image < 900) {
    // uint16_t volt_image = analogRead(A1);
    // This equation computes the value of the unknown resistor (changed 1023 to 1024)
    float value = (float)volt_image * res / (1024 - volt_image); // value is unknown resistor in ohms

    if (value < 1000.0)
      sprintf(_buffer, "%03u.%1u Ohm ", (uint16_t)value, (uint16_t)(value * 10) % 10);
    else if (value < 10000.0)
      sprintf(_buffer, "%1u.%03u Kohm", (uint16_t)(value / 1000), (uint16_t)value % 1000);
    else if (value < 100000.0)
      sprintf(_buffer, "%02u.%02u Kohm", (uint16_t)(value / 1000), (uint16_t)(value / 10) % 100);
    else if (value < 1000000.0)
      sprintf(_buffer, "%03u.%1u Kohm", (uint16_t)(value / 1000), (uint16_t)(value / 100) % 10);
    else
      sprintf(_buffer, "%1u.%03u Mohm", (uint16_t)(value / 1000000), (uint16_t)(value / 1000) % 1000);
  }

  else
    sprintf(_buffer, "<INFINITY>");     // Measuring probes open circuit

  u8g2.setFont(u8g2_font_lubB14_tf);    // Set Lucida 14 font
  u8g2.clearBuffer();
  u8g2.setCursor(5, 30);
  u8g2.print(_buffer);
  u8g2.sendBuffer();

  // Serial.println(_buffer);
  // Serial.println();
  delay(1000);   // update readings once per second. Default was 500
}

void ch_select(byte n) {
  switch (n) {
    case 0:
      digitalWrite(CH0, LOW);
      digitalWrite(CH1, HIGH);
      digitalWrite(CH2, HIGH);
      digitalWrite(CH3, HIGH);
      digitalWrite(CH4, HIGH);
      break;
    case 1:
      digitalWrite(CH0, HIGH);
      digitalWrite(CH1, LOW);
      digitalWrite(CH2, HIGH);
      digitalWrite(CH3, HIGH);
      digitalWrite(CH4, HIGH);
      break;
    case 2:
      digitalWrite(CH0, HIGH);
      digitalWrite(CH1, HIGH);
      digitalWrite(CH2, LOW);
      digitalWrite(CH3, HIGH);
      digitalWrite(CH4, HIGH);
      break;
    case 3:
      digitalWrite(CH0, HIGH);
      digitalWrite(CH1, HIGH);
      digitalWrite(CH2, HIGH);
      digitalWrite(CH3, LOW);
      digitalWrite(CH4, HIGH);
      break;
    case 4:
      digitalWrite(CH0, HIGH);
      digitalWrite(CH1, HIGH);
      digitalWrite(CH2, HIGH);
      digitalWrite(CH3, HIGH);
      digitalWrite(CH4, LOW);
  }
  res = res_table[n];
}  // end of code.

Credits

f.w.mclennan

f.w.mclennan

2 projects • 4 followers
Electronics Engineering Technologist
Thanks to Mirko Pavleski.

Comments