Building a Portable Digital Cable Length Counter

ESP32 · Bourns Optical Encoder · SN74LVC14A · Custom 3D-Printed Housing

By Ilia Kuzmin — 3DIY.ie | Celbridge, Co. Kildare, Ireland

If you work with cables, wire, or filament regularly, you know the problem: measuring length accurately while feeding material off a reel is surprisingly awkward. Tape measures slip. Manual counters require awkward hand positions. Commercial cable counters exist but tend to be expensive, single-purpose tools.

This project solves that with a handheld digital cable length counter built around an ESP32 microcontroller, a Bourns optical encoder, and a custom 3D-printed housing. Total component cost is approximately €31–61. The result is a precise, portable device that measures to within ±1mm over several metres.

All 3D model files (STEP format) for this project are available for purchase on 3DIY.ie/shop — you can print the parts yourself or order a ready-made unit.

1. The Problem — and Why Off-the-Shelf Doesn't Work

The specific problem this device solves is measuring cable that cannot easily be coiled or laid out straight. Imagine a cable already run through a wall, looped in large coils across a floor, or routed through a complex trunking path — situations where a tape measure cannot reach and a laser distance tool is useless. You need to know how many metres of cable you have, but the cable itself is the only thing you can work with.

The solution: walk along the cable with the counter in one hand, feeding the cable through the measurement wheel as you go. The display shows the running total in real time. No assistant needed, no second trip, no guesswork.

Commercial cable counters (from brands like Komelon or Bosch) cost €60–150 and are designed for different workflows — typically measuring off a reel in a fixed position. They are bulky, single-purpose tools. What was needed here was something handheld, lightweight, usable one-handed, and easy to zero with a single button tap.

The engineering challenge was then well-defined: how do you get a measurement wheel to maintain consistent contact with a moving cable of varying diameter, without damaging it, while keeping the encoder reading accurate?

2. Components & Bill of Materials

Total component cost if purchasing everything new: approximately €31–61 depending on encoder choice — AliExpress optical encoder brings the build to around €31, while a Bourns encoder brings it to around €61.

ComponentDetailsApprox. Cost
MicrocontrollerESP32 38-pin DevKit€4–8
EncoderBourns optical incremental, 100 PPR, Quadrature (A/B), 5V. Alternative: Chinese optical encoder from AliExpress€25–40 / ~€11
Level shifterSN74LVC14A — Schmitt Trigger, 5V-tolerant inputs, 3.3V output€0.50–2
Display1602 LCD with I2C backpack (PCF8574), 3.3V compatible€2–4
WheeleSUN Elastic TPU filament — 50mm diameter, ~15g€1–2
HousingPLA filament — rigid enclosure, ~80g€1–2
Reset buttonMomentary tactile switch€0.20–0.50
MiscJumper wire, M3 screws€1–2
FirmwareMicroPython — open sourceFree
TOTALWith AliExpress encoder / With Bourns encoder€31–61

3. The Encoder — Why 100 PPR Optical Is the Right Choice

The encoder used in this project is a Bourns optical incremental encoder — 100 pulses per revolution, quadrature output (channels A and B in 90° phase). Bourns is a premium industrial brand and this encoder reflects that — expect to pay €25–40 new. However, for this project a Chinese alternative from AliExpress with identical specifications works perfectly well at around €11, making the total build cost significantly more accessible.

Optical encoders are strongly preferred over mechanical (contact-type) encoders for this application: they produce clean digital edges with no contact bounce, require no debouncing in software or hardware, and last significantly longer under continuous use.

Key electrical consideration: level shifting

The Bourns encoder runs on 5V and outputs TTL-level signals (High ≥ 4V). The ESP32 GPIO pins are 3.3V logic — connecting 5V TTL directly would damage the microcontroller. The SN74LVC14A was chosen to solve this elegantly:

Encoder channel A connects to GPIO34, channel B to GPIO35 (both input-only pins on ESP32, which is correct for encoder signals).

4. Wheel Diameter — The Maths Behind the Measurement

Choosing the right wheel diameter is a balance between measurement resolution, interrupt frequency, and practical printability. With X4 quadrature decoding (counting both rising and falling edges on both channels), a 100 PPR encoder gives 400 counts per revolution.

Wheel Ø (mm)Resolution (mm/count)Counts/metreFreq @ 1 m/s
300.2364,244 c/m~4,244 Hz
400.3143,183 c/m~3,183 Hz
50 ✓0.3932,546 c/m~2,546 Hz
600.4712,122 c/m~2,122 Hz
800.6281,592 c/m~1,592 Hz

50mm was selected as the optimal diameter: it gives sub-millimetre resolution (0.393mm per count), the interrupt frequency at typical cable-feeding speeds is well within ESP32 capability, and it is a practical size for 3D printing with stable dimensional accuracy.

The actual printed wheel diameter came out at 49.3mm after measuring the finished part — this value was used directly in the firmware as WHEEL_DIAMETER_MM = 49.3 to compensate for any shrinkage.

5. 3D Printed Parts — Housing and Wheel

Cable counter — first iteration enclosure

Cable counter — component layout

TPU Friction Wheel

The measurement wheel is the most critical mechanical component. It needs to grip the cable/wire without deforming it and without slipping under varying tension. Elastic TPU (Shore 95A) was chosen for the wheel:

A spring-loaded pressure arm was considered to maintain consistent contact force, but testing showed that for the intended use case (hand-feeding cable), the weight of the device against the cable provides sufficient and consistent grip without any additional mechanism.

PLA Enclosure

The housing was printed in standard PLA — rigid, dimensionally accurate, and easy to print. The design went through two iterations:

Finished device — startup screen

Rear panel — reset button and TPU wheel

PLA was chosen over PETG for the enclosure because dimensional accuracy is more important than heat resistance for this application — the device is handheld and not exposed to elevated temperatures. If the device were to be used in a vehicle or outdoor environment, PETG or ASA would be more appropriate.

6. Firmware — MicroPython on ESP32

MicroPython was chosen over Arduino C++ for a practical reason: familiarity with Python fundamentals allows faster iteration. The firmware was developed with AI assistance, which significantly accelerated the quadrature decoding logic.

Quadrature decoding with a lookup table

The core of the firmware is an interrupt-driven quadrature decoder using a 16-entry lookup table (Gray code). Both encoder channels trigger interrupts on rising and falling edges:

# X4 quadrature LUT — maps (prev_AB << 2 | curr_AB) to increment
_LUT = (
    0, -1, +1,  0,
   +1,  0,  0, -1,
   -1,  0,  0, +1,
    0, +1, -1,  0
)

def _isr(_):
    global count, prev_ab
    a = a_pin.value()
    b = b_pin.value()
    curr = (a << 1) | b
    idx = (prev_ab << 2) | curr
    count += _LUT[idx]
    prev_ab = curr

This approach handles direction automatically — pulling cable forward increments the count, pulling it back decrements it. The display shows both the length in metres and the raw count value, updated 5 times per second.

Atomic counter reads

Because the counter is modified inside an interrupt handler, the main loop must read it atomically to avoid corrupted values:

irq_state = machine.disable_irq()
cnt = count
machine.enable_irq(irq_state)

Reset button with debouncing

The reset button is connected between GPIO25 and GND, using the ESP32 internal pull-up resistor. An 80ms debounce delay prevents multiple resets from a single press. The counter resets atomically using the same IRQ disable pattern.

Safe mode on startup

A 3-second startup grace period allows Thonny IDE to connect before the main loop begins. Holding the BOOT button (GPIO0) during this window enters safe mode, displaying a message on the LCD and remaining in the MicroPython REPL.

7. Wiring Summary

SignalConnection
Encoder VCC5V rail
Encoder GNDCommon GND
Encoder A outSN74LVC14A input → GPIO34 (ESP32)
Encoder B outSN74LVC14A input → GPIO35 (ESP32)
SN74LVC14A VCC3.3V rail
LCD SDAGPIO21
LCD SCLGPIO22
LCD VCC3.3V or 5V (check your I2C backpack)
Reset buttonGPIO25 → GND (internal pull-up)

8. Results & Accuracy

Device in use — display showing measurement

After calibration using the actual printed wheel diameter (49.3mm), the device measures to within ±2mm over a 5-metre pull — well within the requirements for cable management and filament estimation tasks.

The TPU wheel provides reliable grip on PVC cable jacket, braided cable, and 3D printer filament. On very smooth or thin wire (below ~1mm diameter), some slippage occurs — a spring-loaded pressure arm would solve this for precision applications.

The complete MicroPython firmware, STEP files for the enclosure and wheel, and wiring diagram are included in the downloadable package available at 3DIY.ie/shop.

9. Replicating This Project

The total component cost for this build is approximately €31–61 if purchasing everything new. The encoder is the most significant single cost — any optical incremental encoder with the following specifications will work:

Good options at reasonable cost:

If you use a 3.3V-native encoder, you can skip the SN74LVC14A entirely and connect directly to ESP32 GPIO. This simplifies the wiring and reduces component count.

10. Get the Files

All design files for this project are available on 3DIY.ie:

Files are in STEP format — compatible with SolidWorks, Fusion 360, FreeCAD, and most modern CAD tools. You can print the parts yourself or order a ready-made printed set from the shop.

Get the files on 3DIY.ie/shop →

Ilia Kuzmin — Senior Service Engineer & Founder, 3DIY.ie
Celbridge, Co. Kildare, Ireland · 3diy.ie · Custom 3D Printing & Engineering Repair Services