Beginner · Lesson 3 of 10

Decibels and link budgets

Decibel arithmetic in dB, dBm, dBW and dBi, the Friis transmission equation, free-space path loss checked against ITU-R P.525, and a link budget calculator in numpy

Beginner40 minUpdated 15 Nov 2026Free until 31 Jan 2027

You will learn

  • Convert between watts, dBm and dBW, and combine gains, losses and powers correctly in dB
  • Derive free-space path loss from the Friis transmission equation and match ITU-R P.525 to within 0.05 dB
  • Build a link budget from transmit power, antenna gains, losses and receiver sensitivity and compute the link margin
  • Find the maximum range of a free-space link for a required fade margin

Before this: Complex baseband and IQ samples

A link budget answers one question: does enough power reach the receiver? It adds up every gain and loss between the transmitter’s output and the receiver’s input and compares the result with what the receiver needs. Every radio design starts with one, from a sensor node to a satellite. This lesson covers the decibel arithmetic that makes the sums easy, derives free-space path loss from the Friis transmission equation, checks it against the ITU-R formula, and ends with a small link budget calculator in numpy.

Lesson 01 introduced decibels. Here they get used in earnest.

Decibel arithmetic

A decibel is a ratio of two powers on a log scale: 10 log10(P2 / P1). Because it is a ratio, a bare dB value describes a gain or a loss, never a power. An amplifier has 20 dB of gain. A cable has 3 dB of loss.

An absolute power needs a reference, and the unit names it:

Unit Reference 0 in this unit equals Typical use
dBm 1 mW 1 mW transmit and received power
dBW 1 W 1 W, which is 30 dBm high-power transmitters, satellite EIRP
dBi isotropic antenna gain of an ideal isotropic radiator antenna gain
dB none (a ratio) a factor of 1 gains, losses, SNR

dBm and dBW differ by a constant 30 dB. dBi is antenna gain relative to an antenna that radiates the same power in every direction. No real antenna does that, but the isotropic antenna is the reference that free-space loss formulas assume.

The rules follow from the logarithm. Multiplying powers by gains becomes adding dB. A power in dBm plus a gain in dB is a power in dBm. A power in dBm minus another power in dBm is a ratio in dB, such as a signal-to-noise ratio. What you cannot do is add two powers in dBm. Two signals add in watts, so convert, add and convert back.

import numpy as np

def watts_to_dbm(p_w: float) -> float:
    return 10 * np.log10(p_w / 1e-3)

def dbm_to_watts(p_dbm: float) -> float:
    return 1e-3 * 10 ** (p_dbm / 10)

for p in [1e-12, 1e-6, 1e-3, 0.1, 1.0, 20.0]:
    print(f"{p:8.0e} W = {watts_to_dbm(p):7.1f} dBm = {watts_to_dbm(p) - 30:7.1f} dBW")

# Gains and losses add in dB, but powers must be added in watts
print(f"2x power:  {10 * np.log10(2):.2f} dB")
print(f"0 dBm + 0 dBm (two equal signals) = {watts_to_dbm(2 * dbm_to_watts(0)):.2f} dBm")
print(f"20 dBm + 10 dBm = {watts_to_dbm(dbm_to_watts(20) + dbm_to_watts(10)):.2f} dBm")
   1e-12 W =   -90.0 dBm =  -120.0 dBW
   1e-06 W =   -30.0 dBm =   -60.0 dBW
   1e-03 W =     0.0 dBm =   -30.0 dBW
   1e-01 W =    20.0 dBm =   -10.0 dBW
   1e+00 W =    30.0 dBm =     0.0 dBW
   2e+01 W =    43.0 dBm =    13.0 dBW
2x power:  3.01 dB
0 dBm + 0 dBm (two equal signals) = 3.01 dBm
20 dBm + 10 dBm = 20.41 dBm

A picowatt is −90 dBm, which is a typical order for a received signal. Two equal signals add to 3.01 dB more than either alone. A 10 dBm signal added to a 20 dBm signal raises the total by only 0.41 dB, because it carries a tenth of the power. That last result matters when you add interference to a noise floor: a source 10 dB below the floor raises it by about 0.4 dB.

The Friis transmission equation

Picture a transmitter radiating power Pt equally in all directions. At distance d that power is spread over a sphere of area 4πd², so the power flux density is Pt / (4πd²) watts per square metre. A receiving antenna captures the flux that falls on its effective aperture. Recommendation ITU-R P.525-5 gives the effective aperture of an isotropic receiving antenna as λ²/(4π), where λ is the wavelength. Multiply the two:

Pr = Pt · 1/(4π d²) · λ²/(4π) = Pt · (λ / (4π d))²

Real antennas focus power. An antenna with gain Gt sends Gt times more power in its best direction than the isotropic antenna would. A receive antenna with gain Gr has Gr times the effective aperture. Including both gives the Friis transmission equation, named after Harald Friis, who published it in 1946:

Pr = Pt · Gt · Gr · (λ / (4π d))²

In decibels, the products become sums:

Pr (dBm) = Pt (dBm) + Gt (dBi) + Gr (dBi) − FSPL (dB)
FSPL     = 20 log10(4π d / λ)

FSPL is free-space path loss, the loss between two isotropic antennas. P.525-5 calls it the free-space basic transmission loss and gives the same expression as its equation (5). Its equation (6) writes it in practical units, with f in MHz and d in km:

Lbf = 32.4 + 20 log10(f) + 20 log10(d)    dB

The constant 32.4 is 20 log10(4π · 10⁹ / c), rounded. The next block computes path loss both ways for five frequencies and three distances and reports the largest difference.

import numpy as np

C = 299_792_458.0                # speed of light, m/s (exact by definition)

def fspl_db(f_hz: float, d_m: float) -> float:
    """Free-space path loss between isotropic antennas, from the Friis equation."""
    wavelength = C / f_hz
    return 20 * np.log10(4 * np.pi * d_m / wavelength)

def fspl_p525_db(f_mhz: float, d_km: float) -> float:
    """ITU-R P.525-5 equation (6): f in MHz, d in km."""
    return 32.4 + 20 * np.log10(f_mhz) + 20 * np.log10(d_km)

print(f"exact constant: {20 * np.log10(4 * np.pi * 1e6 * 1e3 / C):.4f} dB")
worst = 0.0
for f_mhz in [433.92, 868.0, 2450.0, 3500.0, 28000.0]:
    for d_km in [0.01, 1.0, 10.0]:
        a, b = fspl_db(f_mhz * 1e6, d_km * 1e3), fspl_p525_db(f_mhz, d_km)
        worst = max(worst, abs(a - b))
        if d_km == 1.0:
            print(f"{f_mhz:8.2f} MHz, 1 km: Friis {a:6.2f} dB, P.525 {b:6.2f} dB")
print(f"largest difference over the grid: {worst:.3f} dB")
print(f"doubling distance adds {fspl_db(2.45e9, 200) - fspl_db(2.45e9, 100):.2f} dB")
exact constant: 32.4478 dB
  433.92 MHz, 1 km: Friis  85.20 dB, P.525  85.15 dB
  868.00 MHz, 1 km: Friis  91.22 dB, P.525  91.17 dB
 2450.00 MHz, 1 km: Friis 100.23 dB, P.525 100.18 dB
 3500.00 MHz, 1 km: Friis 103.33 dB, P.525 103.28 dB
28000.00 MHz, 1 km: Friis 121.39 dB, P.525 121.34 dB
largest difference over the grid: 0.048 dB
doubling distance adds 6.02 dB

The exact constant is 32.4478 dB, so the P.525 shortcut reads 0.048 dB low everywhere. That is well inside the uncertainty of any real link budget. Doubling the distance adds 6.02 dB, and a tenfold increase adds 20 dB. See also the antennas and propagation formula sheet.

Why path loss rises with frequency

The λ² in the effective aperture is the whole story. At a higher frequency an antenna of fixed gain is physically smaller and intercepts less of the passing wave. The power density at distance d does not depend on frequency at all. If you hold the antenna’s physical area fixed instead of its gain, its gain rises with frequency, and at both ends of the link this more than cancels the 20 log10(f) term. That is how millimetre-wave links close: with high-gain antennas, which must then be pointed.

A link budget is a table. Start with transmitter output power. Add or subtract each item on the way to the receiver’s input. Compare the result with the receiver’s sensitivity. The difference is the link margin.

The items, in order:

  1. Transmit power at the radio’s output, in dBm.
  2. Cable and connector loss on the transmit side, in dB.
  3. Transmit antenna gain, in dBi. Items 1 to 3 combine into the EIRP, the effective isotropic radiated power. Compare it with any radiated-power limit that applies in your band and country.
  4. Path loss, in dB. Free-space loss is the floor. Real paths add obstruction, foliage and building losses.
  5. Other losses: polarisation mismatch, body loss for a handheld device, a radome, a margin for ageing.
  6. Receive antenna gain, in dBi, and receive cable loss, in dB.
  7. Receiver sensitivity, in dBm: the weakest signal at which the receiver still meets its error-rate target. Lesson 04 shows where it comes from.

The margin is what is left after the last line. It has to cover what the budget does not model, above all fading. In a Rayleigh fading channel, which lesson 07 covers, the received power is more than 10 dB below its average about 10 % of the time and more than 20 dB below it about 1 % of the time. A budget that closes with 1 dB of margin will fail in practice.

The calculator below holds a 2.45 GHz point-to-point link. The numbers are design assumptions for a teaching example, not the specification of any product. It computes EIRP and received power, then inverts the free-space formula to find the longest distance that still leaves a 10 dB fade margin.

import numpy as np

C = 299_792_458.0                # speed of light, m/s

def fspl_db(f_hz: float, d_m: np.ndarray) -> np.ndarray:
    return 20 * np.log10(4 * np.pi * d_m * f_hz / C)

# An example 2.45 GHz point-to-point link. All values are design assumptions.
link = {
    "tx_power_dbm": 20.0,        # transmitter output
    "tx_cable_loss_db": 1.0,
    "tx_antenna_gain_dbi": 6.0,
    "rx_antenna_gain_dbi": 6.0,
    "rx_cable_loss_db": 1.0,
    "other_losses_db": 3.0,      # polarisation mismatch, body loss, ageing
    "sensitivity_dbm": -92.0,    # receiver sensitivity at the chosen data rate
    "fade_margin_db": 10.0,      # what we want left over
}
f_hz = 2.45e9

eirp_dbm = link["tx_power_dbm"] - link["tx_cable_loss_db"] + link["tx_antenna_gain_dbi"]

def rx_power_dbm(d_m: np.ndarray) -> np.ndarray:
    return (eirp_dbm - fspl_db(f_hz, d_m) - link["other_losses_db"]
            + link["rx_antenna_gain_dbi"] - link["rx_cable_loss_db"])

# Largest path loss that still leaves the fade margin, then the matching distance
max_loss_db = (eirp_dbm - link["other_losses_db"] + link["rx_antenna_gain_dbi"]
               - link["rx_cable_loss_db"] - link["sensitivity_dbm"] - link["fade_margin_db"])
d_max_m = C / (4 * np.pi * f_hz) * 10 ** (max_loss_db / 20)

print(f"EIRP: {eirp_dbm:.1f} dBm")
print(f"allowed free-space loss: {max_loss_db:.1f} dB")
print(f"range with {link['fade_margin_db']:.0f} dB margin: {d_max_m / 1e3:.2f} km")
for d in [100.0, 1000.0, 5000.0]:
    p = rx_power_dbm(np.array(d))
    print(f"at {d / 1e3:5.1f} km: received {p:6.1f} dBm, margin {p - link['sensitivity_dbm']:5.1f} dB")

d_grid = np.logspace(1, 5, 17)   # 10 m to 100 km
print("chart:", ", ".join(f"[{d:.0f}, {p:.1f}]" for d, p in zip(d_grid, rx_power_dbm(d_grid))))
EIRP: 25.0 dBm
allowed free-space loss: 109.0 dB
range with 10 dB margin: 2.74 km
at   0.1 km: received  -53.2 dBm, margin  38.8 dB
at   1.0 km: received  -73.2 dBm, margin  18.8 dB
at   5.0 km: received  -87.2 dBm, margin   4.8 dB
chart: [10, -33.2], [18, -38.2], [32, -43.2], [56, -48.2], [100, -53.2], [178, -58.2], [316, -63.2], [562, -68.2], [1000, -73.2], [1778, -78.2], [3162, -83.2], [5623, -88.2], [10000, -93.2], [17783, -98.2], [31623, -103.2], [56234, -108.2], [100000, -113.2]

The budget reads like this:

Item Value
Transmit power 20.0 dBm
Transmit cable loss −1.0 dB
Transmit antenna gain +6.0 dBi
EIRP 25.0 dBm
Other losses −3.0 dB
Receive antenna gain +6.0 dBi
Receive cable loss −1.0 dB
Sensitivity −92.0 dBm
Required fade margin 10.0 dB
Allowed free-space loss 109.0 dB
Maximum range 2.74 km

At 1 km the link has 18.8 dB of margin, comfortably more than needed. At 5 km it has 4.8 dB, which is too little to survive a deep fade. The chart shows received power against distance on a logarithmic axis. Free-space loss makes it a straight line falling 20 dB per decade, and the link works wherever the line sits above the sensitivity plus the margin.

-120-100-80-60-40101001,00010,000100,000receivedsensitivitysens. + 10 dBpower (dBm)distance (m)
Received power against distance for the example 2.45 GHz link in free space, from the code above, with the receiver sensitivity of −92 dBm and the sensitivity plus a 10 dB fade margin. The received power falls by 20 dB for every tenfold increase in distance and meets the margin line at 2.74 km.

Two habits make budgets trustworthy. Write every item with its unit, because a dBm in a dB slot is the most common error. And keep the assumptions next to the numbers, so that someone can see which line to change when the antenna or the radio changes. The decibels and link budgets cheat sheet is the quick reference for this lesson.

Changing one line at a time

The sums make trade-offs plain. Each 6 dB added anywhere in the budget doubles the free-space range. Swapping both 6 dBi antennas for 12 dBi ones adds 12 dB, which quadruples the range, but narrows the beamwidth so the antennas must be aimed. A receiver 3 dB more sensitive buys the same range as 3 dB more transmit power, usually at lower cost in battery. Halving the data rate typically improves sensitivity by about 3 dB, because the receiver can use half the bandwidth and so admits half the noise. That link between bandwidth, noise and sensitivity is the subject of the next lesson.

Exercise

  1. Convert 47 dBm to watts and to dBW. A base station radiates 47 dBm into an antenna with 17 dBi of gain and 0.5 dB of cable loss. What is its EIRP in dBm and in watts?
  2. Using fspl_db, compute the free-space loss over a 36 000 km path at 12 GHz. Compare it with the 1 km values printed above and explain the difference with one subtraction.
  3. In the calculator, replace the 2.45 GHz carrier with 868 MHz and keep everything else. How far does the 10 dB margin range move, and by what factor? Check the factor against the ratio of the two frequencies.
  4. A regulator caps the link’s EIRP at 20 dBm. Rework the budget with the same antennas. What is the new maximum range?
  5. Extend link with a 15 dB wall-penetration loss for a receiver indoors and report the new range.

Summary

  • dB is a ratio. dBm and dBW are absolute powers referenced to 1 mW and 1 W. dBi is antenna gain referenced to an isotropic antenna. Gains add in dB, but powers add in watts.
  • The Friis transmission equation, Pr = Pt Gt Gr (λ / 4πd)², gives free-space path loss as 20 log10(4πd/λ). ITU-R P.525-5 writes it as 32.4 + 20 log10(f in MHz) + 20 log10(d in km), which matches the exact formula to within 0.048 dB.
  • Free-space loss grows by 6 dB per doubling of distance and 20 dB per decade of distance or frequency. It is a lower bound on real path loss.
  • A link budget runs from transmit power through EIRP, path loss and receive gains to a received power, and compares it with sensitivity. The margin left must cover fading. The example 2.45 GHz link reaches 2.74 km with 10 dB to spare.

Further reading