0. はじめに
(ラズパイが入手困難なこともあり)今更ながら、最近、ESP32にハマっています。今回は、
MicroPythonでSDカードの読み書きとSDカード上のpythonコードを実行する方法を、備忘録としてまとめておきます。
なお、SDカードのアクセスはSPI接続です。
1. SDカードアダプタ
数年前に製作した、マイクロSDカードのSDカードアダプタに直接ピンヘッダをハンダ付けした物を使用します。3.3VのMCUなら直接接続できます。
2.54mmピッチのピンヘッダがギリフィット。各ピンの意味は下表の通り。
SPIでアクセスする場合は1〜7番ピンのみ接続するため、8・9番ピンのハンダ付けは不要です。
ピン | SDモード | SPIモード |
---|---|---|
1 | CD / DAT3 | CS |
2 | CMD | MOSI |
3 | VSS1 | VSS1 (GND) |
4 | VDD | VDD |
5 | CLK | SCK |
6 | VSS2 | VSS2 (GND) |
7 | DAT0 | MISO |
8 | DAT1 | - |
9 | DAT2 | - |
2. ESP32との接続
今回はslot=2を使用し、ESP32の推奨ピンに接続します。
「MISOに指定したピンをプルアップする必要がある」という記事がありますが、無くても問題なく読み書きできます。ただし、これが原因でSDカードやMCUが破損しても責任は持てませんので、自己責任でお願いします。
SDカードアダプタ | SPI | ESP32 |
---|---|---|
1 | CS | 5 |
2 | MOSI | 23 |
3 | GND | GND |
4 | 3v3 | 3.3V |
5 | SCK | 18 |
6 | GND | GND |
7 | MISO | 19 |
3. SDカードのハンドリング
FAT32でフォーマットしたまっさらなマイクロSDカードを装着しESP32をPCに接続。念のためリセットSWポチ。
ターミナル等からESP32のREPLにアクセス
ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:4540
ho 0 tail 12 room 4
load:0x40078000,len:12788
load:0x40080400,len:4176
entry 0x40080680
MicroPython v1.19.1 on 2022-06-18; ESP32 module (spiram) with ESP32
Type "help()" for more information.
>>>
>>> from machine import SDCard
>>> import os
>>> sd = SDCard(slot=2) #slot=2を使用、ESP32の推奨ピンに接続のためパラメタ省略
>>> os.mount(sd, '/sd')
>>> os.mkdir('/sd/lib') #libサブフォルダ作成
>>> os.chdir('/sd/lib')
>>> os.listdir()
[] #当然ながら空っぽ
#pythonコードを書き込む
>>> f = open('hello.py', 'w')
>>> f.write('print("hello!")')
15
>>> f.close()
>>>
>>> os.listdir()
['hello.py'] #ファイルが作成された
>>>
#ファイルを読み出す
>>> f.close()
>>> f = open('hello.py', 'r')
>>> print(f.read())
print("hello!") #読めました
>>> f.close()
>>> import sys
>>> sys.path
['', '.frozen', '/lib']
>>> sys.path.append('/sd/lib') #pathに追加
>>> sys.path
['', '.frozen', '/lib', '/sd/lib']
>>>
#SDカード上のhello.pyを実行
>>> import hello
hello!
>>>
以上のコードで、①SDカードのマウント、②テキストファイル書き込み、③テキストファイル読み込み、④SDカード上のpythonコード実行 ができました。
from machine import SDCard
import os
sd = SDCard(slot=2)
os.mount(sd, '/sd')
os.mkdir('/sd/lib')
os.chdir('/sd/lib')
os.listdir()
f = open('hello.py', 'w')
f.write('print("hello!")')
f.close()
os.listdir()
f = open('hello.py', 'r')
print(f.read())
f.close()
import sys
sys.path.append('/sd/lib')
sys.path
import hello
4. SDカードアクセスの性能
以下のコードにて、SDカード上のテキストファイルのアクセス性能を調べてみた。
- 入力ファイル:1行100文字(UTF-8、改行コード含め101バイト)x 12,800行 = 1,292,800バイト(約1.2MB)
/sd/work.txt
- 入力メソッド:readline()
- ファイルopen〜closeまでの時間
import utime
start = utime.ticks_us()
f = open('/sd/work.txt', 'r')
cnt = 0
while line := f.readline():
cnt += 1
f.close()
print('start', start)
print('end', end := utime.ticks_us())
print('duration', end - start)
print('cnt', cnt)
2回測定し、平均で約10.5秒であった。
読み込み性能としては、約120KB/秒。かなり遅い?
# 1回目
start 54995341
end 65450884
duration 10455543
cnt 12800
# 2回目
start 90385829
end 100999955
duration 10614126
cnt 12800
Seeeduino XIAO SAMD21で同じファイルの入力を測定したところ、約20.9秒でした。ESP32の方が2倍速い。
この性能の差は? と考えたとき、両デバイスのCPUクロック数の違いですかね?
Seeeduino XIAOは48MHz、ESP32は160MHzか240MHz。ちなみに、上記の性能は160MHzのときで、デフォルトは160MHzのようです。
import machine
machine.freq()
160000000
240MHzに変更して再度測定したところ、秒8.3秒に縮まった。約152KB/秒と160MHz時の約27%アップ。
machine.freq(240000000) # 240MHzに設定
240MHzにすることで消費電力も多くなるでしょうが、プログラムからCPUクロック数を動的に変えられるとは驚きです。
5. おわりに
SDカードのアクセス速度は速くはないが、大量の情報を保持できるというメリットがありますね。ただ、ESP32ならクラウドへ保存する方が一般的なのかも?
SDモード(4ビットバス)接続の場合は、どのくらいアクセスが速くなるのだろうか? 別途、測定してみたいと思います。
以上