🦅

【Raspberry Pi Pico W】SPIの使い方(micropython×Thonny)

2024/12/27に公開

1. はじめに

  • OLEDの記事がI2Cばかり出てくるので、SPI用の記事にまとめました

1.1 この記事について

  • Raspberry Pi Pico W(以下、pico)のSPIを使ったサンプルプログラムを記載する
  • 細かい解説というより、備忘録とプログラム+回路図のサンプル重視
  • 入門・解説というより備忘録に近い

1.2 対象読者

  • Picoを使ったことがある
  • Thonnyを使ってPicoにプログラムを書き込み・実行ができる
  • プログラム言語(特にmicropython)が多少読める、書ける

1.3 動作環境

  • PC
    • OS:Windows 11 Home
    • プログラミング環境:Thonny(v4.1.4)
  • Raspberry Pi Pico W
    • ファームウェア:v1.24

2. SPIについて(説明)

  • マイコンと周辺ICで通信する際に使用されるインターフェースの1つ
  • CS, SCLK, MISO, MOSIの4線で通信を行う
  • I2Cよりも高速
SPIについての詳細

Analog Devicesさんの記事がわかりやすかったので、こちらを一読いただくことをお勧めします。

SPI通信インターフェースの基本を学ぶ(入門編) - 通信回路、プロトコルなど _ Analog Devices
https://www.analog.com/jp/resources/analog-dialogue/articles/introduction-to-spi-interface.html

3. 実験

  • picoのSPIはデフォルトで以下の通りとなっている
    • GP16[SPI0 RX] ・・・ MISO(picoがmasterの場合)
    • GP17[SPI0 CSn] ・・・ Chip Select n
    • GP18[SPI0 SCK] ・・・ Serial ClocK
    • GP19[SPI0 TX] ・・・ MOSI(picoがmasterの場合)


https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html

3.1 microSD Card AdapterでmicroSDカードの読み書き

  • microSDカードの読み書きを行うことができる
  • microSDカードのフォーマットは"FAT32"推奨
  • 使用したのは以下のもの(動作電圧は5Vのため、VSYSに接続して使います)

3.1.1 回路図+配線図(Fritzing)

microSD Card Adapter pico
CS GP17[SPI0 CSn]
SCK GP18[SPI0 SCK]
MOSI GP19[SPI0 TX]
MISO GP16[SPI0 RX]
VCC VSYS
GND GND

3.1.2 実際の画像

3.1.3 プログラム例

from machine import Pin, SPI
from os import mount
from sdcard import SDCard

spi = SPI(0, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
cs = Pin(17)
sd = SDCard(spi, cs)
mount(sd, '/sd')

with open('/sd/test.txt', 'rw') as f:
    f.write('Hello, World!!')  # ファイルに書き込み
    res = f.readlines()  # ここでは書き込んだHello, World!!は取得できない
    print(res)

with open('/sd/test.txt', 'r') as f:
    res = f.readlines()  # 書き込み後、with文を出た後なら取得可能
    print(res)
sdcard.pyについて

以下のgithubにあるものを使用しました(picoのlibフォルダの中に保存)
https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/storage/sdcard/sdcard.py

open関数について

python用のドキュメントですが、writeやreadはここを参考にしました
https://docs.python.org/ja/3/library/functions.html#open

3.2 OLEDにmicropythonロゴを描画する(SPI)

  • OLEDはI2Cでの記事が多いため、SPIでの使用例を記載してみました
  • ものによってはDOがSCK, DIがMOSIと記載されているものもあったり、6ピンしかない(RSTがない)などいろんなものがあるようです

3.2.1 回路図+配線図(Fritzing)

  • SPIなのに、pico側のSPI0 RX(miso)は使用しません!
  • 代わりにDC(Data Command)とRES(Reset)を任意のGPIOに接続する必要があります
OLED(SPI) pico
GND GND
VCC 3V3
DO GP18[SPI0 SCK]
DI GP19[SPI0 TX]
RES GP5
DC GP4
CS GP17[SPI0 CSn]

3.2.2 実際の動画

3.2.3 プログラム例

from machine import Pin, SoftSPI
from ssd1306 import SSD1306_SPI
from time import sleep

spi0_SCK = Pin(18)  # DOに接続
spi0_TX = Pin(19)   # DIに接続
spi0_RX = Pin(16)   # 接続しない(使用しない)

# ソフトウェア SPI インタフェース:
spi = SoftSPI(baudrate=500000, polarity=1, phase=0, sck=spi0_SCK, mosi=spi0_TX, miso=spi0_RX)

dc = Pin(4)   # DCに接続
rst = Pin(5)  # RSTに接続
cs = Pin(17)  # CSに接続
display = SSD1306_SPI(128, 64, spi, dc, rst, cs)

# MicroPython のロゴを描画し、テキストを印字します:
display.fill(0)
display.fill_rect(0, 0, 32, 32, 1)
display.fill_rect(2, 2, 28, 28, 0)
display.vline(9, 8, 22, 1)
display.vline(16, 2, 22, 1)
display.vline(23, 8, 22, 1)
display.fill_rect(26, 24, 2, 4, 1)
display.text('MicroPython', 40, 0, 1)
display.text('SSD1306', 40, 12, 1)
display.text('OLED 128x64', 40, 24, 1)
display.show()

for t in range(100):
    display.rotate(t%2==0)  # 奇数で0度回転、偶数で180度回転
    display.show()          # 描画する
    sleep(1)

もっとOLEDの使い方を知りたい方へ

リファレンスを読むことをお勧めします(以下はESP8266用のものですが、一部使えます)
14. SSD1306 OLED ディスプレイの使い方
https://micropython-docs-ja.readthedocs.io/ja/latest/esp8266/tutorial/ssd1306.html

4. まとめ

  • SPIを用いたmicroSDcardAdapter、OLEDを動かすプログラムを紹介した
  • MISOとかSDIとか基板に書いてある略称がバラバラだったりするので、慣れないうちは戸惑いそう
  • CSを使って2つ以上のデバイスを同じバスで動かすのも、今後やってみたい

Discussion