Introduction: Tim's Precision 4‑Wire Low‑Resistance Meter
🔧✨ Build a Precision 4‑Wire Low‑Resistance Meter (0.001–10.000 Ω)
A stand‑alone Kelvin‑sense instrument evolved from a simple adapter concept.
🌟 Introduction
Measuring very low resistances is tricky — lead resistance, contact resistance, and meter burden voltage all conspire to ruin your readings. This project shows you how to build a true 4‑wire Kelvin low‑resistance meter that delivers stable, repeatable measurements down into the milliohm range.
This design began life as a simple “Low Ohms Adapter” for a handheld multimeter. Through iterative testing, empirical validation, and workflow refinement, it evolved into a fully self‑contained instrument with its own constant‑current source, sense amplifier, microcontroller, and digital display.
Although the meter is stand‑alone in operation, it’s powered entirely from a standard USB supply — simply plug a USB cable into a power bank, PC, or wall‑wart and the NodeMCU module provides clean, regulated power for the whole system. No special bench supply required. 🔌⚡
If you want to measure solder joints, switch contacts, PCB traces, heater elements, or transformer windings with confidence — this is the tool. 🔍⚡
🧰 Two Ways to Build It
Choose the build style that fits your workflow:
🟩 1. Breadboard Build (Beginner‑Friendly)
Using the included Fritzing layout, makers can assemble the meter using:
- Standard plug‑in modules
- Passive components
- A solderless breadboard
- Jumper wires
Perfect for experimentation, learning, and quick prototyping.
🟦 2. PCB Build (Professional Finish)
I’ve designed a through‑hole PCB, available via my shared projects on
.
. The PCB acts like a motherboard for the same modules used in the breadboard version.
Benefits:
- Cleaner wiring
- More robust connections
- Easier calibration
- Looks like a real instrument 😎
Both builds use the same schematic, same firmware, and same measurement principles, so readers can choose the path that fits their tools and experience.
🔍 Features
- 🧪 True 4‑wire Kelvin measurement
- 🔌 Constant‑current excitation
- 📊 High‑resolution ADC sampling
- 🔄 Auto‑zero and lead compensation
- 🔋 USB‑powered stand‑alone operation
- 🖥️ Optional UART output for PC logging
- 🎯 Measures approx. 0.001–10.000 Ω depending on configuration
🧠 How It Works (Concept Overview)
Your meter uses the classic Kelvin method:
- Two wires deliver a known constant current through the DUT
- Two separate sense wires measure only the voltage drop
- The microcontroller computes R=V/I
- Sense wires carry almost no current → their resistance doesn’t affect the reading
This eliminates the biggest source of error in low‑ohm measurements.
Think of it as resistance X‑ray vision. 👀⚡
Supplies
Parts List — What You’ll Need
This project uses the same electronics for both builds. The only difference is how the probes connect:
- Breadboard build uses flying leads and jumper wires
- PCB build uses a 4‑pin Kelvin socket on the board
Core Modules (used in both builds)
- NodeMCU ESP8266 module Microcontroller, USB power input, 3.3 V regulator, I²C master, UART, display control
- ADS1115 16‑bit I²C ADC module (slim type) Precision differential voltage measurement for sense lines
- ️ I²C OLED display module (0.96") Shows resistance readings and status info
Passive Components
- R1 – 1 Ω sense resistor 1 W or higher, 1 % tolerance or better
- R2 – 120 Ω resistor Bias resistor for transistor
- R3, R4 – 100 Ω resistors Signal path / base drive
- R5, R6 – 4.7 kΩ resistors I²C pull‑ups to 3.3 V
- ️ VR1 – 10 Ω trimmer Fine current adjustment
- ️ VR10 – 100 Ω trimmer Corse current adjustment
Semiconductors
- ⚙️ Q1 – 2N4401 NPN transistor Drives current through DUT
- ⚡ D1, D2 – 1N4148 diodes Stable voltage drop
️ Switches & Connectors
- SW2 – SPDT switch Mode or function select
- Probe connection (build-specific)
- Breadboard: flying leads or DuPont jumpers to TP1–TP4
- PCB: 4‑pin Kelvin socket (2 current, 2 sense)
- USB power input Supplied via NodeMCU micro‑USB (from power bank, PC, or wall wart)
Mechanical & Build-Specific
Breadboard Build
- Solderless breadboard
- Jumper wires
- Male header pins for modules
- Flying leads for probes
PCB Build
Step 1: 🧠 Learn the Basics — How Do We Measure Resistance?
🧠
Before we build the meter, let’s understand how resistance is actually measured — and why standard multimeters struggle with very low values.
This Mete is based on the Adaptor in the video.
The video above walks through this in detail. There is a second video to show the completed adapter:
🎥 Tim's Low Ohms Resistance Adaptor [Part 2]
🔍 What Your Multimeter Really Does
Multimeters are fundamentally voltmeters. Every mode — current, resistance, even continuity — is built on measuring voltage.
Here’s how each mode works:
- Voltage mode: Just measures the potential difference between the probes. No current is generated.
- Current mode: Inserts a shunt resistor in series with the circuit. Measures the voltage across the shunt. Calculates current using I=V/R.
- Resistance mode: Generates a small known current, sends it through the unknown resistor, and measures the voltage across it. Calculates resistance using R=V/I.
So even in resistance mode, the meter is still just measuring voltage — and doing a calculation.
⚠️ Why Multimeters Struggle With Low Resistance
Here’s the problem:
- The internal current source is tiny — often just a few milliamps or microamps.
- For a small resistor (e.g. 0.1 Ω), the voltage drop is too small to resolve accurately.
- Lead resistance and contact resistance swamp the reading.
- You get unstable, noisy, or completely wrong results.
🛠️ The Adapter Solution — External Current Source
To fix this, we move the current source outside the multimeter.
- The adapter generates a stable, predictable current using a transistor, diode reference, and calibrated resistor.
- The multimeter goes back to doing what it does best: measuring voltage.
- Because the current is fixed, the voltage directly represents resistance.
This is the principle behind the adapter — and it’s the foundation of the stand‑alone meter we’re about to build.
📸 Visual Summary
Here’s a simplified diagram from the video:
- 🔵 Blue and 🟠 orange wires carry current through the DUT
- 🔴 Red and ⚫ black wires measure voltage across the DUT
- The meter reads voltage → you calculate resistance using R=V/I
This is the essence of Kelvin sensing — and it’s what makes our meter accurate down to milliohms.
Based on this lets make a 4-Wire Resistance Meter.
Step 2: 🧱Build the Solderless Breadboard Version
🧱
This version is ideal for experimentation, learning, and quick prototyping. It uses standard modules and passive components, all plugged into a solderless breadboard — no soldering required.
You can follow along using the Fritzing layout provided in the download section. It shows exactly how to place each module and wire the connections.
🧠 What You’re Building
This breadboard version includes:
- 🧠 NodeMCU ESP8266 module (USB-powered)
- 📐 ADS1115 16-bit I²C ADC module
- 🖥️ OLED display (I²C)
- 🔧 Constant-current source using transistor, resistors, and trimmers
- 🧪 Kelvin probe connections (via jumper wires)
- 🔘 Mode switch (SPDT)
- 🔋 Powered via USB (from power bank, PC, or wall adapter)
🧰 What You’ll Need
Refer to the full Parts List from Step 1. For this build, you’ll also need:
- 🧱 Solderless breadboard
- 🔌 Jumper wires (male-to-male)
- 📎 Male header pins (for plugging in modules)
- 🧪 Flying leads or DuPont jumpers for probe connections
🧭 Breadboard Layout Overview
Here’s how the modules are arranged:
- 📦 NodeMCU plugs into one side of the breadboard
- 📦 ADS1115 module placed near the sense resistor (R1)
- 📦 OLED display mounted at the top or side for visibility
- 🔧 Transistor + resistors + trimmers form the current source
- 🧪 Probe wires connect to TP1–TP4 (current and sense paths)
Use the Fritzing diagram to match pin positions and wire colours. Make sure to keep the sense wires separate from the current path — this is critical for Kelvin accuracy.
⚠️ Tips for Reliable Breadboarding
- 🔍 Double-check all power and ground connections
- 🔄 Keep wires short and tidy to reduce noise
- 🔬 Place the 1 Ω sense resistor close to the ADS1115 module
- 🧪 Use firm probe connections — loose clips will affect readings
- 🧼 Clean contact points if readings fluctuate
🧪 Test Before You Power Up
Before plugging in USB power:
- ✅ Check for shorts between power rails
- ✅ Confirm ADS1115 and OLED are wired correctly (SDA/SCL)
- ✅ Verify transistor orientation and resistor values
- ✅ Make sure probe wires are not swapped (current vs sense)
Once everything is in place, you can plug in USB power to the NodeMCU.
💡 Note: The ESP8266 (NodeMCU) will need to be programmed before the system can operate. Details on how to upload the firmware and configure the meter are covered in the next step.
Step 3: 🧩 Programming the ESP8266 (NodeMCU)
🧩 Step 3: Programming the ESP8266 (NodeMCU)
Before your meter can do anything useful, the ESP8266 needs to be programmed with the firmware. We’ll use the Arduino IDE along with the ESP8266 LittleFS Data Upload plugin to upload both the code and the web interface files stored in the data folder.
This step walks you through everything you need to prepare your NodeMCU.
🛠️ 1. Install the Arduino IDE (if you haven’t already)
Download from the official Arduino website and install it normally. You’ll also need to install the ESP8266 board package via the Boards Manager.
📦 2. Install the “ESP8266 LittleFS Data Upload” Plugin
This plugin adds a new menu option to the Arduino IDE that lets you upload files to the ESP8266’s internal flash filesystem (LittleFS).
You’ll need this because the meter’s web interface, CSS, JavaScript, and settings files all live inside the data folder.
Once installed, you’ll see a new menu item:
Tools → ESP8266 LittleFS Data Upload
(see screenshot.)
📁 3. Prepare the Project Folder
This is important:
✔️ All files must be inside a folder with the same name as the .ino file
Example: If your sketch is named:
Then all files must be inside:
This includes:
- The .ino file
- All .h and .cpp files
- The data/ folder (for the web interface)
- The renamed credentials file
Arduino will not compile correctly unless this rule is followed.
🔐 4. Rename “Credentials_(public).h” → “Credentials.h”
To protect my personal WiFi details I rename this file so that I don't accidently publish my personal details, the downloadable version includes:
Code
Before compiling, you must rename it to:
Code
Then open it and update the WiFi settings:
- Choose AP mode or Station mode
- Enter your network name and password (if using Station mode)
- Or leave the defaults for Access Point mode
This file controls how your meter connects to WiFi.
The comments explains the differences.
🌐 5. Update Your Network Details
Inside Credentials.h, you’ll see:
Replace these with your actual WiFi credentials if using Station mode.
If using Access Point mode, you can leave the defaults.
⬆️ 6. Upload the Firmware to the ESP8266
Once everything is in place:
- Select the correct board: Tools → Board → NodeMCU 1.0 (ESP-12E Module)
- Select the correct COM port
- Click the Upload button in the Arduino IDE
- If using an ESP8266 that has had another project on it, you may want to set it to erase all flash?
- Do not erase All Flash after uploading web file or they will get erased also.
(see screenshot.)
This uploads the main firmware.
📂 7. Upload the Web Interface Files (LittleFS)
After the firmware is uploaded:
- Go to Tools → ESP8266 LittleFS Data Upload
- Click it
- The contents of the data/ folder will be uploaded to the ESP8266’s flash filesystem
(see screenshot)
This step is essential — without it, the web interface won’t load.
📘 8. What’s Next?
I will just give some brief details of the code in the next steps.
Step 4: 🧩 the Main Firmware — Low_Ohms_Resistance_Meter.ino
🧩
This is the core firmware that runs the entire meter. It handles:
- 🧠 Reading the ADS1115 ADC
- 🔌 Talking to the OLED
- 🌐 Hosting the web interface
- 📡 Streaming live readings via WebSockets
- 🧮 Calculating resistance using Ohm’s Law
Before we dive into the code, here are the credits for the libraries used.
🙏 Library Credits
I always like to acknowledge the developers who make these libraries available:
- Wire.h — Arduino Team
- ADS1115.h — Baruch Even
- LittleFS.h — ESP8266 Arduino Core Team
- ESP8266WiFi.h — ESP8266 Arduino Core Team
- ESP8266WebServer.h — ESP8266 Arduino Core Team
- WebSocketsServer.h — Markus Sattler
- TIM_SSD1306_I2C.h — My own OLED driver
- Resource.h — My custom fonts
These libraries make the project possible, and giving credit is always good practice.
📘 What This File Does
Here’s a quick overview of the major functions in the .ino file and what each one does. This helps readers understand the flow before they scroll through the full code.
🔌 setupWiFi()
Configures the ESP8266 WiFi mode based on the settings in Credentials.h. Supports:
- Access Point
- Access Point with password
- Station mode (connect to your home network)
Prints connection info to Serial if enabled.
🛠️ setup()
Runs once at startup. It:
- Starts Serial (optional)
- Connects to WiFi
- Initializes I²C
- Configures the ADS1115 for differential measurements
- Mounts LittleFS
- Sets up HTTP routes
- Starts the WebSocket server
- Initializes the OLED
- Shows the splash screen
This is the “boot sequence” of the meter.
🔁 loop()
Runs continuously. It:
- Samples the DUT and shunt voltage every 200 ms
- Sends readings to the browser via WebSockets
- Updates the OLED
- Handles HTTP requests
- Keeps the WebSocket server alive
This is the “heartbeat” of the meter.
📡 readADS_Differential_A0_A1()
Reads the voltage across the DUT using ADS1115 differential mode.
📡 readADS_Differential_A2_A3()
Reads the voltage across the 1 Ω shunt to calculate current.
🧮 sendMeasurement()
This is the core measurement logic:
- Reads DUT voltage
- Reads shunt voltage
- Calculates current
- Calculates resistance
- Sends JSON data to the browser
- Updates the OLED
This is where the meter “thinks.”
🖥️ Set_OLED_Labels()
Draws the static labels on the OLED (title, units, etc.). Changes depending on whether calibration mode is active.
🖥️ Update_OLED()
Updates the live readings on the OLED:
- Current
- DUT voltage
- Resistance
- Calibration values (if enabled)
🎬 ShowSplash()
Displays the splash screen bitmap for 4 seconds at startup.
📄 Full .ino Code
Attachments
Step 5: 🧩 WiFi Settings — Credentials_(public).h
🧩
This file controls how your ESP8266 connects to WiFi. It lets you choose between Access Point mode, Access Point with password, or Station mode (connecting to your home network).
Because this file contains personal network details, the downloadable version is named:
Before compiling, you must rename it to:
This prevents me from accidentally publishing my private WiFi credentials.
🔐 What This File Does
This file controls:
- 🌐 Which WiFi mode the meter uses
- 📶 The SSID and password for Access Point mode
- 🏠 Your home network name and password for Station mode
- 🖥️ Whether Serial debugging is enabled
Only one WiFi mode should be active at a time.
📡 WiFi Modes Explained
🟦 1. Station Mode (recommended)
The ESP8266 connects to your home WiFi network.
- You access the meter from any device already on your network
- No need to switch WiFi on your phone
- Best for workshop or home use
This is the default:
🟩 2. Access Point Mode (open)
The ESP8266 creates its own WiFi network.
- No password
- Good for quick testing
- Works anywhere, even without internet
🟧 3. Access Point Mode (with password)
Same as above, but protected.
✏️ What You Need to Edit
If using Station mode, update these lines:
Replace the text inside the quotes with your actual WiFi name and password.
If using Access Point mode, you can leave the defaults:
📄 Full File (as included in the project)
Attachments
Step 6: 🧩 Custom OLED Driver — TIM_SSD1306_I2C.h & TIM_SSD1306_I2C.cpp
🧩
The low‑ohms meter uses a 128×64 I²C OLED display, and instead of relying on a large, generic library, this project uses a lightweight custom driver written specifically for this meter.
Why?
- ⚡ Faster
- 🧼 Cleaner
- 🎛️ Only includes the features you actually need
- 🧮 Works perfectly with my custom fonts in Resource.h
- 📦 Keeps the firmware small and efficient
This step includes both the header (.h) and implementation (.cpp) files.
📘 What This Driver Does
The custom SSD1306 driver handles:
- Initializing the OLED over I²C
- Clearing and updating the screen
- Drawing text using your custom fonts
- Drawing bitmaps (like your splash screen)
- Printing centered text
- Printing at specific row/column positions
- Efficient screen updates without flicker
It’s designed to be simple, predictable, and easy to modify.
🧠 Key Methods (Quick Overview)
Here’s a brief description of the most important functions so readers know what they’re looking at:
ssd1306_Init()
Initializes the OLED display and configures it for 128×64 mode.
ssd1306_FillScreen(color)
Clears the screen to either Black or White.
ssd1306_UpdateScreen()
Pushes the internal buffer to the OLED. (Your driver uses a full framebuffer for clean updates.)
ssd1306_DrawBitmap(x, y, bitmap, w, h)
Draws a bitmap — used for the splash screen.
ssd1306_PrintString(x, row, text, color, font)
Prints text at a specific row and column.
ssd1306_PrintStringCentered(row, text, color, font)
Centers text horizontally — perfect for titles.
floatToStr()
Utility function for formatting floating‑point values for the OLED.
These functions are used throughout the .ino file to update the display cleanly and efficiently.
📄 TIM_SSD1306_I2C.h
📄 TIM_SSD1306_I2C.cpp
Step 7: 🧩 Font & Bitmap Resources — Resource.h and Resource.cpp
🧩
The low‑ohms meter uses custom fonts and bitmap graphics to keep the OLED display clean, readable, and instrument‑grade. These resources live in two files:
- Resource.h — declarations and font metadata
- Resource.cpp — the actual font tables and bitmap data
These files work hand‑in‑hand with your custom OLED driver (TIM_SSD1306_I2C) to render:
- Titles
- Labels
- Numeric readouts
- The splash screen
- Calibration text
Because the SSD1306 is a pixel‑addressed display, these fonts are stored as raw byte arrays in PROGMEM for efficiency.
🎨 What These Files Do
Resource.h
This file contains:
- Font declarations
- Bitmap declarations
- External references used by the OLED driver
It tells the compiler what resources exist.
Resource.cpp
This file contains:
- The actual font data (byte arrays)
- The splash screen bitmap
- Any additional icons or symbols
It tells the compiler how the resources look.
🧠 Why Custom Fonts?
You chose to use custom fonts because:
- They render faster than large third‑party libraries
- They give you full control over appearance
- They reduce flash usage
- They allow you to modify characters (like your custom “-” and “/” replacements)
- They match the aesthetic of a proper bench instrument
This is especially important for the large numeric font, which is used for the resistance readout.
📘 Key Resources Included
These Resource files typically include:
- Small_Font_6x8 Used for labels, units, and small text.
- Large_Font_8x16 Used for titles and headers.
- Large_Numbers_15x24 Used for the main resistance display.
- SSD1306_Splash_128x64 The startup splash screen bitmap.
These are referenced throughout the .ino file and rendered by your OLED driver.
📄 Resource.h
📄 Resource.cpp
📝 Notes for Makers
- These fonts are binary data, so they must be copied exactly as provided.
- They live in PROGMEM to save RAM.
- You can modify or add fonts if you want to customize the look of the meter.
- The .ino file and OLED driver both depend on these resources being present.
Attachments
Step 8: 🧩 Web Interface Files (data Folder)
🧩
The low‑ohms meter includes a built‑in web interface served directly from the ESP8266 using LittleFS. These files live inside the data/ folder of the project and must be uploaded using the ESP8266 LittleFS Data Upload tool.
Because Instructables does not allow uploading these file types directly, you’ll paste the contents of each file listed below with the exception of "favicon.ico" this needs to be created using an Icon editor and image.
The data folder contains:
- favicon.ico
- index.html
- scripts.js
- styles.css
Let’s go through each one.
🌐 What the Web Interface Does
The browser interface provides:
- Live resistance readings
- Live voltage and current values
- Auto‑updating display via WebSockets
- A clean, responsive layout
- Calibration mode support
Everything is lightweight and optimized for the ESP8266.
📁 1. favicon.ico
This is the small icon shown in the browser tab.
Because Instructables cannot host binary .ico files, you have two options:
✔️ Option A — Create it yourself
Use any icon editor (e.g., GIMP, RealFaviconGenerator, ICOConvert) and recreate the icon using the image below:
(Attached a resistor image)
✔️ Option B — Download it from GitHub
📄 2. index.html
This is the main webpage served by the ESP8266. It loads the CSS, JavaScript, and opens the WebSocket connection.
📄 3. scripts.js
This file handles:
- Opening the WebSocket
- Receiving live measurement data
- Updating the DOM
- Displaying resistance, voltage, current
- Handling calibration mode
📄 4. styles.css
This file controls:
- Layout
- Fonts
- Colors
- Spacing
- Responsive behavior
📝 Notes for Makers
- These files must be placed inside a folder named data
- The folder must sit next to your .ino file
- Upload them using: Tools → ESP8266 LittleFS Data Upload
- The ESP8266 will then serve them automatically when you visit its IP address
Step 9: 🌐 Finding the ESP8266’s IP Address
🌐
Now that the firmware and the web interface files are uploaded, the next step is to find out where your Low‑Ohms Meter lives on your network. To access the web interface, you need the IP address assigned to the ESP8266.
This step explains how to get it, why it changes (or doesn’t), and what to expect from your router.
🧠 How IP Addresses Are Assigned
When the ESP8266 starts up in Station Mode (STA), it connects to your home WiFi network.
Your router then assigns it an IP address using DHCP (Dynamic Host Configuration Protocol).
A few important points:
- 🖥️ The router controls the IP address, not the ESP8266
- 🔢 You cannot reliably set the IP address from the ESP8266 side
- 🆔 Routers track devices by MAC address
- 🔁 Once a router assigns an IP to a device, it usually gives the same IP every time
- 🧹 The only time it changes is when:
- The router is rebooted
- The DHCP table is full
- The lease expires and the router reallocates addresses
- The ESP8266 connects to a different network
So in normal home use, the IP address tends to stay stable.
🛠️ How to See the Assigned IP Address
The easiest way is to use the Arduino IDE Serial Monitor.
✔️ Step 1 — Open Serial Monitor
In the Arduino IDE:
Tools → Serial Monitor
Set the baud rate to 115200.
✔️ Step 2 — Reset the ESP8266
Press the RESET button on the NodeMCU.
✔️ Step 3 — Watch the Boot Messages
On startup, the ESP8266 prints connection information, including:
The number shown after IP: is the address you will use in your browser.
✔️ Step 4 — Open the Web Interface
Enter the IP address into your browser:
You should now see the live Low‑Ohms Meter interface.
📌 What If You’re Using Access Point Mode?
If you selected Access Point (AP) or AP with password in Credentials.h, the ESP8266 creates its own WiFi network.
- Connect your phone or laptop to the ESP8266 WiFi
- The IP address is usually:
Code
But again, the Serial Monitor will confirm it.
📝 Notes for Makers
- If your router supports DHCP reservations, you can lock the ESP8266 to a fixed IP using its MAC address
- This is optional, but useful if you want the meter to always appear at the same address
- If the IP ever changes unexpectedly, simply check the Serial Monitor again.
Step 10: 🎯 Calibration — Achieving Instrument‑Grade Accuracy
🎯
The Low‑Ohms Meter is only as accurate as its calibration. This step ensures the meter knows the true value of the current shunt (R1) and therefore calculates resistance correctly.
The good news? Calibration is simple, repeatable, and only needs to be done once unless you change hardware.
🧠 Why Calibration Matters
The meter measures resistance using:
R=VDUTI
Where:
- VDUT comes from ADS1115 differential A0–A1
- I is calculated from the voltage across R1, the 1 Ω shunt
Even a tiny error in the actual value of R1 (e.g., 1.000 Ω vs 0.994 Ω) will cause a proportional error in all resistance readings.
The firmware includes:
This value must match the real measured resistance of the R1 shunt.
🧪 What You Need
- Your assembled meter (breadboard or PCB)
- A precision multimeter capable of measuring current accurately
- A stable DUT (any resistor between 1–10 Ω works fine)
- USB power for the NodeMCU
- Serial Monitor (optional but helpful)
🔧 Step 1 — Enter Calibration Mode
Calibration mode is controlled by:
Set this to:
Then upload the firmware again.
When calibration mode is active:
- The OLED shows “Calibration”
- The display shows shunt voltage only
- The web interface shows calibration data
This mode isolates the shunt measurement so you can determine the true value of R1.
🔌 Step 2 — Insert an Ammeter in Series
To calibrate R1, you need to know the actual current flowing through the DUT.
Do this:
- Connect your DUT as normal
- Break one of the current wires
- Insert your multimeter in series set to measure current
Your setup should look like:
The ammeter now shows the true current.
📏 Step 3 — Read the Shunt Voltage
On the OLED (in calibration mode), you’ll see:
This is the voltage across the 1 Ω shunt.
Let’s call it:
Vshunt
🧮 Step 4 — Calculate the True Value of R1
Use Ohm’s Law:
R1 = Vshunt / Iactual
Where:
- Vshunt is from the OLED
- Iactual is from your ammeter
Example:
- OLED shows: 0.09944 V
- Ammeter shows: 0.1000 A
R1 = 0.09944 / 0.1000 = 0.9944 Ω
This is the value you place into:
💾 Step 5 — Update the Firmware
- Edit the value in the .ino file
- Set isCalibrateMode back to false
- Upload the firmware again
- Upload the LittleFS data folder again (optional but recommended)
Your meter is now calibrated.
🧪 Step 6 — Verify Accuracy
Test with known resistors:
- 1 Ω
- 0.5 Ω
- 0.1 Ω
- 10 Ω
You should now see stable, accurate readings within the limits of the ADS1115 and your current source.
📝 Notes for Makers
- Calibration only needs to be done once unless R1 is changed
- Temperature drift of R1 is minimal at these currents
- The ADS1115 is factory‑trimmed and extremely stable
- Your firmware uses floating‑point math for precision
- The OLED and web interface both update in real time
Step 11: 🧪 How to Use the Meter — Understanding the 4-Probe Setup
🧪
The Low‑Ohms Meter uses a 4-wire Kelvin connection to measure resistance accurately — even down to milliohms. This step explains:
- Why there are 4 probes
- What each pair does
- How to connect them to your DUT
- How to interpret the readings
🧠 Why 4 Probes?
Standard multimeters use 2 probes — they push current through the DUT and measure voltage across the same contacts. This introduces lead resistance, contact resistance, and probe pressure errors — all of which swamp low‑ohm readings.
Your meter uses 4 probes:
- 🔵🔶 Two for current — to push a known current through the DUT
- 🔴⚫ Two for voltage — to measure the voltage across the DUT
This isolates the voltage measurement from the current path — eliminating contact resistance and lead losses.
This is called a Kelvin connection, and it’s the gold standard for low‑resistance measurement.
🔌 Probe Breakdown
Here’s what each probe does:

The voltage probes connect inside the current path — directly across the DUT — but carry no current. This ensures the voltage reading is pure, unaffected by wire or contact resistance.
🧪 How to Connect to a DUT
- Connect the blue and orange probes to either end of the DUT — this completes the current path
- Connect the red and black probes to the same points — ideally as close to the DUT body as possible
- Make sure the sense probes are inside the current path, not outside the clips or leads
- The OLED and web interface will show:
📏 Interpreting the Readings
- Current is fixed by your range switch (100 mA or 10 mA)
- Voltage is measured across the DUT
- Resistance is calculated using Ohm’s Law:
R = VDUT / I
The OLED and web interface both show:
- Live readings
- Averages
- Graphs (web only)
- Calibration mode (if enabled)
📝 Notes for Makers
- Use firm probe connections — loose clips will affect readings
- Keep sense wires short and direct
- Avoid measuring across long leads or solder joints
- For best results, use Kelvin clips or 4-pin sockets on the PCB version
Step 12: 🧩 Building the PCB Version (PCBWay)
Currently I have the PCB on order and waiting delivery.
As soon as I have the PCB delivered I will update this section with a link to my shared projects page.
🧩
.
Now that you’ve proven the circuit on a solderless breadboard, you can build a professional, reliable, low‑profile version using the custom PCB I designed for this project.
I had the board manufactured by
., and I’ll also be sharing this project on their Shared Projects page. If you order the board through that link, PCBWay gives me a small credit — it helps support future open‑source builds like this one.
🟦 Why Use a PCB?
The PCB version gives you:
- A clean, compact layout
- Proper Kelvin probe routing with controlled geometry
- A solid mechanical base for the NodeMCU, ADS1115, and OLED
- Reduced noise and improved measurement stability
- A choice between socketed modules or a low‑profile soldered build
- A professional look that’s ideal for a bench instrument
All components are identical to the breadboard version — the only difference is the probe connector, which is now a proper PCB‑mounted socket.
🟩 Ordering the PCB from
.
To keep this project sustainable and to support future open‑source builds, the PCB for this meter is not provided as a Gerber download. Instead, the board is available directly through
.’s Shared Projects platform.
This means you can order the exact PCB I designed with a single click, and
. gives me a small credit for each board ordered — which helps fund more projects like this one.
✔️ How to Get the PCB
Once the project is published on
.’s Shared Projects page, you’ll be able to:
- Visit the project link
- See photos, specs, and the board preview
- Choose your solder mask colour
- Add it to your cart
- Order it just like any other PCBWay board
PCBWay handles everything — no Gerber uploads needed.
They typically manufacture and ship within a few days.
🟧 Assembly Options
The PCB is designed to support two different build styles, depending on whether you want modularity or a slim, permanent build.
1️⃣ Option A — Socketed Modules (Beginner‑Friendly)
This version uses female header sockets soldered to the PCB. The NodeMCU, ADS1115, and OLED simply plug in.
✔️ Advantages
- Easy to replace modules
- No risk of overheating the boards
- Great for experimenting or upgrading later
- Ideal for beginners or first‑time builders
✔️ What You Need
- Female header strips (2.54 mm)
- Straight pin headers for the modules
✔️ Assembly Notes
- Solder the sockets first
- Plug the modules in only after all sockets are aligned
- The OLED can be mounted either flush or raised depending on your preference
2️⃣ Option B — Low‑Profile Build (What I’m Using)
For a compact, professional look, you can solder the modules directly to the motherboard using pin headers only — no sockets.
✔️ Advantages
- Much lower profile
- Stronger mechanical assembly
- Cleaner appearance
- Slightly better electrical performance (shorter connections)
✔️ What You Need
- Straight pin headers
- A steady hand
- A willingness to commit the modules permanently
✔️ Assembly Notes
- Solder the pin headers into the PCB first
- Then place the modules on top and solder from above
- Keep the OLED as close to the PCB as possible for a neat finish
- The ADS1115 sits flat and tidy with this method
This is the version shown in the video.
🟨 Probe Connector
The only part that differs from the breadboard version is the Kelvin probe socket. The PCB uses a proper 4‑pin connector footprint, giving you:
- A secure mechanical connection
- Correct spacing for Kelvin clips
- Clear silkscreen labels for TP1–TP4
- Reduced wiring clutter
If you prefer, you can still solder wires directly to the pads.
🟪 Final Assembly
Once the modules are mounted:
- Attach the probe connector
- Add the range switch
- Plug in USB power
- Upload the firmware (same as breadboard version)
- Upload the LittleFS data folder
- Calibrate once
- You’re ready to measure
🧠 OLED Pinout Compatibility — Why I Added Solder Jumpers
One thing I’ve learned from building with these OLED modules is that not all of them follow the same pin order. Some have:
- GND and VCC flipped
- SCL and SDA swapped
- Or even all four pins in a different sequence
To make this PCB compatible with the widest range of OLEDs, I added solder jumpers that let you reconfigure the connections.
🔧 How It Works
Each OLED pin (GND, VCC, SDA, SCL) connects to a 3-pin jumper on the PCB:
- The centre pin goes to the OLED
- You bridge either the left or right pad to select the signal
- This lets you flip GND/VCC or swap SDA/SCL as needed
You only need to solder one bridge per jumper — either left or right, depending on your OLED’s pinout.
✔️ Benefits
- No need to modify the OLED module
- No risk of reverse power damage
- Works with common OLEDs from AliExpress, Amazon, eBay, etc.
- Makes the PCB more beginner-friendly and future-proof
📝 Notes for Makers
- Check your OLED’s pinout before soldering the jumpers
- Use a multimeter or datasheet to confirm the order
- Once set, the jumpers don’t need to be changed again
- If you’re unsure, start with the breadboard version to test your OLED first
The PCB version behaves identically to the breadboard version — just cleaner, sturdier, and more reliable.



![Tim's Piezoelectric Crystal Experiment [Noise Maker]](https://content.instructables.com/FAB/RCS8/MG8A0APJ/FABRCS8MG8A0APJ.png?auto=webp&crop=1%3A1&frame=1&width=130)



