MicroPython on the ESP32

Run main.py on a classic ESP32 board with the official MicroPython firmware: the Firmware panel, the REPL, WiFi and importing from Wokwi.

Which boards

The classic ESP32 boards run MicroPython: the DOIT DevKit V1, the DevKitC and the LOLIN32 Lite, and so do the ESP32-S3 boards: the ESP32-S3 DevKitC-1, the XIAO ESP32-S3 and the Arduino Nano ESP32. The other ESP32 boards (the C3, C6 and the rest) run Arduino sketches only. The Raspberry Pi Pico runs MicroPython too; see the Pico.

What runs is MicroPython v1.29.0 for the ESP32, the official single-core build, byte for byte as micropython.org publishes it, on Mokxi's model of the whole chip, booted from Espressif's own mask ROM. Nothing in the page interprets your Python.

Choosing it in the Firmware panel

  1. Put an ESP32 DevKit V1, DevKitC or LOLIN32 Lite on the canvas.
  2. Open its Firmware panel and pick MicroPython (main.py).
  3. The board's files become a main.py. Write your program there and press Run.

A board whose files have a main.py and no .ino runs MicroPython. An Arduino sketch on the same board runs as before, and nothing of MicroPython is loaded for it.

The first Run of a MicroPython project on an ESP32 downloads the firmware and the chip's ROM, 1.4 MB, and the browser keeps them for every later Run. An Arduino sketch never downloads them.

What Run does with main.py

Run boots the firmware, and the computer on the end of the board's simulated USB cable copies your .py files onto the board the way Thonny and mpremote do: it enters the raw REPL over the board's serial port, writes each file into the board's flash, and soft-reboots it. The board prints MPY: soft reboot, runs boot.py and then main.py.

Every .py, .txt, .json and .csv tab is copied, so a driver such as micropython-lib's ssd1306.py goes in a tab of its own beside main.py and import ssd1306 finds it.

The EN button and machine.reset() keep the files, so main.py runs again, as on a desk. Run again starts from an erased chip.

The Serial Monitor and the REPL

From MPY: soft reboot on, the Serial Monitor is the board's UART0, both ways. Everything print() says shows there. When main.py ends, or you stop it with Ctrl-C, the REPL answers there: type an expression and press Enter.

When a program stops with an error, MicroPython prints a traceback. Mokxi reads it, marks the line in your file, and says what the error usually means, as it does on the Pico.

What works

machine.Pin with interrupts, PWM (the LEDC), ADC on ADC1's eight channels with the four attenuations, I2C and SoftI2C, SPI and SoftSPI, UART(1) and UART(2) on the pins wired to them, neopixel, dht, onewire and ds18x20, and machine.freq() at 80, 160 or 240 MHz.

Not simulated: light and deep sleep, ADC2, PSRAM, the I2C and SPI slave modes, UART flow control, receiving with the RMT, and the watchdogs resetting the board. The build is the single-core one.

WiFi

network.WLAN joins Mokxi's simulated access point, the same one an Arduino sketch's WiFi.begin joins. Its name and password are the board's WiFi properties, which start as Mokxi-Lab and breadboard; change them in the board's properties, and use the same two in wlan.connect(). The board gets 192.168.4.2 over DHCP.

import network, time, urequests

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("Mokxi-Lab", "breadboard")
while not wlan.isconnected():
    time.sleep_ms(250)
r = urequests.get("http://weather.mokxi/")
print(r.json())
r.close()

socket and urequests reach the made-up sites of the simulated network: time.mokxi, weather.mokxi, echo.mokxi and api.mokxi. Any other name is not found, and https:// has nowhere to go. The Cloud panel shows what the board asks for.

Not simulated on the network: the access point mode's clients (WLAN(AP_IF) starts and reports no stations), ESP-NOW, power save, TLS, and any network but the simulated one.

WiFi, simulated covers the network itself.

Importing from Wokwi

A Wokwi project for an ESP32 DevKit V1, DevKitC or LOLIN32 Lite that has a main.py imports as a MicroPython project, with its board set to MicroPython. Its board's network is named Wokwi-GUEST with no password, as on Wokwi, so wlan.connect("Wokwi-GUEST", "") works as written. See Coming from Wokwi.

On a real ESP32

A MicroPython board needs no build. Put MicroPython on the ESP32 with esptool (esptool.py --chip esp32 erase_flash, then esptool.py --chip esp32 write_flash -z 0x1000 ESP32_GENERIC-UNICORE-20260824-v1.29.0.bin, from micropython.org/download/ESP32_GENERIC), then copy main.py onto it with Thonny or mpremote. Put your own network's name and password in wlan.connect(): the .mokxi sites exist only in Mokxi.

Starters

Six starters on a DevKit V1, each on its own page: blink, a button with Pin.irq(), a PWM fade, a DHT22, an SSD1306 OLED and WiFi and the weather. The ESP32 MicroPython simulator walks through all six.

Elsewhere