Learning Hubs
  • ← All Modules
  1. Tools & References
  2. 17  Troubleshooting Flowchart
Learning Hubs
  • 1  Introduction to Learning Hubs
  • Navigation & Discovery
    • 2  Learning Hubs
    • 3  Knowledge Map
    • 4  Visual Concept Map
    • 5  Interactive Concept Navigator
    • 6  Learning Paths
    • 7  Learning Recommendations
    • 8  Role-Based Learning Paths
  • Quizzes & Simulations
    • 9  Quiz Navigator
    • 10  Simulation Playground
    • 11  Simulation Learning Workflow
    • 12  Simulation Catalog
    • 13  Simulation Resources
    • 14  Hands-On Labs Hub
  • Tools & References
    • 15  Tool Discovery Hub
    • 16  Troubleshooting Hub
    • 17  Troubleshooting Flowchart
    • 18  IoT Failure Case Studies
    • 19  Discussion Prompts Hub
    • 20  Quick Reference Cards
    • 21  IoT Code Snippet Library
  • Knowledge Tracking
    • 22  Knowledge Gaps Tracker
    • 23  Gap Closure Process
    • 24  Knowledge Categories & Refreshers
    • 25  Progress Tracking & Assessment
    • 26  Video Gallery
    • 27  Quick Reference: Key Concepts

On This Page

  • 17.1 Learning Objectives
  • 17.2 IoT Troubleshooting Guide
  • 17.3 Select Problem Category
  • 17.4 Troubleshooting Flowchart
  • 17.5 Quick Diagnostic Commands
  • 17.6 Interactive Calculators
  • 17.7 Related Resources
  • Common Pitfalls
  • 17.8 What’s Next
  1. Tools & References
  2. 17  Troubleshooting Flowchart

17  Troubleshooting Flowchart

Step-by-Step Debugging for Common IoT Issues

For Beginners: Troubleshooting Flowchart

When your IoT project is not working, this interactive tool guides you through a series of yes/no questions to find the problem – like a doctor asking about your symptoms to diagnose an illness. Instead of randomly trying fixes, you follow a logical path from symptom to solution. It covers the five most common IoT issues: Wi-Fi problems, messaging failures, sensor errors, battery drain, and debugging difficulties.

In 60 Seconds

This interactive troubleshooting guide provides step-by-step decision trees for the five most common IoT problems: Wi-Fi/Network connectivity, MQTT messaging, sensor issues, power/battery problems, and serial/debug failures. Select your problem category, answer yes/no diagnostic questions, and get targeted solutions with code snippets.

Key Concepts
  • Troubleshooting Flowchart: Decision tree guiding systematic diagnosis of IoT issues by progressively narrowing the problem domain from symptoms to root cause
  • Symptom Isolation: First troubleshooting step identifying the observable failure (device not connecting, data not arriving, incorrect readings) to define the search space
  • Layer-by-Layer Diagnosis: OSI-model-inspired approach verifying each layer (physical, link, network, application) from bottom up to identify where the communication chain breaks
  • Binary Search Debugging: Halving the problem space with each diagnostic test — if A and B together fail but A alone passes, the issue is in B or the A-B interface
  • Differential Diagnosis: Testing multiple hypotheses simultaneously by changing one variable at a time to isolate which factor causes the observed failure
  • Known-Good Reference: Using a verified working device or configuration as a comparison baseline to distinguish environmental from configuration issues
  • Problem Replication: Consistently reproducing a failure before attempting to fix it — intermittent issues that cannot be reliably reproduced cannot be systematically fixed
  • Fix Verification: Confirming that an applied fix resolves the specific failure without introducing new symptoms, by retesting the original failure scenario
Chapter Scope (Avoiding Duplicate Hubs)

This chapter focuses on command-level and code-level diagnostic execution.

  • Use Troubleshooting Hub first when you need symptom-level triage and root-cause category selection.
  • Use Quick Reference Cards when you need broad protocol lookup tables across many topics.
  • Use this chapter when you need a strict yes/no decision path with concrete tests and fix snippets.

17.1 Learning Objectives

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

  • Classify: Categorize IoT failures into the five major problem domains (Wi-Fi/Network, MQTT/Messaging, Sensor, Power/Battery, Serial/Debug) based on observed symptoms
  • Apply: Follow structured decision-tree flowcharts to systematically diagnose connectivity, messaging, sensor, power, and serial communication issues
  • Evaluate: Interpret diagnostic outputs (ping results, MQTT error codes, sensor readings, voltage measurements) to distinguish between hardware, configuration, and environmental root causes
  • Design: Construct a layer-by-layer debugging strategy that isolates failures from the physical layer upward, using binary search and differential diagnosis techniques

17.2 IoT Troubleshooting Guide

Two-Layer Debugging Strategy
  1. Guided Mode: Select your problem category and follow the interactive flowchart. Answer each question honestly, execute diagnostic commands, and record the first failing step.
  2. Deep Mode: If unresolved, rerun with instrumentation (voltage, memory, timing, message paths) to validate assumptions.
  3. Reinforce Learning: Replay one equivalent scenario in a simulator or game after the fix to solidify the debugging pattern.

17.3 Select Problem Category

Show code
viewof problemCategory = Inputs.radio(
  ["Wi-Fi/Network", "MQTT/Messaging", "Sensor Issues", "Power/Battery", "Serial/Debug"],
  {label: "What's the problem?", value: "Wi-Fi/Network"}
)

17.4 Troubleshooting Flowchart

Show code
troubleshootingTrees = {
  return {
    "Wi-Fi/Network": {
      title: "Wi-Fi & Network Troubleshooting",
      color: "#3498DB",
      steps: [
        {
          id: "wifi-1",
          question: "Does the device power on and boot?",
          yes: "wifi-2",
          no: "wifi-power-fix",
          diagnostic: "Check LED indicators or serial output",
          code: "// Check boot - open Serial Monitor at 115200 baud"
        },
        {
          id: "wifi-power-fix",
          type: "solution",
          title: "Power Issue",
          solutions: [
            "Check USB cable - use data cable, not charge-only",
            "Try different USB port or power supply",
            "Verify voltage: ESP32 needs 3.3V, NodeMCU needs 5V via USB",
            "Check for short circuits on the board"
          ],
          code: "// Measure voltage at VIN and 3.3V pins with multimeter"
        },
        {
          id: "wifi-2",
          question: "Does WiFi.begin() return without hanging?",
          yes: "wifi-3",
          no: "wifi-begin-fix",
          diagnostic: "Add timeout to Wi-Fi connection",
          code: `WiFi.begin(ssid, password);
int timeout = 0;
while (WiFi.status() != WL_CONNECTED && timeout < 20) {
  delay(500);
  Serial.print(".");
  timeout++;
}
Serial.println(WiFi.status() == WL_CONNECTED ? "Connected!" : "Failed");`
        },
        {
          id: "wifi-begin-fix",
          type: "solution",
          title: "WiFi.begin() Hanging",
          solutions: [
            "Check SSID and password for typos (case-sensitive!)",
            "Ensure 2.4GHz network (ESP32/8266 don't support 5GHz)",
            "Try WiFi.mode(WIFI_STA) before begin()",
            "Add WiFi.disconnect() before begin() to clear old state",
            "Check if router has MAC filtering enabled"
          ],
          code: `WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
WiFi.begin(ssid, password);`
        },
        {
          id: "wifi-3",
          question: "Does WiFi.status() return WL_CONNECTED?",
          yes: "wifi-4",
          no: "wifi-status-fix",
          diagnostic: "Print Wi-Fi status code",
          code: `Serial.print("WiFi Status: ");
Serial.println(WiFi.status());
// 0=IDLE, 1=NO_SSID_AVAIL, 3=CONNECTED, 4=CONNECT_FAILED, 6=DISCONNECTED`
        },
        {
          id: "wifi-status-fix",
          type: "solution",
          title: "Wi-Fi Not Connecting",
          solutions: [
            "Status 1 (NO_SSID_AVAIL): SSID not found - check spelling, range",
            "Status 4 (CONNECT_FAILED): Wrong password or auth issue",
            "Status 6 (DISCONNECTED): Weak signal - move closer to router",
            "Try static IP if DHCP is slow",
            "Check router logs for connection attempts"
          ],
          code: `// Try static IP
IPAddress ip(192, 168, 1, 100);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WiFi.config(ip, gateway, subnet);
WiFi.begin(ssid, password);`
        },
        {
          id: "wifi-4",
          question: "Can you ping the device from your computer?",
          yes: "wifi-5",
          no: "wifi-ping-fix",
          diagnostic: "Get IP and try ping",
          code: `Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Then run: ping <ip-address> from terminal`
        },
        {
          id: "wifi-ping-fix",
          type: "solution",
          title: "Device Not Responding to Ping",
          solutions: [
            "Ensure computer is on same network/subnet",
            "Check if router has AP isolation enabled (disable it)",
            "Firewall on computer might block ICMP",
            "Try from another device on the network"
          ],
          code: "// Check subnet - both devices should be 192.168.x.x"
        },
        {
          id: "wifi-5",
          question: "Can the device reach the internet?",
          yes: "wifi-success",
          no: "wifi-internet-fix",
          diagnostic: "Try HTTP request to known server",
          code: `HTTPClient http;
http.begin("http://httpbin.org/ip");
int code = http.GET();
Serial.printf("HTTP Response: %d\\n", code);
if (code > 0) Serial.println(http.getString());
http.end();`
        },
        {
          id: "wifi-internet-fix",
          type: "solution",
          title: "No Internet Access",
          solutions: [
            "Check DNS - try IP address instead of hostname",
            "Verify gateway is correct (usually .1 or .254)",
            "Check if router has internet access",
            "Some networks require captive portal login"
          ],
          code: `// Test with IP instead of hostname
http.begin("http://142.250.185.238");  // Google IP`
        },
        {
          id: "wifi-success",
          type: "success",
          title: "Network is Working!",
          message: "Your Wi-Fi connection is functioning correctly. If you're still having issues, they may be application-level (MQTT, HTTP, etc.)"
        }
      ]
    },

    "MQTT/Messaging": {
      title: "MQTT Troubleshooting",
      color: "#9B59B6",
      steps: [
        {
          id: "mqtt-1",
          question: "Is Wi-Fi connected first?",
          yes: "mqtt-2",
          no: "mqtt-wifi-fix",
          diagnostic: "Check Wi-Fi status before MQTT",
          code: `if (WiFi.status() != WL_CONNECTED) {
  Serial.println("WiFi not connected!");
  return;
}`
        },
        {
          id: "mqtt-wifi-fix",
          type: "solution",
          title: "Wi-Fi Required First",
          solutions: [
            "MQTT requires network connectivity",
            "Ensure Wi-Fi is connected before mqtt.connect()",
            "See Wi-Fi troubleshooting flowchart"
          ],
          code: "// Connect Wi-Fi first, then MQTT"
        },
        {
          id: "mqtt-2",
          question: "Does mqtt.connect() return true?",
          yes: "mqtt-3",
          no: "mqtt-connect-fix",
          diagnostic: "Check connection result and state",
          code: `if (mqtt.connect("client-id")) {
  Serial.println("Connected!");
} else {
  Serial.print("Failed, rc=");
  Serial.println(mqtt.state());
}`
        },
        {
          id: "mqtt-connect-fix",
          type: "solution",
          title: "MQTT Connection Failed",
          solutions: [
            "State -4: Connection timeout - check broker address/port",
            "State -3: Connection lost - network issue",
            "State -2: Connect failed - wrong broker/port",
            "State -1: Disconnected - call connect() again",
            "State 4: Bad credentials - check username/password",
            "State 5: Unauthorized - check ACL permissions"
          ],
          code: `// Common broker settings
mqtt.setServer("broker.hivemq.com", 1883);  // Public broker
// OR
mqtt.setServer("test.mosquitto.org", 1883);
// For auth:
mqtt.connect("client-id", "username", "password");`
        },
        {
          id: "mqtt-3",
          question: "Does mqtt.loop() get called regularly?",
          yes: "mqtt-4",
          no: "mqtt-loop-fix",
          diagnostic: "mqtt.loop() must be in main loop",
          code: `void loop() {
  if (!mqtt.connected()) {
    reconnect();
  }
  mqtt.loop();  // MUST be called!
  // ... rest of code
}`
        },
        {
          id: "mqtt-loop-fix",
          type: "solution",
          title: "Missing mqtt.loop()",
          solutions: [
            "mqtt.loop() processes incoming messages and keepalives",
            "Must be called frequently (every loop iteration)",
            "Without it, connection will timeout after ~15 seconds",
            "Don't use long delay() calls that block the loop"
          ],
          code: `// Use non-blocking timing instead of delay()
unsigned long lastPublish = 0;
void loop() {
  mqtt.loop();
  if (millis() - lastPublish > 5000) {
    mqtt.publish("topic", "message");
    lastPublish = millis();
  }
}`
        },
        {
          id: "mqtt-4",
          question: "Does mqtt.publish() return true?",
          yes: "mqtt-5",
          no: "mqtt-publish-fix",
          diagnostic: "Check publish return value",
          code: `if (mqtt.publish("test/topic", "hello")) {
  Serial.println("Published!");
} else {
  Serial.println("Publish failed!");
}`
        },
        {
          id: "mqtt-publish-fix",
          type: "solution",
          title: "Publish Failed",
          solutions: [
            "Check if still connected: mqtt.connected()",
            "Topic might be too long (max ~128 chars safe)",
            "Payload might be too large (default 256 bytes)",
            "Increase buffer: mqtt.setBufferSize(512)"
          ],
          code: `mqtt.setBufferSize(1024);  // Increase buffer
// Check connection before publish
if (!mqtt.connected()) {
  Serial.println("Reconnecting...");
  mqtt.connect("client-id");
}`
        },
        {
          id: "mqtt-5",
          question: "Are subscribed messages being received?",
          yes: "mqtt-success",
          no: "mqtt-subscribe-fix",
          diagnostic: "Check callback and subscription",
          code: `void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message on ");
  Serial.println(topic);
}
// In setup:
mqtt.setCallback(callback);
mqtt.subscribe("test/topic");`
        },
        {
          id: "mqtt-subscribe-fix",
          type: "solution",
          title: "Not Receiving Messages",
          solutions: [
            "setCallback() must be called before connect()",
            "subscribe() must be called after successful connect()",
            "Re-subscribe after reconnection",
            "Check topic matches exactly (case-sensitive)",
            "Use # wildcard to debug: mqtt.subscribe('test/#')"
          ],
          code: `void reconnect() {
  while (!mqtt.connected()) {
    if (mqtt.connect("client-id")) {
      mqtt.subscribe("my/topic");  // Re-subscribe!
    } else {
      delay(5000);
    }
  }
}`
        },
        {
          id: "mqtt-success",
          type: "success",
          title: "MQTT is Working!",
          message: "Your MQTT connection is functioning correctly. Messages are being published and received."
        }
      ]
    },

    "Sensor Issues": {
      title: "Sensor Troubleshooting",
      color: "#E67E22",
      steps: [
        {
          id: "sensor-1",
          question: "Is the sensor powered correctly?",
          yes: "sensor-2",
          no: "sensor-power-fix",
          diagnostic: "Check VCC and GND connections",
          code: "// Measure voltage at sensor VCC pin - should match sensor spec"
        },
        {
          id: "sensor-power-fix",
          type: "solution",
          title: "Sensor Power Issue",
          solutions: [
            "Check sensor voltage requirement (3.3V vs 5V)",
            "ESP32 3.3V pin max ~500mA total",
            "Use external power for high-current sensors",
            "Add decoupling capacitor (100nF) near VCC",
            "Check for loose connections"
          ],
          code: "// Most sensors work at 3.3V, check datasheet"
        },
        {
          id: "sensor-2",
          question: "For I2C: Does I2C scanner find the device?",
          yes: "sensor-3",
          no: "sensor-i2c-fix",
          diagnostic: "Run I2C scanner",
          code: `#include <Wire.h>
void setup() {
  Serial.begin(115200);
  Wire.begin();
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.printf("Found at 0x%02X\\n", addr);
    }
  }
}`
        },
        {
          id: "sensor-i2c-fix",
          type: "solution",
          title: "I2C Device Not Found",
          solutions: [
            "Check SDA/SCL connections (ESP32: SDA=21, SCL=22)",
            "Add pull-up resistors (4.7k-10k to 3.3V)",
            "Check address - some sensors have configurable addresses",
            "Reduce I2C speed: Wire.setClock(100000)",
            "Check for address conflicts"
          ],
          code: `// Try different pins
Wire.begin(SDA_PIN, SCL_PIN);
// Slow down I2C
Wire.setClock(100000);`
        },
        {
          id: "sensor-3",
          question: "Does the sensor library initialize?",
          yes: "sensor-4",
          no: "sensor-init-fix",
          diagnostic: "Check begin() return value",
          code: `if (!sensor.begin()) {
  Serial.println("Sensor init failed!");
  while(1);
}`
        },
        {
          id: "sensor-init-fix",
          type: "solution",
          title: "Sensor Init Failed",
          solutions: [
            "Check if correct library is installed",
            "Verify sensor I2C address matches library default",
            "Try specifying address: sensor.begin(0x76)",
            "Check for library version compatibility",
            "Reset sensor power (turn off, wait 1s, turn on)"
          ],
          code: `// Specify address explicitly
if (!bme.begin(0x76)) {  // or 0x77
  Serial.println("Could not find BME280");
}`
        },
        {
          id: "sensor-4",
          question: "Are readings reasonable (not NaN or extreme)?",
          yes: "sensor-success",
          no: "sensor-reading-fix",
          diagnostic: "Print raw values",
          code: `float value = sensor.readValue();
Serial.printf("Raw: %.2f\\n", value);
if (isnan(value)) Serial.println("NaN detected!");`
        },
        {
          id: "sensor-reading-fix",
          type: "solution",
          title: "Bad Sensor Readings",
          solutions: [
            "NaN: Communication issue or sensor not ready",
            "All zeros: Check power and connections",
            "Extreme values: Check units and scaling",
            "Noisy readings: Add averaging or filtering",
            "Stuck values: Sensor might need calibration or reset"
          ],
          code: `// Add averaging
float readAveraged(int samples) {
  float sum = 0;
  for (int i = 0; i < samples; i++) {
    sum += analogRead(SENSOR_PIN);
    delay(10);
  }
  return sum / samples;
}`
        },
        {
          id: "sensor-success",
          type: "success",
          title: "Sensor is Working!",
          message: "Your sensor is functioning correctly and returning valid readings."
        }
      ]
    },

    "Power/Battery": {
      title: "Power & Battery Troubleshooting",
      color: "#27AE60",
      steps: [
        {
          id: "power-1",
          question: "Does the device work when USB-powered?",
          yes: "power-2",
          no: "power-usb-fix",
          diagnostic: "Test with USB first",
          code: "// Connect to computer USB and check serial output"
        },
        {
          id: "power-usb-fix",
          type: "solution",
          title: "USB Power Issue",
          solutions: [
            "Try different USB cable (data cable, not charge-only)",
            "Try different USB port or computer",
            "Check for short circuits on the board",
            "Measure current draw - might exceed USB limit (500mA)"
          ],
          code: "// USB typically provides 500mA max"
        },
        {
          id: "power-2",
          question: "Is battery voltage in correct range?",
          yes: "power-3",
          no: "power-battery-fix",
          diagnostic: "Measure battery with multimeter",
          code: "// LiPo: 3.0V (empty) to 4.2V (full)"
        },
        {
          id: "power-battery-fix",
          type: "solution",
          title: "Battery Voltage Issue",
          solutions: [
            "Below 3.0V: Battery is dead/damaged - replace",
            "Above 4.2V: Overcharged - dangerous, stop using",
            "Check polarity - reversed will damage board",
            "Use battery with protection circuit (BMS)"
          ],
          code: "// Safe LiPo range: 3.0V - 4.2V"
        },
        {
          id: "power-3",
          question: "Does voltage drop significantly under load?",
          yes: "power-load-fix",
          no: "power-4",
          diagnostic: "Measure voltage while device runs",
          code: "// Measure at VIN while Wi-Fi is active"
        },
        {
          id: "power-load-fix",
          type: "solution",
          title: "Voltage Drop Under Load",
          solutions: [
            "Battery can't supply enough current",
            "Add larger capacitor (100-1000uF) near VIN",
            "Use battery with higher discharge rate (C rating)",
            "Reduce peak current: stagger operations",
            "Check for high resistance in connections"
          ],
          code: `// Stagger high-power operations
WiFi.begin(ssid, pass);
delay(100);  // Let Wi-Fi stabilize
// Then start sensors...`
        },
        {
          id: "power-4",
          question: "Is deep sleep working correctly?",
          yes: "power-5",
          no: "power-sleep-fix",
          diagnostic: "Check sleep current",
          code: `esp_sleep_enable_timer_wakeup(10 * 1000000);  // 10 seconds
esp_deep_sleep_start();
// Measure current during sleep - should be ~10uA`
        },
        {
          id: "power-sleep-fix",
          type: "solution",
          title: "Deep Sleep Not Working",
          solutions: [
            "Disable WiFi/BT before sleep: WiFi.mode(WIFI_OFF)",
            "Some pins prevent sleep - check GPIO states",
            "External components may draw power",
            "Use esp_wifi_stop() for lowest power",
            "Check for LED or other always-on components"
          ],
          code: `// Proper deep sleep sequence
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
btStop();
esp_deep_sleep_start();`
        },
        {
          id: "power-5",
          question: "Is battery life meeting expectations?",
          yes: "power-success",
          no: "power-life-fix",
          diagnostic: "Calculate expected vs actual",
          code: "// Expected hours = mAh / avg_mA"
        },
        {
          id: "power-life-fix",
          type: "solution",
          title: "Battery Life Too Short",
          solutions: [
            "Measure actual current consumption",
            "Increase sleep time, decrease active time",
            "Reduce Wi-Fi usage - it's the biggest drain",
            "Lower CPU frequency: setCpuFrequencyMhz(80)",
            "Use RTC memory to avoid full boot"
          ],
          code: `// Reduce power
setCpuFrequencyMhz(80);  // Instead of 240
// Store data in RTC memory
RTC_DATA_ATTR int bootCount = 0;`
        },
        {
          id: "power-success",
          type: "success",
          title: "Power System is Working!",
          message: "Your power system is functioning correctly with expected battery life."
        }
      ]
    },

    "Serial/Debug": {
      title: "Serial & Debug Troubleshooting",
      color: "#E74C3C",
      steps: [
        {
          id: "serial-1",
          question: "Is the correct COM port selected?",
          yes: "serial-2",
          no: "serial-port-fix",
          diagnostic: "Check Device Manager/System Info",
          code: "// Windows: Device Manager > Ports\n// Mac: ls /dev/cu.*\n// Linux: ls /dev/ttyUSB* /dev/ttyACM*"
        },
        {
          id: "serial-port-fix",
          type: "solution",
          title: "COM Port Not Found",
          solutions: [
            "Install USB-to-Serial driver (CP210x or CH340)",
            "Try different USB port",
            "Check cable is data-capable",
            "On Mac, look for /dev/cu.* devices",
            "On Linux, add user to dialout group"
          ],
          code: "// Linux: sudo usermod -a -G dialout $USER"
        },
        {
          id: "serial-2",
          question: "Is baud rate correct (usually 115200)?",
          yes: "serial-3",
          no: "serial-baud-fix",
          diagnostic: "Match code and monitor baud rate",
          code: "Serial.begin(115200);  // Must match monitor setting"
        },
        {
          id: "serial-baud-fix",
          type: "solution",
          title: "Baud Rate Mismatch",
          solutions: [
            "Code and monitor must use same baud rate",
            "Common rates: 9600, 115200, 921600",
            "Garbage characters = wrong baud rate",
            "Boot messages at 74880 baud (ESP8266)"
          ],
          code: "Serial.begin(115200);  // Standard for ESP32"
        },
        {
          id: "serial-3",
          question: "Do you see any output at all?",
          yes: "serial-4",
          no: "serial-output-fix",
          diagnostic: "Add early serial output",
          code: `void setup() {
  Serial.begin(115200);
  delay(100);  // Wait for serial
  Serial.println("Boot!");
}`
        },
        {
          id: "serial-output-fix",
          type: "solution",
          title: "No Serial Output",
          solutions: [
            "Add delay after Serial.begin()",
            "Check TX pin not used for something else",
            "Try different terminal program",
            "Reset board with monitor already open",
            "Check if boot mode is correct"
          ],
          code: `void setup() {
  Serial.begin(115200);
  while(!Serial) { delay(10); }  // Wait for serial
  Serial.println("Ready!");
}`
        },
        {
          id: "serial-4",
          question: "Is output readable (not garbage)?",
          yes: "serial-success",
          no: "serial-garbage-fix",
          diagnostic: "Check for clear text",
          code: "// Readable: 'Hello World'\n// Garbage: '?x???~'"
        },
        {
          id: "serial-garbage-fix",
          type: "solution",
          title: "Garbage Characters",
          solutions: [
            "Baud rate mismatch - most common cause",
            "Wrong serial mode (8N1 is default)",
            "EMI interference on serial lines",
            "Power supply noise",
            "Try different baud rate: 9600, 74880, 115200"
          ],
          code: "// Try 74880 for ESP8266 boot messages"
        },
        {
          id: "serial-success",
          type: "success",
          title: "Serial is Working!",
          message: "Your serial connection is functioning correctly. You can now debug your code."
        }
      ]
    }
  };
}

// Get current tree
currentTree = troubleshootingTrees[problemCategory]

// State management using viewof for reactivity
viewof troubleshootState = {
  const initialState = {
    currentStep: currentTree.steps[0].id,
    history: [],
    tree: currentTree
  };

  const container = document.createElement('div');
  container.style.display = 'none';
  container.value = initialState;

  // Expose state management functions globally
  window.troubleshootNav = {
    goToStep: (stepId) => {
      container.value = {
        ...container.value,
        history: [...container.value.history, container.value.currentStep],
        currentStep: stepId
      };
      container.dispatchEvent(new Event('input', { bubbles: true }));
    },
    goBack: () => {
      if (container.value.history.length > 0) {
        const newHistory = [...container.value.history];
        const prevStep = newHistory.pop();
        container.value = {
          ...container.value,
          history: newHistory,
          currentStep: prevStep
        };
        container.dispatchEvent(new Event('input', { bubbles: true }));
      }
    },
    reset: () => {
      container.value = {
        ...container.value,
        currentStep: container.value.tree.steps[0].id,
        history: []
      };
      container.dispatchEvent(new Event('input', { bubbles: true }));
    }
  };

  return container;
}

// Find step by ID
findStep = (id) => currentTree.steps.find(s => s.id === id)

// Current step from state
currentStep = troubleshootState.currentStep
history = troubleshootState.history
Show code
// Render current step
html`
<style>
.troubleshoot-container {
  max-width: 800px;
  margin: 0 auto;
}
.troubleshoot-header {
  background: ${currentTree.color};
  color: white;
  padding: 20px;
  border-radius: 12px 12px 0 0;
  text-align: center;
}

.troubleshoot-header h3 {
  margin: 0;
  color: #ffffff;
  font-size: 1.35rem;
  line-height: 1.2;
}

.troubleshoot-content {
  background: white;
  border: 2px solid ${currentTree.color};
  border-top: none;
  border-radius: 0 0 12px 12px;
  padding: 25px;
}
.question-box {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 10px;
  margin-bottom: 20px;
  border-left: 4px solid ${currentTree.color};
}
.question-text {
  font-size: 18px;
  font-weight: bold;
  color: #2C3E50;
  margin-bottom: 15px;
}
.diagnostic-tip {
  background: #E8F6F3;
  padding: 10px 15px;
  border-radius: 6px;
  font-size: 14px;
  color: #16A085;
  margin-bottom: 15px;
}
.code-block {
  background: #1e1e1e;
  color: #d4d4d4;
  padding: 15px;
  border-radius: 8px;
  font-family: 'Fira Code', monospace;
  font-size: 13px;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin-bottom: 20px;
}
.answer-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
  justify-content: center;
}
.answer-btn {
  flex: 1 1 180px;
  padding: 12px 40px;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  font-weight: bold;
  cursor: pointer;
  transition: transform 0.2s, box-shadow 0.2s;
}
.answer-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
.btn-yes {
  background: #27AE60;
  color: white;
}
.btn-no {
  background: #E74C3C;
  color: white;
}
.solution-box {
  background: #FEF9E7;
  border: 2px solid #F39C12;
  border-radius: 12px;
  padding: 20px;
}
.solution-title {
  color: #E67E22;
  font-size: 20px;
  font-weight: bold;
  margin-bottom: 15px;
}
.solution-list {
  margin: 0;
  padding-left: 20px;
}
.solution-list li {
  margin-bottom: 10px;
  color: #2C3E50;
}
.success-box {
  background: #D5F4E6;
  border: 2px solid #27AE60;
  border-radius: 12px;
  padding: 25px;
  text-align: center;
}
.success-icon {
  font-size: 48px;
  margin-bottom: 15px;
}
.success-title {
  color: #27AE60;
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 10px;
}
.nav-buttons {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #eee;
}
.nav-btn {
  padding: 10px 20px;
  border: 1px solid #ccc;
  background: white;
  border-radius: 6px;
  cursor: pointer;
  color: #2C3E50;
  font-weight: 600;
}
.nav-btn:hover {
  background: #f0f0f0;
}
.nav-btn:disabled {
  background: #adb5bd;
  border-color: #adb5bd;
  color: #ffffff;
  cursor: not-allowed;
}
.progress-dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 15px;
}
.progress-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ddd;
}
.progress-dot.active {
  background: ${currentTree.color};
}
.progress-dot.completed {
  background: #27AE60;
}
@media (max-width: 700px) {
  .troubleshoot-header {
    padding: 16px;
  }
  .troubleshoot-content,
  .question-box,
  .solution-box,
  .success-box {
    padding: 16px;
  }
  .question-text {
    font-size: 16px;
  }
  .answer-buttons,
  .nav-buttons {
    flex-direction: column;
  }
  .answer-btn,
  .nav-btn {
    width: 100%;
  }
}
</style>

<div class="troubleshoot-container">
  <div class="troubleshoot-header">
    <h3 style="margin: 0;">${currentTree.title}</h3>
  </div>

  <div class="troubleshoot-content">
    ${(() => {
      const step = findStep(currentStep);
      if (!step) return html`<p>Step not found</p>`;

      if (step.type === "solution") {
        return html`
          <div class="solution-box">
            <div class="solution-title">${step.title}</div>
            <ul class="solution-list">
              ${step.solutions.map(s => html`<li>${s}</li>`)}
            </ul>
            ${step.code ? html`<div class="code-block">${step.code}</div>` : ''}
          </div>
          <div class="nav-buttons">
            <button class="nav-btn" onclick="window.troubleshootNav?.goBack()">Back</button>
            <button class="nav-btn" onclick="window.troubleshootNav?.reset()">Start Over</button>
          </div>
        `;
      }

      if (step.type === "success") {
        return html`
          <div class="success-box">
            <div class="success-icon">&#10004;</div>
            <div class="success-title">${step.title}</div>
            <p>${step.message}</p>
          </div>
          <div class="nav-buttons">
            <button class="nav-btn" onclick="window.troubleshootNav?.goBack()">Back</button>
            <button class="nav-btn" onclick="window.troubleshootNav?.reset()">Start Over</button>
          </div>
        `;
      }

      // Question step
      return html`
        <div class="question-box">
          <div class="question-text">${step.question}</div>
          ${step.diagnostic ? html`<div class="diagnostic-tip"><strong>Tip:</strong> ${step.diagnostic}</div>` : ''}
        </div>

        ${step.code ? html`<div class="code-block">${step.code}</div>` : ''}

        <div class="answer-buttons">
          <button class="answer-btn btn-yes" onclick="window.troubleshootNav?.goToStep('${step.yes}')">Yes</button>
          <button class="answer-btn btn-no" onclick="window.troubleshootNav?.goToStep('${step.no}')">No</button>
        </div>

        <div class="nav-buttons">
          <button class="nav-btn" onclick="window.troubleshootNav?.goBack()" ${history.length === 0 ? 'disabled' : ''}>Back</button>
          <button class="nav-btn" onclick="window.troubleshootNav?.reset()">Start Over</button>
        </div>
      `;
    })()}
  </div>
</div>
`

17.5 Quick Diagnostic Commands

17.5.1 Essential Debug Commands

Network

WiFi status

WiFi.status()

Expected: 3 = Connected

Network

IP address

WiFi.localIP()

Expected: e.g., 192.168.1.100

Signal

Signal strength

WiFi.RSSI()

Expected: -30 (excellent) to -90 (poor)

Memory

Free memory

ESP.getFreeHeap()

Expected: >20000 bytes healthy

Messaging

MQTT state

mqtt.state()

Expected: 0 = Connected

Sensors

I2C scan

See code above

Expected: device addresses listed

17.5.2 Common Error Codes

Wi-Fi Status

0
WL_IDLE_STATUS
1
WL_NO_SSID_AVAIL
3
WL_CONNECTED
4
WL_CONNECT_FAILED
6
WL_DISCONNECTED

MQTT State

-4
Connection timeout
-3
Connection lost
-2
Connect failed
0
Connected
4
Bad credentials

17.6 Interactive Calculators

17.6.1 Debugging Time Savings Calculator

This calculator demonstrates how systematic troubleshooting saves time compared to random trial-and-error.

Show code
viewof numCauses = Inputs.range([4, 32], {
  label: "Number of possible root causes",
  step: 1,
  value: 16
})

viewof timePerTest = Inputs.range([1, 15], {
  label: "Minutes per diagnostic test",
  step: 1,
  value: 5
})

binaryTreeSteps = Math.ceil(Math.log2(numCauses))
trialErrorAvg = (numCauses + 1) / 2
trialErrorWorst = numCauses

binaryTreeTime = binaryTreeSteps * timePerTest
trialErrorAvgTime = trialErrorAvg * timePerTest
trialErrorWorstTime = trialErrorWorst * timePerTest

timeSavingsAvg = trialErrorAvgTime - binaryTreeTime
timeSavingsWorst = trialErrorWorstTime - binaryTreeTime
efficiencyAvg = ((timeSavingsAvg / trialErrorAvgTime) * 100).toFixed(1)
efficiencyWorst = ((timeSavingsWorst / trialErrorWorstTime) * 100).toFixed(1)
Show code
html`
<style>
.calc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
  margin-top: 20px;
}
.calc-card {
  background: #f8f9fa;
  border-left: 4px solid #2C3E50;
  border-radius: 8px;
  padding: 20px;
}
.calc-card.systematic {
  border-left-color: #16A085;
}
.calc-card.trial-error {
  border-left-color: #E74C3C;
}
.calc-title {
  font-size: 18px;
  font-weight: bold;
  color: #2C3E50;
  margin-bottom: 10px;
}
.calc-value {
  font-size: 32px;
  font-weight: bold;
  color: #16A085;
  margin: 10px 0;
}
.calc-value.warning {
  color: #E67E22;
}
.calc-value.danger {
  color: #E74C3C;
}
.calc-detail {
  font-size: 14px;
  color: #7F8C8D;
  margin-top: 8px;
}
.calc-savings {
  background: #D5F4E6;
  border: 2px solid #16A085;
  border-radius: 8px;
  padding: 20px;
  text-align: center;
  margin-top: 20px;
}
.calc-savings-value {
  font-size: 36px;
  font-weight: bold;
  color: #16A085;
}
</style>

<div class="calc-grid">
  <div class="calc-card systematic">
    <div class="calc-title">Systematic (Binary Tree)</div>
    <div class="calc-value">${binaryTreeSteps} steps</div>
    <div class="calc-detail">Maximum steps required</div>
    <div class="calc-value" style="font-size: 24px;">${binaryTreeTime} min</div>
    <div class="calc-detail">Total time (worst case)</div>
  </div>

  <div class="calc-card trial-error">
    <div class="calc-title">Trial & Error</div>
    <div class="calc-value warning">${trialErrorAvg.toFixed(1)} steps</div>
    <div class="calc-detail">Average steps</div>
    <div class="calc-value danger" style="font-size: 24px;">${trialErrorAvgTime.toFixed(1)} min</div>
    <div class="calc-detail">Average time</div>
  </div>
</div>

<div class="calc-savings">
  <div style="font-size: 18px; font-weight: bold; color: #2C3E50; margin-bottom: 10px;">
    Time Savings with Systematic Debugging
  </div>
  <div class="calc-savings-value">${timeSavingsAvg.toFixed(1)} minutes</div>
  <div style="font-size: 16px; color: #16A085; margin-top: 10px;">
    ${efficiencyAvg}% faster on average | ${efficiencyWorst}% faster worst-case
  </div>
  <div style="font-size: 14px; color: #7F8C8D; margin-top: 15px;">
    <strong>Insight:</strong> With ${numCauses} possible causes at ${timePerTest} min each,
    systematic debugging saves ${timeSavingsAvg.toFixed(0)}–${timeSavingsWorst.toFixed(0)} minutes
    by eliminating half the possibilities with each yes/no question.
  </div>
</div>
`

17.6.2 WiFi Signal Quality Calculator

Calculate expected WiFi performance based on RSSI (Received Signal Strength Indicator).

Show code
viewof rssi = Inputs.range([-90, -30], {
  label: "WiFi RSSI (dBm)",
  step: 1,
  value: -60
})

signalQuality = (() => {
  if (rssi >= -50) return { quality: "Excellent", color: "#16A085", performance: "Maximum throughput, stable connection" };
  if (rssi >= -60) return { quality: "Good", color: "#27AE60", performance: "High throughput, reliable" };
  if (rssi >= -70) return { quality: "Fair", color: "#F39C12", performance: "Moderate throughput, occasional drops" };
  if (rssi >= -80) return { quality: "Poor", color: "#E67E22", performance: "Low throughput, frequent disconnects" };
  return { quality: "Very Poor", color: "#E74C3C", performance: "Unusable, constant disconnects" };
})()

signalPercent = Math.max(0, Math.min(100, ((rssi + 100) * 2)))
Show code
html`
<style>
.signal-card {
  background: white;
  border: 2px solid ${signalQuality.color};
  border-radius: 12px;
  padding: 25px;
  margin-top: 20px;
}
.signal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}
.signal-quality {
  font-size: 28px;
  font-weight: bold;
  color: ${signalQuality.color};
}
.signal-rssi {
  font-size: 24px;
  color: #2C3E50;
}
.signal-bar-container {
  background: #ecf0f1;
  height: 30px;
  border-radius: 15px;
  overflow: hidden;
  position: relative;
  margin-bottom: 15px;
}
.signal-bar {
  background: ${signalQuality.color};
  height: 100%;
  width: ${signalPercent}%;
  transition: width 0.3s ease;
}
.signal-bar-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-weight: bold;
  color: #2C3E50;
  font-size: 14px;
}
.signal-performance {
  color: #7F8C8D;
  font-size: 16px;
  margin-top: 10px;
}
@media (max-width: 700px) {
  .signal-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  .signal-quality {
    font-size: 24px;
  }
  .signal-rssi {
    font-size: 20px;
  }
}
</style>

<div class="signal-card">
  <div class="signal-header">
    <div class="signal-quality">${signalQuality.quality}</div>
    <div class="signal-rssi">${rssi} dBm</div>
  </div>
  <div class="signal-bar-container">
    <div class="signal-bar"></div>
    <div class="signal-bar-text">${signalPercent.toFixed(0)}% Signal Strength</div>
  </div>
  <div class="signal-performance">
    <strong>Expected Performance:</strong> ${signalQuality.performance}
  </div>
  <div style="margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px;">
    <strong style="color: #2C3E50;">Troubleshooting Tips:</strong>
    <ul style="margin: 10px 0 0 0; padding-left: 20px; color: #7F8C8D;">
      ${rssi < -70 ? `<li>Move device closer to router or add WiFi extender</li>` : ''}
      ${rssi < -70 ? `<li>Check for physical obstructions (walls, metal objects)</li>` : ''}
      ${rssi < -80 ? `<li>Consider switching to 2.4GHz if using 5GHz (better range)</li>` : ''}
      ${rssi < -80 ? `<li>Check for interference from other devices</li>` : ''}
      ${rssi >= -50 ? `<li>Signal is optimal for IoT applications</li>` : ''}
    </ul>
  </div>
</div>
`

17.6.3 ESP32 Power Consumption Estimator

Estimate battery life based on operation profile and battery capacity.

Show code
viewof batteryCapacity = Inputs.range([100, 5000], {
  label: "Battery capacity (mAh)",
  step: 100,
  value: 1000
})

viewof activePercent = Inputs.range([1, 100], {
  label: "Active time (%)",
  step: 1,
  value: 10
})

viewof useWiFi = Inputs.checkbox(["Use WiFi"], {value: ["Use WiFi"]})
viewof useBLE = Inputs.checkbox(["Use BLE"], {value: []})

// ESP32 power consumption estimates (mA)
deepSleepCurrent = 0.01
cpuOnlyCurrent = 40
wifiActiveCurrent = 240
bleCurrent = 100

activeCurrent = cpuOnlyCurrent +
  (useWiFi.includes("Use WiFi") ? wifiActiveCurrent : 0) +
  (useBLE.includes("Use BLE") ? bleCurrent : 0)

sleepPercent = 100 - activePercent
avgCurrent = (activeCurrent * activePercent / 100) + (deepSleepCurrent * sleepPercent / 100)
batteryLifeHours = batteryCapacity / avgCurrent
batteryLifeDays = batteryLifeHours / 24
Show code
html`
<style>
.power-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 15px;
  margin-top: 20px;
}
.power-stat {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  text-align: center;
  border-top: 4px solid #3498DB;
}
.power-stat-value {
  font-size: 28px;
  font-weight: bold;
  color: #2C3E50;
  margin: 10px 0;
}
.power-stat-label {
  font-size: 14px;
  color: #7F8C8D;
}
.power-breakdown {
  background: white;
  border: 2px solid #3498DB;
  border-radius: 10px;
  padding: 20px;
  margin-top: 20px;
}
.power-breakdown-title {
  font-size: 18px;
  font-weight: bold;
  color: #2C3E50;
  margin-bottom: 15px;
}
.power-row {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #ecf0f1;
}
.power-row:last-child {
  border-bottom: none;
  font-weight: bold;
  color: #3498DB;
}
@media (max-width: 700px) {
  .power-grid {
    grid-template-columns: 1fr;
  }
  .power-stat-value {
    font-size: 24px;
  }
  .power-row {
    gap: 12px;
  }
}
</style>

<div class="power-grid">
  <div class="power-stat">
    <div class="power-stat-label">Average Current</div>
    <div class="power-stat-value">${avgCurrent.toFixed(1)} mA</div>
  </div>
  <div class="power-stat" style="border-top-color: #16A085;">
    <div class="power-stat-label">Battery Life</div>
    <div class="power-stat-value" style="color: #16A085;">
      ${batteryLifeDays >= 1 ? batteryLifeDays.toFixed(1) + ' days' : batteryLifeHours.toFixed(1) + ' hrs'}
    </div>
  </div>
  <div class="power-stat" style="border-top-color: #E67E22;">
    <div class="power-stat-label">Active Current</div>
    <div class="power-stat-value" style="color: #E67E22;">${activeCurrent.toFixed(0)} mA</div>
  </div>
</div>

<div class="power-breakdown">
  <div class="power-breakdown-title">Power Budget Breakdown</div>
  <div class="power-row">
    <span>CPU (always on)</span>
    <span>${cpuOnlyCurrent} mA</span>
  </div>
  ${useWiFi.includes("Use WiFi") ? `
  <div class="power-row">
    <span>WiFi Radio</span>
    <span>${wifiActiveCurrent} mA</span>
  </div>
  ` : ''}
  ${useBLE.includes("Use BLE") ? `
  <div class="power-row">
    <span>BLE Radio</span>
    <span>${bleCurrent} mA</span>
  </div>
  ` : ''}
  <div class="power-row">
    <span>Deep Sleep (${sleepPercent}% of time)</span>
    <span>${deepSleepCurrent} mA</span>
  </div>
  <div class="power-row">
    <span>Weighted Average</span>
    <span>${avgCurrent.toFixed(1)} mA</span>
  </div>
</div>

<div style="margin-top: 15px; padding: 15px; background: #FEF9E7; border-radius: 8px; border-left: 4px solid #F39C12;">
  <strong style="color: #E67E22;">Optimization Tips:</strong>
  <ul style="margin: 10px 0 0 0; padding-left: 20px; color: #7F8C8D;">
    ${activePercent > 20 ? `<li>Reduce active time by using deep sleep more aggressively</li>` : ''}
    ${useWiFi.includes("Use WiFi") ? `<li>WiFi draws 240mA - consider using BLE or LoRa for lower power</li>` : ''}
    ${batteryLifeDays < 7 ? `<li>For week-long battery life, increase sleep time or battery capacity</li>` : ''}
    ${batteryLifeDays >= 30 ? `<li>Excellent power efficiency for IoT deployment!</li>` : ''}
  </ul>
</div>
`

17.7 Related Resources

  • Troubleshooting Hub - More debugging guides
  • Failure Case Studies - Learn from real failures
  • Code Snippet Library - Working code examples
  • MQTT Message Flow - MQTT visualization
  • Troubleshooting Hub - Additional diagnostic strategies
  • IoT Games Hub - Reinforce troubleshooting patterns with short challenge loops
Common Mistake: Skipping the Power Check and Going Straight to Code

The mistake: Rewriting Wi-Fi code before confirming the board has a stable voltage rail.

Why it happens: Many “mysterious” ESP32 failures are really power faults:

  • Wi-Fi bursts can pull about 240 mA
  • weak USB cables or ports sag under load
  • long wires and poor connectors add voltage drop
  • batteries can collapse even when the firmware is correct

Start here before opening the IDE:

  1. Measure VIN or 3.3V while the device is running.
  2. Trigger a high-current event such as Wi-Fi startup.
  3. If voltage drops more than 0.3V, fix the supply path first.
  4. Swap the USB cable before changing code.

Quick diagnostic snippet:

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Wi-Fi (240mA draw)...");
  WiFi.begin("test", "test");
  delay(100);
  Serial.println("Still alive after Wi-Fi init - power OK");
}

If the board browns out or reboots during that test, fix power first with a better cable, stronger supply, or added bulk capacitance.

Rule of thumb: Spend the first 5 minutes on the voltage rail. If power is unstable, software changes are noise.

Match Flowchart Categories to First Diagnostic Steps

Order: Following a Troubleshooting Decision Tree

Place these flowchart navigation steps in the correct order.

Key Takeaway

17.7.1 Putting Numbers to It

  • 16 possible root causes in a binary tree means 4 yes/no checks max
  • the same 16 causes by trial and error take 8.5 attempts on average
  • at 5 min per test, that is 20 min versus 42.5 min
  • systematic debugging is about 2x faster on average and 4x faster worst-case

Systematic debugging follows a binary decision tree: start with the most fundamental check (power, connectivity), then progressively narrow the root cause. Each branch provides diagnostic commands and ready-to-use code fixes, turning hours of frustration into minutes of methodical diagnosis.

Can’t Find Your Issue?

If your problem isn’t covered here, check the Discussion Prompts Hub to ask peers, or search the code snippets for working examples.

Concept Relationships: Diagnostic Troubleshooting Workflows

Wi-Fi Decision Tree

Relates to MQTT Troubleshooting

Wi-Fi must work before MQTT, so these flowcharts are sequential dependencies rather than separate branches.

Sensor I2C Scanner

Relates to ADC Resolution

I2C issues are often misdiagnosed as ADC problems, so check the bus before tuning measurement logic.

Power Diagnostics

Relates to Battery Life Calculator

Voltage measurements validate whether the modeled power budget matches the real device behavior under load.

Cross-module connection: Code Snippet Library - Ready-to-use diagnostic code snippets referenced in flowchart solutions

Common Pitfalls

1. Skipping to Advanced Diagnostic Steps Before Verifying Basics

Engineers with experience jump immediately to protocol analysis or log review before checking whether the device has power, the cable is connected, or the broker address is correct. Basic checks (power, physical connection, IP connectivity) catch 40-60% of IoT issues and take 2 minutes. Always complete the basic verification layer before advanced diagnosis.

2. Making Multiple Changes Simultaneously When Debugging

Changing the broker URL, QoS level, and TLS settings simultaneously makes it impossible to determine which change fixed (or broke) the system. Change one variable at a time and test between changes. This takes longer but produces definitive understanding of the cause.

3. Declaring an Intermittent Issue Fixed After One Successful Test

An IoT device that fails 1 in 100 connections requires running 500+ connection tests to verify a fix with 99% confidence. Declaring a fix successful after 5 successful tests provides only 95% confidence that a 1-in-20 failure rate is resolved — far from sufficient for production verification. Use statistical testing for intermittent issues.

🧠 Knowledge Check

17.8 What’s Next

In the next chapter, we’ll explore Failure Case Studies drawn from real-world IoT deployments that went wrong. You’ll learn about:

  • Documented failures in smart home, industrial IoT, and smart city projects with root cause analysis
  • Common failure patterns including cascading failures, security breaches, and integration breakdowns
  • Lessons learned and prevention strategies you can apply to your own projects

Previous Troubleshooting Hub

Current Troubleshooting Flowchart

Next IoT Failure Case Studies

Label the Diagram

Code Challenge

16  Troubleshooting Hub
18  IoT Failure Case Studies