この記事ははJLCPCBの提供でお送りします。
JLCPCBとは
jlcpcb.com
(↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
JLCPCBとは、プリント基板製造などで有名な香港の企業です。
日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。
値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。
この記事の作例もJLCPCBに基板を発注して実現しました。
グリッド楽器igetaとは
まぁ世の中によくあるグリッド型の電子楽器的なものを自分も作ってみようという試みです。
有名なところだとTENORI-ONとか Launch Padというものがあったりしますね。
igetaは8x8のスイッチと8x8のLEDを搭載した入力装置です。
音声出力する機能もあり、オーディオアンプやボリュームも搭載しています
仕様
- Raspberry Pi Pico
- 8x8=64個 タクトスイッチ
- 8x8=64個 LED
- NS8002オーディオアンプモジュール
- ボリューム
今回はRaspberry Pi Picoの性能に全のっかりで行きます
パーツ紹介 - NS8002オーディオアンプモジュール
AliExpressで発見したモノラルのオーディオアンプモジュールです。
詳しいことはよく知らないですが、今まで使っていたLM386よりも3.3Vで大きな音が出る点が気に入っています。
その他のパーツたち
タクトスイッチはFusionPCBを使って(ほぼ)はんだ付けせずに自作ゲーム機を作った(PCBA) - inajob's blogで紹介した DTSM-62K-S-V-T/R(SN431)です。
楽器としてはカチカチ音が鳴る点が微妙かもしれませんが、軽いタッチ(100gF)で押せるのでなかなか気に入っています。
LEDは以前購入していた1206サイズの赤色LEDを使いました。別に何色でも良いので、次作る時は別の色にしようかなと思います。
ボリュームはオリジナルのマクロパッドを作ってみた - inajob's blogで紹介したB103です。薄型の部品で、側面にちょっとした隙間があれば実装できる点が気に入っています。
Raspberry Pi Picoは言わずと知れた有名なマイコンボードです。ちょっと前まではArduno Nanoをメインに使っていたのですが、最近の半導体不足の影響か価格が高騰しています。またArduino Nanoに搭載されているマイコンであるATmegaはどうも質の悪い偽物が出回っているようで、一見ちゃんと動いているようでも、細かい部分の動作がおかしい個体があるように見えます。
一方でRaspberry Pi Picoは安価で、性能が高く、コアとなるRP2040も新しいマイコンのためか、偽物の情報もあまり聞かないので、最近はこちらをメインに利用しています。
基板の設計
今回の基板のキモは大量のタクトスイッチとLEDの接続です。
タクトスイッチ64個とLED64個をどうやってRaspberry Pi Picoに接続するかという話です。
よくあるのはマトリクスで配線する方法ですが、これは64個の部品を制御するのに16個のGPIOが必要となります。
素朴にLEDとタクトスイッチのそれぞれをマトリクス配線するとなると16+16=32のGPIOが必要となります
Raspberry Pi PicoのGPIOは28個なので、このままではGPIOが足りません。
そこで今回は、Charlieplexingという手法を採用します。この手法により16個のGPIOでこれらの制御ができます。
しかしCharieplexingは配線が複雑で、回路図を描くのが難しいという課題があります。
これについても様々な解決策があるのですが、今回はikkeiplexingという手法を採用しました。
この手法は https://twitter.com/jh3kxmさんが考案されたもので、ikkeiplexing shieldのページのPDFが非常に参考になりました。
回路図を示すと以下のような感じとなりました
左下がタクトスイッチ(とダイオード)、右上がLEDで、左縦一列の16個のGPIOで制御できます。
LEDが抵抗なしでGPIOと接続されていますがRP2040はGPIOの電流制限の機能があるようなので、正しく設定して利用すれば問題ないと理解しています。(https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf のp239 2mA, 4mA, 8mA, 12mAの間で設定可能)
で、後は基板を設計するだけ!
だけ、と書きましたが、意外とこの基板配線が複雑で、配置を工夫する必要がありました。
配線は自動配線ツールのFreeroutingに丸投げなのですが、配置が悪いといくら待っても配線が完了しない感じになります。
Raspberry Pi Picoはスルーホール穴での実装はせずに、端面スルーホールを利用し表面実装することにしました。これで裏面が自由に使えるので配線の複雑さが緩和されます。
オーディオアンプNS8002は、出来合いのモジュールを使う方法と、直接基板に実装する方法の2パターンに対応しました。
(直接基板に実装するパターンは、手元に部品がなくまだ動作が確認できていないですが・・)
JLCPCBに発注
今回も発注はJLCPCBです。今回の基板の色は黒色です。
この基板も10cm×10cmに収まるように設計したので5枚だと $2 + 送料です。
jlcpcb.com
(↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
実装
今回はとにかく、タクトスイッチ、ダイオード、発光ダイオードの数が多いというのが大変なところでした。
ひたすらはんだ付けです・・
そんな中で、今回もいくつかのトラブルが起きました。
配線が足りてない!
今回のミスです。単純にCharieplexingの配線を間違えており、必要な部分が結線されていませんでした。
いくつかのパターンをカットし、8本の配線を後から追加で足すことで、正しい回路に修正しましたが、表面はもじゃもじゃのケーブルが這うことになりました。
USBケーブルが基板と干渉する
Raspberry Pi Picoを基板の端からやや内側に配置したことと、端面スルーホールを利用して表面実装したために、Raspberry Pi PicoのUSBポートが基板にかなり近くなってしまいました。
その影響で、USBケーブルを指そうとすると基板と干渉してしまいうまく接続できない問題が起きました。
これはどうしようもないか・・と思ったのですが、手元にあるちょっと変わった形のUSBケーブルを使うと、何とか干渉せずに接続することが出来ました。
とはいえ、一般的なUSBケーブルが刺さらないのは問題なので、次回は直したいところです。
完成
何とか動作するものが出来ました。
ソフトウェアの実装
今回はCircuitPythonで実装しました。
今回の回路設計に用いたCharieplexingという手法の難しい所は配線だけではなく、ソフトウェアの実装についてもです。
適切な順番でGPIOを制御しないと、意図しないLEDが光ったり、正しくキー入力を検知できない問題が起きます。
CircuiyPythonはプログラムを変更してから実行するまでのサイクルがC/C++と比べると早いので(特にコンパイルが不要というのが大きい)こういう試行錯誤には向いていると感じました。
一応「楽器」ということで、音を鳴らす機能も付けてみることにしました。CircuitPythonには音を鳴らすためのSynthioというライブラリがデフォルトで同梱されているのでこれを使うことにしました。
Synthioはとてもシンプルな制御で、和音も鳴らすことが出来るのでちょっとした音の鳴るおもちゃを作るのに非常に便利だと感じました。
ただCircuitPyhton自体がネイティブと比べると処理が遅いので、凝ったことをしようとすると音が途切れてしまったり、期待した速度で動かないことなどがあるので、そういう場合はおとなしくC/C++を使うのがよさそうです。
ということで、できました。
押したキーに対応するLEDが点灯し、かつそのキーに対応した音が鳴るプログラムです。
同時押しにも対応しており、同時押しすると和音を演奏できます。
"""
igeta-pico test
Copyright (c) 2023 inajob
This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
"""
import digitalio
from board import *
import time
import synthio
import audiopwmio
audio = audiopwmio.PWMAudioOut(GP18)
synth = synthio.Synthesizer(sample_rate=22050)
audio.play(synth)
p1 = GP2
p2 = GP3
p3 = GP4
p4 = GP5
p5 = GP6
p6 = GP7
p7 = GP8
p8 = GP9
p9 = GP10
p10 = GP11
p11 = GP12
p12 = GP13
p13 = GP14
p14 = GP15
p15 = GP16
p16 = GP17
ports = [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16]
pports = []
for p in ports:
pports.append(digitalio.DigitalInOut(p))
sw = [
[True, True, True, True, True, True, True, False],
[True, True, True, True, True, True, True, True],
[False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False],
]
def scanKey(n):
for i in range(8):
pports[i].switch_to_input(digitalio.Pull.UP)
pports[n + 8].switch_to_output(False)
for i in range(8):
if pports[i].value:
if sw[i][n]:
pass
else:
synth.release(i*8+n+64)
else:
if sw[i][n]:
synth.press(i*8+n + 64)
else:
pass
sw[i][n] = pports[i].value
pports[n + 8].switch_to_input(None)
def scanLed(n):
for i in range(8):
if sw[n][i]:
pports[i].switch_to_input(None)
else:
pports[i].switch_to_output(False)
pports[8 + n].switch_to_output(True)
time.sleep(0.001)
pports[8 + n].switch_to_input(None)
while True:
for i in range(8):
scanKey(i)
for i in range(8):
pports[i].switch_to_output(False)
pports[i+8].switch_to_input(None)
for i in range(8):
scanLed(i)
まとめ
グリッド楽器igetaを作ることが出来ました。
この過程で以下を学ぶことが出来ました
- Charieplexingを使い多数のスイッチとLEDを制御
- Raspberry Pi Pico + CircuitPythonを使ってCharieplexingを実現
- Synthioを使った簡易的な楽器の作成
あとやりたいこととしては、筐体の作成、楽器としての機能の拡充、乾電池駆動でモバイル楽器化などを考えています。まぁボチボチやります。
おまけ 過去のigeta
実はこのグリッド楽器igetaは過去に別のアプローチで試作したことがありました。
その時は Arduino NanoとCH451を使った構成でした。
CH451というのが、この時のキモで、8×8入力、8×8出力を一気に扱えるインターフェースICです。
しかし、作ってから気づいたのですがこのCH451はキーの同時押しに対応しておらず、楽器として利用するには機能が足りないという点でお蔵入りとなりました。
また、この時は小型のスイッチと3Dプリンタで作成したスイッチのカバープレートを組み合わせて、スイッチ自体が光るような見た目にできないかと模索していました。
この試みは一定の成果があり、キーが光るような見た目の筐体を作ることはできたのですが、手元の3Dプリンタの精度ではどうしてもキーが引っかかったりとか、押し心地にムラが出る、という結果となりました。
ということで今回は素朴に6mm角のタクトスイッチをそのまま使う設計としました。
この過去のigetaでも音を鳴らすところまではプログラムを作り、それなりに遊んだりもしました。
こういう過去があっての今回のigetaの製作につながっています。
ってこれやってたの2021年5月とかですね、、意外と歴史があります。