Writing to the filesystem

Getting the temperature in the REPL is all well and good, but requires you to type the command every time.

Thankfully, CircuitPython 2.0.0 also introduced the storage module, which lets you access the internal storage of the board. There isn’t a lot of it, but for storing a few readings it should be plenty. By default you can write to the system via USB (ie saving code.py) and not in code, so first you’ll need to change that.

Setting readonly to False on boot

You can only use this in boot.py, which is executed before the USB connection is made. If boot.py doesn’t exist, create it with this:

Warning: once you start this you need to continue until the end of the section or you’ll have problems writing code to the board. If you’d prefer to be safe, just read this and skip to the next section, “Selectively setting readonly to False on boot”.
Download: file
import storage

storage.remount("/", False)

On every boot the root filesystem will be mounted so that CircuitPython can write to it.

boot.py only runs on first boot of the device, not if you re-start the REPL with ^D or if you save the file, so you must EJECT the USB drive, then physically press the reset button!

You can now write to the internal storage via the REPL:

Download: file
>>> with open("/tmp.txt", "a") as fp:
...     fp.write("hello, world!")
...

You might need to reboot the board before you see the file, but it will be there in the file explorer.

Only one thing can have write access at a time, though, so by allowing your Python code to write to the device you’ve disabled USB write access. This means updating code.py will no longer work! Even worse, you can’t edit boot.py either, so at first you might think you’re stuck like this forever.

Luckily, you can edit and remove/rename files via the REPL:

Download: file
>>> import os
>>> os.listdir("/")
>>> os.rename("/boot.py", "/boot.bak")

Then reboot the device and you’ll be able to edit via USB as normal.

Selectively setting readonly to False on boot

Recreate boot.py:

import board
import digitalio
import storage

switch = digitalio.DigitalInOut(board.D0)
switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.UP

# If the D0 is connected to ground with a wire
# CircuitPython can write to the drive
storage.remount("/", switch.value)

This will read the value of the D0 pin, which has been set to a pullup: it reads True (HIGH, 1, etc in Arduino) if it has not been grounded, but if connected to ground it reads False. Since we want it to be readonly False when the board should be written by the code and not USB, you only need to connect the D0 pin to ground when you want the board to be able to write via the code.

boot.py only runs on first boot of the device, not if you re-start the REPL with ^D or if you save the file, so you must EJECT the USB drive, then physically press the reset button!

The Circuit Playground makes this easy: the D7 pin is the toggle switch.

On other boards, like the Gemma M0, you’ll need to use wires or alligator clips like so:

This guide was first published on Sep 27, 2017. It was last updated on Sep 27, 2017. This page (Writing to the filesystem) was last updated on Sep 17, 2019.