CircuitPython on the Pico
Run code.py on a Pico with the official CircuitPython firmware: the Firmware panel, the CIRCUITPY drive, libraries, the REPL and Wokwi imports.
Which boards
The plain Raspberry Pi Pico runs CircuitPython, and so does the Arduino
Nano RP2040 Connect, with CircuitPython's own build for it: the same RP2040,
with board.LED on D13 (GPIO 6) and board.I2C() on A4 and A5. See
the Nano RP2040 Connect. The Raspberry
Pi Pico W runs its own build, with its CYW43439 radio chip modeled, so
board.LED lights and WiFi works on Mokxi's simulated network (see
WiFi on the Pico W). The ESP32-S3-DevKitC-1 runs
CircuitPython too, with its own build and its REPL and drive on the S3's
native USB; WiFi is not simulated under CircuitPython there. The Pico runs
MicroPython too; see the Pico.
What runs is CircuitPython 10.3.1 for the Raspberry Pi Pico, the official Adafruit firmware, byte for byte as circuitpython.org publishes it, on Mokxi's simulated RP2040. Nothing in the page interprets your Python.
Choosing it in the Firmware panel
- Put a Raspberry Pi Pico, a Pico W, an Arduino Nano RP2040 Connect or an ESP32-S3-DevKitC-1 on the canvas.
- Open its Firmware panel and pick CircuitPython (code.py).
- The board's files become a
code.py. If they hold work of your own, you are asked first. Write your program there and press Run.
A board whose files have a code.py and no .ino runs CircuitPython. An
Arduino sketch or a MicroPython project on the same board runs as before, and
nothing of CircuitPython is loaded for it.
The first Run of a CircuitPython project downloads the firmware, and the browser keeps it for every later Run. An Arduino sketch never downloads it.
The CIRCUITPY drive and code.py
CircuitPython keeps its files on a drive called CIRCUITPY, in the board'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.
Then the computer on the end of the Pico's simulated USB cable opens the
board's serial port and saves code.py onto the drive over USB, the way your
own computer does when you save it from your editor. CircuitPython sees the
save and reloads, as it does on a desk, and runs code.py with the Serial
Monitor connected, so every line it prints is shown.
code.py prints about two seconds after Run. Most of that is CircuitPython's
own: the one-second safe-mode window at boot, while the LED on GP25 blinks,
and the wait after a save before it reloads.
microcontroller.reset() and the watchdog keep the drive, so code.py runs
again; what it prints before the serial port opens again is lost, as on a
desk. Run again starts from a freshly written drive.
Libraries
Mokxi reads your import lines and puts the Adafruit libraries it finds into
the drive's lib/ folder by itself, 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_bme280adafruit_display_text(withadafruit_ticks)adafruit_displayio_ssd1306adafruit_framebuf(with itsfont5x8.binat the top of the drive)adafruit_hcsr04adafruit_requests(withadafruit_connection_manager)adafruit_ssd1306neopixel
Each one is downloaded only when a program imports it. A tab named after a
library, such as neopixel.py, is your own and is used instead. Modules built
into the firmware (board, digitalio, analogio, pwmio, busio, time,
displayio, terminalio, i2cdisplaybus and the rest) need nothing.
The Serial Monitor and the REPL
The Serial Monitor is the board's USB serial port, both ways: what code.py
prints, its tracebacks, and Code done running. when it ends.
- Ctrl-C stops
code.pywith aKeyboardInterrupt. - Any key then enters the REPL, and
>>>answers there. - Ctrl-D reloads and runs
code.pyagain.
When a program stops with an error, CircuitPython prints a traceback. Mokxi
reads it, marks the line in your file, and says what the error usually means
in CircuitPython's words: a MicroPython module in a CircuitPython program, a
missing pull-up, a pin already in use, or board.I2C(), which the Pico does
not have (use busio.I2C(board.GP5, board.GP4)).
What works, and what does not
digitalio, analogio, pwmio, busio.I2C and busio.UART work, so
adafruit_bme280, adafruit_ssd1306 and displayio with
adafruit_display_text talk to the parts on the canvas.
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.
Not simulated: the second core; audiobusio, audiopwmio and picodvi; and
reading the drive from the computer, which only saves to it.
WiFi on the Pico W
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_requests (which the editor puts in
lib/ with the adafruit_connection_manager it needs) reach the made-up
.mokxi sites, such as http://weather.mokxi/:
import wifi, socketpool, adafruit_requests
wifi.radio.connect("Mokxi-Lab", "breadboard")
print("Connected, IP address", wifi.radio.ipv4_address)
requests = adafruit_requests.Session(socketpool.SocketPool(wifi.radio))
print(requests.get("http://weather.mokxi/").json())
Any other name is not found, and https:// has nowhere to go. Not simulated:
Bluetooth, the access point mode's clients and power save.
wifi.radio.ap_info raises NotImplementedError, because CircuitPython's
Pico W port does not implement it.
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. See
Coming from Wokwi.
On a real board
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).
On a Pico W, drag the .uf2 from circuitpython.org/board/raspberry_pi_pico_w
instead, and put your own network's name and password in code.py. On a Nano
RP2040 Connect, jumper REC to GND while you plug it in instead, and drag the
.uf2 from circuitpython.org/board/arduino_nano_rp2040_connect. On the
ESP32-S3-DevKitC-1, plug in its USB port (the one marked USB, not UART) and
use the installer at circuitpython.org/board/espressif_esp32s3_devkitc_1_n8.
Starters
Starters on a Pico, each on its own page: blink, a button, a NeoPixel rainbow, a BME280 and text on an SSD1306 OLED. The CircuitPython simulator walks through them.
Elsewhere
- The boards: the Raspberry Pi Pico and the Nano RP2040 Connect
- MicroPython on the ESP32: MicroPython on the ESP32