For an index to all my stories click this text
A microcontroller like the Raspberry Pi Pico has a lot of memory for IOT projects. 256K Ram and 2MB on board Flash memory seems a lot of storage. And indeed it is if you are saving your programs in the flash memory and doing IOT projects.
If you are working with audio files like we were doing in the talking thermometer (click here http://lucstechblog.blogspot.com/2024/11/pico-audio-part-4-talking-thermometer.html) and talking clock stories (click here http://lucstechblog.blogspot.com/2024/11/pico-audio-part-5-talking-clock.html ) then 2MB storage suddenly is tight.
Attaching an SD card is the option to get a lot of storage to your Pico.
The previous article in this series showed how to attach an SD card to the Raspberry Pi Pico. This story tells how to use it in MicroPython. You can read it here:
http://lucstechblog.blogspot.com/2025/01/pico-sdcard-part-1-hardware.html
First a word of caution !!!
I tested the SD card on a Raspberry Pi Pico W. Everything worked just fine. Then I switched to the Pico without wifi and it did not work anymore. Back to the Pico W and everything worked again !!! What could be the issue ?? After some search I found the solution and it is easy. I was testing the SD card on one of my first Pico's. The one I wrote my first book about the Pico on. And then it became clear. Obvious I was working on a Pico with an old version of Python. So update your Pico so that you at least have MicroPython v1.19.1. installed.
Another thing to note is that the card must be formatted in the FAT32 format. Actually this is the standard format most cards are formatted in. When in doubt re-format the SDcard on your PC. Newer filesystems like NTFS and Linux filesystems are not recognized by the driver.
The SD card driver
To use an SD card with the Pico you need a driver for MicroPython. And for one reason or another the SDcard driver disappeared from the current MicroPython repositry on Github. Fortunately I succeeded in locating it in an old repositry:
https://github.com/micropython/micropython-esp32/tree/esp32/drivers/sdcard
For your convenience I have put up a copy of the driver on my own Github repositry. You can find it here:
https://github.com/Lucvolders/MicroPython/blob/main/Libraries/SDcard/sdcard.py
AND MIT LICENSE
https://github.com/micropython/micropython-esp32/blob/esp32/LICENSE
You need to install this driver manually.
First step is to click on sdcard.py so the file opens. Then copy the file. In Thonny open a new file and paste the copied file.
Then save it in your Pico's lib folder. Use save-as.for this.
Give this file the exact name: sdcard.py like I did as you can see in the picture. And save it in the lib folder. If you give the file another name or misspell a letter the driver will not work.
Storing data on the card
Now everything is in place we can start using the SD card for storing data and reading it back.
Here is a small program that writes one line of text to a file on the SD card.
import os from machine import SPI, Pin import sdcard spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) os.mount(sd, '/sd') file = open('/sd/test.txt', 'a') file.write('Testing the SD card') file.close() Let us look at the different parts of the program. import os from machine import SPI, Pin import sdcard
The first 3 lines import the required libraries. We need the os and the sdcard library for the filesystem and the addressing of the SD card. The machine library is needed to control Pico's pins.
spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12))
cs = Pin(13)
sd = sdcard.SDCard(spi, cs)
These lines define the pins where the SD card is connected to. The previous story discussed how the SD card is connected to the Pico (or Pico W). Check that story for the details. You can find it here XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The last line makes an instance of the SDcard driver with the defined pins and we call it sd which is easy to refer to.
os.mount(sd, '/sd')
This line activates the SD card.
file = open('/sd/test.txt', 'a')
The first thing to do is to open a file. The open command begins with defining where the file is located and the name of the file. So the file is on the SD card (/sd) in it's home directory "/" and has the name "test.txt". You can use any name you like. Best thing is to use the same name conventions as on your PC so you can easily exchange data later on.
In this example we are going to write to the SD card's home directory which is addressed as "/". Later on I show how to make subdirectories just like a lib directory on the Pico itself.
When opening a file there are 3 options.
w for writea for append
r for read
If you want to overwrite an existing file use the w option. For adding text to a file use the a option. For reading from a file use the r option.
As we have an empty SD card I could have used the w (write) option. The a (append) option will create the file if it does not exist.
file.write('Testing SD the card')
This is the line that writes the data ("Testing the SD card") to the card.
You can replace the text line with a variable which in a real life project you will certainly do.
file.close()
After writing you MUST close the file. If you do not issue this command any data that is still in the memory of the Pico and not written to the SD card will be lost.
Please note that you can only write strings to the SD card. If you want to store figures convert them to a string first.
Here is an example that would write the value 88.6 to the test.txt file.
file = open('/sd/test.txt', 'w') a = str(88.6) file.write(a) file.close()
Reading data from the card
Reading data from an SD card is almost the the same as writing to the card.
file = open('/sd/test.txt', 'r') data = file.read() file.close() print(data)
The file is opened, the data is read with file.read and the file is closed. Then we can print the data.
Please note that you can alter the names of the variables to your liking. You can use for example storedtemps in stead of file, or temp in stead of data. Use names that are meaningful.
Formatting the text
Look at the next example:
file.write('Testing SD the card') file.write('for this story')
To read those lines you will need to use 2 read commands like this:
line1 = file.read() line2 = file.read()
And later on you would print the lines:
print(line1) print(line2)
This would show in the shell:
>>> %Run -c $EDITOR_CONTENT
Testing SD the card for this story
>>>
Although you used 2 file.write() lines in the program they are stored as 1 line and there is no space between the "card"and "for" text.
To achieve that each line is printed on a new line on your screen you need to use a so called escape character. The escape character for a new line is \n. So you shouls alter the lines in:
file = open('/sd/test.txt', 'w') file.write('Testing SD the card\n') file.write('for this story') file.close() If you now read the file with: file = open('/sd/test.txt', 'r') line1 = file.read() line2 = file.read() file.close() print(line1) print(line2)
The shell shows the next lines.
>>> %Run -c $EDITOR_CONTENT
Testing SD the card
for this story
>>>
There are several escape characters available but "\n" is the most important one. The one you will use most.
For completeness I give you here all the escape characters that I tested :
\' — Single quote
\" — Double quote
\\ — Backslash
\n — New line
\r — Carriage return
\t — Horizontal tabulator
Storing a lot of data
Writing one or two lines to the SD card is ok. But what if you need to store lots of data.
Here is a small program that stores 10 random values.
import os from machine import SPI, Pin import sdcard import random spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) os.mount(sd, '/sd') file = open('/sd/testvalues.txt', 'w') for i in range(1, 11): number = random.randint(15 , 30) numstring = str(number)+"\n" file.write(numstring) file.close()
The random function is imported at the beginning of the program.
In the for loop a random number is created with a value between 15 and 30. That number is converted to a string and "\n" is added to that string so every value is written on a new line.
And here is an example that shows how to read the values.
import os from machine import SPI, Pin import sdcard spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) os.mount(sd, '/sd') file = open('/sd/testvalues.txt', 'r') for i in range(1, 11): value = file.readline() value = int(value) print(value) file.close()
The command file.readline() reads one line from the file and puts it in the variable value. This variable is a string as everything written to the SD card is a string. The variable is converted to an integer and then printed in the shell.
This only works if you know how many lines of text are present in the file. In this example we know that from the previous program where the data is written. In a real life situation you might not know this.
A better option would therefore be this:
import os from machine import SPI, Pin import sdcard import random import time spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) os.mount(sd, '/sd') file = open('/sd/testvalues.txt', 'r') valuelist = [] for value in file: value = int(value) valuelist.append(value) file.close() print(valuelist)
A list (a kind of array) is defined with the name valuelist[]. The for loop reads all lines in the program and puts them into the list. If we wish, and yes in real life you would, you can pick an individual value from the list and perform some action on it.
If you need the fourth value from the list you can retrieve that with:
need = valuelist[3]
In this example you can stop reading the file when the value variable equals a certain number. You can achieve that with the next lines:
for value in file: value = int(value) if value == 15: break valuelist.append(value) file.close() print(valuelist)
If the read value is equal to 15 the break command is executed which stops the for loop.
Working with lists and files is also discussed in my book "Raspberry Pi Pico Simplified" and in "Raspberry Pico W Simplified" on which you can find a link at the bottom of this page.
The file system.
Just like on your PC you will want to see the contents of the SD card, make directories, remove directories, rename files, and delete files. That is all possible.
Before you can use the commands for the file system functions you will have to activate the SD card. Here is a small program that does that for you:
import os from machine import SPI, Pin import sdcard spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) os.mount(sd, '/sd')
This is how my file structure looks in Thonny.
Run the above lines TWICE !!
And suddenly the SD card appears in Thonny's file structure.
Click on the small + sign in front of the sd directory and the directory will open. Just as on your PC.
You can access certain file commands from Thonny by clicking with the right mouse button on a file. AS you can see you can create a new directory, delete the (highlited) file or copy that file to your PC.
You can change the PC's directory by clicking at the top in Thonny Files section on This computer and stroll through your directories like you are used to.
The file system with Thonny.
In Thonny's shell you can type the commands for manipulating files on your SD card. This only works if the SD card is still activated. The SD card is still activated when it is visible in Thonny's file structure.
If it is not visible anymore run the small activation program shown above.
Here are the commands you can use.
Directory
print(os.listdir('/sd'))
This will show the contents of the SD card as text. You will see the sub-directories and the files.
Change Directory
os.chdir("/sd/name")
This will change the working directory to the named subdirectory. Any command you will give next will effect the files in the subdirectory "name"
As you can see you do not have to give any parameters to os.listdir() as the file system knows that "/sd/Programs" is the working directory you are operating in.
Remove a file
os.remove("example.txt")
This command removes the file example.txt from the working directory.
Make a directory
os.mkdir("test")
This will create a new directory in the working directory. If you need to create a directory in the home directory of your SD card use:
os.mkdir("/sd/test")
Or first change the working directory back to the home directory with os.chdir("/sd")
Remove a directory
os.rmdir("/sd/test")
This command will remove the complete directory "test" including its contents.
Rename a file
If you need to rename a file use the following command:
os.rename("/sd/oldname", "/sd/newname")
Please not that you have to use the complete name. If a file has the name test.py and you try to rename it like: os.rename("/sd/test", "/sd/testnew.py") then you will get an error. If you rename it like this: os.rename("/sd/test.py", "/sd/newtest") then the file will not be recognized as a MicroPython file as the .py is missing inn the name.
A few footnotes.
All the above commands start with os. like os.mkdir() etc. That is because the import command at the top of the program is used as:
import os
If you use something like:
import os as filesys
Then you can start the commands like:
filesys.mkdir()
here is an example that shows what I mean.
import os as filesystem from machine import SPI, Pin import sdcard spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) filesystem.mount(sd, '/sd') print(filesystem.listdir('/sd'))
The same way you can alter the name of the SD card in storage or any name you like.
import os as filesystem from machine import SPI, Pin import sdcard spi = SPI(1,sck=Pin(14), mosi=Pin(15), miso=Pin(12)) cs = Pin(13) sd = sdcard.SDCard(spi, cs) filesystem.mount(sd, '/storage') print(filesystem.listdir('/storage'))
As you can see I changed the name of the SD card as well as the name with which I am using the filesystem.
And the last note is already obvious from the above program. You can use all the commands in a program. You can even use a variable as a parameter for filenames etc.
Next step.
The Pico's audio like described in the previous story in ehich the programs get the audio files from the SD card !!! Let's make an audio player that can play your favorite music or podcasts !!!
Till next time
have fun !!
Luc Volders