How long can quarter-wavelength stubs on PCBs actually be?

Using a quarter-wavelength stub length as the maximum length for stubs on PCBs is a common rule of thumb in RF design. But how long can these stubs actually be across different frequencies and PCB materials?

This helpful chart allows you to decide instantly:

Quarter Wavelength Stub Length.svg

Code to generate this plot

We use UliEngineering to calculate the propagation speed in different PCB materials based on their relative permittivity (epsilon r), and matplotlib to create the plot:

Plot-Quarter-Wavelength-Stub-Length.py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter, LogLocator

# UliEngineering imports
from UliEngineering.Electronics.PropagationSpeed import propagation_speed
from UliEngineering.EngineerIO import format_value

# Fixed mu_r, typically 1.0 for non-magnetic materials
mu_r = 1.0

# Epsilo_r range - https://techoverflow.net/2025/11/18/relative-permittivity-epsilon-r-of-different-pcb-materials-collection/
ers = [2.14, 4.2, 4.8]
er_labels = [r"Ultra-low $\epsilon_r$ PFTE laminate", "Aluminium PCB", "Standard FR4 PCB"]

# Frequency axis: 10 MHz to 10 GHz
frequencies = np.logspace(np.log10(10e6), np.log10(10e9), num=500)

# Plotting
plt.style.use("ggplot")
fig, ax = plt.subplots(figsize=(10, 12))

# Generate colors
colors = plt.cm.viridis(np.linspace(0, 1, len(ers)))

for er, c in zip(ers, colors):
    v = propagation_speed(er, mu_r)  # propagation speed in m/s
    lengths = v / (4.0 * frequencies)  # quarter-wavelength in meters
    ax.loglog(frequencies, lengths, color=c, lw=2, label=rf"$\epsilon_r={er:.1f}$ - " + er_labels[ers.index(er)])

# Add a legend containing epsilon_r (LaTeX)
legend = ax.legend(loc='upper right', fontsize='small')

ax.set_xlabel("Frequency")
ax.set_ylabel("λ/4 length")
ax.set_title("λ/4 stub length vs Frequency")
ax.grid(True, which="both", ls="--")

# Axis formatters using EngineerIO format_value
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: format_value(x, "Hz")))
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, pos: format_value(y, "m")))
# Enable minor ticks and add minor tick labels on the Y axis
ax.minorticks_on()
# For log scale axes, make sure minor locators are set so minor ticks show up properly
ax.yaxis.set_minor_locator(LogLocator(base=10.0, subs=(2,3,4,5,6,7,8,9)))
ax.yaxis.set_minor_formatter(FuncFormatter(lambda y, pos: format_value(y, "m")))
# Style minor tick labels: 30% smaller and 70% gray
maj_ylabels = ax.yaxis.get_ticklabels(which='major')
if len(maj_ylabels) > 0:
    base_size = maj_ylabels[0].get_size()
else:
    base_size = plt.rcParams.get('ytick.labelsize', plt.rcParams.get('font.size', 10))
ax.tick_params(axis='y', which='minor', labelsize=base_size * 0.7, labelcolor='0.7', colors='0.7')
# Also set x-axis minor ticks and style them with smaller rotated labels
ax.xaxis.set_minor_locator(LogLocator(base=10.0, subs=(2,3,4,5,6,7,8,9)))
ax.xaxis.set_minor_formatter(FuncFormatter(lambda x, pos: format_value(x, "Hz")))
maj_xlabels = ax.xaxis.get_ticklabels(which='major')
if len(maj_xlabels) > 0:
    base_x_size = maj_xlabels[0].get_size()
else:
    base_x_size = plt.rcParams.get('xtick.labelsize', plt.rcParams.get('font.size', 10))
ax.tick_params(axis='x', which='minor', labelsize=base_x_size * 0.7, labelcolor='0.7', colors='0.7')
for tl in ax.get_xminorticklabels():
    tl.set_rotation(90)
for tl in ax.get_xmajorticklabels():
    tl.set_rotation(90)

fig.tight_layout()
plt.savefig("Quarter-Wavelength-Stub-Length.svg")

Check out similar posts by category: Electronics, Python