Chapitre 2 — La couche physique#

La couche physique est la fondation de toute communication réseau. Elle définit comment les bits sont transformés en signaux physiques et transmis sur un support. Sans elle, aucune des couches supérieures n’existerait.

Hide code cell source

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
import pandas as pd
import seaborn as sns
sns.set_theme(style="whitegrid", palette="muted")
plt.rcParams.update({
    "figure.dpi": 120,
    "font.family": "DejaVu Sans",
    "axes.spines.top": False,
    "axes.spines.right": False,
})

Signaux analogiques et numériques#

Signal analogique#

Un signal analogique varie de façon continue dans le temps. La voix humaine, la radio FM, les signaux sur un câble téléphonique traditionnel sont analogiques. Un signal sinusoïdal est caractérisé par :

  • Amplitude A : hauteur du signal (en volts)

  • Fréquence f : nombre d’oscillations par seconde (en Hz)

  • Phase φ : décalage temporel (en radians)

\[s(t) = A \cdot \sin(2\pi f t + \varphi)\]

Signal numérique#

Un signal numérique ne prend que des valeurs discrètes (typiquement 0 et 1). Les ordinateurs et réseaux modernes travaillent en numérique. La conversion entre analogique et numérique se fait par échantillonnage (ADC) et reconstruction (DAC).

Hide code cell source

t = np.linspace(0, 0.004, 2000)
f = 1000  # 1 kHz

fig, axes = plt.subplots(2, 2, figsize=(13, 7))
fig.suptitle("Signaux analogiques et numériques", fontsize=14, fontweight="bold")

# Signal sinusoïdal pur
ax = axes[0, 0]
signal_sin = np.sin(2 * np.pi * f * t)
ax.plot(t * 1000, signal_sin, color="#e74c3c", linewidth=1.8)
ax.set_title("Signal sinusoïdal (1 kHz)")
ax.set_xlabel("Temps (ms)")
ax.set_ylabel("Amplitude (V)")
ax.set_ylim(-1.4, 1.4)

# Signal avec harmoniques (signal carré approché)
ax = axes[0, 1]
signal_carre = sum(np.sin(2 * np.pi * (2*k+1) * f * t) / (2*k+1) for k in range(10))
signal_carre /= np.max(np.abs(signal_carre))
ax.plot(t * 1000, signal_carre, color="#e67e22", linewidth=1.8)
ax.set_title("Signal carré (approximé par harmoniques)")
ax.set_xlabel("Temps (ms)")
ax.set_ylabel("Amplitude normalisée")

# Signal numérique NRZ
ax = axes[1, 0]
bits = [1, 0, 1, 1, 0, 0, 1, 0]
t_num = np.linspace(0, len(bits), len(bits) * 200)
signal_nrz = np.array([bits[min(int(x), len(bits)-1)] * 2 - 1 for x in t_num])
ax.step(t_num, signal_nrz, where="post", color="#2980b9", linewidth=2)
ax.set_title("Signal numérique NRZ")
ax.set_xlabel("Temps (symboles)")
ax.set_ylabel("Niveau (V)")
ax.set_ylim(-1.5, 1.5)
ax.set_yticks([-1, 1])
ax.set_yticklabels(["0 (−V)", "1 (+V)"])
for i, b in enumerate(bits):
    ax.text(i + 0.5, 1.25, str(b), ha="center", va="center",
            fontsize=11, fontweight="bold", color="#2980b9")

# Spectre de fréquences
ax = axes[1, 1]
freqs = np.fft.rfftfreq(len(t), t[1]-t[0])
spectre = np.abs(np.fft.rfft(signal_sin))
ax.plot(freqs / 1000, spectre, color="#27ae60", linewidth=1.5)
ax.set_title("Spectre fréquentiel du signal sinusoïdal")
ax.set_xlabel("Fréquence (kHz)")
ax.set_ylabel("Amplitude")
ax.set_xlim(0, 3)

plt.tight_layout()
plt.show()
_images/43bf3d340e956ff87c46e3f60103dc383add8217f134b22fd7643e42cae8580e.png

Bande passante#

La bande passante (bandwidth) désigne l’intervalle de fréquences qu’un canal peut transmettre sans atténuation excessive. Elle est mesurée en Hz. À ne pas confondre avec le débit (mesuré en bits/s), bien que les deux soient liés.

Bande passante ≠ Débit

La bande passante en Hz est une propriété physique du canal. Le débit en bits/s est la quantité de données transmises par seconde. La relation entre les deux est donnée par les théorèmes de Nyquist et Shannon.


Théorèmes de Nyquist et Shannon#

Théorème de Nyquist (canal sans bruit)#

Pour un canal de bande passante B et M niveaux de signal distincts :

\[D_{max} = 2B \log_2 M \quad \text{(bits/s)}\]

Exemple : Un câble téléphonique de 3 kHz avec 4 niveaux → \(D_{max} = 2 \times 3000 \times \log_2 4 = 12\,000\) bits/s.

Théorème de Shannon-Hartley (canal bruité)#

Pour un canal de bande passante B et un rapport signal/bruit (SNR) :

\[C = B \log_2\!\left(1 + \frac{S}{N}\right) \quad \text{(bits/s)}\]

C est la capacité de Shannon — limite théorique absolue du débit, indépendamment du codage.

import math

def capacite_shannon(bande_hz: float, snr_db: float) -> float:
    """Calcule la capacité de Shannon (bits/s)."""
    snr_lineaire = 10 ** (snr_db / 10)
    return bande_hz * math.log2(1 + snr_lineaire)

def debit_nyquist(bande_hz: float, niveaux: int) -> float:
    """Calcule le débit maximal de Nyquist (bits/s) sans bruit."""
    return 2 * bande_hz * math.log2(niveaux)

print("=== Théorème de Shannon ===")
exemples = [
    ("Téléphone RTC",        3_400,  30),
    ("ADSL2+",             2_208_000,  40),
    ("Wi-Fi 802.11n (40 MHz)", 40_000_000,  25),
    ("Fibre monomode (1 THz)", 1_000_000_000_000, 30),
]
for nom, bande, snr in exemples:
    c = capacite_shannon(bande, snr)
    print(f"  {nom:<35} B={bande:>15,} Hz  SNR={snr:>3} dB  → C≈{c:>15,.0f} bits/s")

print("\n=== Théorème de Nyquist ===")
for bande, niveaux, desc in [(3400, 2, "Téléphone, binaire"),
                               (3400, 4, "Téléphone, 4 niveaux"),
                               (40e6, 256, "Wi-Fi, 256-QAM")]:
    d = debit_nyquist(bande, niveaux)
    print(f"  {desc:<30} B={int(bande):>12,} Hz  M={niveaux:>4}  → D≈{d:>15,.0f} bits/s")
=== Théorème de Shannon ===
  Téléphone RTC                       B=          3,400 Hz  SNR= 30 dB  → C≈         33,889 bits/s
  ADSL2+                              B=      2,208,000 Hz  SNR= 40 dB  → C≈     29,339,587 bits/s
  Wi-Fi 802.11n (40 MHz)              B=     40,000,000 Hz  SNR= 25 dB  → C≈    332,375,010 bits/s
  Fibre monomode (1 THz)              B=1,000,000,000,000 Hz  SNR= 30 dB  → C≈9,967,226,258,836 bits/s

=== Théorème de Nyquist ===
  Téléphone, binaire             B=       3,400 Hz  M=   2  → D≈          6,800 bits/s
  Téléphone, 4 niveaux           B=       3,400 Hz  M=   4  → D≈         13,600 bits/s
  Wi-Fi, 256-QAM                 B=  40,000,000 Hz  M= 256  → D≈    640,000,000 bits/s

Hide code cell source

fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# Capacité de Shannon en fonction du SNR
ax = axes[0]
snr_range = np.linspace(0, 40, 200)
for bande, label, color in [(3400, "Téléphone 3.4 kHz", "#e74c3c"),
                              (100e3, "DSL 100 kHz",      "#e67e22"),
                              (20e6,  "Wi-Fi 20 MHz",     "#27ae60"),
                              (160e6, "Wi-Fi 160 MHz",    "#2980b9")]:
    capacites = [capacite_shannon(bande, s) / 1e6 for s in snr_range]
    ax.plot(snr_range, capacites, label=label, linewidth=2)
ax.set_xlabel("SNR (dB)")
ax.set_ylabel("Capacité (Mbit/s)")
ax.set_title("Capacité de Shannon vs SNR")
ax.legend(fontsize=8)
ax.grid(True, alpha=0.4)

# Débit Nyquist en fonction du nombre de niveaux
ax2 = axes[1]
niveaux_range = [2**n for n in range(1, 11)]  # 2, 4, 8, ..., 1024
for bande, label, color in [(3400, "3.4 kHz", "#e74c3c"),
                              (1e6,  "1 MHz",   "#27ae60"),
                              (40e6, "40 MHz",  "#2980b9")]:
    debits = [debit_nyquist(bande, m) / 1e6 for m in niveaux_range]
    ax2.semilogx(niveaux_range, debits, marker="o", label=label, linewidth=2, markersize=5)
ax2.set_xlabel("Nombre de niveaux M (échelle log)")
ax2.set_ylabel("Débit max Nyquist (Mbit/s)")
ax2.set_title("Débit Nyquist vs niveaux de signal")
ax2.legend(fontsize=9)
ax2.grid(True, alpha=0.4)

plt.tight_layout()
plt.show()
_images/c438e676891cd14bd8c57f890a0fcb47ec973edc0cd48e46dc464419798a0d5c.png

Médias de transmission#

Paire torsadée#

La paire torsadée est le média le plus répandu dans les réseaux locaux. Elle est constituée de fils de cuivre torsadés par paires pour réduire les interférences électromagnétiques (diaphonie).

Catégorie

Débit max

Portée max

Usage

Cat5e

1 Gbit/s

100 m

Ethernet 1000BASE-T

Cat6

10 Gbit/s

55 m

Ethernet 10GBASE-T

Cat6a

10 Gbit/s

100 m

Data centers

Cat8

40 Gbit/s

30 m

Data centers haute densité

Fibre optique#

La fibre optique transmet la lumière dans un fil de verre ou de plastique. Elle est immune aux interférences électromagnétiques et offre des distances bien supérieures.

Type

Cœur

Usage

Portée

Monomode (SMF)

8–10 µm

WAN, longue distance

Jusqu’à 100 km sans répéteur

Multimode OM3

50 µm

Data centers

300 m à 10 Gbit/s

Multimode OM4

50 µm

Data centers

550 m à 10 Gbit/s

La fibre monomode n’autorise qu’un seul mode de propagation de la lumière (pas de dispersion modale), ce qui permet des distances et des débits bien supérieurs.

Wi-Fi (IEEE 802.11)#

Le Wi-Fi utilise les bandes de fréquences 2.4 GHz, 5 GHz et 6 GHz. Chaque génération améliore le débit grâce à des canaux plus larges et des modulations plus efficaces.

Norme

Fréquence

Débit max théorique

Technologie

802.11g

2.4 GHz

54 Mbit/s

OFDM

802.11n (Wi-Fi 4)

2.4/5 GHz

600 Mbit/s

MIMO, canaux 40 MHz

802.11ac (Wi-Fi 5)

5 GHz

6.9 Gbit/s

MU-MIMO, 256-QAM

802.11ax (Wi-Fi 6)

2.4/5/6 GHz

9.6 Gbit/s

OFDMA, 1024-QAM


Codages en ligne#

Le codage en ligne (line coding) définit comment les bits 0 et 1 sont représentés électriquement sur le support. Un bon codage doit permettre la synchronisation, éviter les longues séquences de même symbole et faciliter la détection d’erreurs.

NRZ (Non-Return-to-Zero)#

  • NRZ-L : 1 = niveau haut, 0 = niveau bas. Simple, mais perd la synchronisation sur de longues séquences identiques.

  • NRZ-I : Transition sur 1, pas de transition sur 0. Mieux pour la synchro, mais toujours problème avec les longues séquences de 0.

Manchester#

Chaque bit contient une transition au milieu de la période : 1 = transition bas→haut, 0 = transition haut→bas. Synchronisation parfaite, mais la bande passante nécessaire est doublée. Utilisé dans l’Ethernet 10BASE-T.

4B5B#

Groupe de 4 bits encodés en 5 bits, garantissant un maximum de deux 0 consécutifs. Suivi d’un codage NRZ-I. Utilisé dans Fast Ethernet (100BASE-TX) et FDDI.

Hide code cell source

bits = [1, 0, 1, 1, 0, 0, 0, 1, 0, 1]

def nrz_signal(bits, samples=50):
    """Génère un signal NRZ-L."""
    signal = []
    for b in bits:
        signal.extend([1.0 if b == 1 else -1.0] * samples)
    return np.array(signal)

def manchester_signal(bits, samples=50):
    """Génère un signal Manchester (IEEE 802.3 : 0 = haut→bas, 1 = bas→haut)."""
    signal = []
    for b in bits:
        half = samples // 2
        if b == 1:
            signal.extend([-1.0] * half + [1.0] * (samples - half))
        else:
            signal.extend([1.0] * half + [-1.0] * (samples - half))
    return np.array(signal)

def nrzi_signal(bits, samples=50):
    """Génère un signal NRZ-I (transition sur 1)."""
    signal = []
    niveau = -1.0
    for b in bits:
        if b == 1:
            niveau = -niveau
        signal.extend([niveau] * samples)
    return np.array(signal)

samples = 60
t = np.linspace(0, len(bits), len(bits) * samples)

sig_nrz     = nrz_signal(bits, samples)
sig_nrzi    = nrzi_signal(bits, samples)
sig_manch   = manchester_signal(bits, samples)

fig, axes = plt.subplots(3, 1, figsize=(13, 8), sharex=True)
fig.suptitle("Codages en ligne pour la séquence : " + "".join(map(str, bits)),
             fontsize=13, fontweight="bold")

for ax, signal, title, color in zip(
        axes,
        [sig_nrz, sig_nrzi, sig_manch],
        ["NRZ-L (Non-Return-to-Zero Level)",
         "NRZ-I (Non-Return-to-Zero Inverted)",
         "Manchester (IEEE 802.3)"],
        ["#e74c3c", "#2980b9", "#27ae60"]):
    ax.step(t, signal, where="post", color=color, linewidth=2)
    ax.set_ylim(-1.6, 1.8)
    ax.set_yticks([-1, 1])
    ax.set_yticklabels(["0 (−V)", "1 (+V)"])
    ax.set_ylabel("Niveau")
    ax.set_title(title, fontsize=10, fontweight="bold", color=color)
    ax.axhline(0, color="#cccccc", linewidth=0.8, linestyle="--")
    # Affiche les bits
    for i, b in enumerate(bits):
        ax.text(i + 0.5, 1.5, str(b), ha="center", va="center",
                fontsize=11, fontweight="bold", color=color)
    # Lignes verticales de délimitation
    for i in range(len(bits) + 1):
        ax.axvline(i, color="#cccccc", linewidth=0.8, linestyle=":")

axes[-1].set_xlabel("Temps (symboles)")
plt.tight_layout()
plt.show()
_images/95a7c51a3e8b37135c266f5a3fc8882dc739ba55ad0d28448bc1d90ba301b89e.png

Modulation#

La modulation permet de transposer un signal numérique sur une porteuse analogique pour la transmission sur des supports radio ou optiques.

Modulations de base#

AM (Amplitude Modulation) : L’amplitude de la porteuse varie selon le signal.

FM (Frequency Modulation) : La fréquence varie selon le signal. Plus robuste aux perturbations d’amplitude.

PM (Phase Modulation) : La phase de la porteuse varie.

QAM (Quadrature Amplitude Modulation)#

La QAM combine modulation d’amplitude et de phase. Un symbole QAM encode plusieurs bits simultanément en choisissant un point dans un espace 2D (constellation). En 16-QAM, chaque symbole encode 4 bits (16 points). En 256-QAM, 8 bits par symbole.

OFDM (Orthogonal Frequency Division Multiplexing)#

Utilisé dans Wi-Fi (802.11a/g/n/ac/ax), 4G (LTE) et 5G, OFDM divise le canal en de nombreuses sous-porteuses orthogonales de faible débit. Avantages :

  • Résistance aux évanouissements sélectifs en fréquence

  • Bonne efficacité spectrale

  • Facile à égaliser avec une FFT

Hide code cell source

fig, axes = plt.subplots(2, 2, figsize=(13, 10))
fig.suptitle("Modulations numériques", fontsize=14, fontweight="bold")

t_mod = np.linspace(0, 2e-6, 2000)
fc = 5e6  # porteuse 5 MHz

# ---- ASK (Amplitude Shift Keying) ----
ax = axes[0, 0]
bits_demo = [1, 0, 1, 1, 0]
t_ask = np.linspace(0, len(bits_demo), len(bits_demo) * 200)
porteuse = np.sin(2 * np.pi * 5 * t_ask)  # 5 cycles par symbole
amp = np.array([bits_demo[min(int(x), len(bits_demo)-1)] for x in t_ask], dtype=float)
ax.plot(t_ask, amp * porteuse, color="#e74c3c", linewidth=1.2)
ax.set_title("ASK — Amplitude Shift Keying")
ax.set_xlabel("Temps (symboles)")
ax.set_ylabel("Signal")
for i, b in enumerate(bits_demo):
    ax.text(i + 0.5, 1.2, str(b), ha="center", fontsize=11, fontweight="bold", color="#e74c3c")

# ---- FSK (Frequency Shift Keying) ----
ax = axes[0, 1]
signal_fsk = []
for b in bits_demo:
    freq = 8 if b == 1 else 3  # fréquences différentes selon le bit
    t_sym = np.linspace(0, 1, 200)
    signal_fsk.extend(np.sin(2 * np.pi * freq * t_sym))
t_fsk = np.linspace(0, len(bits_demo), len(bits_demo) * 200)
ax.plot(t_fsk, signal_fsk, color="#2980b9", linewidth=1.2)
ax.set_title("FSK — Frequency Shift Keying")
ax.set_xlabel("Temps (symboles)")
ax.set_ylabel("Signal")
for i, b in enumerate(bits_demo):
    ax.text(i + 0.5, 1.2, str(b), ha="center", fontsize=11, fontweight="bold", color="#2980b9")

# ---- Constellation 16-QAM ----
ax = axes[1, 0]
n_points = 16
gray_code = []
for i in range(4):
    for j in range(4):
        # Mappage Gray 2D
        gi = i ^ (i >> 1)
        gj = j ^ (j >> 1)
        gray_code.append((gi, gj))

levels = [-3, -1, 1, 3]
for code, (ci, cj) in zip(range(16), [(levels[g[0]], levels[g[1]]) for g in gray_code]):
    ax.scatter(ci, cj, color="#e74c3c", s=80, zorder=3)
    ax.text(ci + 0.15, cj + 0.15,
            f"{code:04b}", fontsize=7, color="#333333")

ax.axhline(0, color="#cccccc", linewidth=0.8)
ax.axvline(0, color="#cccccc", linewidth=0.8)
ax.set_xlim(-4.5, 4.5)
ax.set_ylim(-4.5, 4.5)
ax.set_title("Constellation 16-QAM (4 bits/symbole)")
ax.set_xlabel("Composante I (en phase)")
ax.set_ylabel("Composante Q (quadrature)")
ax.set_aspect("equal")
ax.grid(True, alpha=0.3)

# ---- Constellation 64-QAM ----
ax = axes[1, 1]
levels8 = np.arange(-7, 8, 2)  # -7, -5, -3, -1, 1, 3, 5, 7
for i in levels8:
    for j in levels8:
        ax.scatter(i, j, color="#27ae60", s=30, zorder=3, alpha=0.8)

ax.axhline(0, color="#cccccc", linewidth=0.8)
ax.axvline(0, color="#cccccc", linewidth=0.8)
ax.set_xlim(-9, 9)
ax.set_ylim(-9, 9)
ax.set_title("Constellation 64-QAM (6 bits/symbole)")
ax.set_xlabel("Composante I")
ax.set_ylabel("Composante Q")
ax.set_aspect("equal")
ax.grid(True, alpha=0.3)
# Cercles de bruit simulé
rng = np.random.default_rng(42)
for i in levels8:
    for j in levels8:
        bruit = rng.normal(0, 0.3, (20, 2))
        ax.scatter(i + bruit[:, 0], j + bruit[:, 1],
                   color="#27ae60", s=5, alpha=0.15, zorder=2)

plt.tight_layout()
plt.show()
_images/eb7e755f5c6d242fcb007af7145a4a6add95310048858496cf9bc6b7f4b7ce18.png

OFDM visualisé#

Hide code cell source

fig, axes = plt.subplots(2, 1, figsize=(13, 8))
fig.suptitle("OFDM — Multiplexage par répartition en fréquences orthogonales", fontsize=13, fontweight="bold")

t_ofdm = np.linspace(0, 1, 1000)
n_subcarriers = 8
freqs_sub = np.arange(1, n_subcarriers + 1)
couleurs = plt.cm.tab10(np.linspace(0, 1, n_subcarriers))

# Sous-porteuses individuelles
ax = axes[0]
signal_total = np.zeros_like(t_ofdm)
for f_sub, color in zip(freqs_sub, couleurs):
    amp = np.random.choice([-1, 1])  # BPSK simple
    s = amp * np.cos(2 * np.pi * f_sub * t_ofdm)
    ax.plot(t_ofdm, s + f_sub * 2.5, color=color, linewidth=1.2, alpha=0.8)
    signal_total += s
ax.set_title(f"8 sous-porteuses OFDM individuelles (f₁ à f₈)")
ax.set_ylabel("Fréquence (offset)")
ax.set_xlabel("Temps")
ax.set_yticks(freqs_sub * 2.5)
ax.set_yticklabels([f"f{i}" for i in freqs_sub], fontsize=8)

# Signal OFDM composite
ax2 = axes[1]
ax2.plot(t_ofdm, signal_total, color="#8e44ad", linewidth=1.5)
ax2.fill_between(t_ofdm, signal_total, alpha=0.15, color="#8e44ad")
ax2.set_title("Signal OFDM composite (somme des 8 sous-porteuses)")
ax2.set_xlabel("Temps")
ax2.set_ylabel("Amplitude")

plt.tight_layout()
plt.show()
_images/0d06f322f1ba9c304e8c5add80804114efb494c056ee24f7f73c71017228fe46.png

Calculs de débit : exemples pratiques#

import math

print("=" * 65)
print("Calculs de débit — Théorèmes de Nyquist et Shannon")
print("=" * 65)

scenarios = [
    {
        "nom": "Câble téléphonique (POTS)",
        "bande_hz": 3400,
        "snr_db": 38,
        "niveaux_nyquist": 8,
        "description": "Ligne téléphonique classique 300–3400 Hz",
    },
    {
        "nom": "ADSL2+",
        "bande_hz": 2_208_000,
        "snr_db": 40,
        "niveaux_nyquist": 512,
        "description": "ADSL2+ montée en débit, bande 138 kHz – 2.2 MHz",
    },
    {
        "nom": "Wi-Fi 802.11n canal 40 MHz",
        "bande_hz": 40_000_000,
        "snr_db": 30,
        "niveaux_nyquist": 64,
        "description": "OFDM, 64-QAM, canal 40 MHz",
    },
    {
        "nom": "Wi-Fi 6 (802.11ax) 160 MHz",
        "bande_hz": 160_000_000,
        "snr_db": 35,
        "niveaux_nyquist": 1024,
        "description": "1024-QAM, canal 160 MHz, 8 flux MIMO",
    },
    {
        "nom": "5G NR mmWave (800 MHz)",
        "bande_hz": 800_000_000,
        "snr_db": 20,
        "niveaux_nyquist": 256,
        "description": "5G millimétrique, canal de 800 MHz",
    },
]

for s in scenarios:
    c_shannon = s["bande_hz"] * math.log2(1 + 10**(s["snr_db"] / 10))
    c_nyquist = 2 * s["bande_hz"] * math.log2(s["niveaux_nyquist"])
    print(f"\n{'─'*65}")
    print(f"  {s['nom']}")
    print(f"  {s['description']}")
    print(f"  Bande passante   : {s['bande_hz']:>15,} Hz")
    print(f"  SNR              : {s['snr_db']:>15} dB")
    print(f"  → Shannon  Cmax  : {c_shannon:>15,.0f} bits/s  ({c_shannon/1e6:.1f} Mbit/s)")
    print(f"  → Nyquist  Dmax  : {c_nyquist:>15,.0f} bits/s  ({c_nyquist/1e6:.1f} Mbit/s)")
    print(f"  Facteur limitant : {'Shannon (bruit)' if c_shannon < c_nyquist else 'Nyquist (niveaux)'}")
=================================================================
Calculs de débit — Théorèmes de Nyquist et Shannon
=================================================================

─────────────────────────────────────────────────────────────────
  Câble téléphonique (POTS)
  Ligne téléphonique classique 300–3400 Hz
  Bande passante   :           3,400 Hz
  SNR              :              38 dB
  → Shannon  Cmax  :          42,920 bits/s  (0.0 Mbit/s)
  → Nyquist  Dmax  :          20,400 bits/s  (0.0 Mbit/s)
  Facteur limitant : Nyquist (niveaux)

─────────────────────────────────────────────────────────────────
  ADSL2+
  ADSL2+ montée en débit, bande 138 kHz – 2.2 MHz
  Bande passante   :       2,208,000 Hz
  SNR              :              40 dB
  → Shannon  Cmax  :      29,339,587 bits/s  (29.3 Mbit/s)
  → Nyquist  Dmax  :      39,744,000 bits/s  (39.7 Mbit/s)
  Facteur limitant : Shannon (bruit)

─────────────────────────────────────────────────────────────────
  Wi-Fi 802.11n canal 40 MHz
  OFDM, 64-QAM, canal 40 MHz
  Bande passante   :      40,000,000 Hz
  SNR              :              30 dB
  → Shannon  Cmax  :     398,689,050 bits/s  (398.7 Mbit/s)
  → Nyquist  Dmax  :     480,000,000 bits/s  (480.0 Mbit/s)
  Facteur limitant : Shannon (bruit)

─────────────────────────────────────────────────────────────────
  Wi-Fi 6 (802.11ax) 160 MHz
  1024-QAM, canal 160 MHz, 8 flux MIMO
  Bande passante   :     160,000,000 Hz
  SNR              :              35 dB
  → Shannon  Cmax  :   1,860,352,717 bits/s  (1860.4 Mbit/s)
  → Nyquist  Dmax  :   3,200,000,000 bits/s  (3200.0 Mbit/s)
  Facteur limitant : Shannon (bruit)

─────────────────────────────────────────────────────────────────
  5G NR mmWave (800 MHz)
  5G millimétrique, canal de 800 MHz
  Bande passante   :     800,000,000 Hz
  SNR              :              20 dB
  → Shannon  Cmax  :   5,326,569,186 bits/s  (5326.6 Mbit/s)
  → Nyquist  Dmax  :  12,800,000,000 bits/s  (12800.0 Mbit/s)
  Facteur limitant : Shannon (bruit)

Hide code cell source

# Graphique comparatif des débits théoriques
fig, ax = plt.subplots(figsize=(11, 6))

noms = [s["nom"] for s in scenarios]
shannon_vals = [s["bande_hz"] * math.log2(1 + 10**(s["snr_db"] / 10)) / 1e6 for s in scenarios]
nyquist_vals = [2 * s["bande_hz"] * math.log2(s["niveaux_nyquist"]) / 1e6 for s in scenarios]

x = np.arange(len(noms))
width = 0.35
bars1 = ax.bar(x - width/2, shannon_vals, width, label="Shannon Cmax", color="#2980b9", alpha=0.85)
bars2 = ax.bar(x + width/2, nyquist_vals, width, label="Nyquist Dmax", color="#e74c3c", alpha=0.85)

for bar, val in zip(bars1, shannon_vals):
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5,
            f"{val:.0f}", ha="center", va="bottom", fontsize=8, color="#2980b9")
for bar, val in zip(bars2, nyquist_vals):
    ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5,
            f"{val:.0f}", ha="center", va="bottom", fontsize=8, color="#e74c3c")

ax.set_yscale("log")
ax.set_ylabel("Débit (Mbit/s) — échelle log")
ax.set_title("Comparaison des débits théoriques (Nyquist vs Shannon)", fontsize=12, fontweight="bold")
ax.set_xticks(x)
ax.set_xticklabels(noms, rotation=20, ha="right", fontsize=9)
ax.legend()
ax.grid(True, axis="y", alpha=0.4)
plt.tight_layout()
plt.show()
_images/7acc6705c6b0a0e20a0fa9e0b7982fcf49440e81f4c0275d43519cdb0c1a113a.png

Résumé#

Points clés du chapitre 2

  • Un signal analogique varie continûment ; un signal numérique prend des valeurs discrètes.

  • Le théorème de Nyquist donne le débit max en l’absence de bruit ; Shannon tient compte du bruit (SNR).

  • La paire torsadée (Cat5e–Cat8) couvre jusqu’à 100 m à 1–40 Gbit/s ; la fibre optique couvre des dizaines de kilomètres.

  • Les codages en ligne (NRZ, Manchester, 4B5B) définissent comment les bits sont représentés électriquement.

  • La modulation QAM encode plusieurs bits par symbole (16-QAM = 4 bits, 256-QAM = 8 bits).

  • L”OFDM divise le canal en nombreuses sous-porteuses orthogonales pour résister aux interférences sélectives en fréquence.

Technologie

Débit réel

Portée

Fréquence / Média

Cat5e (1GbE)

1 Gbit/s

100 m

Cuivre, paires torsadées

Cat6a (10GbE)

10 Gbit/s

100 m

Cuivre, paires torsadées

Fibre OM4

25 Gbit/s

400 m

Verre, multimode

Fibre SMF

100 Gbit/s+

> 80 km

Verre, monomode

Wi-Fi 6 (2×2)

~1.2 Gbit/s

~50 m intérieur

5/6 GHz, OFDMA

5G mmWave

~4 Gbit/s

< 500 m

26–40 GHz, OFDM