Solution for Analyzing link budget for a medical body area network#
Constants
P_TX_DB = -30 # dB
G_TX_DB = 2
G_RX_DB = 3
L_MISC_DB = 6
FLOOR_WIDTH = 100 # m
FLOOR_HEIGHT = 30
F = 2400e6 # Hz, Worst case
# We want to analyze the worst case.
# Worst case frequency is 2400 MHz because attenuation at higher frequencies is higher.
# For the thermal noise
BANDWIDTH = 2e6 # Hz
TEMPERATURE = 290 # K
# ITU indoor model
N_OFFICE_2GHZ = 30 # Office area 1.8-2 GHz
P_F_SAME_FLOOR = 0 # Same floor
DATA_RATE = 125e3 # bits
PACKET_SIZE = 32 * 8 # bits
Furthest distance from the receiver based on the diagonal of the floor
from sympy import sqrt
(distance := sqrt(FLOOR_WIDTH**2 + FLOOR_HEIGHT**2) / 2)
\[\displaystyle 5 \sqrt{109}\]
Define link budget equations in dB:
Free-space model#
from sympy import Eq, log, symbols
l_fs, d, f = symbols(r"l_\mathrm{fs} d, f")
(l_fs_eq := Eq(l_fs, 20 * log(d, 10) + 20 * log(f, 10) - 147.55))
\[\displaystyle l_\mathrm{fs} = \frac{20 \log{\left(d \right)}}{\log{\left(10 \right)}} + \frac{20 \log{\left(f \right)}}{\log{\left(10 \right)}} - 147.55\]
ITU indoor model#
l_itu, n, p_f = symbols(r"l_\mathrm{itu-indoor} n p_\mathrm{f}")
(l_itu_eq := Eq(l_itu, 20 * log(f, 10) + n * log(d, 10) + p_f - 28))
\[\displaystyle l_\mathrm{itu-indoor} = \frac{n \log{\left(d \right)}}{\log{\left(10 \right)}} + p_\mathrm{f} + \frac{20 \log{\left(f \right)}}{\log{\left(10 \right)}} - 28\]
\(p_\mathrm{rx}\)#
snr, p_tx, g_tx, l_p, g_rx, l_misc, p_rx, l_thermal = symbols(
r"""
\mathrm{snr}
p_\mathrm{tx}
g_\mathrm{tx}
l_\mathrm{p}
g_\mathrm{rx}
l_\mathrm{misc}
p_\mathrm{rx}
l_\mathrm{thermal}
"""
)
(p_rx_eq := Eq(p_rx, p_tx + g_tx - l_p + g_rx - l_misc))
\[\displaystyle p_\mathrm{rx} = g_\mathrm{rx} + g_\mathrm{tx} - l_\mathrm{misc} - l_\mathrm{p} + p_\mathrm{tx}\]
Thermal noise#
from math import log10
from scipy.constants import Boltzmann
B = 10 * log10(BANDWIDTH) # dBHz
t = 10 * log10(TEMPERATURE) # dBK
k = 10 * log10(Boltzmann) # dBW/K/Hz
(l_thermal_db := B + t + k)
-140.9648872375883
SNR#
(snr_eq := Eq(snr, p_rx - l_thermal))
\[\displaystyle \mathrm{snr} = - l_\mathrm{thermal} + p_\mathrm{rx}\]
Substitution and numeric evaluation free-space model#
Substitute and use \(l_\mathrm{fs}\) as \(l_\mathrm{p}\).
subs = {
p_tx: P_TX_DB,
g_tx: G_TX_DB,
d: distance,
f: F,
g_rx: G_RX_DB,
l_misc: L_MISC_DB,
l_thermal: l_thermal_db,
p_rx: p_rx_eq.rhs,
}
subs_fs = subs.copy()
subs_fs.update(
{
l_p: l_fs_eq.rhs,
}
)
\(p_\mathrm{rx}\)
(p_rx_evald := p_rx_eq.rhs.evalf(subs=subs_fs))
\[\displaystyle -105.407889900359\]
\(p_\mathrm{rx}\):
SNR
(snr_evald := snr_eq.rhs.evalf(subs=subs_fs))
\[\displaystyle 35.5569973372296\]
l_fs_eq.rhs.evalf(subs=subs_fs)
\[\displaystyle 74.4078899003587\]
import pandas as pd
def display_table(subs):
data = [
["p_tx", P_TX_DB],
["g_tx", G_TX_DB],
["l_p", -int(l_p.evalf(subs=subs))],
["g_rx", G_RX_DB],
["l_misc", -L_MISC_DB],
["p_rx", int(p_rx_evald)],
["l_thermal", int(-l_thermal_db)],
["snr", int(snr_eq.rhs.evalf(subs=subs))],
]
# TODO convert them to Latex symbols
# using `p_tx` and then wrapping with $ works in Jupyter
# but not in HTML output
df = pd.DataFrame(data)
df.columns = ["Parameter", "Value"]
return df
display_table(subs_fs)
Parameter | Value | |
---|---|---|
0 | p_tx | -30 |
1 | g_tx | 2 |
2 | l_p | -74 |
3 | g_rx | 3 |
4 | l_misc | -6 |
5 | p_rx | -105 |
6 | l_thermal | 140 |
7 | snr | 35 |
Substitution and numeric evaluation ITU model#
subs_itu = subs.copy()
subs_itu.update(
{
l_p: l_itu_eq.rhs,
n: N_OFFICE_2GHZ,
p_f: P_F_SAME_FLOOR,
}
)
display_table(subs_itu)
Parameter | Value | |
---|---|---|
0 | p_tx | -30 |
1 | g_tx | 2 |
2 | l_p | -211 |
3 | g_rx | 3 |
4 | l_misc | -6 |
5 | p_rx | -105 |
6 | l_thermal | 140 |
7 | snr | -101 |
Data rate sufficient?#
(transmitted_bits_per_second := PACKET_SIZE * 10)
2560
print("Yes" if DATA_RATE >= transmitted_bits_per_second else "No")
Yes
Battery consumption analysis#
(duty_cycle := transmitted_bits_per_second/ DATA_RATE )
0.02048
p_tx_linear = 10 ** (P_TX_DB / 10) # W
energy_for_one_week = p_tx_linear * duty_cycle * 60 * 60 * 24 * 7
print(f"Energy needed for one week: {energy_for_one_week}")
Energy needed for one week: 12.386303999999999
RECHARGABLE_AA_BATTERY_ENERGY = 1.2 * 2.5 * 60 * 60 # 1.2 V * 2500 mAh
print("2 rechargable AA batteries' energy: ", 2 * RECHARGABLE_AA_BATTERY_ENERGY)
2 rechargable AA batteries' energy: 21600.0
print("Two AA sufficient?")
print("Yes" if 2 * RECHARGABLE_AA_BATTERY_ENERGY > energy_for_one_week else "No")
Two AA sufficient?
Yes
Is the modulation scheme appropriate?#
# For 10^-10 we need 14 dB @QPSK
EB_PER_N0_DB = 14 # dB
R_B = 125e3 # bit
eb_per_n0 = 10 ** (EB_PER_N0_DB / 10)
n_0 = Boltzmann * TEMPERATURE
e_b = eb_per_n0 * n_0
p_rx_ = e_b * R_B
p_rx_db_ = 10 * log(p_rx_, 10)
print(f"Minimum P_rx ~{int(p_rx_db_)} dB")
print()
Minimum P_rx ~-139 dB
print("Modulation scheme appropriate for free-space?")
print("Yes" if p_rx.evalf(subs=subs_fs) > p_rx_db_ else "No")
Modulation scheme appropriate for free-space?
Yes
print("Modulation scheme appropriate for ITU indoor?")
print("Yes" if p_rx.evalf(subs=subs_itu) > p_rx_db_ else "No")
Modulation scheme appropriate for ITU indoor?
No
Conclusions#
The device does not have enough link margin.
LOS transmission feasible, but obstructed (non-LOS) transmission not possible
Every room should have a receiver
One week runtime is not possible.
The batteries could be changed more often
The measurement frequency could be reduced.