PyPortal IoT Device

The Adafruit PyPortal is a great little IoT device with lots of projects available. It’s an awesome H/W and S/W platform that inspires many creative ideas. The PyPortal uses an ATMEL (Microchip) ATSAMD51J20, and an Espressif ESP32 Wi-Fi coprocessor. PyPortal has a 3.2″ 320 x 240 color TFT resistive touch screen and has several built-in sensors. It also has support for a micro-SD Card. The device itself shows up as a USB drive when plugged into a computer — but not the micro-SD Card 🙁

Software support for PyPortal is via CircuitPython. There is a great Integrated Development Environment (IDE) available in the form of Mu. Mu is a simple Python editor that also has a built-in serial-port terminal. It allows command-line input of CircuitPython for instant programming, testing, and debugging. This feature is referred to as the REPL (Read-Evaluate-Print-Loop). Deployment of code to a PyPortal is immediate with Mu’s “Save” function.

As I was experimenting with my PyPortal, I wanted to put code and resources (images, fonts, code) on a removable micro-SD Card. Easy to do on my computer but not obvious how to do on PyPortal 🙁 I looked at several PyPortal sample apps and perused CircuitPython docs available on the Explore and Learn Area on the Adafruit websitet

I’m sharing what I learned in a hopefully concise manner to save others time and frustration 😉

Mu editor & IDE on Mac

First follow the PyPortal setup instructions! Update firmware to the latest version, install CicuitPython, and make sure you have installed the Adafruit CIrcuitPython Library Bundle. You should then have a “lib” folder at the root of the CIRCUITPY drive. Finally, insert a micro-SD Card formatted with the FAT or FAT32 filesystem.

OK, let’s test! In Mu, connect to the PyPortal via the serial terminal. You should type in the following in the REPL area:

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 4.0.0-beta.6 on 2019-03-30; Adafruit PyPortal with samd51j20

>>> import board
>>> import storage
>>> import adafruit_sdcard
>>> import os
>>> import digitalio
>>> import busio
>>> spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
>>> cs = digitalio.DigitalInOut(board.SD_CS)
>>> sdcard = adafruit_sdcard.SDCard(spi, cs)
>>> vfs = storage.VfsFat(sdcard)
>>> storage.mount(vfs, "/sd")
>>> os.listdir('/sd')
['TESTdir', '.Trashes']

Another way to do this is to create “code.py” file on the PyPortal – as opposed to using the interactive REPL:

import board
import storage
import adafruit_sdcard
import os
import digitalio
import busio
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
cs = digitalio.DigitalInOut(board.SD_CS)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
os.listdir('/sd')

NOTE: per a comment, below, as of the late June 2019 PyPortal / CircuitPython update you automatically get an “/sd” directory if you configure a PyPortal object. You can skip all the initialization code above. You can do the “os.listdir(‘/sd’)” to confirm after doing (something like) “pyportal=PyPortal( <parameters> )

The “os.listdir()” line should show you files & directories on the CICUITPY drive. The “os.listdir(‘/sd’)” line should show any files or directories on the micro-SD Card. It may be empty if you have never written to the card or you may see something like “[‘.Trashes’]” as this is a hidden directory created on MacOS. You can also create a directory and check that it was created.

>>> os.listdir('/sd')
['.Trashes']
>>> os.mkdir('/sd/TESTdir')
>>> os.listdir('/sd')
['TESTdir', '.Trashes']
>>> # unmount the microSD-Card for removal
>>> storage.umount('/sd')
>>> os.listdir('/sd')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file/directory

You can now insert, mount, and unmount a micro-SD Card. You can also create directories. The last piece of the puzzle is to create, read, write and delete files 🙂 Start by mounting a micro-SD Card to “/sd” You can use CicuitPython built-in filesystem methods to manipulate files:

>>> os.listdir('/sd')
['TESTdir', '.Trashes']
>>> f = open('/sd/TESTfile.txt', 'w')
>>> f.write('Hello, World!')
13
>>> f.close()
>>> os.listdir('/sd')
['TESTdir', 'TESTfile.txt', '.Trashes']
>>> f = open('/sd/TESTfile.txt')
>>> f.read()
'Hello, World!'
>>> f.close()
>>> os.listdir('/sd')
['TESTdir', 'TESTfile.txt', '.Trashes']
>>> os.remove('/sd/TESTfile.txt')
>>> os.listdir('/sd')
['TESTdir', '.Trashes']
>>> 

For more information, check out the Adafruit CircuitPython API reference. For micro-SDCard mounting check out the storage module. For OS-type functions look at the os module. There is a nice write-up of file manipulation (read, write, delete, etc.) in the MicroPython docs. Please leave questions and feedback in the comments.