25  Simulating Hardware Programming

25.1 Learning Objectives

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

  • Understand the role and benefits of hardware simulation in IoT development
  • Use online simulators for rapid prototyping without physical hardware
  • Simulate Arduino, ESP32, Raspberry Pi, and other microcontroller platforms

Key Concepts

  • Hardware Simulation: Executing actual firmware in a virtual environment that models the timing, register behavior, and peripheral responses of physical microcontroller hardware
  • Wokwi: A browser-based IoT hardware simulator supporting ESP32, Arduino, Raspberry Pi Pico with virtual sensors, displays, and communication modules; enables firmware testing without purchasing hardware
  • Tinkercad Circuits: Autodesk’s web-based circuit and code simulator for Arduino projects; integrates schematic capture with code execution and multimeter/oscilloscope probes
  • Virtual Peripheral: A simulated hardware module (LED, LCD, DHT22 sensor, servo) that responds to the same electrical signals and protocols as the real component
  • Register-Level Simulation: Simulation that models the actual hardware registers of the MCU, enabling low-level peripheral configuration code to run correctly without physical hardware
  • Simulation Breakpoint: A debugger pause point set in simulated firmware; allows inspection of register values, variable states, and memory contents at a specific program location
  • Waveform Viewer: A tool in hardware simulators that captures and displays the digital signals on GPIO pins over time, enabling timing analysis without a physical oscilloscope
In 60 Seconds

Hardware simulation in tools like Wokwi and Tinkercad lets you run actual microcontroller firmware with virtual sensors, displays, and communication modules before purchasing any hardware — catching code bugs and circuit design errors that would otherwise require multiple expensive physical prototyping iterations.

  • Test and debug firmware in virtual environments
  • Validate circuit designs before hardware assembly
  • Recognize limitations of simulation and when physical hardware is required
  • Transition from simulated to physical hardware deployments
  • Apply best practices for simulation-driven development workflows

Design methodology gives you a structured, proven process for creating IoT systems from initial concept to finished product. Think of it like following a recipe when cooking a complex meal – the methodology tells you what to do first, how to handle each step, and how to bring everything together into a successful final result.

“You do not need to buy hardware to start programming IoT devices,” said Max the Microcontroller excitedly. “Simulators like Wokwi let you build virtual circuits and write real code for Arduino, ESP32, and Raspberry Pi – all in your web browser! If your code crashes, no real components get damaged.”

Sammy the Sensor listed the benefits: “You can test your sensor reading code at home without buying a single sensor. You can simulate extreme temperatures without putting anything in a freezer. And you can share your project with classmates just by sending a link – no need to ship hardware!”

“But simulators have limits,” cautioned Lila the LED. “They cannot perfectly replicate radio interference, battery behavior under load, or how components act in extreme heat. That is why you start in simulation, get the code mostly right, then move to real hardware for final testing.” Bella the Battery agreed, “Simulate first to save time and money, then validate on real devices to catch what simulation misses!”

25.2 Introduction

Hardware simulation enables developers to write, test, and debug embedded firmware without physical devices. This capability accelerates development, reduces costs, enables remote collaboration, and allows experimentation without risk of damaging components. Modern simulators provide pixel-perfect emulation of microcontroller behavior, peripheral interactions, and even wireless communication, making them invaluable tools throughout the development lifecycle.

Definition

Hardware Simulation is the process of creating a virtual model of embedded hardware (microcontrollers, sensors, circuits) that executes firmware code and emulates device behavior in software, allowing development and testing without physical components.

25.2.1 How Hardware Simulation Works

Hardware simulation creates a virtual model of microcontroller hardware that executes real firmware code. The simulator emulates CPU instruction execution cycle-by-cycle, maintains virtual registers and memory, simulates peripheral interfaces (GPIO, I2C, SPI, ADC), and provides virtual sensor inputs you can control. When your firmware reads a GPIO pin, the simulator returns the virtual pin state. When firmware writes to an I2C device, the simulator emulates the I2C transaction and updates the virtual device state. This allows full firmware development and debugging without physical hardware, though timing precision and analog behavior may be idealized compared to real silicon.

This topic is covered in four focused chapters:

25.3 Chapter Overview

25.3.1 Hardware Simulation Fundamentals

For beginners - Learn why hardware simulation matters and when to use it. This chapter covers:

  • What hardware simulation is and how it works
  • Flight simulator analogy for understanding simulation benefits
  • Comparison of physical hardware vs. simulation approaches
  • Decision framework for choosing simulation vs. hardware
  • Your first 5-minute simulation exercise

25.3.2 Online Hardware Simulators

Hands-on with simulators - Explore specific simulation platforms with embedded interactive examples:

  • Wokwi: Arduino and ESP32 simulation with Wi-Fi, sensors, and displays
  • Tinkercad Circuits: Beginner-friendly visual block programming
  • SimulIDE: Desktop-based real-time simulation with measurement tools
  • Proteus Design Suite: Professional PCB design with simulation
  • Video tutorials for getting started

25.3.3 Platform-Specific Emulation and Debugging

Advanced emulation - Deep dive into professional emulation and debugging:

  • QEMU: Full Raspberry Pi OS emulation for software development
  • Renode: Multi-architecture simulation with deterministic execution
  • Debugging techniques: Breakpoints, variable watching, serial monitors
  • Logic analyzers and GDB: Advanced signal analysis and debugging
  • Testing strategies: Unit testing, integration testing, fuzz testing
  • Simulation limitations: Timing, peripherals, analog behavior

25.3.4 Simulation-Driven Development and Testing

Professional workflows - Production-ready development practices:

  • Four-phase workflow: Design, validation, optimization, production
  • IoT testing pyramid: Unit, integration, system, and field tests
  • Hardware-in-the-loop (HIL): Bridge simulation and physical testing
  • CI/CD integration: Automated testing with GitHub Actions
  • Transition checklists: From simulation to hardware deployment
  • Knowledge checks: Quiz questions to test understanding

25.4 Quick Start Guide

Your Goal Start Here
New to simulation? Fundamentals
Try simulators now Online Tools
Advanced debugging Platform Emulation
Production workflow Testing & Validation

25.5 Key Insight

The optimal development workflow combines simulation for initial development (80-90% of work) with targeted physical hardware testing for validation and optimization. Simulation excels at rapid prototyping, code development, education, collaboration, and automated testing, while physical hardware remains essential for timing validation, analog accuracy, environmental testing, and production certification.

Scenario: Build an ESP32 weather station that reads DHT22 sensor every 10 seconds, displays on OLED, and sends data via MQTT—all before buying hardware.

Step 1: Create Wokwi Project

Visit wokwi.com, create new ESP32 project.

Step 2: Add Virtual Components

diagram.json:

{
  "version": 1,
  "author": "IoT Developer",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-esp32-devkit-v1", "id": "esp32", "top": 0, "left": 0 },
    { "type": "wokwi-dht22", "id": "dht1", "top": 96, "left": 192 },
    { "type": "wokwi-ssd1306", "id": "oled1", "top": 32, "left": 300 }
  ],
  "connections": [
    [ "dht1:VCC", "esp32:3V3", "red", ["v0"] ],
    [ "dht1:GND", "esp32:GND", "black", ["v0"] ],
    [ "dht1:SDA", "esp32:D15", "green", ["v0"] ],
    [ "oled1:VCC", "esp32:3V3", "red", ["v0"] ],
    [ "oled1:GND", "esp32:GND", "black", ["v0"] ],
    [ "oled1:SCL", "esp32:D22", "yellow", ["v0"] ],
    [ "oled1:SDA", "esp32:D21", "blue", ["v0"] ]
  ]
}

Step 3: Write Code in Wokwi IDE

#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define DHT_PIN 15
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);
  dht.begin();

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("SSD1306 allocation failed");
    while(1);
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Weather Station");
  display.display();
  delay(2000);
}

void loop() {
  float temp = dht.readTemperature();
  float humidity = dht.readHumidity();

  if (isnan(temp) || isnan(humidity)) {
    Serial.println("Failed to read DHT sensor!");
    return;
  }

  // Display on OLED
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.print(temp, 1);
  display.println(" C");
  display.print(humidity, 0);
  display.println(" %");
  display.display();

  // Send to serial (simulates MQTT)
  Serial.printf("Temperature: %.1f C, Humidity: %.0f%%\n", temp, humidity);

  delay(10000);  // Read every 10 seconds
}

Step 4: Test in Simulation

Click “Start Simulation” in Wokwi. Observe:

  • OLED displays: 24.5 C and 62%
  • Serial monitor shows: Temperature: 24.5 C, Humidity: 62%
  • Virtual DHT22 changes values when you click on it

Step 5: Debug an Issue

Intentionally introduce bug:

float temp = dht.readTemperature() + 100;  // Bug: adds 100!

Simulation immediately shows 124.5 C on OLED. Fix discovered in 10 seconds without touching hardware!

Step 6: Add MQTT (Advanced)

Wokwi supports Wi-Fi simulation:

#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqttServer = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  // ... previous setup code ...

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");

  client.setServer(mqttServer, 1883);
}

void loop() {
  if (!client.connected()) {
    if (client.connect("WokwiWeatherStation")) {
      Serial.println("MQTT connected");
    }
  }
  client.loop();

  float temp = dht.readTemperature();
  float humidity = dht.readHumidity();

  // ... display code ...

  // Publish to MQTT
  char payload[50];
  snprintf(payload, sizeof(payload), "{\"temp\":%.1f,\"hum\":%.0f}", temp, humidity);
  client.publish("wokwi/weather", payload);
  Serial.printf("Published: %s\n", payload);

  delay(10000);
}

Simulation shows MQTT messages published successfully!

Step 7: Transition to Hardware

After 2 hours of simulation (code debugged, logic verified): 1. Order ESP32 ($5), DHT22 ($4), OLED ($6) = $15 total 2. Breadboard wiring matches Wokwi diagram exactly 3. Upload identical code via Arduino IDE 4. Works on first try! (Because logic was validated in simulation)

Time Saved: Without simulation, would have spent 2-3 days waiting for parts, then 2-4 hours debugging breadboard wiring issues. Simulation compressed this to 2 hours of productive development.

Key Lesson: Use simulation for logic development and debugging. Use hardware for final validation and edge cases (timing, electrical noise, real-world sensor behavior).

Simulation accelerates development by eliminating hardware delays. How much faster?

Physical hardware workflow: Breadboard wiring (30 min) + Component ordering (3-7 days) + Debugging wrong pins (1-2 hours) = ~3-7 days first iteration

Simulation workflow: Drag components (2 min) + Wire connections (5 min) + Debug code (30 min) = 37 minutes first iteration

\[\text{Speedup} = \frac{7\text{ days} \times 24\text{ h}}{37\text{ min}} = \frac{10,080\text{ min}}{37\text{ min}} \approx 272\times\]

This 270× speed advantage is why hardware simulation is the first step in professional IoT development—iterate rapidly in software before committing to physical components.

Question Simulation Hardware Rationale
Do you have the physical components? No parts yet Have parts Obvious: can’t use what you don’t own
Are you learning/teaching embedded programming? Simulation first Hardware after basics Simulation avoids destroying components with wiring mistakes
Is the code logic-heavy (algorithms, state machines)? Simulation Either Logic bugs caught faster in simulation (instant reset, no reflashing)
Does it involve precise timing (microsecond-level)? Hardware Hardware Simulators abstract timing—real hardware reveals race conditions
Is it analog signal processing? Hardware Hardware Simulators use idealized analog models (no noise, perfect linearity)
Wireless communication (Wi-Fi, BLE, LoRa)? Simulation for happy path Hardware for real RF Simulation can’t model interference, range limits, multipath fading
Power consumption critical? Hardware with power profiler Hardware Simulators estimate power but miss real leakage currents and sleep modes
Team collaboration (remote workers)? Simulation Hardware (mail parts) Shareable Wokwi link = instant collaboration, no shipping delay
Rapid iteration (change code 20× in an hour)? Simulation Simulation Reflashing hardware 20× is tedious; simulation reset is instant
Environmental testing (temperature, humidity)? Hardware in chamber Hardware Simulators don’t model temperature effects on components
Final validation before production? Hardware Hardware Simulation is for development; hardware is for validation

Workflow Strategy (Best Practice):

Phase 1: Concept (Simulation)
├─ Validate algorithm logic
├─ Test edge cases (overflow, divide-by-zero)
├─ Debug state machine transitions
└─ Share with team for review
   Duration: Hours to 1-2 days
   Cost: $0

Phase 2: Prototype (Simulation + Hardware)
├─ Order components (run simulation while waiting)
├─ Breadboard assembly
├─ Flash validated code from simulation
├─ Test on hardware: timing, analog accuracy, wireless range
└─ Discover hardware-specific issues (e.g., pull-up resistors needed)
   Duration: 3-7 days
   Cost: $20-100 (components)

Phase 3: Optimization (Hardware)
├─ Measure real power consumption
├─ Test in environmental chamber (-40°C to +85°C)
├─ Long-duration stability testing (24-48 hours)
└─ Optimize for production (reduce components, cut costs)
   Duration: 1-4 weeks
   Cost: $100-500 (test equipment, samples)

Phase 4: Production (Hardware)
├─ PCB design
├─ Manufacture pilot run (10-100 units)
├─ Automated testing fixtures
└─ Field trials with real users
   Duration: 1-3 months
   Cost: $1,000-$10,000+

Key Decision Points:

  • 80% of code logic → Develop in simulation
  • 20% of timing-critical/analog code → Develop on hardware
  • 100% of final validation → Test on hardware
Common Mistake: Assuming Simulation = Reality

The Mistake: A team develops an ESP32 + ultrasonic sensor (HC-SR04) in Wokwi, achieving perfect 2cm accuracy. On physical hardware, readings fluctuate wildly (±50cm) and sometimes timeout.

Why It Happens:

Simulators model ideal behavior, not real-world chaos:

What Simulation Models:

  • Perfect square-wave pulses
  • Instant signal propagation
  • No electrical noise
  • Unlimited MCU processing power
  • Ideal power supply (zero ripple)

What Hardware Has:

  • Ringing and reflections on long wires
  • Electrical noise from switching power supplies
  • Temperature-dependent signal timing
  • Interrupt latency and jitter
  • Voltage drops under load

Specific HC-SR04 Example:

In Wokwi:

digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);

duration = pulseIn(ECHO_PIN, HIGH);  // Always returns valid value
distance = duration * 0.034 / 2;     // Perfect calculation

Works every time: distance = 25.3 cm

On Hardware:

distance = 25.3 cm
distance = 75.8 cm  // Why?!
distance = 12.4 cm  // Inconsistent!
distance = 0 cm     // pulseIn() timeout!

Root Causes (Hardware-Specific Issues):

  1. Long jumper wires (30cm) act as antennas, picking up noise
    • Fix: Use short wires (<10cm) or twisted pair
  2. No pull-down resistor on ECHO pin
    • Floating pin reads random noise when sensor not pulsing
    • Fix: Add 10kΩ pull-down resistor
  3. Power supply noise
    • HC-SR04 draws 15mA pulse current, causing voltage sag
    • ESP32 ADC/timing affected by voltage fluctuations
    • Fix: Add 10μF decoupling capacitor near sensor VCC
  4. Interrupt conflicts
    • pulseIn() blocks interrupts, breaking Wi-Fi if called too often
    • Fix: Use interrupt-based pulse measurement instead
  5. Temperature sensitivity
    • Speed of sound varies: 343 m/s at 20°C, 331 m/s at 0°C
    • Simulation assumes constant 343 m/s
    • Fix: Measure ambient temperature, adjust: speed = 331.3 + (0.606 * tempC)

The Fixed Hardware Code:

// Add temperature compensation and noise filtering
const int SAMPLES = 5;
float distances[SAMPLES];

float readDistance() {
  // Collect multiple samples
  for (int i = 0; i < SAMPLES; i++) {
    digitalWrite(TRIG_PIN, LOW);
    delayMicroseconds(5);
    digitalWrite(TRIG_PIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG_PIN, LOW);

    long duration = pulseIn(ECHO_PIN, HIGH, 30000);  // 30ms timeout
    if (duration == 0) {
      distances[i] = -1;  // Mark invalid
    } else {
      float tempC = dht.readTemperature();
      float soundSpeed = 331.3 + (0.606 * tempC);
      distances[i] = (duration * soundSpeed) / 20000.0;  // cm
    }
    delay(60);  // HC-SR04 needs 60ms between readings
  }

  // Median filter (discard outliers)
  std::sort(distances, distances + SAMPLES);
  return distances[SAMPLES / 2];
}

Now hardware matches simulation: distance = 25.2 cm (stable!)

General Lessons:

Issue Simulation Hardware Reality Fix
Wiring Perfect connections Loose, noisy, capacitive Solder, short wires, shielding
Power Ideal 3.3V/5V Ripple, sag, dropout Decoupling caps, LDO regulator
Timing Microsecond precision Jitter, interrupt latency Measure actual timing, add margin
Sensors Instant, perfect response Warm-up time, drift Add delays, calibration routines
Wireless No interference Wi-Fi conflicts, range limits Channel selection, antenna placement

Key Takeaway: Simulation develops logic. Hardware discovers reality. Always plan for hardware validation time (expect 2-3 iterations to fix issues simulation couldn’t reveal).

25.6 Knowledge Check

25.7 Concept Check

Question 1: Your code works perfectly in Wokwi simulation but fails on real ESP32 hardware. What are three possible causes?

Show Answer
  1. Timing differences - Real hardware has interrupt latency; simulation is idealized
  2. Power supply noise - Real hardware has voltage ripple; simulation assumes perfect 3.3V
  3. Missing pull-up resistors - I2C requires external pull-ups; simulation may provide them automatically

Question 2: Can simulation replace all physical hardware testing?

Show Answer No! Simulation is excellent for logic development (80-90% of work) but cannot validate: precise timing (<1ms resolution), analog signal accuracy, RF interference, power consumption, or environmental effects (temperature, humidity). Always validate critical functions on real hardware.

25.8 Concept Relationships

Prerequisites:

  • Prototyping Software - Firmware development basics
  • Microcontroller Fundamentals - MCU architecture understanding

Builds Toward:

Complements:

25.9 See Also

25.10 Try It Yourself

Setup: Open Wokwi.com and create new ESP32 project

Task: Create a circuit where pressing a button toggles an LED on/off

Steps:

  1. Add components: ESP32, LED (GPIO 2), Button (GPIO 15), resistors
  2. Wire circuit in diagram.json
  3. Write firmware:
const int LED_PIN = 2;
const int BUTTON_PIN = 15;
bool ledState = false;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  static bool lastButton = HIGH;
  bool currentButton = digitalRead(BUTTON_PIN);

  if (lastButton == HIGH && currentButton == LOW) {
    ledState = !ledState;
    digitalWrite(LED_PIN, ledState);
  }
  lastButton = currentButton;
  delay(50);  // Debounce
}
  1. Run simulation, click button

What to Observe:

  • Does LED toggle on button press?
  • What happens without delay(50) debounce? (hint: multiple toggles!)
  • Try changing to BUTTON_PIN INPUT mode without pull-up - what happens?

Expected Outcome: LED toggles on each button press. Without debounce, mechanical contact bounce causes multiple rapid toggles. This demonstrates why simulation is great for logic testing but real hardware reveals timing/debounce needs.

Common Pitfalls

Simulators approximate real MCU timing but do not model clock jitter, interrupt latency variation, or peripheral DMA timing accurately. Code that works in simulation may fail on real hardware if it relies on precise microsecond timing. Always verify timing-critical code on actual hardware.

Simulation environments are too clean — they don’t model power supply noise, GPIO capacitance effects, or signal rise/fall time degradation with cable length. Real hardware reveals bugs that simulation never triggers. Use simulation for logic validation, then always test on hardware for integration.

Wokwi and other simulators model sleep mode power consumption approximately. A simulated 10 µA deep sleep may be 50 µA on real hardware due to leakage through GPIO pull-ups or peripheral power consumption not modeled in the simulator. Always measure real hardware for power-sensitive designs.

Most simulation tests exercise the normal operating sequence. Real devices encounter power glitches, sensor read errors, buffer overflows, and unexpected reset events. Actively inject failure conditions (disconnect the virtual I2C sensor mid-simulation) to validate error handling code.

25.11 What’s Next

Start with Hardware Simulation Fundamentals to understand why simulation matters, or jump directly to Online Hardware Simulators to try embedded Wokwi simulators immediately.

Previous Current Next
Reading a Spec Sheet Simulating Hardware Programming Simulating Testing and Validation