Raspberry Pi PicoでMicroPythonでPWM信号でスピーカーでメロディー演奏

　※2/8追記　よく見たら圧電スピーカーじゃなくて普通のダイナミックスピーカーでした
　2021年1月、Raspberry Pi Foundationからマイコンボード[Raspberry Pi Picoが発表されました](https://www.raspberrypi.org/documentation/pico/getting-started/ "Getting Started with Raspberry Pi Pico – Raspberry Pi")。その後1週間ほどで日本国内でも発売され、税別500円ほどで購入できるようになっています。
　今回はRaspberry Pi Picoのセットアップから、Lチカ、そしてPWM信号出力によるスピーカーでのメロディー演奏までをやってみます。
# 購入～ピンヘッダのはんだ付け
　国内では[スイッチサイエンス](https://www.switch-science.com/catalog/6900/)や[KSY](https://raspberry-pi.ksyic.com/)、[秋月電子通商](https://akizukidenshi.com/catalog/g/gM-16132/)、その他電子工作系ショップなどで購入できます。失敗を恐れずに色々なことに挑戦できるので複数買っておくのをおすすめします。10個買っても5000円なので。
![私は3つ買いました](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/2b70c3e2-574d-a52c-2771-e01c624fe33c.jpeg "私は3つ買いました")
　PicoはGPIO端子がスルーホールになっているだけなので、開発しやすくするためにピンヘッダをはんだ付けします。必要な道具は、

* はんだ、はんだこて、こて台などのはんだ付け道具セット
* ピンヘッダ（20ピン×2本）
* ブレッドボード

![はんだ付けセット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/1078362e-b85c-1191-06af-e879f2f3fbbc.jpeg "はんだ付けセット")
　ピンヘッダは40ピンの長さで売られていることが多いので、ニッパーで2等分して20ピン×2本にします。
![ニッパーで切断](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/b9a15e9b-42b7-a15b-0fbe-a0730e049319.jpeg "ニッパーで切断")
　ピンヘッダーの長い方をブレッドボードに差し込んでその上にPicoを乗せると、はんだ付けがしやすくなります。
![ピンヘッダーの長い方をブレッドボードに差し込む](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/835c4556-23dd-25c4-3297-8731b1a45aee.jpeg "ピンヘッダーの長い方をブレッドボードに差し込む")
![Picoを乗せる](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/8f345ab2-7fa8-97f4-c9f3-b8482f630297.jpeg "Picoを乗せる")
　はんだ付けのやり方は[はんだこてメーカーのサイト](https://handa-craft.hakko.com/support/good-soldering.html "理想のはんだ付け | はんだ付けテクニックを学ぼう！ | [HAKKO]")やその他いろんな所で解説されていますので、初めての場合はよく調べてから挑戦しましょう。
![はんだ付けする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/d69d4ca9-686b-6a3d-4c66-d7247f89f58c.jpeg "はんだ付けする")
　はんだ付けできました。
![はんだ付け完了・表](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/933a6f91-b2e4-f7b9-7a67-03d918433ecb.jpeg "はんだ付け完了・表") ![はんだ付け完了・裏](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/09709634-eaa0-41ac-ca2a-3c16ceea47c4.jpeg "はんだ付け完了・裏")
# MicroPythonのインストールと開発環境の用意
　続いてPicoに電源を入れますが、購入時のままだとPicoに電源を入れても特に何もできません。PicoがMicroPythonを実行できるように実行環境をインストールする必要があります。インストールするためのファイルは[Raspberry Pi Picoの公式サイト](https://www.raspberrypi.org/documentation/pico/getting-started/ "Getting Started with Raspberry Pi Pico – Raspberry Pi")からダウンロードできます。ページ上部の「Getting started with MicroPython」タブをクリックし、その下の「Download UF2 file」ボタンからUF2ファイルをダウンロードします。（UF2とはUSB Flashing Formatのことで、Microsoftが開発したマイコンのためのファイル形式だそうです。）
![MicroPythonのタブを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/e344d134-6c20-6797-4ddd-d810b44a58f8.png "MicroPythonのタブを選択")
![ダウンロード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/3c379b88-3e80-3dd5-fed7-e680c73fbd2e.png "ダウンロード")
　次にPicoをパソコンのUSBポートに接続しますが、UF2ファイルをインストールする場合は特別な接続の仕方を行う必要があります。Pico本体の表面に「BOOTSEL」と書かれたスイッチがあるので、これを押しながらUSBケーブルを接続してください。こうすることで、パソコン上には「RPI-RP2」という名前で通常のUSBマスストレージドライブ（USBメモリ）として表示されます。
![BOOTSELを押したまま接続](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/7f913623-b182-231f-5add-781893905e82.jpeg "BOOTSELを押したまま接続")
![USBマスストレージドライブとして表示される](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/63592fa6-9cbf-26b9-6821-2ff15fed0dc4.png "USBマスストレージドライブとして表示される")
　先ほどダウンロードしたUF2ファイルをこのRPI-RP2の中にドラッグ＆ドロップすることで、自動でインストールが実行されます。インストールが終わるとUSBマスストレージドライブが一旦接続解除されます。
![スクリーンショット 2021-02-07 131148.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/41c9923d-2db9-9fa9-5b69-db6999b97b8d.png)
　これでPico上でMicroPythonが実行できるようになりました。USBケーブルは繋いだまま次のステップへ移ります。（以降、Picoを開発する時はBOOTSELスイッチは押さずにUSBケーブルを接続するだけでOKです。）
　次にMicroPythonを書くためのIDEを用意します。公式がビギナーガイドでおすすめしているThonnyはシンプルで使いやすい初心者向けIDEです。[こちらの公式サイトからダウンロード](https://thonny.org/ "Thonny, Python IDE for beginners")します。
![Thonny公式サイトからダウンロード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/ab1ea476-d194-2431-0128-c34f5dfb3f4e.png "Thonny公式サイトからダウンロード")
　ダウンロードしたファイルを実行し、ソフトをインストールします。特に設定はいじらずデフォルトのままインストールしてしまって大丈夫です。
　Thonnyを起動し、画面右下のインタプリタを「MicroPython (Raspberry Pi Pico)」を選択。またシンプルモード画面はシンプルすぎて逆に使いにくいので、画面右上の「Switch to regular mode」を選択してレギュラーモードに切り替えるのをおすすめします。
![Thonny画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/831e11ae-23ac-96b7-825a-6c2afb85d551.png "Thonny")
　これで開発環境も整いました。それでは次の項でMicroPythonのコードを書いていきます。
# Lチカさせる
　Lチカとは「LEDをチカチカ光らせること」の略で、マイコンやフィジカルコンピューティングの最初の動作テストでよく行われる定番の動作です。Raspberry Pi Picoには基板上に1つのLEDがあらかじめ接続されているので、これを光らせてみます。
　以下のMicroPythonプログラムをThonnyに入力します。

```Python:led_blink.py
from machine import Pin # GPIOを制御するためのクラス Pin をインポート
import utime            # 時間を制御するためのクラス utime をインポート

led_onboard = Pin(25, Pin.OUT) # 基板上のLEDはGPIO25番に接続されている

while True: # ↓のコードを繰り返し実行する
    led_onboard.toggle() # GPIO25番の信号をオン/オフ切り替える
    utime.sleep(0.5) # 0.5秒待つ
```
　入力したら、緑色の「Run」ボタンを押してプログラムを実行します。
![プログラムを記述してRunボタンを押す](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/036316c9-4cbe-d188-5237-e18d3cd16d59.png "プログラムを記述してRunボタンを押す")
　プログラムを実行しようとすると、その前にプログラムをどこに保存するか聞かれます。パソコン上でもPico上でもどちらでも構いませんので、「led_blink.py」のような適当な名前をつけて保存してください。
![実行する前にファイルを保存](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/9e41b82c-c4d8-4430-9e59-506f6dad6a61.png "実行する前にファイルを保存")
　実行結果はどうでしょうか？Pico上のLEDがチカチカすれば成功です。おめでとうございます！
<blockquote class="twitter-tweet" data-theme="light"><p lang="ja" dir="ltr">Raspberry Pi Pico、Lチカできたよ<br>かわいいね <a href="https://t.co/tzflUZjSgx">pic.twitter.com/tzflUZjSgx</a></p>&mdash; undo (@undo) <a href="https://twitter.com/undo/status/1356930544005652481?ref_src=twsrc%5Etfw">February 3, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
# スピーカーを接続し、PWM信号を送出してメロディーを鳴らす
　さて、いよいよスピーカーを鳴らします。今回は短くて簡単なピタゴラスイッチのテーマを演奏してみます。
　用意するスピーカーは何でもいいですが、Raspberry Piに対応！とか書いてある品だと安心かもしれません。私は近所のハードオフでジャンク品の携帯ゲーム機を買ってきて分解し内蔵スピーカーを拝借しました。
![DS Liteの内蔵スピーカー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/7beb63a9-8184-6747-ca76-dee7ef53568b.jpeg "DS Liteの内蔵スピーカー")
ブレッドボードを使って、適当なピンに接続します。一応抵抗を挟みましたが無くても動作しました。（真ん中あたりに繋いでいる黒いタクトスイッチはPicoをリセットするためのもので、このプログラム実行においては不要です。）
![スピーカーを接続](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222969/7b0e8400-3a27-fbe3-d98e-3da6a5a437f8.jpeg "スピーカーを接続")
　次にMicroPythonコードです。スピーカーの音を出すためには一定の周波数で振動する信号を送出し、その信号を受けたスピーカーを振動させる必要があります。この一定周波数で振動する信号をPWM（Pulse Width Modulation、パルス幅変調）信号を使って作り出します。

```Python:pythagoraswitch.py
from machine import Pin, PWM, Timer

speaker = PWM(Pin(17, Pin.OUT)) # スピーカーを接続しているGPIO（この例では17番）を作成し、それをPWM()へ渡す
led_onboard = Pin(25, Pin.OUT) # 基板上のLEDを光らせたいのでGPIO25作成

# 使用する音の周波数を宣言しておく。ピタゴラスイッチは低いラ～高いドまでの音を使う
A4 = 440
B4 = 493.883
C5 = 523.251
C5s= 554.365
D5 = 587.330
E5 = 659.255
F5 = 698.456
F5s= 739.989
G5 = 783.991
A5 = 880
B5 = 987.767
C6 = 1046.502

# bps = 6.4 # 原曲128bpm / 60秒 = 2.1333...bps * 3連符 = 6.4bps
mspb = 156 # 6.4bpsの逆数 = 0.156ms　これが8分3連符ひとつ分の音の長さ、音の間隔となる

# ピタゴラスイッチのメロディーを配列で作成。1要素が8分3連符ひとつ分の音の長さになる。0は無音（休符）
melody = [D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,C6,B5,0,G5,A5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,B4,A4,0,B4,C5,0,C5s,D5,0,0,D5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,C6,B5,0,G5,A5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,B4,A4,A4,A4,A4,A4,A4,A4,A4,A4,0,0,F5,E5,0,E5,F5s,E5,F5s,G5,G5,G5,D5,0,B4,C5,0,C5,D5,C5s,D5,B4,B4,B4,0,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,G5,F5s,0,D5,E5,0,D5,E5,0,D5,E5,0,C6,B5,0,0,G5,0,0,0,0,0,0,0,0,0,0,0,0,0,D5,E5,0,D5,E5,0,C6,B5,0,0,G5]
i = 0

# 音を鳴らすためのコールバック関数
def beat(timer):
    global melody
    global led_onboard
    global i
    global speaker
    
    if i >= len(melody): # メロディーを最後まで演奏し終えたら
        speaker.deinit() # スピーカーのPWMを破棄して
        led_onboard.value(0) # LEDを消して
        timer.deinit() # タイマーを破棄して終了
        
    elif int(melody[i]) == 0: # メロディー音が0、つまり無音（休符）の場合
        speaker.duty_u16(0) # PWMのDutyを0とすることで波形は出力されずLOWとなり、音は出ない
        led_onboard.value(0) # LEDを消す
        
    else:
        speaker.freq(int(melody[i] + 0.5)) # PWMの周波数を次のメロディー音の周波数に変更する。整数で渡す必要があるので、+0.5してから小数点以下切り捨て（thanks @naohiro2g）
        speaker.duty_u16(0x8000) # PWMのDutyを50％に戻し、音を出す。Dutyは0～0xFFFFつまり65535までの間の値で設定
        led_onboard.value(1) # LEDを光らせる

    i += 1 # メロディーを次に進めて終わり

# 8分3連符の間隔でコールバックを呼ぶタイマーを作成し、メロディースタート
tim = Timer()
tim.init(period=mspb, mode=Timer.PERIODIC, callback=beat)

```

　コードの意味はコメントの通りですが要点だけピックすると、まず `speaker = PWM(Pin(17, Pin.OUT))` でPWMオブジェクトを作成します。引数にはPinオブジェクトを渡します。
　PWMオブジェクトは周波数とデューティを設定してやることでPWM信号を送出します。周波数は `speaker.freq(周波数（Hz）)` 関数で、デューティは `speaker.duty_u16(デューティ値（4ケタの16進数、もしくはintで直接0～65535）)` で設定します。スピーカーを動かすだけなのでデューティ値は50％にしておけば音が出ます。周波数を上げ下げすることでスピーカーの振動の速さが変わり、音の高さが変わるわけです。
　`tim = Timer()` でタイマーを作成し、一定間隔でbeatメソッドをコールバックします。メロディー音の周波数が入った配列を順に回してPWM信号を出力し、スピーカーに演奏させます。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Raspberry Pi PicoでMicroPythonでPWM信号でスピーカーを鳴らしてピタゴラスイッチを演奏したよ<br><br>　　　⁽⁽ ₍₍ 🎱　ピ<br><br>PicoのセットアップからLチカ、そしてメロディー演奏までを⬇️の記事に書いたから見てね<br> <a href="https://t.co/09SQqaZXnC">https://t.co/09SQqaZXnC</a> <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <a href="https://twitter.com/hashtag/RpspberryPiPico?src=hash&amp;ref_src=twsrc%5Etfw">#RpspberryPiPico</a> <a href="https://twitter.com/hashtag/%E3%83%94%E3%82%BF%E3%82%B4%E3%83%A9%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81?src=hash&amp;ref_src=twsrc%5Etfw">#ピタゴラスイッチ</a> <a href="https://t.co/37rMyqCMDx">pic.twitter.com/37rMyqCMDx</a></p>&mdash; undo (@undo) <a href="https://twitter.com/undo/status/1358309286414221313?ref_src=twsrc%5Etfw">February 7, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>