Source: https://mokxi.com/learn/pico-circuitpython-simulator
Updated: 2026-10-26

Learn

# CircuitPython simulator: the official firmware on a Pico, online

Beginner

Written by the Mokxi team, updated October 26, 2026

Start building free Open the editor

Or see every lesson.

- 455 parts on the bench
- 43 boards running now
- 1.00x real time, on every board

Click to open it in the editor

Press Run. The official CircuitPython firmware boots, code.py is saved onto the CIRCUITPY drive, and both LEDs blink.

Mokxi runs CircuitPython on the Raspberry Pi Pico, the Pico W, the Arduino Nano RP2040 Connect and the ESP32-S3-DevKitC-1. Put a Pico on the canvas, choose CircuitPython (code.py) in its Firmware panel, write code.py and press Run. What runs is the official Adafruit firmware, CircuitPython 10.3.1 for the Raspberry Pi Pico, byte for byte as circuitpython.org publishes it, on Mokxi’s instruction-level RP2040. Nothing in the page interprets your Python.

The board boots the way a real one does: CircuitPython mounts its CIRCUITPY drive, waits out its one-second safe-mode window while the LED on GP25 blinks, and starts USB. The computer on the end of the board’s simulated USB cable then opens its serial port and saves code.py onto the drive, as your own computer does when you save from your editor, and CircuitPython’s auto-reload runs it.

The circuit above is the first of the starters below: board.LED blinks the Pico’s own LED and a red LED on GP15, and the Serial Monitor says on and off.

## How code.py gets onto the board

CircuitPython keeps its files on a drive called CIRCUITPY, in the Pico’s flash. At Run, Mokxi writes that drive before the board powers on: the firmware’s own boot_out.txt, the Adafruit libraries your program imports under lib/, and every .py, .txt, .json, .csv and .toml tab but code.py.

code.py itself is saved over USB, block by block, the way an operating system writes a file to a USB drive. CircuitPython takes the save into its flash and reloads, and code.py runs with the Serial Monitor connected, so every line it prints is shown. It prints about two seconds after Run, most of that CircuitPython’s own safe-mode window and the wait after a save before it reloads.

## Blink with digitalio

digitalio.DigitalInOut(board.LED) is the Pico’s own LED on GP25, and board.GP15 drives a red LED through 220 ohms to ground. The two light together, and the Serial Monitor prints on and off after CircuitPython’s code.py output: line.

code.py: blink an LED

## A button with the pin’s pull-up

A button from GP14 to ground, with switch_to_input(pull=digitalio.Pull.UP): the pin reads True until the button is pressed, and False while it is held. The program prints Press the button, lights the board’s LED while you hold it, and counts each press once.

code.py: a button lights the LED

## A NeoPixel rainbow with the neopixel library

Eight WS2812 LEDs on GP16. Adafruit’s neopixel library goes into lib/ by itself, and it sends the strip’s bits from one of the Pico’s PIO state machines, as on a real Pico. The colors turn around the strip, and every 64 steps the program prints the step and the first pixel’s color, starting step 64 first pixel.

code.py: a NeoPixel rainbow

## A BME280 with adafruit_bme280

busio.I2C(board.GP5, board.GP4) is the Pico’s I2C0, SCL first and then SDA. Adafruit’s adafruit_bme280 library reads the sensor; you do not add it anywhere, as the editor puts it in the drive’s lib/ folder when code.py imports it. With the part set to 22.5 C and 45% it prints 22.5 C 45.0 % humidity and the pressure every two seconds, and when you change the temperature on the part the next reading follows it.

code.py: a BME280 to the Serial Monitor

## Text on an SSD1306 OLED with displayio

displayio draws on the OLED through adafruit_displayio_ssd1306, and adafruit_display_text makes the labels, in the firmware’s own terminalio font. Both libraries, and the adafruit_ticks that adafruit_display_text needs, go into lib/ by themselves. The program writes a title and a counter that goes up once a second, and prints count 0, count 1 and on.

code.py: text on an SSD1306 OLED

## WiFi on the Pico W

The Pico W runs CircuitPython’s own build for it, with its CYW43439 radio chip modeled from its pins: board.LED is the LED on the radio chip, and wifi.radio.connect() joins Mokxi’s simulated access point. Its name and password are the board’s WiFi properties, which start as Mokxi-Lab and breadboard. socketpool and Adafruit’s adafruit_requests, with the adafruit_connection_manager it needs, both put in lib/ for you, then fetch the made-up .mokxi sites of the simulated network, such as http://weather.mokxi/.

The network is simulated: names outside .mokxi are not found, and https:// has nowhere to go. Bluetooth, the access point mode’s clients and power save are not simulated, and wifi.radio.ap_info raises NotImplementedError, as CircuitPython’s Pico W port does not implement it.

## The libraries that go into lib/ by themselves

Mokxi reads each import line and puts the Adafruit libraries it finds into the drive’s lib/ folder, with what they import in turn, as circup would. They are Adafruit’s own compiled .mpy files from their CircuitPython 10.x bundle, unchanged: adafruit_bme280, adafruit_display_text (with adafruit_ticks), adafruit_displayio_ssd1306, adafruit_framebuf (with its font5x8.bin at the top of the drive), adafruit_hcsr04, adafruit_requests (with adafruit_connection_manager), adafruit_ssd1306 and neopixel. A tab named after a library, such as neopixel.py, is your own and is used instead.

Modules built into the firmware need nothing: board, digitalio, analogio, pwmio, busio, time, displayio, terminalio, i2cdisplaybus and the rest.

## The REPL

The Serial Monitor is the Pico’s USB serial port, both ways: what code.py prints, its tracebacks, and Code done running. when it ends. Ctrl-C stops code.py with a KeyboardInterrupt, any key then enters the REPL, where >>> answers, and Ctrl-D reloads and runs code.py again.

When a program stops with an error, Mokxi marks the line in your file and says what the error usually means in CircuitPython’s words: a MicroPython module such as machine in a CircuitPython program, a missing pull-up, a pin in use, or board.I2C(), which the Pico does not have.

## What works, and what does not

Working: digitalio, analogio, pwmio, busio.I2C and busio.UART, with the parts on the canvas; adafruit_bme280, adafruit_ssd1306 with adafruit_framebuf, and displayio with adafruit_display_text. The PIO runs too, so neopixel_write and the neopixel library light a WS2812 strip, and pulseio.PulseIn reads the echo that adafruit_hcsr04 times an HC-SR04 with. A reset from inside, with microcontroller.reset() or the watchdog, keeps the drive, so code.py runs again.

Not simulated yet: the second core; audiobusio, audiopwmio and picodvi; and reading the drive from the computer, which only saves to it. The ESP32-S3-DevKitC-1 runs CircuitPython too, with its own build and its REPL and drive on the S3’s native USB, but WiFi is not simulated under CircuitPython there.

## Importing from Wokwi

A Wokwi project for the Pico, the Pico W, the Nano RP2040 Connect or the ESP32-S3-DevKitC-1 with a code.py imports with its board set to CircuitPython, and runs. On another board its code.py is kept as text, and the import says why. Wokwi may have used another CircuitPython version; the import report says which one runs here.

## The same code on a real Pico

A CircuitPython board needs no build. Put CircuitPython on the Pico (hold BOOTSEL while you plug it in, then drag the .uf2 from circuitpython.org/board/raspberry_pi_pico onto the RPI-RP2 drive), then save code.py onto the CIRCUITPY drive that appears, and copy any libraries it imports into CIRCUITPY/lib (circup install does it for you).

## Questions

Is this real CircuitPython?

Yes. The board runs the official CircuitPython 10.3.1 firmware for the Raspberry Pi Pico, the same .uf2 circuitpython.org publishes, byte for byte, on a simulated RP2040. Nothing in the web page interprets your Python.

Which boards run CircuitPython?

The Raspberry Pi Pico; the Pico W, with WiFi on the simulated network; the Arduino Nano RP2040 Connect with CircuitPython’s own build for it, where `board.LED` is the LED on D13 and `board.I2C()` is on A4 and A5; and the ESP32-S3-DevKitC-1. Choose CircuitPython (code.py) in the board’s Firmware panel. The same Pico can run MicroPython (main.py) or an Arduino sketch instead.

Do I need to install libraries?

No. The Adafruit libraries a program imports, from the ones Mokxi has, go into the drive’s lib/ folder at Run by themselves, with what they need in turn, as circup would put them there.

Does it download anything?

The first Run of a CircuitPython project downloads the firmware, and the browser keeps it for every later Run. Each library is downloaded only when a program imports it. An Arduino sketch never downloads either.

Related

## Keep going

Raspberry Pi Pico MicroPython in Your Browser Raspberry Pi Pico Pinout: GPIO, PWM, ADC and Power CircuitPython blink on a Pico Beginner CircuitPython button on a Pico Beginner CircuitPython NeoPixel rainbow on a Pico Beginner CircuitPython BME280 on a Pico Beginner CircuitPython OLED text on a Pico Beginner Help: CircuitPython on the Pico The project page, with the full sketch Beginner

Sources

## Where the facts on this page come from

- circuitpython.org: CircuitPython for the Raspberry Pi Pico (10.3.1, 2026-09-14)
- CircuitPython documentation

## 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 free Open the editor
