Can You Run Arduino Code on an ESP32? Complete Guide (August 2026)

I get this question almost every week from readers who are upgrading from an Arduino Uno or Nano to something more capable. The short answer is yes, you can run Arduino code on an ESP32, and in most cases the same sketch will work after a few small adjustments. The longer answer involves a software layer called the ESP32 Arduino Core, a couple of hardware quirks you must respect, and a handful of libraries that will need swapping. In this guide I’ll walk through everything you need to know, including how I ported my own Arduino weather station project over to an ESP32 last month and what surprised me along the way.

Quick Answer: Yes, You Can Run Arduino Code on ESP32

Yes, you can run Arduino code on an ESP32 using the open-source ESP32 Arduino Core maintained by Espressif. The core provides an Arduino-compatible layer on top of ESP-IDF, so the familiar setup() and loop() functions, digitalWrite(), Serial.print(), and most Arduino libraries all work on ESP32 hardware. The main things to watch are pin numbers (ESP32 GPIO labels differ from Arduino pin numbers), logic voltage (ESP32 is 3.3V, not 5V), and the few Arduino libraries that depend on AVR-specific hardware registers.

What Is the ESP32 Arduino Core?

The ESP32 Arduino Core is an open-source software layer that lets you program Espressif’s ESP32 family of microcontrollers using the Arduino IDE and the Arduino programming language. Officially maintained by Espressif on GitHub, the core translates familiar Arduino functions into calls that the ESP32’s dual-core Xtensa LX6 (or RISC-V on newer variants) processor can execute.

Think of it as a translator sitting between your sketch and the silicon. Your code looks and feels like standard Arduino, but underneath it’s calling ESP-IDF functions, FreeRTOS tasks, and ESP32-specific peripheral drivers. You can still mix in Arduino-style code and pure ESP-IDF calls in the same sketch, which makes the platform extremely flexible.

The core also exposes ESP32-specific features through standard Arduino abstractions. Calling WiFi.begin() turns on the radio, BLEDevice::init() starts the Bluetooth stack, and analogWrite() drives the LED PWM controller. Most Arduino users won’t notice the underlying complexity unless they go looking for it.

How to Install the ESP32 Arduino Core (Step by Step)

Installation takes about five minutes on a fresh Arduino IDE. Here’s the exact process I follow on my Windows machine, and the steps are nearly identical on macOS and Linux.

Step 1: Install the Arduino IDE. Download version 2.x from the official Arduino site. The legacy 1.8.x IDE works too, but the newer IDE handles board packages more smoothly.

Step 2: Add the ESP32 board manager URL. Open File > Preferences and paste this URL into the “Additional boards manager URLs” field:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Step 3: Install the ESP32 package. Go to Tools > Board > Boards Manager, search for “esp32”, and click Install on the “esp32 by Espressif Systems” entry. The package is roughly 250 MB, so give it a minute.

Step 4: Install the USB driver. Most ESP32 dev boards use either the CP210x or CH340 USB-to-serial chip. CP210x drivers come from Silicon Labs, while CH340 drivers come from the manufacturer. If your board isn’t recognized, this is almost always the cause.

Step 5: Select your board and port. Go to Tools > Board and pick your specific ESP32 variant (Dev Module, WROOM-32, S3, C3, etc.). Then pick the COM port from Tools > Port. On my setup the NodeMCU-32S shows up as a Silicon Labs CP210x device.

That’s it. You can now upload any Arduino sketch to your ESP32 by pressing the upload button.

Key Differences Between Arduino and ESP32 You Must Know

Most Arduino code runs on ESP32 without modification, but a few hardware differences will bite you if you’re not aware of them. These are the four that matter most in real projects.

Logic voltage: 3.3V versus 5V. This is the single biggest gotcha. The Arduino Uno runs GPIO at 5V, while every ESP32 GPIO is 3.3V. Feeding 5V into an ESP32 pin can damage it. If you have a 5V sensor, you need a level shifter or a 3.3V-compatible alternative. The good news is that ESP32 inputs are 5V-tolerant on most pins when used as inputs to read signals, but as outputs they will only drive 3.3V. If you’re designing your own boards, you can read more about power supply considerations for microcontrollers in our related guide.

Pin numbering. Arduino pins are labeled by their function on the board (D0, D1, A0), while ESP32 GPIOs are numbered by their internal silicon identifier. On an ESP32, “GPIO 2” is just pin number 2 on the chip, not pin 2 on the dev board. The silkscreen on most dev boards prints both, but always confirm before wiring.

Analog input resolution. The Arduino Uno’s ADC is 10-bit (0 to 1023). The ESP32’s ADC is 12-bit (0 to 4095), and there are known linearity issues on ADC2 when Wi-Fi is active. For accurate analog readings, use ADC1 (GPIO 32 through 39) and consider calibrating with analogSetAttenuation().

Memory and speed. The ESP32 has 520 KB of SRAM, 4 MB of flash (typically), and runs at 240 MHz across two cores. The Arduino Uno has 2 KB of RAM, 32 KB of flash, and runs at 16 MHz. Your sketches will compile larger and run faster, but you’ll also be more tempted to use that extra memory for sloppy code.

Library Compatibility: What Works and What Doesn’t

The good news is that most popular Arduino libraries work on ESP32 with zero changes. The Wire, SPI, EEPROM (now using Preferences), Servo, Adafruit_GFX, Adafruit_SSD1306, DHT, FastLED, and NeoPixel libraries all function correctly. Libraries that depend on AVR-specific registers (anything that pokes hardware timers directly, or libraries written for ATmega328P only) generally won’t work and need ESP32-specific replacements.

Here is a practical compatibility breakdown based on my testing and community feedback.

  • Fully compatible out of the box: Wire (I2C), SPI, SoftwareSerial (limited), Servo, Adafruit sensor libraries, FastLED, NeoPixel, RTClib, SD, Wire-based displays.
  • Compatible with minor changes: EEPROM (replaced by Preferences.h), IRremote (some send/receive pins differ), Adafruit_IO (check Wi-Fi client setup).
  • Not compatible without porting: Anything that uses AVR assembly, direct register manipulation for timers, libraries tied to ATmega-specific ADC behavior.
  • ESP32 has native alternatives: Instead of SoftwareSerial use the ESP32 hardware UARTs, instead of EEPROM use Preferences, instead of the Wi-Fi shield libraries use the built-in WiFi.h and HTTPClient.h.

If a library isn’t compiling on ESP32, the first thing I check is whether the library’s repository has an ESP32 branch or if a community fork supports it. Most popular libraries on GitHub now include ESP32 support in the default branch.

How to Port Existing Arduino Code to ESP32

Porting an Arduino sketch to ESP32 usually takes 10 to 30 minutes for a simple project, longer if you have hard-coded pin numbers or AVR-specific libraries. Here’s the workflow I follow.

Step 1: Inventory your pins and peripherals. Make a list of every pin number, every I2C address, every SPI device, and every library your sketch uses. This becomes your translation checklist.

Step 2: Map Arduino pins to ESP32 GPIOs. Replace each Arduino pin number with the ESP32 GPIO you’ll actually use. For example, if your Arduino sketch uses D13 for the built-in LED, the ESP32 equivalent is GPIO 2 (most dev boards). Keep a comment in the code so you remember the mapping later.

Step 3: Update voltage assumptions. If your sketch assumes 5V analog readings, scale the values. The 3.3V reference voltage on the ESP32 means an analog reading of 4095 equals 3.3V, not 5V. Adjust any threshold comparisons accordingly.

Step 4: Replace AVR-specific libraries. Swap EEPROM for Preferences, swap SoftwareSerial for a hardware UART if possible, and replace any direct register access with Arduino-standard function calls.

Step 5: Test on hardware. Upload the modified sketch and watch the Serial Monitor at 115200 baud (the ESP32 default). If anything goes wrong, the error usually appears within the first few seconds of boot.

For example, my Arduino weather station used DHT22 on pin D2, an SSD1306 OLED on I2C, and stored calibration values in EEPROM. The ESP32 version uses GPIO 4 for the DHT22, the same I2C bus for the OLED, and Preferences instead of EEPROM. Total code changes were about 15 lines.

Common Errors and Fixes When Running Arduino Code on ESP32

After porting dozens of sketches and helping forum users debug theirs, these are the errors that come up most often. Keep this checklist handy.

“A fatal error occurred: Failed to connect to ESP32” usually means the USB driver isn’t installed or you picked the wrong COM port. Reinstall the CP210x or CH340 driver, restart the IDE, and verify the port under Tools > Port.

“Brownout detector was triggered” means the ESP32 isn’t getting enough current. Many USB ports on older computers can’t supply the 500 mA peaks the ESP32 draws when Wi-Fi is active. Use a powered USB hub or a dedicated 3.3V supply rated for at least 500 mA.

GPIO doesn’t respond often means you picked a strapping pin. GPIO 0, 2, 5, 12, and 15 have special boot-time functions on some ESP32 variants. Avoid them in your design, or pull them to the correct level during reset.

Sketch won’t upload after a successful first upload is the classic “auto-reset not working” problem. Hold the BOOT button, press and release RESET, release BOOT, then try uploading again. Most dev boards add a USB-to-serial DTR circuit that handles this automatically, but cheap clones sometimes skip it.

Wi-Fi crashes when reading analog sensors on ADC2 is a known silicon quirk. Use ADC1 pins (GPIO 32 to 39) instead, or sample the analog signal before initializing Wi-Fi.

Compilation takes forever. The ESP32 toolchain is bigger than AVR. First compile can take two to five minutes, and incremental compiles usually take 20 to 60 seconds. Be patient, and consider the new Arduino IDE 2.x which caches compiled objects aggressively.

When ESP32 Is the Better Choice Over Arduino

There are clear cases where the ESP32 is the better pick, and equally clear cases where a classic Arduino still wins. The ESP32 shines whenever you need wireless connectivity, multitasking, or more memory than an 8-bit board can offer.

The most obvious advantage is built-in Wi-Fi and Bluetooth. Projects that would need a $20 Wi-Fi shield on Arduino get wireless connectivity for free on ESP32, plus BLE for low-energy peripherals. If you’re building IoT devices, sensor networks, or anything that talks to a phone, the ESP32 saves both money and code complexity.

The dual-core processor running at 240 MHz lets you run Wi-Fi handling on one core and your application code on the other. Combined with FreeRTOS underneath, you can build responsive real-time systems that wouldn’t be possible on an Uno.

For projects that need over-the-air updates, the ESP32 has the ArduinoOTA library and built-in HTTPS update support. You can flash new firmware over Wi-Fi without touching the board, which is invaluable for devices mounted in hard-to-reach places.

Stick with a classic Arduino when you need bulletproof 5V GPIO, simpler toolchains, ultra-low-cost boards, or rock-solid timing on a single thread. For learning embedded basics, blinking LEDs, or driving motors, the Uno and Nano remain excellent choices. You can always start with Smashing Robotics tutorials on either platform and migrate later.

Frequently Asked Questions

Can I use Arduino code on ESP32 without modification?

In many cases yes, simple sketches using only digitalWrite, analogRead, Serial, Wire, and SPI work on ESP32 with no changes. You will need to update pin numbers to match ESP32 GPIOs, swap AVR-specific libraries like EEPROM for Preferences, and watch out for 3.3V logic instead of 5V. Any code that pokes AVR hardware registers directly will not work.

Do all Arduino libraries work on ESP32?

Most popular Arduino libraries work on ESP32, including Wire, SPI, Servo, FastLED, NeoPixel, Adafruit_GFX, Adafruit_SSD1306, DHT, RTClib, and SD. Libraries that depend on AVR-specific hardware registers or ATmega timers generally need ESP32 alternatives. Check each library’s GitHub repository for ESP32 support or a community fork.

Why is ESP32 harder to program than Arduino?

ESP32 is more complex because it has a dual-core processor, FreeRTOS underneath, and more peripherals than an Arduino Uno. Compilation takes longer, there are more configuration options, and beginners sometimes get tripped up by GPIO strapping pins, Wi-Fi interaction with ADC2, and brownout detection. Once you get past the first sketch, however, the Arduino abstractions make it feel very familiar.

What are the main pin differences between Arduino and ESP32?

Arduino pins are labeled by board function such as D0, D1, A0, while ESP32 pins are labeled by internal GPIO numbers like GPIO 2, GPIO 4, GPIO 32. The mapping is not 1:1, so you must translate each pin manually. Some ESP32 GPIOs (0, 2, 5, 12, 15) are strapping pins with special boot behavior and should be avoided for general use.

Is ESP32 better than Arduino for IoT projects?

ESP32 is almost always the better choice for IoT projects because it has built-in Wi-Fi and Bluetooth, a dual-core 240 MHz processor, 520 KB of RAM, and support for OTA firmware updates. An Arduino Uno needs a separate Wi-Fi shield, has only 2 KB of RAM, and runs at 16 MHz. For IoT, the ESP32 wins on price, capability, and code simplicity.

Conclusion

Yes, you can run Arduino code on an ESP32, and for most projects the transition is straightforward. Install the ESP32 Arduino Core through the board manager, swap your pin numbers, respect the 3.3V logic level, and use the Arduino abstractions you already know. With those four steps in place, your Arduino sketches will run faster, use less power for Wi-Fi projects, and unlock a world of wireless and dual-core features that the Uno simply can’t match.

For more microcontroller projects, robotics guides, and embedded tutorials, browse the rest of Smashing Robotics or drop me a comment with your specific porting question.

Leave a Comment