36  Wireless Propagation Lab

In 60 Seconds

This practical lab teaches wireless deployment through hands-on ESP32 experiments: measure RSSI across distance and through obstacles, observe packet loss under interference, and validate link budget calculations against real-world results. Key findings: maintain RSSI above -70 dBm for reliable operation, add 15-20 dB link margin for production deployments, walls cost 3-15 dB each depending on material, and the 2.4 GHz band experiences significant interference from Wi-Fi and microwave ovens during peak hours.

36.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Classify the key factors affecting indoor vs outdoor wireless deployment and their dB-level impacts
  • Select appropriate antenna types for different IoT applications based on gain and coverage requirements
  • Evaluate engineering trade-offs in wireless system design decisions using link budget analysis
  • Measure and interpret RSSI values from Wi-Fi networks using an ESP32 microcontroller
  • Simulate packet transmission with acknowledgment and retransmission mechanisms under varying conditions
  • Correlate distance, obstacles, and interference with signal quality through hands-on experimentation
  • Diagnose wireless connectivity failures by applying site survey methodology and measurement techniques
  • Core Concept: Wireless design has to be validated twice: first with a link-budget estimate, then with real on-site measurements through walls, clutter, and interference.
  • Key Metric: Use RSSI together with receiver sensitivity and fading margin; a deployment target of RSSI above -70 dBm with 15-20 dB link margin is a strong starting point.
  • Trade-off: Lower frequencies and higher-gain antennas extend range, but they cost antenna size, bandwidth, coverage angle, or regional flexibility.
  • Protocol/Algorithm: The log-distance path-loss model plus a link-budget calculation gives the baseline prediction before field testing.
  • Deployment Consideration: Site surveys must include worst-case times, not just quiet lab conditions, because forklifts, people, Wi-Fi traffic, and doors all change the RF environment.
  • Common Pattern: Predict, measure, compare, and tune: calculate the budget, collect RSSI data, explain the gap, then adjust channel, antenna, placement, or power.
  • Performance Benchmark: Treat packet loss below 5%, RSSI better than -70 dBm, and double-digit fade margin as signs that the link is ready for production trials.

36.2 For Beginners: Wireless Propagation Lab

What is this lab about?

Imagine you’re designing a smart building system with temperature sensors. You need to answer: “Can my sensors reliably talk to the gateway?” This lab teaches you how to find out BEFORE buying equipment.

The challenge: Wireless signals are invisible. You can’t see if they’re weak or strong, blocked by walls, or fighting with other Wi-Fi networks. This lab gives you tools to “see” wireless signals through measurements.

What you’ll learn:

  1. RSSI (Received Signal Strength Indicator): Think of this like Wi-Fi bars on your phone, but with actual numbers. -40 dBm = excellent (5 bars), -80 dBm = terrible (1 bar). You’ll learn why -70 dBm is the magic threshold for IoT reliability.

  2. Distance matters: Radio signals get weaker as you move away from the source. Not linearly (like a ruler), but exponentially (like compound interest). This lab shows you the exact rate: every time you double the distance, you lose about 6-9 dB of signal.

  3. Walls are expensive: Each wall between your sensor and gateway costs signal strength. Drywall = 3-5 dB loss, concrete = 10-15 dB. Three concrete walls = 30-45 dB loss! This lab helps you budget for wall losses.

  4. Interference is real: That microwave oven? Your neighbor’s Wi-Fi? They all fight for the same 2.4 GHz airspace. This lab simulates interference so you can see how it crashes packet delivery.

  5. Link budget = signal bank account: If you start with +20 dBm transmit power and lose 80 dB through distance/walls/interference, you end up with -60 dBm at the receiver. Is that enough? This lab teaches you to calculate and verify your “signal budget.”

The practical test: You’ll use an ESP32 board (costs ~$10) to measure real Wi-Fi signals. LEDs light up showing signal quality: green = excellent, yellow = good, orange = marginal, red = too weak. You’ll walk around, press buttons to simulate interference and distance changes, and watch packet delivery success rate drop as signal weakens.

Why this matters: A wireless IoT system that works 80% of the time is useless. You need 99.9% reliability. This lab shows you the difference between “it might work” (-75 dBm, 15% packet loss) and “it definitely works” (-60 dBm, 2% packet loss). That 15 dB difference is the margin between success and failure.

Time investment: 45-60 minutes for the simulator lab, or 2-3 hours if you build it with real hardware. Either way, you’ll gain intuition about wireless propagation that textbook formulas can’t provide.

36.3 Prerequisites

Before diving into this chapter, you should be comfortable with:

Learning Progression

Beginner path (if you’re new to wireless): 1. Read Radio Wave Basics - Understand dBm and signal strength 2. Try the smartphone RSSI exercise (above) - Hands-on with familiar tech 3. Run the Wokwi simulator lab - Safe, no hardware needed 4. Study the Expected Outcomes section - Interpret results 5. Optional: Build with real ESP32 hardware

Intermediate path (if you know wireless theory): 1. Review link budget formulas from Path Loss chapter 2. Jump to Challenge 1 - Test distance vs RSSI relationship 3. Use Interactive Link Budget Calculator - Verify theoretical predictions 4. Try Challenge 2 & 3 - Explore interference and retransmissions

Advanced path (if you’re deploying IoT systems): 1. Skip to “Real-World Measurement Techniques” section 2. Apply site survey methodology to your deployment 3. Use “Common Measurement Pitfalls” as troubleshooting checklist 4. Refer to warehouse case study for deployment insights


36.4 Practical Propagation Considerations

36.4.1 Path Loss Visualization

Understand how signal strength decreases with distance through this interactive visualization:

(a)
(b)
(c)
(d)
(e)
(f)
(g)
(h)
(i)
Figure 36.1: Interactive visualization showing RSSI vs distance for different frequencies and path loss exponents
Experiment with the Controls
  • Frequency: Lower frequencies (915 MHz) have less path loss than higher frequencies (5 GHz)
  • Path Loss Exponent: Indoor environments (n=3-4) have more obstacles than outdoor (n=2-2.5)
  • TX Power: Higher transmit power extends the distance before signal becomes unusable

36.4.2 Indoor vs Outdoor Deployment

Indoor challenges:

  • Walls reduce signal (3-15 dB per wall)
  • Metal structures (elevators, ductwork) block signals
  • Furniture and people absorb signals
  • Multipath from reflections

Outdoor challenges:

  • Distance (requires more power or better sensitivity)
  • Weather (rain attenuation at higher frequencies)
  • Interference from other systems
  • Regulatory power limits

36.4.3 Antenna Considerations

Antenna Type Gain Pattern Best For
Chip antenna 0 dBi Omnidirectional Size-constrained devices
Dipole 2-3 dBi Omnidirectional General purpose
Monopole (whip) 2-5 dBi Omnidirectional Portable devices
Patch 6-9 dBi Directional Ceiling mount, fixed direction
Yagi 10-15 dBi Highly directional Point-to-point links
Parabolic 20-30 dBi Very narrow beam Long-range backhaul

Let’s calculate the range improvement from upgrading antenna gain.

Scenario: ESP32 sensor at 100m range with 0 dBi chip antenna. What’s the new range with 12 dBi Yagi?

Link budget with chip antenna:

  • TX power: +20 dBm
  • TX antenna: 0 dBi
  • RX antenna: +3 dBi (gateway)
  • Path loss at 100m, 2.4 GHz: 80 dB
  • Received power: \(20 + 0 + 3 - 80 = -57\) dBm

Link budget with Yagi (12 dBi):

  • Received power: \(20 + 12 + 3 - L_{path} = -57\) dBm (keep same RSSI)
  • Solve for new path loss: \(35 - L_{path} = -57\)
  • \(L_{path} = 92\) dB (was 80 dB)

Find new distance using FSPL: \(80 = 20\log_{10}(100) + 20\log_{10}(2400) + 32.45\) \(92 = 20\log_{10}(d) + 20\log_{10}(2400) + 32.45\)

Difference: \(92 - 80 = 12 = 20\log_{10}(d/100)\) \(d/100 = 10^{12/20} = 3.98\)

New range: \(100 \times 3.98 = 398\) m ≈ 400 meters

Result: 12 dB antenna gain = 4× range extension (100m → 400m)!

Antenna Gain Rule of Thumb

Every 3 dB of antenna gain doubles your effective range (or lets you halve your transmit power for the same range).

36.5 Engineering Tradeoffs

Tradeoff: Sub-GHz vs 2.4 GHz Frequency Band

Option A: Sub-GHz (868/915 MHz) - 9 dB less path loss than 2.4 GHz at same distance, excellent wall penetration, 5-15 km outdoor range, longer battery life due to fewer retransmissions. Cost: Lower data rates (0.3-50 kbps), larger antennas (8-17 cm), region-specific regulations

Option B: 2.4 GHz (Wi-Fi, BLE, Zigbee) - Higher data rates (up to 2 Mbps), smaller antennas (3 cm), global ISM band availability, mature ecosystem with commodity pricing. Cost: 50-200m typical range, poor penetration through walls, crowded spectrum with Wi-Fi/microwave interference

Decision factors: Choose sub-GHz for outdoor deployments, large facilities, or through-wall coverage (agriculture, smart city, building-wide sensors). Choose 2.4 GHz for high-bandwidth needs (cameras), small form factors (wearables), or when leveraging existing Wi-Fi infrastructure. Consider hybrid: sub-GHz for wide-area sensors, 2.4 GHz for localized high-bandwidth devices.

Tradeoff: Transmit Power vs Battery Life

Option A: Higher Transmit Power - Extended range, better link margin, more reliable connections in challenging environments. Cost: Proportionally higher power consumption, may hit regulatory limits (14 dBm EU, 30 dBm US), potential interference with nearby devices

Option B: Lower Transmit Power with Better Antennas/Sensitivity - Every 3 dB antenna gain doubles effective range without battery cost, receiver sensitivity improvements extend range. Cost: Larger/more expensive antennas, may require external antenna connectors, directional antennas limit coverage pattern

Decision factors: For battery-powered devices, invest in better antennas and sensitive receivers rather than higher transmit power. A 6 dBi antenna gain provides 4x effective range versus 0 dBi at same battery cost. For mains-powered gateways, maximize transmit power within regulatory limits. Always calculate link budget before deployment.

Tradeoff: Link Margin vs Cost

Option A: Conservative Link Margin (20-30 dB) - Reliable operation through seasonal changes, weather, vegetation growth, and interference variations. Cost: Higher transmit power or better antennas, potentially more gateway/repeater infrastructure

Option B: Aggressive Link Margin (10-15 dB) - Lower infrastructure cost, smaller devices with simpler antennas, meets requirements under ideal conditions. Cost: Intermittent connectivity during rain/snow, signal degradation as vegetation grows, vulnerability to new interference sources

Decision factors: Mission-critical applications (safety systems, medical alerts) should target 25-30 dB margin. Cost-sensitive deployments can start with 15 dB margin but must plan for remediation. Outdoor deployments need higher margins than indoor due to weather variability. Always conduct site surveys at worst-case times (peak interference, full foliage).

Tradeoff: Omnidirectional vs Directional Antennas

Option A (Omnidirectional): 360-degree coverage with 0-5 dBi gain. Simple deployment - no alignment needed. Works for mobile devices and multi-direction communication. Typical gain: Chip antenna 0 dBi, dipole 2-3 dBi, ground plane 5-6 dBi. Cost: Lower antenna cost, but may need more transmit power or shorter range.

Option B (Directional): Concentrated beam with 6-20+ dBi gain in specific direction. Yagi: 10-15 dBi, 30-60 degree beam. Parabolic: 20-30 dBi, 5-15 degree beam. Patch: 6-9 dBi, 60-90 degree beam. Benefit: Every 3 dB gain doubles effective range. Cost: Requires precise alignment, fixed installation, reduced coverage angle.

Decision Factors: Choose omnidirectional for gateways serving devices in all directions, mobile devices, or when coverage pattern is unknown. Choose directional for point-to-point links (building-to-building), extending range to specific remote areas, or reducing interference from unwanted directions. Key calculation: A 12 dBi Yagi provides 4x the range of a 0 dBi chip antenna at same transmit power - critical for reaching distant sensors without boosting power.

Tradeoff: Single High-Power Gateway vs Multiple Low-Power Gateways

Option A (Single High-Power Gateway): One gateway with maximum regulatory transmit power (14 dBm EU, 30 dBm US) and high-gain antenna (6-12 dBi). Covers 2-10 km radius depending on environment. Lower infrastructure cost. Single point of management. Downside: Single point of failure, edge devices may struggle with uplink (they have power constraints even if gateway doesn’t).

Option B (Multiple Low-Power Gateways): Distributed gateways every 1-3 km with standard antennas. Redundant coverage - if one fails, neighbors provide backup. Better uplink reliability since devices are closer. Enables location via RSSI triangulation. Cost: More infrastructure ($500-1,500 per gateway), more installation sites, more backhaul connections needed.

Decision Factors: Choose single gateway for pilot deployments, cost-constrained projects, or areas with good line-of-sight. Choose multiple gateways when 99.9%+ uptime is required, deploying in urban environments with obstacles, or when location tracking is needed. Key insight: Uplink (device to gateway) is usually the limiting factor - a powerful gateway doesn’t help if battery-powered sensors can’t transmit back. Adding gateways improves both coverage and sensor battery life by allowing lower transmit power.


36.6 Knowledge Check

Check your understanding of key propagation ideas:


36.7 Lab: Wireless Communication Fundamentals

Learning Objectives

By completing this interactive hardware lab, you will be able to:

  • Measure and interpret RSSI (Received Signal Strength Indicator) values from Wi-Fi networks
  • Visualize signal quality through LED indicators representing different RSSI thresholds
  • Simulate packet transmission with acknowledgment (ACK) and retransmission mechanisms
  • Quantify interference effects by observing packet loss under simulated interference conditions
  • Correlate distance with signal quality through simulated range scenarios
  • Analyze link budget concepts by observing how signal strength affects communication reliability
  • Implement adaptive communication based on real-time signal quality measurements

Prerequisites: Basic Arduino/C++ syntax, understanding of wireless propagation concepts from this chapter

Estimated Time: 45-60 minutes

36.7.1 What You Will Learn

This hands-on lab demonstrates the core concepts of wireless communication that were covered theoretically in this chapter:

Concept Theory Section Lab Demonstration
RSSI measurement Understanding Signal Strength Real Wi-Fi RSSI readings with LED visualization
Link quality Link Budget Packet success rate vs signal strength
Interference RF Interference Patterns Simulated interference affecting packet delivery
Fading Fading and Multipath Random signal variations and their effects
Path loss Free Space Path Loss Distance-based signal attenuation simulation

36.7.2 Components

Component Purpose Wokwi Element
ESP32 DevKit Wi-Fi-enabled microcontroller for RSSI measurement esp32:devkit-v1
Green LED Excellent signal indicator (RSSI > -50 dBm) led:green
Yellow LED Good signal indicator (-50 to -60 dBm) led:yellow
Orange LED Fair signal indicator (-60 to -70 dBm) led:orange
Red LED Poor signal indicator (< -70 dBm) led:red
Blue LED Packet transmission activity indicator led:blue
White LED Acknowledgment received indicator led:white
Push Button 1 Simulate interference burst button
Push Button 2 Simulate distance increase (weaker signal) button
Push Button 3 Send test packet / Reset statistics button
Resistors (6x 220 ohm) Current limiting for LEDs resistor

36.7.3 Interactive Wokwi Simulator

Use Wokwi in a separate tab to explore wireless communication fundamentals. This is more reliable than an embedded iframe, especially on mobile and in locked-down browsers.

Launch the Wokwi Workspace

Open the ESP32 Wokwi workspace

After Wokwi opens:

  • Add an ESP32 DevKit V1
  • Wire the LEDs and buttons using the connection table below
  • Paste the complete Arduino sketch from this lab into the editor
  • Start the simulation and use the Serial Monitor to inspect RSSI, retries, and packet-loss behavior
Simulator Tips
  • Wire first: Connect all components before pasting code
  • Paste code: Copy the complete code below into the editor
  • Run: Click the green “Play” button to compile and run
  • Serial Monitor: View detailed RSSI data, packet statistics, and link analysis
  • Buttons: Use on-screen buttons to simulate interference, distance changes, and packet transmission
  • Wi-Fi Note: In Wokwi, Wi-Fi scanning shows simulated networks; the code demonstrates RSSI concepts regardless of actual Wi-Fi connectivity

36.7.4 Circuit Connections

Wire the circuit in Wokwi before entering the code:

ESP32 Pin Connections:
----------------------
GPIO 2  --> Green LED (+)  --> 220 ohm Resistor --> GND  (Excellent signal)
GPIO 4  --> Yellow LED (+) --> 220 ohm Resistor --> GND  (Good signal)
GPIO 5  --> Orange LED (+) --> 220 ohm Resistor --> GND  (Fair signal)
GPIO 18 --> Red LED (+)    --> 220 ohm Resistor --> GND  (Poor signal)
GPIO 19 --> Blue LED (+)   --> 220 ohm Resistor --> GND  (TX activity)
GPIO 21 --> White LED (+)  --> 220 ohm Resistor --> GND  (ACK received)
GPIO 15 --> Button 1       --> GND  (Interference simulation)
GPIO 16 --> Button 2       --> GND  (Distance simulation)
GPIO 17 --> Button 3       --> GND  (Send packet / Reset)
Wireless propagation lab circuit diagram showing ESP32 with antenna and signal measurement setup
Figure 36.3: Circuit diagram showing ESP32 connections to signal quality LEDs, communication LEDs, and control buttons for the wireless communication lab.

36.7.5 Complete Arduino Code

Copy and paste this complete code into the Wokwi simulator:

// =============================================================================
// Wireless Communication Fundamentals Lab - ESP32
// Demonstrates: RSSI measurement, packet transmission, interference, link budget
// Educational IoT Lab - Wireless Propagation Concepts
// =============================================================================

#include <WiFi.h>

// =============================================================================
// PIN DEFINITIONS
// =============================================================================

// Signal Quality LEDs (RSSI thresholds)
#define LED_EXCELLENT   2    // Green  - RSSI > -50 dBm
#define LED_GOOD        4    // Yellow - RSSI -50 to -70 dBm
#define LED_FAIR        5    // Orange - RSSI -70 to -80 dBm
#define LED_POOR        18   // Red    - RSSI < -80 dBm

// Communication Status LEDs
#define LED_TX          19   // Blue  - Packet transmission
#define LED_ACK         21   // White - Acknowledgment received

// Control Buttons
#define BTN_INTERFERENCE 15  // Simulate RF interference
#define BTN_DISTANCE     16  // Simulate distance increase
#define BTN_SEND         17  // Send packet / Long press = reset

// =============================================================================
// RSSI THRESHOLDS (dBm) - Based on standard Wi-Fi quality metrics
// =============================================================================

#define RSSI_EXCELLENT  -50  // Very close to AP, excellent quality
#define RSSI_GOOD       -60  // Good signal, reliable connection
#define RSSI_FAIR       -70  // Acceptable, may have occasional issues
#define RSSI_POOR       -80  // Weak signal, packet loss likely
#define RSSI_UNUSABLE   -90  // Very weak, connection unreliable

// =============================================================================
// WIRELESS SIMULATION PARAMETERS
// =============================================================================

// Path Loss Model Parameters (Log-distance model)
#define PATH_LOSS_EXPONENT    3.0    // Indoor environment (n=2.5-4)
#define REFERENCE_DISTANCE    1.0    // Reference distance in meters
#define REFERENCE_RSSI        -40    // RSSI at 1 meter (dBm)

// Fading Simulation
#define FADING_VARIANCE       8      // Standard deviation for shadow fading (dB)
#define MULTIPATH_VARIANCE    4      // Fast fading variation (dB)

// Interference Parameters
#define INTERFERENCE_DURATION 3000   // Interference burst duration (ms)
#define INTERFERENCE_PENALTY  25     // RSSI reduction during interference (dB)

// Packet Transmission Parameters
#define PACKET_SIZE           64     // Simulated packet size (bytes)
#define BASE_PACKET_LOSS      0.02   // 2% base packet loss rate
#define ACK_TIMEOUT           500    // ACK timeout (ms)
#define MAX_RETRIES           3      // Maximum retransmission attempts

// =============================================================================
// GLOBAL VARIABLES
// =============================================================================

// Wireless State
float simulatedDistance = 10.0;      // Simulated distance in meters
int currentRSSI = -55;               // Current RSSI value (dBm)
int baseRSSI = -55;                  // Base RSSI without fading
bool interferenceActive = false;     // Interference burst active
unsigned long interferenceStartTime = 0;

// Packet Statistics
unsigned long packetsSent = 0;
unsigned long packetsReceived = 0;
unsigned long packetsLost = 0;
unsigned long totalRetries = 0;
float packetLossRate = 0.0;
float averageRetries = 0.0;

// Communication State
bool awaitingAck = false;
unsigned long lastPacketTime = 0;
int currentRetries = 0;
int lastPacketId = 0;

// Button Debouncing
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 200;
unsigned long buttonPressStart = 0;
bool longPressDetected = false;

// Timing
unsigned long lastRSSIUpdate = 0;
unsigned long lastStatsDisplay = 0;
const unsigned long RSSI_UPDATE_INTERVAL = 500;
const unsigned long STATS_DISPLAY_INTERVAL = 5000;

// Wi-Fi Scanning
int networksFound = 0;
String strongestNetwork = "";
int strongestRSSI = -100;

// =============================================================================
// SETUP FUNCTION
// =============================================================================

void setup() {
    Serial.begin(115200);
    delay(1000);

    // Initialize LED pins
    pinMode(LED_EXCELLENT, OUTPUT);
    pinMode(LED_GOOD, OUTPUT);
    pinMode(LED_FAIR, OUTPUT);
    pinMode(LED_POOR, OUTPUT);
    pinMode(LED_TX, OUTPUT);
    pinMode(LED_ACK, OUTPUT);

    // Initialize button pins with internal pullup
    pinMode(BTN_INTERFERENCE, INPUT_PULLUP);
    pinMode(BTN_DISTANCE, INPUT_PULLUP);
    pinMode(BTN_SEND, INPUT_PULLUP);

    // Turn off all LEDs initially
    clearAllLEDs();

    // Startup LED sequence
    startupSequence();

    // Print welcome message
    printWelcome();

    // Initialize Wi-Fi in station mode for scanning
    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);

    // Initial Wi-Fi scan
    performWiFiScan();

    // Initialize random seed
    randomSeed(analogRead(0) + millis());

    Serial.println("\n=== Lab Ready! ===");
    Serial.println("Press Button 3 to send a packet");
    Serial.println("Press Button 1 to simulate interference");
    Serial.println("Press Button 2 to increase simulated distance");
    Serial.println("Long-press Button 3 (2s) to reset statistics\n");
}

// =============================================================================
// MAIN LOOP
// =============================================================================

void loop() {
    unsigned long currentTime = millis();

    // Update RSSI simulation periodically
    if (currentTime - lastRSSIUpdate >= RSSI_UPDATE_INTERVAL) {
        updateRSSISimulation();
        updateSignalLEDs();
        lastRSSIUpdate = currentTime;
    }

    // Display statistics periodically
    if (currentTime - lastStatsDisplay >= STATS_DISPLAY_INTERVAL) {
        displayStatistics();
        lastStatsDisplay = currentTime;
    }

    // Handle interference timeout
    if (interferenceActive && (currentTime - interferenceStartTime >= INTERFERENCE_DURATION)) {
        interferenceActive = false;
        Serial.println("[INTERFERENCE] Interference burst ended");
        Serial.println("               Signal returning to normal\n");
    }

    // Handle ACK timeout
    if (awaitingAck && (currentTime - lastPacketTime >= ACK_TIMEOUT)) {
        handleAckTimeout();
    }

    // Process button inputs
    handleButtons();
}

// =============================================================================
// RSSI SIMULATION AND CALCULATION
// =============================================================================

void updateRSSISimulation() {
    // Calculate base RSSI using log-distance path loss model
    // PL(d) = PL(d0) + 10 * n * log10(d/d0)
    float pathLoss = 10.0 * PATH_LOSS_EXPONENT * log10(simulatedDistance / REFERENCE_DISTANCE);
    baseRSSI = REFERENCE_RSSI - (int)pathLoss;

    // Add shadow fading (slow fading) - Gaussian distribution
    int shadowFading = (int)(gaussianRandom() * FADING_VARIANCE);

    // Add multipath fading (fast fading) - smaller, faster variations
    int multipathFading = (int)(gaussianRandom() * MULTIPATH_VARIANCE);

    // Calculate current RSSI
    currentRSSI = baseRSSI + shadowFading + multipathFading;

    // Apply interference penalty if active
    if (interferenceActive) {
        currentRSSI -= INTERFERENCE_PENALTY;
    }

    // Clamp RSSI to realistic range
    currentRSSI = constrain(currentRSSI, -100, -20);
}

float gaussianRandom() {
    // Box-Muller transform for Gaussian distribution
    static bool hasSpare = false;
    static float spare;

    if (hasSpare) {
        hasSpare = false;
        return spare;
    }

    float u, v, s;
    do {
        u = (float)random(0, 10000) / 5000.0 - 1.0;
        v = (float)random(0, 10000) / 5000.0 - 1.0;
        s = u * u + v * v;
    } while (s >= 1.0 || s == 0.0);

    s = sqrt(-2.0 * log(s) / s);
    spare = v * s;
    hasSpare = true;
    return u * s;
}

// =============================================================================
// SIGNAL QUALITY LED DISPLAY
// =============================================================================

void updateSignalLEDs() {
    // Clear all signal LEDs first
    digitalWrite(LED_EXCELLENT, LOW);
    digitalWrite(LED_GOOD, LOW);
    digitalWrite(LED_FAIR, LOW);
    digitalWrite(LED_POOR, LOW);

    // Light appropriate LED based on RSSI
    if (currentRSSI >= RSSI_EXCELLENT) {
        digitalWrite(LED_EXCELLENT, HIGH);  // Green - Excellent
    } else if (currentRSSI >= RSSI_GOOD) {
        digitalWrite(LED_GOOD, HIGH);       // Yellow - Good
    } else if (currentRSSI >= RSSI_FAIR) {
        digitalWrite(LED_FAIR, HIGH);       // Orange - Fair
    } else if (currentRSSI >= RSSI_POOR) {
        digitalWrite(LED_POOR, HIGH);       // Red - Poor
    } else {
        // Below -80 dBm: blink red to indicate critical
        digitalWrite(LED_POOR, (millis() / 250) % 2);
    }
}

// =============================================================================
// PACKET TRANSMISSION SIMULATION
// =============================================================================

void sendPacket() {
    if (awaitingAck) {
        Serial.println("[TX] Already awaiting ACK, please wait...");
        return;
    }

    packetsSent++;
    lastPacketId++;
    currentRetries = 0;

    // Visual feedback - TX LED on
    digitalWrite(LED_TX, HIGH);

    Serial.println("\n========================================");
    Serial.printf("[TX] Sending Packet #%d\n", lastPacketId);
    Serial.printf("     Size: %d bytes\n", PACKET_SIZE);
    Serial.printf("     Current RSSI: %d dBm\n", currentRSSI);
    Serial.printf("     Signal Quality: %s\n", getSignalQualityString());
    Serial.printf("     Interference: %s\n", interferenceActive ? "ACTIVE" : "None");

    // Calculate packet loss probability based on RSSI
    float lossProb = calculatePacketLossProbability();
    Serial.printf("     Packet Loss Probability: %.1f%%\n", lossProb * 100);

    // Simulate transmission
    simulateTransmission(lossProb);
}

float calculatePacketLossProbability() {
    // Packet loss probability increases as RSSI decreases
    // Using a sigmoid-like function centered around the fair threshold

    float baseLoss = BASE_PACKET_LOSS;

    if (currentRSSI >= RSSI_EXCELLENT) {
        // Excellent signal: minimal loss
        return baseLoss;
    } else if (currentRSSI >= RSSI_GOOD) {
        // Good signal: low loss
        return baseLoss + 0.02;
    } else if (currentRSSI >= RSSI_FAIR) {
        // Fair signal: moderate loss
        return baseLoss + 0.08;
    } else if (currentRSSI >= RSSI_POOR) {
        // Poor signal: significant loss
        return baseLoss + 0.20;
    } else {
        // Very poor signal: high loss
        float additionalLoss = 0.30 + (RSSI_POOR - currentRSSI) * 0.03;
        return min(baseLoss + additionalLoss, 0.70f);
    }
}

void simulateTransmission(float lossProb) {
    // Determine if packet is lost
    float randomValue = (float)random(0, 1000) / 1000.0;

    if (randomValue < lossProb) {
        // Packet lost - simulate waiting for ACK
        Serial.println("     [SIMULATING] Packet transmitted...");
        awaitingAck = true;
        lastPacketTime = millis();

        // Schedule packet loss (ACK timeout will handle)
        Serial.println("     Status: Awaiting ACK...\n");
    } else {
        // Packet received successfully
        Serial.println("     [SIMULATING] Packet transmitted...");
        delay(50);  // Simulate transmission time

        // Simulate successful reception and ACK
        receiveAck();
    }
}

void receiveAck() {
    packetsReceived++;
    awaitingAck = false;

    // Visual feedback
    digitalWrite(LED_TX, LOW);
    digitalWrite(LED_ACK, HIGH);

    // Calculate latency (simulated)
    int latency = 20 + random(0, 30);  // 20-50ms typical

    Serial.println("     [RX] ACK Received!");
    Serial.printf("     Round-Trip Time: %d ms\n", latency);
    Serial.printf("     Retries needed: %d\n", currentRetries);
    Serial.println("     Status: SUCCESS");
    Serial.println("========================================\n");

    // Brief ACK LED indication
    delay(200);
    digitalWrite(LED_ACK, LOW);

    // Update statistics
    updateStatistics();
}

void handleAckTimeout() {
    currentRetries++;
    totalRetries++;

    Serial.printf("     [TIMEOUT] No ACK received (attempt %d/%d)\n",
                  currentRetries, MAX_RETRIES);

    if (currentRetries >= MAX_RETRIES) {
        // Max retries exceeded - packet lost
        packetsLost++;
        awaitingAck = false;

        digitalWrite(LED_TX, LOW);
        // Flash red LED to indicate loss
        for (int i = 0; i < 3; i++) {
            digitalWrite(LED_POOR, HIGH);
            delay(100);
            digitalWrite(LED_POOR, LOW);
            delay(100);
        }

        Serial.println("     [FAILED] Max retries exceeded - Packet LOST");
        Serial.println("     This demonstrates why link margin is important!");
        Serial.println("========================================\n");

        updateStatistics();
    } else {
        // Retransmit
        Serial.println("     [RETRANSMIT] Attempting retransmission...\n");

        // Quick blink TX LED
        digitalWrite(LED_TX, LOW);
        delay(50);
        digitalWrite(LED_TX, HIGH);

        // Retry with slightly different loss probability (channel may change)
        float lossProb = calculatePacketLossProbability();
        lastPacketTime = millis();
        simulateTransmission(lossProb);
    }
}

// =============================================================================
// INTERFERENCE SIMULATION
// =============================================================================

void triggerInterference() {
    interferenceActive = true;
    interferenceStartTime = millis();

    Serial.println("\n========================================");
    Serial.println("[INTERFERENCE] RF Interference Burst Detected!");
    Serial.println("              Source: Simulated 2.4 GHz interference");
    Serial.printf("              Duration: %d ms\n", INTERFERENCE_DURATION);
    Serial.printf("              RSSI Impact: -%d dB\n", INTERFERENCE_PENALTY);
    Serial.println("              Effect: Increased packet loss, degraded SNR");
    Serial.println("========================================\n");

    // Visual indication - blink all LEDs briefly
    flashAllLEDs(3, 100);
}

// =============================================================================
// DISTANCE SIMULATION
// =============================================================================

void increaseDistance() {
    // Increase simulated distance
    float oldDistance = simulatedDistance;

    if (simulatedDistance < 20) {
        simulatedDistance += 5;
    } else if (simulatedDistance < 50) {
        simulatedDistance += 10;
    } else if (simulatedDistance < 100) {
        simulatedDistance += 25;
    } else {
        simulatedDistance = 10;  // Reset to close range
    }

    // Calculate path loss change
    float oldPathLoss = 10.0 * PATH_LOSS_EXPONENT * log10(oldDistance / REFERENCE_DISTANCE);
    float newPathLoss = 10.0 * PATH_LOSS_EXPONENT * log10(simulatedDistance / REFERENCE_DISTANCE);
    float pathLossChange = newPathLoss - oldPathLoss;

    Serial.println("\n========================================");
    Serial.println("[DISTANCE] Simulated Distance Changed");
    Serial.printf("           Old distance: %.0f m\n", oldDistance);
    Serial.printf("           New distance: %.0f m\n", simulatedDistance);
    Serial.printf("           Path loss change: +%.1f dB\n", pathLossChange);
    Serial.println("           ");
    Serial.println("           This demonstrates the inverse-square law:");
    Serial.println("           Doubling distance adds ~6 dB path loss");
    Serial.println("========================================\n");

    // Update RSSI immediately
    updateRSSISimulation();
    updateSignalLEDs();

    // Print new signal status
    printSignalStatus();
}

// =============================================================================
// BUTTON HANDLING
// =============================================================================

void handleButtons() {
    unsigned long currentTime = millis();

    // Check for button presses with debouncing
    if (currentTime - lastDebounceTime < debounceDelay) {
        return;
    }

    // Button 1: Interference simulation
    if (digitalRead(BTN_INTERFERENCE) == LOW) {
        lastDebounceTime = currentTime;
        triggerInterference();
    }

    // Button 2: Distance increase
    if (digitalRead(BTN_DISTANCE) == LOW) {
        lastDebounceTime = currentTime;
        increaseDistance();
    }

    // Button 3: Send packet / Long press for reset
    static bool btn3WasPressed = false;

    if (digitalRead(BTN_SEND) == LOW) {
        if (!btn3WasPressed) {
            buttonPressStart = currentTime;
            btn3WasPressed = true;
            longPressDetected = false;
        } else if (!longPressDetected && (currentTime - buttonPressStart > 2000)) {
            // Long press detected - reset statistics
            longPressDetected = true;
            resetStatistics();
        }
    } else {
        if (btn3WasPressed && !longPressDetected) {
            // Short press - send packet
            lastDebounceTime = currentTime;
            sendPacket();
        }
        btn3WasPressed = false;
    }
}

// =============================================================================
// STATISTICS AND DISPLAY
// =============================================================================

void updateStatistics() {
    if (packetsSent > 0) {
        packetLossRate = (float)packetsLost / packetsSent * 100.0;
        averageRetries = (float)totalRetries / packetsSent;
    }
}

void displayStatistics() {
    Serial.println("\n--- Link Quality Statistics ---");
    Serial.printf("Current RSSI: %d dBm (%s)\n", currentRSSI, getSignalQualityString());
    Serial.printf("Simulated Distance: %.0f m\n", simulatedDistance);
    Serial.printf("Interference: %s\n", interferenceActive ? "ACTIVE" : "None");
    Serial.println("");
    Serial.printf("Packets Sent: %lu\n", packetsSent);
    Serial.printf("Packets Received: %lu\n", packetsReceived);
    Serial.printf("Packets Lost: %lu\n", packetsLost);
    Serial.printf("Packet Loss Rate: %.1f%%\n", packetLossRate);
    Serial.printf("Total Retries: %lu\n", totalRetries);
    Serial.printf("Avg Retries/Packet: %.2f\n", averageRetries);
    Serial.println("-------------------------------\n");
}

void resetStatistics() {
    packetsSent = 0;
    packetsReceived = 0;
    packetsLost = 0;
    totalRetries = 0;
    packetLossRate = 0.0;
    averageRetries = 0.0;
    simulatedDistance = 10.0;
    interferenceActive = false;
    lastPacketId = 0;

    Serial.println("\n========================================");
    Serial.println("[RESET] All statistics cleared!");
    Serial.println("        Distance reset to 10m");
    Serial.println("        Ready for new measurements");
    Serial.println("========================================\n");

    // Visual feedback
    flashAllLEDs(2, 200);
}

void printSignalStatus() {
    Serial.printf("Signal Status: RSSI = %d dBm\n", currentRSSI);
    Serial.printf("Quality: %s\n", getSignalQualityString());

    // Link budget analysis
    int linkMargin = currentRSSI - RSSI_UNUSABLE;
    Serial.printf("Link Margin: %d dB above minimum\n", linkMargin);

    if (linkMargin > 20) {
        Serial.println("Assessment: Excellent margin, very reliable link");
    } else if (linkMargin > 10) {
        Serial.println("Assessment: Good margin, reliable link");
    } else if (linkMargin > 5) {
        Serial.println("Assessment: Low margin, occasional issues possible");
    } else {
        Serial.println("Assessment: Critical margin, unreliable link!");
    }
}

const char* getSignalQualityString() {
    if (currentRSSI >= RSSI_EXCELLENT) return "EXCELLENT";
    if (currentRSSI >= RSSI_GOOD) return "GOOD";
    if (currentRSSI >= RSSI_FAIR) return "FAIR";
    if (currentRSSI >= RSSI_POOR) return "POOR";
    return "VERY POOR";
}

// =============================================================================
// WIFI SCANNING
// =============================================================================

void performWiFiScan() {
    Serial.println("\n[SCAN] Scanning for Wi-Fi networks...");

    networksFound = WiFi.scanNetworks();

    if (networksFound == 0) {
        Serial.println("[SCAN] No networks found");
        Serial.println("       (This is normal in Wokwi simulator)");
        Serial.println("       Using simulated RSSI values for demonstration\n");
    } else {
        Serial.printf("[SCAN] Found %d networks:\n", networksFound);

        strongestRSSI = -100;
        strongestNetwork = "";

        for (int i = 0; i < min(networksFound, 5); i++) {
            Serial.printf("       %d: %s (%d dBm) %s\n",
                         i + 1,
                         WiFi.SSID(i).c_str(),
                         WiFi.RSSI(i),
                         (WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? "[OPEN]" : "[SECURED]");

            if (WiFi.RSSI(i) > strongestRSSI) {
                strongestRSSI = WiFi.RSSI(i);
                strongestNetwork = WiFi.SSID(i);
            }
        }

        if (strongestNetwork.length() > 0) {
            Serial.printf("\n[SCAN] Strongest network: %s at %d dBm\n",
                         strongestNetwork.c_str(), strongestRSSI);
            // Use real RSSI as starting point
            currentRSSI = strongestRSSI;
            baseRSSI = strongestRSSI;
        }
        Serial.println("");
    }

    WiFi.scanDelete();
}

// =============================================================================
// UTILITY FUNCTIONS
// =============================================================================

void clearAllLEDs() {
    digitalWrite(LED_EXCELLENT, LOW);
    digitalWrite(LED_GOOD, LOW);
    digitalWrite(LED_FAIR, LOW);
    digitalWrite(LED_POOR, LOW);
    digitalWrite(LED_TX, LOW);
    digitalWrite(LED_ACK, LOW);
}

void flashAllLEDs(int times, int delayMs) {
    for (int i = 0; i < times; i++) {
        digitalWrite(LED_EXCELLENT, HIGH);
        digitalWrite(LED_GOOD, HIGH);
        digitalWrite(LED_FAIR, HIGH);
        digitalWrite(LED_POOR, HIGH);
        delay(delayMs);
        digitalWrite(LED_EXCELLENT, LOW);
        digitalWrite(LED_GOOD, LOW);
        digitalWrite(LED_FAIR, LOW);
        digitalWrite(LED_POOR, LOW);
        delay(delayMs);
    }
}

void startupSequence() {
    // Sequential LED test
    int leds[] = {LED_EXCELLENT, LED_GOOD, LED_FAIR, LED_POOR, LED_TX, LED_ACK};

    for (int i = 0; i < 6; i++) {
        digitalWrite(leds[i], HIGH);
        delay(150);
        digitalWrite(leds[i], LOW);
    }

    // All on briefly
    for (int i = 0; i < 6; i++) {
        digitalWrite(leds[i], HIGH);
    }
    delay(300);
    clearAllLEDs();
}

void printWelcome() {
    Serial.println("\n");
    Serial.println("================================================================");
    Serial.println("     WIRELESS COMMUNICATION FUNDAMENTALS LAB                    ");
    Serial.println("     ESP32 Wi-Fi RSSI & Packet Transmission Simulator           ");
    Serial.println("================================================================");
    Serial.println("                                                                ");
    Serial.println("  This lab demonstrates key wireless propagation concepts:      ");
    Serial.println("                                                                ");
    Serial.println("  1. RSSI Measurement     - Signal strength in dBm             ");
    Serial.println("  2. Path Loss            - Signal weakens with distance       ");
    Serial.println("  3. Fading               - Random signal variations           ");
    Serial.println("  4. Interference         - External signal disruption         ");
    Serial.println("  5. Packet Loss          - Failed transmissions               ");
    Serial.println("  6. Retransmissions      - Recovery from packet loss          ");
    Serial.println("  7. Link Budget          - Margin above minimum signal        ");
    Serial.println("                                                                ");
    Serial.println("================================================================");
    Serial.println("  LED Indicators:                                               ");
    Serial.println("    GREEN  = Excellent signal (> -50 dBm)                       ");
    Serial.println("    YELLOW = Good signal      (-50 to -60 dBm)                  ");
    Serial.println("    ORANGE = Fair signal      (-60 to -70 dBm)                  ");
    Serial.println("    RED    = Poor signal      (< -70 dBm)                       ");
    Serial.println("    BLUE   = Transmitting packet                                ");
    Serial.println("    WHITE  = ACK received                                       ");
    Serial.println("                                                                ");
    Serial.println("================================================================");
    Serial.println("  Controls:                                                     ");
    Serial.println("    Button 1 = Simulate interference burst (3 seconds)         ");
    Serial.println("    Button 2 = Increase simulated distance                     ");
    Serial.println("    Button 3 = Send test packet                                ");
    Serial.println("    Button 3 (hold 2s) = Reset all statistics                  ");
    Serial.println("                                                                ");
    Serial.println("================================================================");
    Serial.println("\n");
}

36.7.6 Real-World Measurement Techniques

Beyond the simulator, here’s how to conduct actual wireless measurements:

Equipment needed: ESP32 with battery, laptop with serial monitor, measuring tape, floor plan, clipboard

Procedure:

  1. Grid Survey: Divide deployment area into 5m × 5m grid. Mark measurement points on floor plan.

  2. Height Variation: Measure at actual sensor installation height (e.g., 2m for ceiling mount, 0.5m for floor sensors). Height changes can affect RSSI by 3-8 dB due to ground reflection.

  3. Multiple Orientations: At each point, measure with sensor in 4 orientations (0°, 90°, 180°, 270°). Polarization mismatch can cause 10-20 dB loss. Record all 4 values and use the average.

  4. Time-of-Day Testing: Measure during peak occupancy hours. In office buildings, RSSI can drop 5-10 dB during work hours due to human body absorption (each person ≈ 3 dB loss if blocking line-of-sight).

  5. Interference Check: Use Wi-Fi analyzer app to check channel congestion. If target channel has > 3 APs, add 3-5 dB penalty to link budget for co-channel interference.

  6. Obstacle Catalog: Document walls crossed between sensor and gateway:

    • Drywall: 3-5 dB each
    • Concrete block: 10-15 dB
    • Metal studs/ductwork: 15-25 dB
    • Glass windows: 2-3 dB
    • Brick: 8-12 dB

Analysis: Create heat map showing RSSI values. Identify “dead zones” (RSSI < -80 dBm). For borderline locations (-75 to -80 dBm), flag for additional gateway or repeater.

Real Example: 3-floor office building (100m × 50m per floor). Single gateway on Floor 2. Survey revealed: - Same-floor coverage: -55 to -70 dBm (excellent) - Floor 1 directly below gateway: -65 to -75 dBm (good) - Floor 3 directly above: -70 to -80 dBm (marginal) - Stairwell areas: -50 to -60 dBm (signal channeling effect) - Corners of Floor 1 & 3: -85 to -90 dBm (unusable)

Solution: Added 2 repeaters on Floors 1 and 3, positioned near stairwells to leverage signal channeling. Result: Full building coverage with minimum -68 dBm everywhere.

Pitfall 1: “My measurements keep changing”

  • Cause: RSSI naturally fluctuates ±3-5 dB due to multipath fading
  • Fix: Take 10 samples at each location, record min/avg/max. Use average for link budget, ensure minimum is above -80 dBm

Pitfall 2: “One sensor worked great in lab, fails in deployment”

  • Cause: Lab testing done on bench (1m height, clear line-of-sight). Deployment has different height, obstacles, orientation
  • Fix: Always test at actual installation height and location before mounting permanently

Pitfall 3: “Coverage was fine during installation weekend, fails on Monday”

  • Cause: Building empty during weekend. People absorb 2.4 GHz signals. Full occupancy = 5-10 dB degradation
  • Fix: Return for weekday peak-hour survey, or add 10 dB “people penalty” to weekend measurements

Pitfall 4: “RSSI is -65 dBm but packets still drop”

  • Cause: Good RSSI doesn’t guarantee good SNR. Hidden interference (nearby Wi-Fi AP, microwave, Bluetooth) degrades SNR
  • Fix: Use spectrum analyzer or Wi-Fi scanner to check for co-channel interference. Switch to less congested channel

Pitfall 5: “Can’t hit 100m range despite theoretical calculations”

  • Cause: FSPL assumes free space. Real environments have path loss exponent n=3-4 (not n=2)
  • Fix: Use log-distance model with realistic n value. Measure RSSI at 10m and 50m to calculate actual path loss exponent: n = (RSSI_10m - RSSI_50m) / (10 × log10(50/10))

Real Example: Smart parking sensors in underground garage. Initial test showed -60 dBm at sensor location (gateway on surface level, 50m away, one concrete floor). Deployment failed completely.

Investigation:

  • Test was conducted at midnight (empty garage)
  • During business hours: hundreds of cars (metal obstacles)
  • Cars caused 15-20 dB additional loss from reflection/absorption
  • Concrete ceiling: 15 dB loss (initially estimated 10 dB)

Solution: Moved gateway into garage, reduced distance from 50m to 20m average. Added second gateway for far corner. New deployment successful with -60 to -75 dBm coverage.

36.7.7 Challenge Exercises

After running the basic lab, try these challenges to deepen your understanding:

36.7.8 Try It: Quick RSSI Measurement Exercise

Before diving into the full lab, try this 5-minute exercise with your smartphone:

What you’ll need: Smartphone with Wi-Fi analyzer app (free apps: “WiFi Analyzer” on Android, “Airport Utility” on iOS)

Quick Exercise (5 minutes):

  1. Baseline: Stand 2 meters from your Wi-Fi router. Note the RSSI value (typically -30 to -50 dBm at this distance)

  2. Distance Test: Walk to 5m, 10m, and 20m from router. Record RSSI at each distance:

    • Expected: ~6 dB loss per distance doubling
    • Example: 2m (-40 dBm) → 4m (-46 dBm) → 8m (-52 dBm) → 16m (-58 dBm)
  3. Obstacle Test: Stand 5m from router with clear line-of-sight. Note RSSI. Now move to same distance but with a wall between you and router. Calculate wall loss:

    • Example: Clear LOS (-50 dBm) vs. Through wall (-58 dBm) = 8 dB wall loss
  4. Height Test: Measure RSSI at floor level (0.5m), waist level (1m), and overhead (2m) at same horizontal distance. You may see 3-5 dB variation due to ground reflection and antenna orientation.

  5. Interference Check: In the app, check how many networks are on the same channel as yours. Each additional network on your channel reduces effective capacity by ~20-30%.

What you’ll discover:

  • Distance truly matters: Doubling distance = ~6 dB loss
  • Walls are expensive: Each wall costs 3-15 dB depending on material
  • Height affects signal: Ground reflections create constructive/destructive interference
  • 2.4 GHz is crowded: 10+ networks in urban areas is common

Time to complete: 5 minutes | Difficulty: Beginner | Cost: Free (uses phone only)

Challenge 1: Link Budget Analysis

Objective: Observe how distance affects packet loss rate.

Skills practiced: Data collection, correlation analysis, link budget interpretation

Estimated time: 15 minutes

Steps:

  1. Reset statistics (long-press Button 3)
  2. At 10m distance, send 20 packets and record packet loss rate
  3. Increase distance to 50m (press Button 2 multiple times)
  4. Send another 20 packets and record the new packet loss rate
  5. Compare the two rates

Questions to Answer:

  • At what distance does packet loss become significant?
  • How does this relate to the link budget concept?
  • What RSSI threshold correlates with unreliable communication?
Challenge 2: Interference Impact

Objective: Measure the effect of interference on communication reliability.

Skills practiced: Experimental design, statistical analysis, troubleshooting

Estimated time: 20 minutes

Steps:

  1. Reset statistics
  2. Send 10 packets without interference, record success rate
  3. Reset statistics
  4. Trigger interference (Button 1), then immediately send 10 packets
  5. Compare the packet loss rates

Questions to Answer:

  • How much does interference degrade packet delivery?
  • Why is fading margin important in real deployments?
  • How do retransmissions help recover from interference?
Challenge 3: Retransmission Analysis

Objective: Understand adaptive retransmission behavior.

Skills practiced: Reliability mechanisms, latency-throughput trade-offs, protocol design

Estimated time: 25 minutes

Steps:

  1. Set distance to maximum (100m)
  2. Enable interference
  3. Send 15 packets and observe retransmission patterns
  4. Note the average retries per successful packet

Questions to Answer:

  • How many retries are typically needed at poor signal levels?
  • What is the trade-off between reliability and latency?
  • When should you give up on retransmissions?

36.7.9 Lab Results Analyzer

Visualize how RSSI affects packet delivery:

(a)
(b)
(c)
(d)
Figure 36.4: Packet loss probability vs RSSI showing how signal quality affects reliability
Key Insight

Notice the sharp increase in packet loss below -70 dBm. This is why industry best practice recommends maintaining RSSI above -70 dBm for IoT deployments. A mere 10 dB difference (from -70 to -80 dBm) can change reliability from 90% to less than 70%.

36.7.10 Expected Outcomes

After completing this lab, you should observe and understand:

Key Observations

1. RSSI and Signal Quality Relationship

  • Green LED (> -50 dBm): Nearly 100% packet success (99.5-99.9%), typical data rates 2 Mbps, latency 10-20 ms
  • Yellow LED (-50 to -60 dBm): > 95% packet success (95-98%), data rates 1-2 Mbps, latency 20-30 ms, occasional retransmission
  • Orange LED (-60 to -70 dBm): ~90% packet success (88-92%), data rates 250-500 kbps, latency 30-50 ms, frequent retransmissions (1-2 per packet)
  • Red LED (< -70 dBm): Significant packet loss begins (70-85% success), data rates < 250 kbps, latency > 100 ms, multiple retries often exhaust limit

Quantitative Analysis: Each 10 dB drop in RSSI roughly doubles packet loss rate: - -60 dBm: 4% loss → Average 25 packets between failures - -70 dBm: 10% loss → Average 10 packets between failures - -80 dBm: 30% loss → Average 3 packets between failures - -90 dBm: 70% loss → Only 1 in 3 packets succeeds

2. Distance vs Signal Strength

  • Each distance doubling reduces RSSI by approximately 6-9 dB (depending on path loss exponent n)
    • Free space (n=2): 6 dB per doubling (10m: -60 dBm → 20m: -66 dBm → 40m: -72 dBm)
    • Indoor (n=3): 9 dB per doubling (10m: -60 dBm → 20m: -69 dBm → 40m: -78 dBm)
    • Dense urban (n=4): 12 dB per doubling (10m: -60 dBm → 20m: -72 dBm → 40m: -84 dBm)
  • At 100m simulated distance with n=3, signal is typically -80 to -85 dBm (“poor” range)
  • This demonstrates the inverse-square law in action, plus environment-dependent excess loss

Practical Implication: To extend range from 50m to 100m (2× distance): - Option A: Add 9 dB link budget through higher TX power (+9 dBm = 8× power consumption) - Option B: Add 9 dBi antenna gain (4× power on same battery) - Option C: Add 3 dB TX gain + 3 dB RX gain + 3 dB better sensitivity (balanced approach)

3. Interference Effects

  • Active interference reduces effective RSSI by 25 dB (as configured in lab code)
  • Even excellent signals (-50 dBm) can drop to poor (-75 dBm) during interference bursts
  • Real-world interference sources and impacts:
    • Microwave oven: 20-30 dB degradation within 5m, duration 20-120 seconds per cooking cycle
    • Wi-Fi channel overlap: 5-15 dB degradation (continuous if on same channel)
    • Bluetooth devices: 3-8 dB degradation (intermittent, frequency hopping reduces impact)
    • Cordless phones: 10-20 dB degradation when active (older 2.4 GHz models)
    • USB 3.0 devices: 5-10 dB degradation within 1m (broadband noise)

Spectrum Strategy: In 2.4 GHz band, only channels 1, 6, and 11 don’t overlap. If deploying Zigbee/Thread: - Wi-Fi on channels 1 & 6 → Use Zigbee channel 25 (2.475 GHz, avoids both) - Wi-Fi on channels 6 & 11 → Use Zigbee channel 15 (2.425 GHz, below Wi-Fi) - High interference everywhere → Consider sub-GHz (868/915 MHz) for critical sensors

Measurement Protocol: Before deployment, scan spectrum for 24-hour period to identify peak interference times. Deploy sensors during worst-case conditions to ensure adequate margin.

4. Retransmission Behavior

  • Retries increase significantly below -70 dBm RSSI
  • Maximum retries (3) often exhausted at very poor signal levels
  • Average retries/packet provides a practical link quality metric

5. Link Budget Implications

  • Link margin = Current RSSI - Minimum usable RSSI (-90 dBm)
  • Margins > 20 dB provide reliable operation
  • Margins < 10 dB result in frequent packet loss
Real-World Applications

The concepts demonstrated in this lab directly apply to:

Lab Concept Real-World Application
RSSI thresholds Wi-Fi access point placement, coverage planning
Path loss model Predicting wireless range before deployment
Interference simulation Understanding 2.4 GHz band congestion
Packet retransmission Protocol reliability mechanisms (TCP, LoRaWAN)
Link budget analysis Antenna selection, transmit power configuration

Industry Best Practice: Always deploy with at least 15-20 dB link margin to account for fading, interference, and environmental changes over time.


Scenario: A warehouse deployed 50 Zigbee temperature sensors that work perfectly during night shifts but experience 30% packet loss during day shifts when forklifts are operating.

Given:

  • Sensor locations: 3-5 meters above floor on warehouse racks
  • Distance to coordinator: 10-40 meters
  • RSSI during night: -65 to -75 dBm (good signal)
  • RSSI during day: -68 to -78 dBm (only 3 dB worse, but 30% packet loss)
  • Frequency: 2.4 GHz (Zigbee Channel 15, 2.450 GHz center)
  • Warehouse has metal shelving and concrete floor

Problem Analysis:

Step 1: Spectrum Scan During Day Shift

  • Discovered Wi-Fi access points on Channels 6 and 11 (2.437 GHz and 2.462 GHz)
  • Zigbee Channel 15 (2.450 GHz) overlaps with both Wi-Fi channels
  • Forklift operations correlate with Wi-Fi camera uploads (video surveillance)

Step 2: Multipath Investigation

  • Metal racking creates significant multipath reflections
  • Moving forklifts change the multipath environment dynamically
  • Fast fading creates temporary signal nulls (Rayleigh fading)

Step 3: Link Budget Check

  • Path loss at 40m (worst case): 20log(40) + 20log(2450) - 27.55 = 32 + 67.8 - 27.55 = 72.3 dB
  • Tx power: +8 dBm, Rx sensitivity: -100 dBm
  • Link budget: 8 - (-100) = 108 dB available
  • Free-space path loss: 72.3 dB
  • Free-space link margin: +35.7 dB (looks great in theory!)

But sensors work at night… Why?

Step 4: The “N” Factor (Path Loss Exponent)

  • Free space assumes n=2, but warehouse is NOT free space
  • Metal shelving and line-of-sight paths reduce effective n to 2.5-2.8
  • Actual path loss: 91.65 + 25log(0.04) = 91.65 + 25(-1.4) = 91.65 - 35 = 56.65 dB
  • With n=2.5: Path loss ≈ 80-90 dB (much better!)
  • Link margin during night: 108 - 85 = +23 dB (explains night success)

Root Causes Identified:

  1. Interference: Wi-Fi overlaps Zigbee during day (5-8 dB effective SNR degradation)
  2. Multipath fading: Moving forklifts create 6-10 dB temporary fades
  3. Marginal link budget: Sensors are operating near sensitivity threshold

Solution Implemented:

Option 1: Change Zigbee Channel (Chosen) - Moved from Channel 15 (2.450 GHz) to Channel 26 (2.480 GHz) - Avoids both Wi-Fi channels (6 and 11) - Result: Packet loss dropped from 30% to 3% during day shifts - Cost: Zero (just configuration change)

Option 2: Add Zigbee Routers (Backup) - Placed 8 additional routers at mid-points between sensors and coordinator - Reduces hop distance from 40m to 20m - Path loss reduction: 20log(20/40) = -6 dB improvement - Cost: $320 (8 routers × $40 each)

Lessons Learned:

  1. RSSI alone doesn’t tell the story: Signal strength was only 3 dB worse during day, but SNR degradation from interference caused 30% packet loss

  2. Spectrum analysis is essential: Without scanning for Wi-Fi interference, the team would have blamed “faulty sensors”

  3. Path loss models are guidelines, not laws: The warehouse’s metal structure actually helped propagation (n=2.5 instead of n=3-4 typical indoor)

  4. Frequency planning matters: Zigbee and Wi-Fi can coexist, but channel selection must avoid overlap

  5. Link margin prevents troubleshooting: If the initial deployment had 15-20 dB margin instead of barely working at -24 dB, interference and multipath fading would have been absorbed without packet loss

Key Takeaway: Wireless systems that work 70-80% of the time are often just 3-6 dB away from 99% reliability. Small improvements (better antennas, frequency planning, reducing interference) make the difference between a frustrating deployment and a reliable system.

36.8 How It Works: RSSI Measurement and Signal Analysis

How It Works: ESP32 Wi-Fi RSSI Measurement

The big picture: The ESP32’s Wi-Fi radio measures received signal strength (RSSI) by comparing the incoming signal power to a calibrated internal reference, converting the analog power level to a digital dBm value that ranges from -20 dBm (very strong) to -100 dBm (very weak).

Step-by-step breakdown:

  1. Scanning Phase: ESP32 switches radio to each Wi-Fi channel (1-13), listens for 100ms, and decodes beacon frames from nearby access points - Real example: In an office with 15 APs, scan finds all networks in ~1.3 seconds (13 channels × 100ms)

  2. Signal Measurement: Radio’s AGC (automatic gain control) adjusts receiver gain to measure signal power, ADC samples at 40 MHz, and digital signal processor averages 4000 samples per network - Real example: At -60 dBm input, AGC amplifies by 40 dB to bring signal to ADC’s optimal -20 dBm range

  3. RSSI Calculation: Firmware converts raw ADC reading to calibrated dBm using factory-programmed lookup table accounting for temperature and frequency variations - Real example: Raw ADC value 2048 (mid-range) maps to -70 dBm after applying 5 dBm correction for 2.45 GHz channel

  4. Signal Quality Classification: Software compares RSSI to threshold ranges (Excellent: > -50 dBm, Good: -50 to -60 dBm, Fair: -60 to -70 dBm, Poor: < -70 dBm) to determine link quality and adjust transmission parameters - Real example: At -68 dBm, system classifies as “Fair” and may reduce data rate or increase error correction

Why this matters: RSSI measurement accuracy is ±3 dBm, so values fluctuate (e.g., -67, -69, -68 dBm) even without movement. This is normal measurement noise, not actual signal changes. Understanding these thresholds helps you interpret the lab measurements correctly.

36.9 Concept Relationships

This chapter connects to other IoT topics:

Related Concept Chapter Link Relationship
Path Loss Theory Path Loss and Link Budgets Lab validates FSPL formula with real measurements
Fading Effects Fading and Interference Observe multipath and shadowing firsthand
ESP32 Programming ESP32 Fundamentals Wi-Fi.scanNetworks() and RSSI API
Sensor Placement Deployment Best Practices RSSI measurements guide sensor positioning

Common Pitfalls

An RSSI reading of -68 dBm can still perform badly if interference, retries, or multipath collapse the usable SNR. Always pair signal-strength checks with packet-loss observations, channel occupancy, and a realistic link-margin calculation.

Capturing one clean RSSI reading beside the gateway tells you almost nothing about a hallway corner, a closed fire door, or a busy shift with active Wi-Fi cameras. Walk the full path, record min/avg/max readings, and repeat the survey during busy hours.

Teams often raise transmit power first even when the real problem is a poor antenna angle, bad mounting height, or an unexpected concrete wall in the path. Fix placement, polarization, and channel plan before assuming more power will solve the deployment.

36.10 Summary

Concept Key Points
Indoor Challenges Walls (3-15 dB loss each), metal structures, furniture absorption
Outdoor Challenges Distance, weather, interference, regulatory limits
Antenna Selection 3 dB gain = 2x range; omnidirectional vs directional trade-offs
Key Trade-offs Sub-GHz vs 2.4 GHz, power vs battery, margin vs cost
Lab Findings RSSI > -70 dBm for reliability, 15-20 dB margin recommended

36.11 See Also

Related Labs and Tools:

Wireless Fundamentals:

Key Takeaway

Real-world wireless performance always underperforms theoretical calculations due to multipath, interference, and obstacle absorption. The most critical lab findings: RSSI above -70 dBm ensures reliable packet delivery; each wall reduces signal by 3-15 dB depending on material (drywall 3 dB, concrete 10-15 dB); and always deploy with at least 15-20 dB link margin to account for fading, interference, and environmental changes over time. Test during peak occupancy hours – a system that works at midnight may fail at noon.

The Sensor Squad went on a field trip to test wireless signals in the real world!

Sammy the Sensor stood in one corner of the building with his radio, and Max the Microcontroller walked around measuring signal strength.

“At 5 meters with nothing in the way, signal strength is -45 dBm. Strong!” Max reported from the next room.

“Now I’m behind a brick wall – -62 dBm. The wall ate 17 dB of my signal!” Max called from further away.

Lila the LED tracked the results on a chart: “Look! Signal gets weaker with distance AND walls. Two walls and 20 meters = -78 dBm. Getting weak!”

Bella the Battery noticed something strange: “Hey, the signal dropped to -85 dBm when someone turned on the microwave! It came back when the microwave stopped.”

Max nodded: “Microwave ovens blast 2.4 GHz energy – the same frequency as our Wi-Fi and Bluetooth! That’s interference. The lesson: always test your wireless system during busy hours, not at midnight when everything is quiet.”

Sammy concluded: “Real-world wireless is messier than math predicts. Build in extra margin and test, test, test!”


36.12 What’s Next

With wireless propagation lab skills mastered, you are ready to apply these measurement techniques to specific wireless technologies and deployment scenarios:

Chapter Focus Area
LPWAN Introduction Apply propagation concepts to long-range IoT technologies
LoRaWAN Overview Explore how LoRa achieves long range with link budget trade-offs
Signal Processing Essentials Deepen signal analysis skills beyond RSSI measurement
Protocol Selection Framework Choose the right wireless protocol based on propagation requirements
Energy-Aware Considerations Balance transmit power, range, and battery life in deployments
ESP32 Wi-Fi Examples Extend lab skills with advanced ESP32 Wi-Fi programming