Source: https://mokxi.com/learn/esp32-blink-led
Updated: 2026-09-27

Learn

# Blink an LED on the ESP32-C3

Written by the Mokxi team, updated September 27, 2026

Sign up free or see every lesson

- 192 parts on the bench
- 25 boards running now
- 1.00x real time, on every board

Click to open it in the editor

The board's built-in blink program, plus an LED and a 220 ohm resistor on GPIO 8.

The board this models is a real ESP32-C3-DevKitM-1, not a generic stand-in: a single-core RISC-V chip at 160 MHz, with its own GPIO numbering that does not match an Arduino's pin silkscreen at all. There is no pin printed "13" here; the built-in LED sits on GPIO 8, so `LED_BUILTIN` on this board means 8, and that is the pin the circuit above wires an external LED and resistor to as well.

Press Run and both the board's own LED and the breadboard LED blink together, once a second, from firmware that really is compiled for this chip and really does run on its modeled RISC-V core rather than a stand-in animation.

Download the lesson plan (PDF)

## Which board this models

Say the exact board, because more than one ESP32-C3 board exists and they are not interchangeable: this is the DevKitM-1, Espressif's own development board, not the smaller third-party "SuperMini" boards that share the same chip but a different pinout and layout. If you own a SuperMini, GPIO 8 is still the right pin to look for in code, but do not expect the physical pin positions on this diagram to match a different board's silkscreen.

The chip underneath both boards is the same ESP32-C3: a single RISC-V core, GPIO, a UART and a SYSTIMER on a real, documented memory map. Firmware for the peripherals this simulator models can move to a physical DevKitM-1, where it still needs testing. What differs between boards sharing the same chip is which pins are broken out to a header and in what order.

## Wiring the LED at 3.3 volts, not 5

This is the one number that genuinely changes between an Arduino Uno and an ESP32-C3: the C3's GPIO pins drive 3.3 volts, not 5. Run the same resistor math with that supply instead, (3.3 V minus roughly 2 V) divided by 220 ohms, and the current comes out closer to 6 milliamps, against the Uno's roughly 13.6 mA at the same resistor value. The same LED will run visibly dimmer here, and it is worth lowering the resistor a little, to something like 150 ohms, to get back to a similar brightness rather than assuming the Uno's values carry over unchanged.

## What is different under the same three calls

`digitalWrite()`, `pinMode()` and `delay()` read identically on every board Mokxi models, and that is deliberate: the Arduino core hides the chip underneath them. What changes here is everything below that line. The C3 is a single 32-bit RISC-V core clocked at 160 MHz against the Uno's 8-bit AVR core at 16 MHz, and `delay()` here is timed from the SYSTIMER, a peripheral the ATmega328P does not have, rather than from a general-purpose timer pressed into service for it. None of that changes what the sketch above does; it changes how much headroom is left over for everything else a C3-based project tends to want to do at the same time, like reading a sensor over I2C or driving a small display, which is a large part of why this chip is a common choice once a project outgrows a single blinking LED.

## The code

The sketch is the same shape as the Uno's, because `digitalWrite()`, `pinMode()` and `delay()` are the same Arduino-style calls on every board Mokxi models; only the pin number and the comment describing it change.

firmware/examples/blink, the ESP32-C3 build (the exact program running above)

## Common mistakes

The two mistakes specific to this board, beyond the LED-backwards and missing-resistor mistakes that apply everywhere: reading the silkscreen number as if it were the GPIO number, which it usually is not on a dev board with its pins broken out on a header printed with the chip's own names; and assuming any GPIO is free to use for anything. A handful of the C3's pins are strapping pins, sampled once at boot to choose things like the boot mode, and driving them low with an external part at power-on can stop the board starting the way you expect. GPIO 8 has no such role, which is one more reason it is the pin the built-in LED and this example both use.

A third mistake worth naming because it is easy to make once and never again: assuming `analogWrite()` behaves here exactly as it does on an Uno. It does the same job on both, but not the same way: an Uno's call reaches one of six pins a timer's compare output is wired to, and the C3's reaches any pin at all, because LEDC's channels are routed through the GPIO matrix rather than soldered to a pad. The page on PWM fade covers what actually changes between the two boards, and it is worth reading before assuming a fade sketch will port over unchanged.

And a fourth, easy to overlook because it costs nothing to get wrong here: forgetting that GPIO 8 doubles as the pin the on-board LED is already wired to. Wiring an external LED to the same pin is fine, and is exactly what the circuit above does, but it means the on-board LED and the breadboard LED will always show the same state; wiring a second, independent LED needs a second, unused GPIO instead.

## Powering the board and the LED together

The DevKitM-1 is powered over its own USB connector in this simulator, the same as the real board, so nothing about the LED circuit needs to supply the chip itself. What the LED and resistor draw comes from the GPIO pin, at 3.3 V, not from a separate rail, and the current math above already accounts for that. On the real board this matters slightly more than it does here: a GPIO pin has a real maximum source current, and a resistor picked too small is the difference between a safely current-limited LED and a pin asked to supply more than it is rated for.

## Questions

Is this the same program as the Arduino Uno blink example?

The same shape and the same three calls, but a separate build: the ELF here targets a RISC-V core on the real ESP32-C3 memory map, not the ATmega328P the Uno examples target, and GPIO 8 replaces pin 13.

Does WiFi work in this simulator?

WiFi works over a simulated network with the Arduino WiFi calls. There is no radio, no 802.11 and no real internet; Bluetooth is not simulated.

Which pins can I safely blink an LED on?

Most of the broken-out GPIO pins work fine for a simple digitalWrite LED; the board page lists which are strapping pins worth avoiding for anything driven at power-on.

Is the ESP32-C3 simulator free to use?

Yes, with no account needed to open it and try it, the same as every board Mokxi models.

Can firmware built here run on a real ESP32-C3-DevKitM-1?

For the peripherals this simulator models, an ELF built here targets the real register offsets for GPIO, UART and timer-driven code like this example. Test it on the physical board before relying on it.

Do I need to know RISC-V assembly to use this board?

No. Every example here is written in the same Arduino-style C++ as the Uno examples; the RISC-V core underneath is what actually executes the compiled program, but nothing about writing a sketch for this board requires knowing that.

Related

## Keep going

ESP32 analogRead: 12 Bits, Attenuation and ADC2 ESP32 HTTP GET Request: Fetch the Weather as JSON Arduino Uno vs ESP32 vs Pico: Which to Learn First? The ESP32-C3 simulator The same first program on an Arduino Uno Eight LEDs from three pins: the 74HC595

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building Open the editor
