The best overall Arduino simulation tool for most makers is Wokwi. It runs natively in the browser, supports modern architectures (ESP32, Pi Pico, Uno R4 WiFi), and accurately simulates IoT protocols like MQTT and WiFi. Use Autodesk Tinkercad Circuits strictly for basic Arduino Uno R3 analog/digital learning, and reserve Proteus for deep SPICE-level PCB trace analysis. If you are starting a new embedded project today, default to Wokwi.
The Decision Tree: Which Simulator to Pick
Choosing a simulator depends entirely on your target silicon and whether you need to simulate physical layer electronics (SPICE) or just firmware logic. Below is the decision matrix to terminate your search.
| Criteria | Wokwi | Tinkercad Circuits | Proteus Design Suite |
|---|---|---|---|
| Board Support | ESP32, Pi Pico, Uno R3/R4, STM32 | Uno R3, Micro:bit v1, Lilypad | AVR, PIC, ARM, extensive custom SPICE |
| IoT / WiFi Simulation | Yes (Native MQTT, HTTP, WiFi) | No | Limited (requires complex VSM setup) |
| Cost | Free (Open source core) | Free (Autodesk account required) | ~$300+ (Commercial license) |
| Best Use Case | Firmware logic, IoT, modern MCUs | Classroom basics, simple analog | PCB trace analysis, mixed-signal SPICE |
Project Spec Sheet & Pin Mapping
To demonstrate Wokwi's capabilities, we will build an I2C environmental monitor. This project is notorious for causing simulation headaches due to SRAM limits on the Uno R3 and I2C address conflicts.
Parts List (Exact Variants)
- MCU: Wokwi Arduino Uno R3 (ATmega328P, 16MHz, 2KB SRAM)
- Sensor: Adafruit BME280 I2C Breakout (Simulated as generic BME280 in Wokwi)
- Display: SSD1306 128x64 I2C OLED (Monochrome, 0x3C address)
Pin Mapping Table
| Component Pin | Arduino Uno R3 Pin | Wire Color (Virtual) | Notes |
|---|---|---|---|
| BME280 VIN | 5V | Red | Wokwi tolerates 5V on I2C logic, real hardware needs 3.3V |
| BME280 GND | GND | Black | Common ground required |
| BME280 SCL | A5 | Yellow | I2C Clock |
| BME280 SDA | A4 | Blue | I2C Data |
| OLED VCC | 5V | Red | SSD1306 charge pump handles 5V |
| OLED GND | GND | Black | Common ground |
| OLED SCL | A5 | Yellow | Shared I2C bus with BME280 |
| OLED SDA | A4 | Blue | Shared I2C bus with BME280 |
Complete Compilable Code
This code targets the Arduino Uno R3 (AVR) architecture. It includes explicit pin definitions, I2C initialization checks, and error handling to prevent silent failures.
Wokwi Setup Requirement: Unlike the Arduino IDE, Wokwi requires a libraries.txt file in your project root to fetch dependencies. Create a new file named libraries.txt and add:
Adafruit SSD1306
Adafruit GFX Library
Adafruit BME280 Library
Main Sketch (sketch.ino):
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_BME280.h>
// --- Pin Definitions & Constants ---
#define PIN_SDA A4
#define PIN_SCL A5
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define BME_ADDRESS 0x76 // Wokwi default BME280 address
// --- Object Instantiation ---
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_BME280 bme;
void setup() {
Serial.begin(115200);
while(!Serial); // Wait for serial monitor (optional in Wokwi)
// Initialize I2C with explicit pins (good practice for portability)
Wire.begin(PIN_SDA, PIN_SCL);
// 1. Initialize OLED with error handling
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed or not found"));
for(;;); // Halt execution to prevent phantom I2C writes
}
// 2. Initialize BME280 with error handling
if (!bme.begin(BME_ADDRESS, &Wire)) {
Serial.println(F("Could not find a valid BME280 sensor, check wiring!"));
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("BME280 ERROR");
display.display();
for(;;);
}
// Configure Display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
}
void loop() {
float tempC = bme.readTemperature();
float humidity = bme.readHumidity();
float pressure = bme.readPressure() / 100.0F;
// Render to OLED
display.clearDisplay();
display.setCursor(0, 0);
display.print("Temp: "); display.print(tempC); display.println(" C");
display.print("Hum: "); display.print(humidity); display.println(" %");
display.print("Pres: "); display.print(pressure); display.println(" hPa");
display.display();
// Mirror to Serial
Serial.print(tempC); Serial.print(",");
Serial.print(humidity); Serial.print(",");
Serial.println(pressure);
delay(2000); // 2Hz update rate
}
Debugging Simulation Errors
When your simulation fails to compile or crashes at runtime, follow this exact diagnostic path.
The First Three Things to Check
- Verify
libraries.txtsyntax: Wokwi does not auto-magically know your includes. If the file is missing or misspelled, compilation fails immediately. - Check I2C Hex Addresses: The physical Adafruit BME280 defaults to
0x77, but Wokwi's virtual BME280 defaults to0x76. The SSD1306 is almost always0x3C. Mismatched hex addresses cause silent hangs. - Monitor the Serial Output: Open the Wokwi Serial Terminal (bottom right). If the setup loop halts, the serial debug strings will tell you exactly which sensor failed initialization.
Exact Error Strings & Ranked Causes
Error 1: fatal error: Adafruit_SSD1306.h: No such file or directory
- Cause A (95% likely): You forgot to create the
libraries.txtfile in the Wokwi project root, or you named itlibraries.txt.txt(Windows file extension hiding issue). - Cause B (5% likely): The library name in the text file is misspelled. It must exactly match the Arduino Library Manager registry name.
Error 2: SSD1306 allocation failed (Printed to Serial, screen stays blank)
- Cause A (90% likely): SRAM Exhaustion. The ATmega328P on the Uno R3 has only 2048 bytes of SRAM. The
Adafruit_SSD1306library allocates a 1024-byte frame buffer (128x64 / 8). Adding the BME280 library and Wire buffers pushes you over the edge. Thenewoperator fails, returning null. - Fix: Switch to the U8g2 library in Wokwi, which supports "page buffer" mode (using only ~128 bytes of RAM), or change your target board in Wokwi to an ESP32 (which has 520KB of SRAM).
Error 3: Could not find a valid BME280 sensor, check wiring!
- Cause A: Address mismatch. Change
#define BME_ADDRESS 0x76to0x77in the code, or use the Wokwi I2C scanner snippet to poll the bus. - Cause B: You wired the BME280 to the SPI pins instead of I2C in the virtual diagram. Ensure SDA/SCL are used, not MOSI/MISO.
Extending and Simplifying the Build
Once the baseline simulation is stable, you must decide whether to scale the project up for production or strip it down for resource-constrained hardware.
How to Extend (Adding IoT)
If you want to push this sensor data to a dashboard, the Uno R3 is the wrong tool.
Action: Delete the Uno R3 in Wokwi and drop in an ESP32 DevKit V1.
The I2C pins on the ESP32 default to GPIO 21 (SDA) and GPIO 22 (SCL). Update your #define statements accordingly. You can then add the WiFi.h and PubSubClient libraries to your libraries.txt and push the BME280 data to an MQTT broker. Wokwi provides a free, simulated MQTT broker at wss://mqtt.wokwi.com for testing without local network setup.
How to Simplify (Resource Constraints)
If you are forced to use an 8-bit AVR (like an ATtiny85 or a bare ATmega328P on a custom PCB) and cannot afford the 1KB SRAM hit of the Adafruit OLED library:
Action: Remove the OLED entirely. Rely solely on Serial.println() for debugging, or switch to a 16x2 I2C Character LCD using the LiquidCrystal_I2C library, which requires less than 50 bytes of SRAM to operate. For comprehensive sensor integration guides, refer to the Adafruit BME280 documentation.






