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.
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?
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.
| Component | Details | Approx. Cost |
|---|---|---|
| Microcontroller | ESP32 38-pin DevKit | €4–8 |
| Encoder | Bourns optical incremental, 100 PPR, Quadrature (A/B), 5V. Alternative: Chinese optical encoder from AliExpress | €25–40 / ~€11 |
| Level shifter | SN74LVC14A — Schmitt Trigger, 5V-tolerant inputs, 3.3V output | €0.50–2 |
| Display | 1602 LCD with I2C backpack (PCF8574), 3.3V compatible | €2–4 |
| Wheel | eSUN Elastic TPU filament — 50mm diameter, ~15g | €1–2 |
| Housing | PLA filament — rigid enclosure, ~80g | €1–2 |
| Reset button | Momentary tactile switch | €0.20–0.50 |
| Misc | Jumper wire, M3 screws | €1–2 |
| Firmware | MicroPython — open source | Free |
| TOTAL | With AliExpress encoder / With Bourns encoder | €31–61 |
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).
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/metre | Freq @ 1 m/s |
|---|---|---|---|
| 30 | 0.236 | 4,244 c/m | ~4,244 Hz |
| 40 | 0.314 | 3,183 c/m | ~3,183 Hz |
| 50 ✓ | 0.393 | 2,546 c/m | ~2,546 Hz |
| 60 | 0.471 | 2,122 c/m | ~2,122 Hz |
| 80 | 0.628 | 1,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.


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:


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.
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.
| Signal | Connection |
|---|---|
| Encoder VCC | 5V rail |
| Encoder GND | Common GND |
| Encoder A out | SN74LVC14A input → GPIO34 (ESP32) |
| Encoder B out | SN74LVC14A input → GPIO35 (ESP32) |
| SN74LVC14A VCC | 3.3V rail |
| LCD SDA | GPIO21 |
| LCD SCL | GPIO22 |
| LCD VCC | 3.3V or 5V (check your I2C backpack) |
| Reset button | GPIO25 → GND (internal pull-up) |

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.
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.
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