RP2 用クイックリファレンス

Raspberry Pi Pico

Raspberry Pi Pico 開発ボード (画像出所: Raspberry Pi 財団)。

以下は、Raspberry Pi RP2xxx ボードのためのクイックリファレンスです。このボードを初めて使う場合は、まず次のマイクロコントローラの概要を確認することを勧めます

MicroPython のインストール

チュートリアルの章: RP2xxx での MicroPython の始め方 を参照してください。そこにはトラブルシューティングについても記載されています。

ボードの一般的な制御

MicroPython REPL は USB シリアルポートで利用できます。タブ補完は、オブジェクトにどのようなメソッドがあるかを調べるのに便利です。貼り付けモード(ctrl-E)は、大きめの Pythonコードを REPL に貼り付けるのに便利です。

machine モジュール:

import machine

machine.freq()          # CPU の現在の周波数を取得
machine.freq(240000000) # CPU の周波数を 240 MHz に設定

rp2 モジュール:

import rp2

遅延とタイミング

time モジュールを使います:

import time

time.sleep(1)           # 1秒間、一時停止する
time.sleep_ms(500)      # 500ミリ秒間、一時停止する
time.sleep_us(10)       # 10マイクロ秒間、一時停止する
start = time.ticks_ms() # ミリ秒カウンター値を取得
delta = time.ticks_diff(time.ticks_ms(), start) # 時差を計算

タイマー

RP2040 のシステムタイマペリフェラルは、グローバルなマイクロ秒のタイムベースを提供し、そのための割り込みを生成します。現在、ソフトウェアタイマが利用可能であり、その数は(メモリが許す限り)無制限です。タイマーID (現時点では id=1 がサポートされています)を指定する必要は無く、デフォルトで指定されます。

machine.Timer クラスを使います:

from machine import Timer

tim = Timer(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2))

ピンと GPIO

machine.Pin クラスを使います:

from machine import Pin

p0 = Pin(0, Pin.OUT)    # GPIO 0 の出力ピンを作成
p0.on()                 # ピンを "on" (high) レベルに設定
p0.off()                # ピンを "off" (low) レベルに設定
p0.value(1)             # ピンを on/high に設定

p2 = Pin(2, Pin.IN)     # GPIO 2 の入力ピンを作成
print(p2.value())       # 値 0 または 1 を取得

p4 = Pin(4, Pin.IN, Pin.PULL_UP) # 内部プルアップ抵抗を有効化
p5 = Pin(5, Pin.OUT, value=1) # 作成時にピンを high に設定

プログラマブル IO (PIO)

PIO は低レベルの IO インターフェースを一から構築するのに便利です。アセンブリ命令の詳細な説明については rp2 モジュールを参照してください。

PIO を使って 1Hz で LED を点滅させる例:

from machine import Pin
import rp2

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
    # 周期: 1 + 7 + 32 * (30 + 1) = 1000
    set(pins, 1)
    set(x, 31)                  [6]
    label("delay_high")
    nop()                       [29]
    jmp(x_dec, "delay_high")

    # 周期: 1 + 7 + 32 * (30 + 1) = 1000
    set(pins, 0)
    set(x, 31)                  [6]
    label("delay_low")
    nop()                       [29]
    jmp(x_dec, "delay_low")

# Pin(25) に出力する blink_1hz の StateMachine を作成/始動
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
sm.active(1)

UART (シリアルバス)

UART0 と UART1 の2つの UART があります。UART0 は GPIO 0/1、12/13、16/17 にUART1 は GPIO 4/5、8/9 にマッピングできます。

machine.UART を参照

from machine import UART, Pin
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart1.write('hello')  # 5バイト書き出す
uart1.read(5)         # 5バイトまで読み込む

注釈

REPL over UART はデフォルトで無効になっています。REPL over UART を有効にする方法については RP2xxx での MicroPython の始め方 を参照してください。

PWM (パルス幅変調)

8つの独立したチャンネルがあり、それぞれが2つの出力を持ち、合計で 16 の PWM チャンネルがあり、7Hz から 125Mhz までのクロックに対応しています。

machine.PWM クラスを使います:

from machine import Pin, PWM

pwm0 = PWM(Pin(0))      # ピンから PWM オブジェクトを作成
pwm0.freq()             # 現在の周波数を取得
pwm0.freq(1000)         # 周波数を設定
pwm0.duty()             # 現在のデューティ比を取得
pwm0.duty(200)          # デューティ比を設定
pwm0.deinit()           # PWM を無効化

ADC (アナログ/デジタル変換)

RP2040 には合計5つの ADC チャンネルがあり、そのうちの4つ(GP26, GP27, GP28, GP29)は 12 ビットの SAR ベースの ADC です。ADC0, ADC1, ADC2, ADC3 の入力信号は,それぞれ GP26, GP27, GP28, GP29 に接続できます(Pico 基板では GP29 は VSYS に接続)。標準的な ADC のレンジは 0-3.3V です。5チャンネル目は内蔵の温度センサに接続されており、温度の測定に使えます。

machine.ADC クラスを使ってください:

from machine import ADC, Pin
adc = ADC(Pin(26))     # ADC ピンの ADC オブジェクトを作成
adc.read_u16()         # 0.0v - 3.3v 範囲を 0-65535 の値で読込み

ソフトウェア SPI バス

ソフトウェア SPI (ビットバンギング)はすべてのピンで動作し、 machine.SoftSPI クラスを介してアクセスします:

from machine import Pin, SoftSPI

# 与えたピンから SoftSPI バスを構築
# 極性 polarity は SCK のアイドル状態
# phase=0 は SCK の第1エッジでサンプルを意味、chase=1 は第2を意味
spi = SoftSPI(baudrate=100_000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))

spi.init(baudrate=200000) # ボーレートを設定

spi.read(10)            # MISO で 10 バイト読込み
spi.read(10, 0xff)      # 10 バイト読込み、その間 MOSI に 0xff を出力

buf = bytearray(50)     # バッファを作成
spi.readinto(buf)       # 与えたバッファに読込み(この場合は 50 バイト)
spi.readinto(buf, 0xff) # 与えたバッファに読込み、MOSI に 0xff を出力

spi.write(b'12345')     # MOSI に 5 バイト書込み

buf = bytearray(4)      # バッファを作成
spi.write_readinto(b'1234', buf) # MOSI に書き込み、MISO からバッファに読み込み
spi.write_readinto(buf, buf) # MOSI に buf を書き込み、MISO から buf に読み込み

警告

現在のところ、ソフトウェア SPI を初期化するときには sck, mosi, miso すべて を指定しなければなりません。

ハードウェア SPI バス

RP2040 には machine.SPI クラスを使ってアクセスできる2つのハードウェア SPI があり、先のソフトウェア API と同じメソッドが使えます:

from machine import Pin, SPI

spi = SPI(1, 10_000_000)  # Default assignment: sck=Pin(10), mosi=Pin(11), miso=Pin(8)
spi = SPI(1, 10_000_000, sck=Pin(14), mosi=Pin(15), miso=Pin(12))
spi = SPI(0, baudrate=80_000_000, polarity=0, phase=0, bits=8, sck=Pin(6), mosi=Pin(7), miso=Pin(4))

ソフトウェア I2C バス

ソフトウェア I2C (ビット・バンギングを使用)は、出力可能なすべてのピンで動作し、 machine.SoftI2C クラスを使ってアクセスします。

from machine import Pin, SoftI2C

i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100_000)

i2c.scan()              # デバイスをスキャン

i2c.readfrom(0x3a, 4)   # アドレス 0x3a のデバイスから 4 バイト読み込み
i2c.writeto(0x3a, '12') # アドレス 0x3a のデバイスに '12' を書き込み

buf = bytearray(10)     # 10バイトのバッファを作成
i2c.writeto(0x3a, buf)  # 与えたバッファをペリフェラルに書き込み

ハードウェア I2C バス

ハードウェア I2C には machine.I2C クラスを使ってアクセスしますこのクラスには先述のソフトウェア I2C と同じメソッドがあります:

from machine import Pin, I2C

i2c = I2C(0)   # デフォルトの割当て: scl=Pin(9), sda=Pin(8)
i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=400_000)

I2S バス

machine.I2S を参照:

from machine import I2S, Pin

i2s = I2S(0, sck=Pin(16), ws=Pin(17), sd=Pin(18), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object
i2s.write(buf)             # オーディオサンプルのバッファを I2S デバイスに書き込む

i2s = I2S(1, sck=Pin(0), ws=Pin(1), sd=Pin(2), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # I2S オブジェクトの作成
i2s.readinto(buf)          # I2S デバイスからのオーディオサンプルでバッファを埋める

ws のピン番号は sck のピン番号よりも1つ大きくなければなりません。

I2S クラスは、現在のところ技術プレビューとして提供しています。プレビュー期間中、ユーザーの皆様からのフィードバックをお待ちしています。このフィードバックに基づいて、I2S クラスの API と実装が変更される可能性があります。

2つのI2Sバス、id=0 と id=1 がサポートされています。

リアルタイムクロック (RTC)

machine.RTC を参照:

from machine import RTC

rtc = RTC()
rtc.datetime((2017, 8, 23, 2, 12, 48, 0, 0))  # 指定の日時(2017/8/23 1:12:48)
                                              # を設定
rtc.datetime() # 日時を取得

WDT (ウォッチドッグタイマー)

RP2040 にはカウントダウンタイマーであるウォッチドッグが搭載されており、これがゼロになるとチップの一部を再起動できます。

machine.WDT を参照:

from machine import WDT

# WDT を有効化し、タイムアウトを 5s に設定(最低値は 1s)
wdt = WDT(timeout=5000)
wdt.feed()

OneWire ドライバー

OneWire ドライバーはソフトウェアで実装され、すべてのピンで動作します:

from machine import Pin
import onewire

ow = onewire.OneWire(Pin(12)) # GPIO 12 で OneWire バスを作成
ow.scan()               # バス上のデバイスリストをスキャン
ow.reset()              # バスをリセット
ow.readbyte()           # 1バイト読込み
ow.writebyte(0x12)      # バスに1バイト書込み
ow.write('123')         # バスに複数バイト書込み
ow.select_rom(b'12345678') # ROM コードで指定したデバイスを選択

DS18S20 と DS18B20 デバイス用の特定のドライバーがあります:

import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)
for rom in roms:
    print(ds.read_temp(rom))

4.7k のプルアップ抵抗をデータラインに接続してください。convert_temp() メソッドは、温度をサンプリングするたびに呼び出す必要があることに注意してください。

NeoPixel/APA106 ドライバー

neopixelapa106 モジュールを使います(訳注: 今のところ apa106 モジュールは rp2 でサポートされていません):

from machine import Pin
from neopixel import NeoPixel

pin = Pin(0, Pin.OUT)   # NeoPixel 駆動のための GPIO 0 を出力に設定
np = NeoPixel(pin, 8)   # 8ピクセル用の NeoPixel ドライバーを GPIO 0 で作成
np[0] = (255, 255, 255) # 第1ピクセルを白に設定
np.write()              # 全ピクセルにデータ書込み
r, g, b = np[0]         # 第1ピクセルの色を取得

APA106 ドライバーは NeoPixel を継承していますが、内部的には異なる色順を使っています:

from apa106 import APA106
ap = APA106(pin, 8)
r, g, b = ap[0]

APA102 (DotStar)はクロック端子が追加されているため、別のドライバーを使います。