Raspberry Pi PicoとCircuitPythonで和音楽器を作る

この記事ははJLCPCBの提供でお送りします。
JLCPCBとは

jlcpcb.jp (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
JLCPCBとは、プリント基板製造などで有名な香港の企業です。
日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。
値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。
この記事の作例はJLCPCBに基板を発注して作成した、以前の基板を更に活用した内容です。
これは何?
私が作っているRakuChordは、もともとArduino UNOなどで用いられているATmega328をメインCPUとしたものでした。 しかし昨今半導体の高騰や新しい組み込み向けのCPUの登場により、ATmega328以外の選択肢も模索したいという気持ちが高まってきました。
ということでこの記事ではRaspberry Pi Picoに搭載されていることでおなじみのRP2040を使って和音楽器を作る方法について紹介します。
Raspberry Pi Picoでのプログラミング
今回利用するのはRP2040-Zeroという開発ボードで、厳密にはRaspberry Pi Picoとは異なります。 しかし回路の構成はほぼRaspberry Pi Picoと同じなので、Raspberry Pi Picoでもほぼ同じように和音楽器を作ることができるはずです。
Raspberry Pi Picoに搭載されているRP2040は、ATmega328などの8bit CPUと比べるとかなりパワフルなマイコンです。 C/C++での開発はもちろんできますがMicroPythonやCircuitPythonなどのインタプリタ言語も動作します。
今回は和音楽器の作成にあたり、CircuitPythonを使うことを選択しました。
C/C++と違い、インタプリタ型のCircuitPythonでの開発は、少し変更して実行してみるというトライ&エラーがやりやすく、高速に開発することができると感じました。 最終的にパフォーマンスの要件などでC/C++を使うとしても、プロトタイプとしてCircuitPythonを使って動作検証を行うのはかなりアリだと思います。
CircuitPythonで和音を鳴らす
CircuitPythonはインタプリタ方式のプログラミング言語で、C/C++と比べると明らかに実行速度が遅いです。 そのため、音の生成、特に和音の生成などをCircuitPythonの層で実装することは現実的ではありません。
しかしCircuitPythonには標準の組み込みのモジュールとしてsynthioという和音をサポートして音源ライブラリが搭載されており、これを利用することで、気軽なインタプリタ方式のプログラミング言語で、高速動作が要求される和音の生成を実現することができます。
synthio
RP2040で動作するPythonの実装としては有名なのはMicroPythonとCircuitPythonがあります。これらはそれぞれ微妙に違った特性を持っていますが、今回CircuitPythonを選択したのは、CircuitPythonには組み込みライブラリとしてsynthioがあったからです。
このライブラリは音を鳴らすためのもので、今回やりたい和音の生成もサポートしています。
配線
synthioはDAC出力とPWM出力をサポートしています。今回は追加部品が不要なPWM出力を利用します。 このために出力ピンは適切なRCフィルタを構成のが定石のようですが、ちょっと試す分には、深く考えずスピーカやオーディオアンプを直接繋いでも動作を確認できます。 参考元の資料では1kΩの抵抗と100nFのコンデンサでRCフィルタを作成していました。

単音を鳴らしてみる
以下のようなシンプルなソースコードでファの音を0.5秒毎にON/OFFできます。
import board, time import synthio import audiopwmio audio = audiopwmio.PWMAudioOut(board.GP10) synth = synthio.Synthesizer(sample_rate=22050) audio.play(synth) while True: synth.press(65) # midi note 65 = F4 time.sleep(0.5) synth.release(65) time.sleep(0.5)
和音を鳴らしてみる
和音を鳴らすのも単音と同じようにできます。
import board, time import audiopwmio import synthio audio = audiopwmio.PWMAudioOut(board.GP10) synth = synthio.Synthesizer(sample_rate=22050) audio.play(synth) while True: synth.press( (65,69,72) ) # midi notes 65,69,72 = F4, A4, C5 time.sleep(0.5) synth.release( (65,69,72) ) time.sleep(0.5)
from github.com
キー操作に対応して音を鳴らしてみる
ここまでの例は無限ループでsleepさせて音を鳴らしていましたが、ここをキーの入力判定に書き換えればキー操作に対応して音を鳴らすことが出来る、いわゆる「楽器」を作ることが出来ます
この例ではRaspberry Pi PicoのGPIO2番にタクトスイッチつながっており、スイッチを押下することでGNDとショートするような回路を想定しています。

import board, time import audiopwmio import synthio audio = audiopwmio.PWMAudioOut(board.GP10) synth = synthio.Synthesizer(sample_rate=22050) audio.play(synth) p1 = digitalio.DigitalInOut(board.GP2) p1.direction = digitalio.Direction.INPUT p1.pull = digitalio.Pull.UP isPlaying= False while True: if p1.value == False and isPlaying== False: synth.press( (65,69,72) ) # midi notes 65,69,72 = F4, A4, C5 isPlaying= True else: if isPlaying== True: synth.release( (65,69,72) ) isPlaying= False
和音を鳴らす以外の処理が複雑になると音が途切れてしまう問題の対処
さて、ここまでで電子楽器を作るための準備が整いました。 しかし、楽器を作りこんでいくにしたがって、音を鳴らす以外の処理が増えてきます。前述のキーの入力検出に始まり、画面の制御なども実装していくと、だんだん生成される音にノイズが混じるようになってきます。
これはsynthioの音波の生成がほかの処理により遅れてしまい、音の再生スピードに追い付かなくなることから発生するようです。

根本的には、音波の生成以外の処理を減らせば、この問題は起きませんが、もっと処理を詰め込むことは出来ないでしょうか?
こんな時に役立つのがsynthioのバッファリング機能です。
synthioでは、生成する音波をバッファにためておく機能があり、これを使うことで、少しほかの処理が複雑になっても、バッファにためておいたデータの分だけ時間に余裕が出来ます。
ただ、バッファを大きくすればするほど、音の生成にラグが生じるので、バッファの大きさには注意が必要です。楽器として使いやすくするうえではバッファをなるべく小さくして、キーを入力したらなるべく早く音が鳴ってくれる方がが扱いやすいので、ここは操作性とのトレードオフとなります。
import board, time import audiopwmio import audiomixer import synthio audio = audiopwmio.PWMAudioOut(board.GP10) # ここからがバッファリングの処理 mixer = audiomixer.Mixer(sample_rate=22050, buffer_size=2048) # ここの2048を大きくするとバッファを大きくできる synth = synthio.Synthesizer(sample_rate=22050) mixer.voice[0].play(synth) mixer.voice[0].level = 0.25 # 音量の調整もできる # ここまでバッファリングの処理 p1 = digitalio.DigitalInOut(board.GP2) p1.direction = digitalio.Direction.INPUT p1.pull = digitalio.Pull.UP isPlaying= False while True: if p1.value == False and isPlaying== False: synth.press( (65,69,72) ) # midi notes 65,69,72 = F4, A4, C5 isPlaying= True else: if isPlaying== True: synth.release( (65,69,72) ) isPlaying= False
OLEDの制御
さて、ここまでで和音楽器として実用的なものが作れるようになりましたが、私の作ろうとしている楽器には128x64のI2C接続のOLEDが搭載されており、キーの入力に合わせてOLEDの表示も変更する必要がありました。
CircuitPythonは組み込みのライブラリではOLED制御をするためのものが含まれていないのでOLEDを制御するためのライブラリを導入します。
OLED制御のライブラリはCircuitPython Library Bundleという標準的なライブラリ集に含まれているので、これをダウンロードします。
この中に含まれるファイルをRaspberry Pi Picoのファイルシステムにコピーします。
adafruit_framebuf.mpy, adafruit_ssd1306.mpyをlib以下に、font5x8.binをルートに配置します。
ここまで準備すれば、以下のようなプログラムでOLEDに文字を表示できます。
import board import busio import adafruit_ssd1306 i2c = busio.I2C(board.GP11, board.GP10) oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c) oled.text("Hello World!",20,5,1) oled.show()
OLEDの表示と和音生成の両立
しかし上記の方法でOLEDを制御しつつ音を鳴らそうとすると、画面表示にCPU処理を使いすぎてしまい、かなり大きなバッファを設けないとノイズが発生してしまう問題が起きました。
しかし、バッファを大きくすると前述のようにラグが大きくなり、実用に耐えない楽器となってしまうという問題があります。
色々調べているうちに、OLEDの画面転送のオプションを変更し、1つの画面をいくつかに分割して更新することで、バッファを小さく保ったままノイズのない音を生成することが出来ました。
これは、OLEDの画面転送を分割することで、その隙間にsynthioの音波生成の処理を実行することが出来るようになるからだと考えています。
副作用として画面の更新が少し遅くなりますが、楽器を操作するうえで気になるほどではありませんでした。

import board import busio import adafruit_ssd1306 i2c = busio.I2C(board.GP11, board.GP10) # page_addressing=True により画面更新を分割する oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, page_addressing=True) # なぜか手元のOLEDだと表示位置がずれるので微調整 oled.page_column_start[1] = oled.page_column_start[1] -4 oled.text("Hello World!",20,5,1) # page_addressingの設定を変更したのでこのshowの中身の動作が変わり、画面更新を分割して実行する oled.show()
ATmega328用の基板を流用してRP2040の動作の確認をする
ここまでで、ソフトウェア的にRakuChord的なものをRP2040で実行できる目途が立ちました。
ここからは、ハードウェア的にRakuChord的な構成を作り、動作検証をしていきたいので、このために新たに基板を作る必要がありそうです、、、が、、
そういえば以前表面実装部品版RakuChordの改良版を作った - inajob's blogの記事で作成したRakuChordは、キー入力のためのピンを引き出して設計していたので、この基板を流用して、RP2040の開発ボードと無理やりくっつけることで、ハードウェア的な動作確認もできるのでは?と考えました。

その結果がこちら!

動画はこちら
21個のキーの入力を受け付けるために3*7のマトリクスで処理しているので、全部で10本の信号線と電源の線をつなげる必要があり、こんな風にモジャモジャになりました。アンプやスピーカーもつなげました。
これで、RP2040をコアとしたRakuChordの試作機が完成しました。
こんなこともあろうかと、キー入力のパッドを引き出しておいてよかったです。
で、実際にRakuChord的なソフトウェアをCircuitPythonで作って、触ってみたところ、、特に問題なく動作しそうでした。
さて、次はこの構成を踏まえてRP2040をコアとしたRakuChordの基板を発注するぞ!という気持ちです。(それはまた別の話と言うことで・・)
まとめ
今までATmega328を使っていたRakuChordのCPUをRP2040かつCircuitPythonに変更できるかを色々検証しました。
C/C++に比べるとパフォーマンスの低いCircuitPythonでも、工夫すれば音の生成とOLEDの描画が出来そうなことがわかりました。
CircuitPythonでの開発は非常に手軽なので、簡単な電子楽器を作ろうと考えている方にはとてもお勧めの手法です。
また、過去に作成したATmega328用のボードの「こんなこともあろうかと」用意しておいた拡張端子をうまく利用することで、新たに基板を設計する前に、動作確認することが出来ました。
参考
Synthioの活用法については以下のリポジトリが参考になりました
UARTで書き込みできるCH32V003開発ボードを作った

この記事ははJLCPCBの提供でお送りします。
JLCPCBとは

jlcpcb.jp (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
JLCPCBとは、プリント基板製造などで有名な香港の企業です。
日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。
値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。
この記事の作例もJLCPCBに基板を発注して実現しました。
これは何?
以前CH32V003を使った基板を作って遊びました。今回はその時の知見を活かして、UARTで書き込みできるCH32V003開発ボードを作成してみました。
inajob.hatenablog.jp inajob.hatenablog.jp
仕様
この基板は何か専用の機能を持つものではなく、汎用的な開発基板です。
- CH32V003F4P6
- USBコネクタ(フットプリントのテストのため3種)
- USBシリアル変換IC CH340G
- RSTスイッチ、BOOTスイッチ
- 自動リセット回路(ESP32などの回路をまねたもの)
- WCH-LinkE接続用端子
基板の設計
今回の基板は以前作ったCH32V003の基板とよく似たものですが、USBシリアル変換ICとRSTスイッチ、BOOTスイッチが搭載されているのが特徴です。 また、Arduinoではおなじみの自動リセットの仕組みを実現するための回路も搭載しています。
今回利用するファームウェアは、起動時にPC0の状態を読み取り、LOWであれば書き込みモードに入るという動作をするものです。 これを実現するためにBOOTスイッチを搭載しています。つまり、BOOTスイッチを押しながらRSTスイッチを押すことで書き込みモードに入るということです。

CH32V003のUART書き込みのサンプルは、PC0がHIGHであれば書き込みモードに入るような作りになっていますが、ここではESP32などで良く用いられる自動リセット回路をまねて作る関係でこの動作を変更してLOWであれば書き込みモードに入るという作りに変更しました。
さらにこの基板で特徴的なのは3つのUSBポートです。 これは何か3つに特別な機能がある、というわけではなく、手元にある3種類のUSBソケットの実装練習のためのものです。
3つのうち2つがUSB Type-Cのソケットなので、CC1、CC2ピンのための抵抗も配置します。(この抵抗が無いとType-C -> Type-Cケーブルを使った時に給電されないことが起きるようです)

JLCPCBに発注
今回も発注はJLCPCBです。基板は赤色にしました。また基板の厚さを1mmにしています。
jlcpcb.jp (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
動作確認のための実装
CH340GはArduino Nanoのクローンなどでよく利用されているICで、自分もそのような基板を自作したことがあるので、難なく実装できました。 CH32V003F4P6も前回の挑戦ではんだ付けしたことがあったので、こちらも簡単。
MicroUSBコネクタはよく使うのですが、なかなか実装のコツがつかめず、よく接続不良を起こしてしてしまいます。ホットエアーガンを使い今回は(たまたま)一発で動作しました。
ということで、あっという間に実装できました。
自動書き込み回路や、あと2つのUSBコネクタの実装は後回しです。
ブートローダーの準備と、書き込みテスト
CH32V003でさらに遊んでみた - inajob's blogで紹介した74thさんのファームウェアを少し改造して利用しました。 74thさんのものは書き込みモードに入る際にPC0をHIGHにする必要がありましたが、今回はPC0がLOWのときに書き込みモードに変更したものを用意しました。
このファームウェアをWCH-LinkEを使いブートローダー領域に書き込めば準備は完了です。
基板上のMicro USB端子をパソコンとつなげ、BOOTスイッチを押しながら、RSTスイッチを押して書き込みモードにしたのちに、74thさん作のCLIツールを使い適当なプログラムを書き込み、最後にRSTスイッチを押して、実行モードにすれば、書き込んだプログラムが動き始めます。
USBソケットの実験
前述したようにこの基板には3つのUSBソケットのフットプリントがあります。

Micro USB

いつものソケットです。ここまでの実験ではこのソケットを使い接続しています。 このソケット、実装の難易度はそこそこ高く、個人的にははんだごてではうまく実装できず、ホットエアーで実装しています。
いつも使っているのですが、Micro USBということで、稀にコネクタが「もげ」るという事故が起きます。 ということで、そろそろ自分もUSB Type-Cのコネクタを試してみたいなと考えていました。
そこで出てきたのが次の2つのUSB Type-Cソケットです
USB Type-C(スルーホール)

スルーホール型のソケットです。後述の表面実装のものと比べると価格が高いのですが、実装しやすそうだなと思い、今回試してみることにしました。
スルーホール型ではあるのですが、足がそこまで長くないため、一般的な厚さ1.6mmの基板では足が下まで届かないので、はんだ付けが難しいようで、今回は厚さ1mmの基板としました。
スルーホールとはいえ、かなりピンが近くにあるので、はんだ付けは気を遣いましたが、何とかはんだごてで実装し、動作することを確認しました。
USB Type-C(表面実装)

よく見かけるソケットです。ピンの幅が狭く、実装の難易度が高そうに見えます。 はんだごてで実装するとすぐにブリッジ思想だったので、ホットエアーを使って実装しました。
フットプリントは以下の記事を参考にして、いくつかのパッドを長くすることで、はんだ付けしやすいようにしました。

心配しましたが、こちらも動作することを確認しました。
自動書き込み回路の動作確認
最後に、ESP32などの開発ボードでよくみられる、トランジスタを2つ使った、自動書き込み回路の動作を確認しました。 この回路は抵抗付きのトランジスタが2つ内蔵されたUMH3Nという部品により実現されます。(この部品は以前ESPboyというオープンソースの携帯ゲーム機を日本用に再設計してみた - inajob's blogで利用したことがありました)


ちょっと小さな部品ですが、これを実装します。
このトランジスタ2つをうまく組み合わせて、USBシリアル変換ICの~DTR, ~RTS信号を、CH32V003のリセット信号と、書き換えモード切替信号(PC0)への入力に変換します。
ESP32などでは書き込みツールがDTR、RTS信号をうまい具合に制御してくれるのですが、今回はそういうツールが無いので、Pythonのスクリプトを用意して、書き込みモードへの切り替えの動作を実現しました。
具体的には以下のようなコードで書き込みモードに入ります
import serial ser = serial.Serial() ser.port = "COM14" # 利用するポートの番号 ser.baudrate = 115200 # Write mode ser.setDTR(True) ser.setRTS(False) ser.open() ser.close()
そして以下のようなコードで実行モードに入ります
import serial ser = serial.Serial() ser.port = "COM14" # 利用するポートの番号 ser.baudrate = 115200 # Run mode ser.setDTR(False) ser.setRTS(True) ser.open() ser.close()
これと74thさん作のCLIツールを組み合わせると、Arduino風の書き込み環境となります。
まとめ
ということで、一度ブートローダーを用意してしまえば、後は開発基板のみで書き換えができる基板が完成しました。
まぁ、CH32V003でやるならこの方法ですが、もう一つ上のスペックのCH32V203などではIC単体でUSB書き込み機能を備えているので、あえてCH32V003でここまでする意味はないかもしれませんが、構成例の一つとして、誰かの役に立てば幸いです。
また、自動リセット回路について、CH32V003でも期待通り動くことが確認できました。
おまけとして、3種類のUSBソケットの実装実験が出来ました。ホットエアーガンがあればどのソケットもそこまで難しくなく実装できることが確認できました。
参考
自動リセット回路の動作原理について詳しく説明されています days-of-programming.blogspot.com
前回記事に続き 74th.hateblo.jp
CH32V003でさらに遊んでみた

この記事ははJLCPCBの提供でお送りします。
JLCPCBとは

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
JLCPCBとは、プリント基板製造などで有名な上海の企業です。
日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。
値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。
この記事の作例もJLCPCBに基板を発注して実現しました。
前回までのあらすじ
以前作った基板を流用して CH32V003 で遊んでみることにしました。
CH32V003F4P6を自分ではんだ付けしてみる
前回の記事では、CH32V003の開発ボードを使ったため、CH32V003F4P6を直接はんだ付けすることはしませんでした。
しかし、この基板は開発ボードでも、ICを直接実装するでも、どちらでも動作するように作っていたので、今回は直接のはんだ付けを試してみました。
表面実装でピンの間は0.65mmでこれが10*2=20か所はんだ付けします。
うまくはんだ付けできるか心配でしたが、意外と簡単にはんだ付けできました。

過去の実績としてはATmega328が0.8㎜ピッチで32か所というのがありましたが、これと比べると今回のはんだ付けは簡単でした。

というのも、ATmega328はICの4辺すべてに足が出ているQFPと呼ばれるパッケージで、今回の物は2辺に足が出ているTSSOPと呼ばれるパッケージだったというのが大きいです。
分析するに、QFPの方はICの向きが少しずれるとどこかの辺のピンがパッドからずれてしまうのに対し、TSSOPの方はピンのある辺に水平にずれる分には問題ないというのが原因だと感じました。

ピッチは今回のICの方が細かかったですが、その点はあまり気になりませんでした。
温調付きのはんだごてと、フラックスがあれば比較的簡単だと思いますので、挑戦する方はこれらの機材をそろえると良いと思います。
最低限動作に必要な部品
改めて回路を見直してみると、このICは周辺の部品は、ほぼ何もなくても動くことがわかりました。 開発ボードには水晶発振子が付いていましたが、ICの内部にも発振機能があるようで、精度が多少悪くなりますがこちらを使うようにすれば、水晶発振子は不要でした。
いわゆる「おまじないコンデンサ」と言ったりするパスコン(バイパスコンデンサ)を一応1つ取り付けました。

書き込み
書き込みは開発ボードを使った時と同様にWCH-LinkEという専用の書き込み機を使いました。 ソフトウェアは前回の記事で紹介したch32v003funを利用しました。
専用書き込み機を使わずに書き換える方法
WCH-LinkEを使わないと書き換えられないのが少し気になって、調べてみると、WCH社が公式のサンプルとしてUART経由でプログラムを書き換えることが出来るサンプルプログラムを公開していることを知りました。
UARTを使って書き換えるといえば、よく知られている例だとArduino UNOなどの方式です。
この方式は、素朴ですが、ボード上にUSBシリアル変換ICを搭載することで、そのボード単体で開発が完結するという点で魅力的です。 (もちろん一番初めにこのプログラムを書き込むためにWCH-LinkEが必要なのですが、一度書き込んでしまえば以降はUARTで書き換えることが出来ます。)
さらに、このWCH社が提供しているサンプルの細かい問題点を解消したものを74thさんが作っているのを発見したので、今回はこちらを利用しました。
WCH-LinkEにはUSBシリアル変換の機能も搭載されているので、この書き換えの仕組みもWCH-LinkEで動作確認できました。また念のため手元にあったCH340G搭載のUSBシリアル変換モジュールを使っても書き換えが出来ました。

書き込みのためにはPC側で動作する書き込みソフトが必要となります。WCH社公式のWindows専用ツール、74thさん作のCLIツールの2つがありますがどちらでも書き込みできました。
RSTスイッチでリセットされない問題
74thさんが改良したプログラムでは以下の2つの変更が加わっていました
- UART通信の精度を上げるため書き込み速度を115200に低下させる
- 書き換えモードに入るためのピンをプルダウンし、ピンに何もつながっていないときは、実行モードとする
これで随分使いやすくなっていたのですが、74thさんのブログでも言及されているのですが、RSTスイッチの挙動が少し期待と異なるという問題が残っていました。
RSTスイッチは私の利用している開発ボードではタクトスイッチと接続されており、このスイッチを押すことでマイコンボードを「リセット」しプログラムをはじめから実行しなおすことができます。

UARTで書き込みを実現するプログラムは、起動時に特定のピンの状態を確認し、それがHIGHであれば書き込みモードに入り、LOWであれば実行モードに入るというロジックとなっています。
こういう書き込みロジックはESP32などでも採用されており、このようなボードにはBOOTスイッチとRESETスイッチが搭載されていることが一般的です。
BOOTスイッチを押しながらRESETスイッチを押すことで書き込みモードで起動し、BOOTスイッチを押さずにRESETスイッチを押すと、実行モードで起動するというのが期待する動作です。
もちろん手でスイッチを操作する以外にも、USBシリアル変換ICのDTRやRTSの信号をうまく使って、自動的に書き込みモードに入るというようなことも行われたりします。
さて、今回のUARTで書き込みを実現するプログラムを利用する際、このRSTスイッチはどのようにふるまうかというと・・
- 書き込みモードで起動中
- RSTスイッチを押すと、実行モードで起動する
- 書き込みピンをHIGHにしてRSTスイッチを押すと、書き込みモードで起動する
- 実行モードで起動中
- RSTスイッチを押すと、再び実行モードで起動する
- 書き込みピンをHIGHにしてRSTスイッチを押しても、再び実行モードで起動する(ここがおかしい!!)
実行モードで起動中に、書き込みピンをHIGHにしたときに、書き込みモードに移行せず、実行モードとなってしまうことが期待と違うと感じました。
この原因を調べるためにソースコードを見てみると、UARTで書き込みを実現するプログラムは以下のように実装されているようでした
- UARTで書き込みを実現するロジックはFlashメモリのBOOT領域に書き込まれている
- BOOT領域の処理の一番初めに書き込みピンの状態を確認するロジックがある
- ここでLOWが検出されると、User領域から実行するフラグを立ててソフトウェアリセットをする
- User領域を実行中にRSTスイッチによるリセットが起きても、User領域から再実行される
というような動きをしているようでした。(データシートで細かい裏付けをしているわけではなく、あくまで挙動から推測した動きです)
ということで、以下のような処理をUser領域に書くことで、User領域を実行中にRSTスイッチによりリセットされたときにBOOT領域の処理が実行されるようにしてみたところ、期待通りに実行モードで起動中にRSTスイッチを押した際に、書き込みモードで起動することが確認できました。
if(RCC->RSTSCKR & RCC_PINRSTF){ // リセットボタンを押されて起動した場合に真となる
FLASH->BOOT_MODEKEYR = FLASH_KEY1;
FLASH->BOOT_MODEKEYR = FLASH_KEY2;
FLASH->STATR |= (1<<14);
NVIC_SystemReset();
}
要は、UARTで書き込みする対象のプログラムに、おまじない的に、このロジックを入れておけば良いということです。
さて、今回はここまでの調査で打ち切りましたが、この先はUSBシリアル変換ICを搭載した基板を作ったり、RSTやDTRで自動プログラム機能を作りこんだ書き込み用のプログラムを作ったりすると、Arduinoっぽく書き込みできる仕組みが作れそうです。
そこまでしてUARTで書き込みしたい?
ここで調査を打ち切ったのは、CH32V003をどこまで頑張って使い倒すか?ということを考えたからです。
実はCH32VシリーズのCH32V203は、CH32V003よりは高いですが、その分スペックも良く、USB経由でのファームウェア書き込みもサポートしています。
ここまでCH32V003をArduino的に書き換える方法を探ってきましたが、そんなに頑張らなくともCH32V203を使えばよいのでは・・?という気がしてきました。
ということで、近いうちにCH32V203を購入して、その使い勝手を確かめてみることとします。
日本で買うなら RISC-V MCU CH32V203 ProMicro Like 開発ボードキット(¥1,500) [74th-034] - 74th Books & Gadgets - BOOTH、AliExpressでもいくつかの開発ボードを見つけることが出来ます。
まとめ
前回記事では、開発ボードを利用していましたが、ICを直接基板に実装する方法も試すことが出来ました。
これにより開発ボードに頼らずに、スタンドアローンなガジェットを作れるようになりました。
Arduino互換のSDKも整備されてきているようなので、次何か作る時の候補に入れておくことにします。
2023まとめ

今年もいろいろなことがありました。
毎年恒例ですがまとめていきます。
ピックアップニュース
ポッドキャストを始めた
5月ごろから#inajob の試しに録音してみた を始めました。なんだかんだでほぼ毎週配信できています。
ポッドキャスト仲間とのコミュニケーションが出来たり、音声編集のテクニックが身についたり得るものが多くありました。
また、ポッドキャストをよく聞くようにもなり、お気に入りのポッドキャストもたくさんできました。 副次的な効果として、日記をしっかり書くようになり、日々をより噛み締めて生活できるようになり、人生を濃くすることが出来ていると感じます。
ChatGPTを活用し始めた
このブログではあまり紹介していませんでしたが、自分の日記をChatGPTに分析させたり、omoikaneに参加して、ChatGPTを使ったSFプロトタイピングを体験したりしました。
このあたりの話は以下のポッドキャストのエピソードでも話しています。
PASMOがバズる
誤ってPASMOを洗濯機に投入してしまい、破片しか残らなかったエピソードがバズりいくつかのメディアで記事にしてもらいました。 平和な内容でバズるのはまぁインターネットと言う感じで面白かったです。
ステータス
- 今の家に引っ越してから7年目
- 会社に入ってから14年目
- 結婚して7年ちょっと
- 娘が生まれて3年目
子供がいる生活にもだんだんと慣れてきて、そういった環境でもできる新たな挑戦などにも取り組めていると思います。引き続きやっていこう!
今年学んだスキル
今年は技術的なところというよりは、家族周りのスキルアップも多かった年でした。 親の介護なんていう次なる課題も見えてきて、色々と考える機会となりました。
- 高速道路の運転
- 親の介護周りの知識
- 子連れ外出
- ポッドキャストの配信・ポッドキャストを聞く
- ChatGPT
- CadQuery
- ロジックアナライザの使い方
- 静電容量タッチセンサーの作り方
- CircuitPythonで和音
- CH32V003で和音
- ホットエアーガンでRP2040実装
今年買ったもの
ハンドソープディスペンサー(娘の手洗いがずいぶん楽になりました)
ヘッドセット(ポッドキャストの録音はこれで行っています。リーズナブル!)
電気圧力鍋(料理で大活躍)
ロボットペット(親の方が欲しかった、クリスマスプレゼント)
レゴ(親も楽しい、誕生日プレゼント)
ScanSnap S1500(全然使える、中古で買った)
コンパクトなキーボード
感想
昨年から模索している非同期コミュニケーション手段の1つとしてScrapboxに加えてポッドキャストの配信を始めたというのが一番大きな変化です。
最新の技術であるChatGPTを触ることが出来ているのも良かったです。
朝ジョギングを始めるなど、健康維持についても行動できているので、継続していきたいです。
娘も3歳となり、一緒に技術展示のイベントに参加したり、宿泊を伴う旅行に連れて行けるようになったりと、行動の幅が広がったのも良かったです。引き続き、英才教育・・という名の親の趣味に付き合わせていきたいなと思っています。
月別生データ
1月
- 親子2人で電車でお出かけ
- 動画で子守するのを解禁
- 凧揚げ
- 内窓を設置
- 前半は風邪、後半は胃腸炎
ひらがなおもちゃを作る
自分の娘のためのおもちゃを設計している。
— ina_ani@3歳児のパパ (@ina_ani) 2023年1月5日
うちの3Dプリンターは多色対応してないから上だけ塗るかな・・
下の面は初めは丸だったのだけど、向きがわかりにくいかと思い四角に変更。おもちゃって色々考えて作られてますね。#パパ育 pic.twitter.com/baolzN7q0f
RakuChordのSMD版を作る inajob.hatenablog.jp
2月
- 節分
- 水族館にいく
- 成田空港にいく
おしたくボード改
妻の作った「おしたくボード」が大活躍!
— ina_ani@3歳児のパパ (@ina_ani) 2023年2月24日
以前出した時はまだ早すぎたみたいだが、今ならOK!#パパ育 pic.twitter.com/BPoeZA4qyl
MakePython Audio Expansionレビュー inajob.github.io
HandiPiを作る inajob.hatenablog.jp
事前に議事録を作る方式について qiita.com
3月
なぜなぜ分析
娘が「なぜなぜ分析」してくる件
— ina_ani@3歳児のパパ (@ina_ani) 2023年3月3日
明日は休みだよ
「なんで休みなの?」
土曜だからね
「なんで土曜日は休みなの?」
パパとママが休みだからね
「なんで、パパとママは休みなの?」
(娘)ちゃんと遊びたいからね
「なんで遊びたいの?」
(娘)ちゃんがかわいいからね
「可愛いと遊びたいの?」#パパ育
おもちゃの分解
これ動かなくなってしまった
— ina_ani@3歳児のパパ (@ina_ani) 2023年3月4日
開けたら直せるかな?
電源周りならワンチャン直せるかも?
しかしオートスリープ機能もあるし、そこが壊れてると辛そう pic.twitter.com/YpNOAUFEO5
Web Assembly qiita.com
ChatGPTに英語記事の要約を頼む実験
OLEDの不良品を激安のロジックアナライザーで分析 scrapbox.io
オーディオコメンタリーメーカーを作る github.com
3Dプリンタの寸法チェック用モデル
1mm, 2mm, 3mm, 4mmのサンプルを作った。
— ina_ani@3歳児のパパ (@ina_ani) 2023年3月24日
これを差し込んで寸法を調整する#3Dプリンター pic.twitter.com/TlvmNv0B4J
蛇口延長用アダプタ
周りに合わせて白フィラメントにした!
— ina_ani@3歳児のパパ (@ina_ani) 2023年3月28日
まだ若干蛇口が下を向くけど、まぁ一旦これで完成かな pic.twitter.com/S7d5LwyNBS
ESPHomeを試す(が結局プログラミングすることに・・)
4月
レタスの発芽(失敗)
なんか枯れてきた芽があるな、、まだ土への移植は早い気がするけど、、 pic.twitter.com/nZb5k7XfDZ
— ina_ani@3歳児のパパ (@ina_ani) 2023年4月11日
PASMOがバズる
Pasmoが無くなったと先週気づいて、どこに行ったかなー、、と思ってたら洗濯機の糸屑フィルターから出てきた、、
— ina_ani@3歳児のパパ (@ina_ani) 2023年4月7日
これ、タッチして改札通れるかな、、? pic.twitter.com/6DzDnRdiWh
電子メモパッドのレビュー inajob.github.io
小型のフルカラーLEDのテスト基板 inajob.hatenablog.jp
モノクロ液晶の試食
試運転。
— ina_ani@3歳児のパパ (@ina_ani) 2023年4月30日
全表示内容をメモリに持たせようとしたらメモリ不足で表示が壊れる、、
たまたまに”hello inajob”が表示できた pic.twitter.com/VmlbNH4rmP
ESP32で動く日本語入力対応Wiki的なもの
少しわかりづらいけどM5Stackとキーボードを繋げて、日本語入力できるWikiみたいな仕組みが作れた!
— ina_ani@3歳児のパパ (@ina_ani) 2023年4月30日
操作性には改良の余地があるが、なかなか面白いぞ! pic.twitter.com/nQV79WA6DG
5月
- ポッドキャストを始める
枝豆・トマトを植える
今年は枝豆やってみよう pic.twitter.com/mwYyWEt62Z
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月4日
埼玉県近代美術館
コインロッカーに、みるからに怪しいオブジェが!!#埼玉県近代美術館 pic.twitter.com/cOxkkhfX9z
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月14日
電気圧力釜を買った
My New Gear… pic.twitter.com/83HIn3DuIt
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月20日
DIYこいのぼり
牛乳パックでこどもの日っぽい工作をした。
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月1日
シールを娘に貼ってもらったが、目を描いたりハサミで切るところも手伝って貰えばよかったな#パパ育 pic.twitter.com/O9VtaWbUZK
粘土に夢中
あぶらねんど を買ったので(親が)作った
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月19日
娘に好評#パパ育 pic.twitter.com/6xA8Cx0G7Q
自動ハンドソープディスペンサー購入
トイレの最中
ジャーン!!
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月20日
これは前から目をつけていた「トイレの最中」という大蔵餅のお菓子!!
娘のトイトレの役に立つかなw?
(むしろ逆効果?) pic.twitter.com/1SPR89FAgU
ケースづくり
ケース設計むずいな pic.twitter.com/jNUP91nYyV
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月4日
ESP32搭載のDIY時計ガジェットキットレビュー inajob.github.io
ペン型マルチメーターレビュー inajob.github.io
乾電池駆動のArduino Nanoボード inajob.hatenablog.jp
Vision Five2試食
ダイソーで買ったおもちゃ
できたー!
— ina_ani@3歳児のパパ (@ina_ani) 2023年5月29日
増し締めしたらかなりしっかりした!
これは楽しい
1つしか買わなかったけどあと2種も買えばよかったかな pic.twitter.com/FIV6XIuYoH
6月
- 長靴を買った
- 七五三の前撮り
- KEY PALETTOを購入
- omoikane参加
- blueskyを始める
ノートパソコンのバッテリーが膨らむ
悲報、、ノートパソコンのバッテリーが、、、 pic.twitter.com/Q1fnHTzp6F
— ina_ani@3歳児のパパ (@ina_ani) 2023年6月17日
ジャガイモを収穫
ささやかながら、じゃがいもを収穫。日光が足りなかったかな? pic.twitter.com/v9iERbbCbm
— ina_ani@3歳児のパパ (@ina_ani) 2023年6月9日
スカイツリーを見に行く
なう
— ina_ani@3歳児のパパ (@ina_ani) 2023年6月25日
高いなー pic.twitter.com/MrpEdgcjOq
Raspberry Pi Picoを使った携帯ゲーム機 inajob.hatenablog.jp
7月
- 地域のソーメン流し参加
- ブルーベリー狩り
- 打ち上げ花火を見る
- Threadsに参加
- (今更)Twitter API V2を試す
- ヘッドセット、ロジクールH111rを買った
- SNSを同期する仕組みの作成
トマト、枝豆の収穫
トマトもいい感じになってきた!
— ina_ani@3歳児のパパ (@ina_ani) 2023年7月5日
娘も普段はトマトはあまり食べてくれないけど、自分で収穫したら(薄皮が結構分厚いけど)頑張って食べてくれた! pic.twitter.com/Qen1wTj98d
絵を描いて教える
朝から娘がヨーグルトをひっくり返した。
— ina_ani@3歳児のパパ (@ina_ani) 2023年7月17日
どうも「悲しかったことを絵に描く」というアンガーマネージメント?が気に入ったらしく、「ヨーグルトこぼした絵を描いてー」と言ってきたので描いた。
ついでに「む」も覚えてもらう作戦#パパ育 pic.twitter.com/rHUz86qpUZ
交通事故の話をしたら、「絵に描いてくれ」と言われたので描いてみた、、
— ina_ani@3歳児のパパ (@ina_ani) 2023年7月5日
納得してくれたかな、、#パパ育 pic.twitter.com/b5OQ8vEKMg
お金やさん
なんか、娘がお金並べてた
— ina_ani@3歳児のパパ (@ina_ani) 2023年7月23日
「おかねやさん」とのこと、、
本を持っていくとお金に変えてくれるらしい、、ブックオフか、、?#パパ育 pic.twitter.com/Zlw3H2Sc9P
8月
Raspberry Pi Pico搭載のマクロパッド inajob.hatenablog.jp
バタフライピー
レモンを入れると色が変わる紅茶
— ina_ani@3歳児のパパ (@ina_ani) 2023年8月23日
バタフライピーというものらしい pic.twitter.com/F28MktTDuG
流行ってるようなので、ビリヤニ。
— ina_ani@3歳児のパパ (@ina_ani) 2023年8月12日
最近辛いものを食べるとお腹を下すので妻のを少し分けてもらった。
このご飯の方だけでも美味しいので、こっちだけ買えないかな? pic.twitter.com/movQUQeT9m
ポップコーン
ポップコーン作った
— ina_ani@3歳児のパパ (@ina_ani) 2023年8月5日
親の方がワクワクしてた
娘は音が怖くて避難してた#パパ育 pic.twitter.com/Iwsxm4XE7x
市販キーボード用のマウンタ
家にあるコンパクトなキーボードのマウンタを作ってみた。
— ina_ani@3歳児のパパ (@ina_ani) 2023年8月18日
この穴に他のモジュールをくっつけることを想定してる#3Dプリンター pic.twitter.com/AWL1JpTUJ0
ログ機能付きの電流計自作
よーし、画面付きの電流計が作れたぞ!
— ina_ani@3歳児のパパ (@ina_ani) 2023年8月26日
過去しばらくの電流の動きが見れるのが便利そう pic.twitter.com/dmn66LfcoZ
フレキシブルHDMIケーブル
スリムなHDMIケーブルを求めて、、フレキシブルケーブルのやつを購入 pic.twitter.com/ptKtALlq7T
— ina_ani@3歳児のパパ (@ina_ani) 2023年8月25日
9月
- 写真データをGoogle Photosから自宅のNASに移行
- synthioを試す
- Raspberry Pi Picoで遊ぶ
- MSX0で遊ぶ
- NS8002オーディオアンプ実験
- CH32V003で和音実験
- 遊園地に行く
自作キーボード inajob.hatenablog.jp
10月
RP2040実装練習
ホットエアーガンでRP2040実装できた! pic.twitter.com/ytVa01Rta3
— ina_ani@3歳児のパパ (@ina_ani) 2023年10月20日
11月
- 幼稚園の入園面談
- 国立科学博物館に行く
- ChatGPT with Voiceで子守してみる
- サーキュレーターを買った
- 加湿器を買った
- 喰い切りニッパーを買った
- Milk-V Duo試食
- CadQueryを学ぶ
娘を連れてNT東京2023を見に行った
子連れ参戦 pic.twitter.com/jAJjRWVRRE
— ina_ani@3歳児のパパ (@ina_ani) 2023年11月4日
不良品と思われるATmega328の調査
怪しいATmega328の実験ができるようになった。が、買ってすぐのものは問題なさそうだな、、実装時に壊してるのかな? pic.twitter.com/M6yXNt9qsO
— ina_ani@3歳児のパパ (@ina_ani) 2023年11月5日
12月
- 娘を連れて高尾山に登る
- 娘がアデノウイルスにかかる
コストコ入会
My new card...!
— ina_ani@3歳児のパパ (@ina_ani) 2023年12月2日
エンタメ的に入ってみたかったので、、
知り合いで入ってみたい方、声かけてもらえれば一緒に入ることができますよ!(ただしうちの3歳の娘とセットになると思いますが、、) pic.twitter.com/dkgEkuKl3n
クリスマスオーナメントを作る
iPhoneで加工して少しそれっぽく見えるようにしてみたり、、(チート) pic.twitter.com/voZ8YpFUtX
— ina_ani@3歳児のパパ (@ina_ani) 2023年12月3日
クリスマスツリーを作る
今年のDIYツリー、さらに飾って写真にいい感じに加工した pic.twitter.com/KAZU8j6QE5
— ina_ani@3歳児のパパ (@ina_ani) 2023年12月24日
Loona購入
My New Gear...
— ina_ani@3歳児のパパ (@ina_ani) 2023年12月24日
ロボットペットのLoonaです! pic.twitter.com/0iuDLNF4j9
CH32V003を使った和音の鳴るピアノ基板

この記事ははJLCPCBの提供でお送りします。
JLCPCBとは

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
JLCPCBとは、プリント基板製造などで有名な香港の企業です。
日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。
値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。
この記事の作例もJLCPCBに基板を発注して実現しました。
これは何?
CH32V003という最近流行りのRISC-Vの激安マイコンモジュールを使って楽器を作ってみました。
仕様
- 128*64 モノクロOLED
- CH32V003
- NS8002オーディオアンプモジュール
- 鍵盤を含む20個のタクトスイッチ
- スピーカ
- オーディオジャック
- ボリューム
パーツ紹介-CH32V003F4P6
最近流行りのWCH社製のRISC-Vマイコンです。 CH32VのシリーズはほかにもありますがCH32V003はその中でも最も廉価なシリーズです。
秋月電子でも販売しており、記事執筆時点では1つ50円です
プログラムメモリ16KB, RAM 2KB、GPIO18個というシンプルなスペックですが、ちょっとした電子工作のロジックを作るには十分です。
パーツ紹介-CH32V003モジュール
今回のピアノ基板はCH32V003F4P6を基板に直接取り付けることもできますが、よくあるCH32V003を搭載した開発ボードを使うこともできます。

今回はまずはこのCH32V003モジュールを利用する方法で組み立てました。
CH32V003はUSBデバイスの機能を持っていないので当然ですが、このモジュールのUSB端子は電源用で、書き込みを行うことは出来ません。
書き込みのためには専用の書き込み装置であるWCH-Linkが必要となります。(セット販売しているものを買いました)
基板の設計
今まで私は、この手のちょっとした音が鳴るガジェットを作ったことは結構あるので、ここまでのブログ記事などでも紹介しているような「鉄板」の構成で設計しました。
20個のタクトスイッチは 4*5のマトリクス配線とし、同時押しをサポートするためにダイオードを実装しています。
オーディオ周りはいつものスイッチ付きのオーディオジャックや、NS8002オーディオアンプ、ボリューム、表面実装スピーカなどを採用しました。

JLCPCBに発注
今回も発注はJLCPCBです。基板の色は白にしました。
この基板も10cm×10cmに収まるように設計したので5枚だと $2 + 送料です。
jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
実装
今回はそこまで複雑な回路ではないので、サクッと実装できました。


ソフトウェアの実装
今回のチャレンジはソフトウェアです。CH32V003は比較的新しいマイコンなので、参考となるソースコードが少ないのが現状です。
CH32V003公式の開発環境としてはMounRiver Studio IDEというGUIのIDEと公式のSDKを使う手があるのですが、どうも大げさな開発環境で、肌になじまなかったので、シンプルなch32v003funを使うことにしました。
ch32v003funはシンプルな実装ですが、このくらいの規模のCH32V003の開発には必要十分で、サンプルも豊富です。 いくつかのサンプルを組み合わせることで目的のプログラムを作ることが出来ました。
- blink
- まずはLEDをチカチカします
- これで最低限の雰囲気をつかみました
- tim2_pwm
- 音を鳴らすために利用するPWMの機能
- LEDをフェードイン・フェードアウトするような使い方にも利用できます
- systick_irq
- 音源のオシレータを一定時間ごとに進めるためにタイマ割込みの機能
- i2c_oled
- I2C接続のOLEDの制御
- ホビー電子工作でよく利用するSSD1306向けの描画ロジックが便利です
ch32v003funを使うにあたっては以下のブログ記事が非常に参考になりました。
つぎはぎですがソースコードはこんな感じです (ch32v003funのi2c_oledのexampleを以下のように書き換えて、ビルドしました)

激安RISC-VマイコンのCH32V003で和音が鳴るピアノ的な実験
— ina_ani@3歳児のパパ (@ina_ani) 2023年12月27日
あとでブログ記事にします! pic.twitter.com/anxwkKBn2y
まとめ
安価なRISC-VマイコンであるCH32V003を使って、和音の鳴るピアノ的な楽器を作ることが出来ました。
ch32v003funという軽量なライブラリを利用して、比較的簡単に楽器的なロジックを作れることがわかりました。
自分が今までよく利用していたArduino UNOのメインマイコンであるATmega328は半導体不足で価格が高騰し、今ではだいぶ落ち着きましたが、それでもまだ価格が高止まっています。また、ATmega328は昔からあるマイコンであることもあってテキトーに買うと偽物が混ざっているようなこともあり困っていました。
CH32V003は非常に安く、新しいマイコンであるため今のところ偽物の情報も聞きません。
ちょっとここらで、メインで使うマイコンをCH32シリーズに移行してみても良いかも・・と感じました。
グリッド楽器igetaを作った

この記事はは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++を使うのがよさそうです。
ということで、できました。
今月の制作
— ina_ani@3歳児のパパ (@ina_ani) 2023年11月25日
8x8キー、8x8LED、制御はRaspberry Pi pico
名前はigeta pic.twitter.com/8BJbvK1xfB
押したキーに対応する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) #synth.press((65,69,72)) 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) # active 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) # deactive 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) #time.sleep(0.1) pports[8 + n].switch_to_output(True) # flash time.sleep(0.001) pports[8 + n].switch_to_input(None) # Hi-Z while True: # scan switch for i in range(8): scanKey(i) # LED for i in range(8): pports[i].switch_to_output(False) pports[i+8].switch_to_input(None) #time.sleep(1) 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でも音を鳴らすところまではプログラムを作り、それなりに遊んだりもしました。
やったー!MIDIシーケンサ出来たよ!
— ina_ani@3歳児のパパ (@ina_ani) 2021年6月3日
ここまで来たら次は音源も内蔵したい。 pic.twitter.com/QviCKtPBhC
自作グリッド楽器「igeta」スタンドアローン化してみた pic.twitter.com/VljcwcSXEo
— ina_ani@3歳児のパパ (@ina_ani) 2022年6月5日
こういう過去があっての今回のigetaの製作につながっています。
ってこれやってたの2021年5月とかですね、、意外と歴史があります。
表面実装部品版RakuChordの改良版を作った

この記事ははJLCPCBの提供でお送りします。
JLCPCBとは

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
JLCPCBとは、プリント基板製造などで有名な香港の企業です。
日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。
値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。
この記事の作例もJLCPCBに基板を発注して実現しました。
表面実装版RakuChordとは?
RakuChordというのはinajobが開発している電子楽器です。
ワンタッチで和音を演奏できるボタンがあり、だれでも比較的簡単に演奏ができるという電子楽器で、少しずつバージョンアップをさせながら、電子工作キットとしての販売をしています。
以前RakuChordの表面実装版を作ったことがありましたが、今回はこれの更なる改良版です。
今回の表面実装版RakuChordの設計
基本的な設計は前回の表面実装版RakuChordと同じです
前回は6mmのスイッチで、修飾キーは基板裏面に配置したのですが、どうにも使い勝手が悪かったので、今回の改良で12mmタクトスイッチを採用し、従来のRakuChordの操作性を再現することと、修飾キーを上側に並べることを試すことにしました。
- タクトスイッチは12mmスルーホール
- 表面実装版と謳っているいるが、家にこの部品がたくさんあるのでスルーホールを使うことにする
- 昇圧回路は安価な昇圧モジュールも利用できるようにする
- 7つの修飾キーは基板裏面ではなく、90度の角度が付いたものを上辺に並べる
- 相変わらず10cm×10cmに収める(安いので)
- 表面実装部品のサイズを0603に変更(以前は1206)
90度の角度が付いたタクトスイッチ
以前、AliExpressでタクトスイッチのアソートを買ったのですが、その中に90度の角度が付いたものがあり、これを使うことにしました。

タクトスイッチのアソートは100種類のタクトスイッチがそれぞれ5個ずつ入っているような商品で、スイッチ好きの人にはたまらないものとなっています。お勧めです。
基板の設計
今回は以前作ったデータを改良する形で設計を行いました。そのため比較的簡単に設計が完了しました。 (前回の作例を記事にしていたおかげで、修正が必要なバグが探しやすかったです)
実際論理回路図の変更部分は非常に少なく、フットプリントの付け替えや、拡張端子の引き出し程度でした。
実体配線図は、さすがに流用することが難しいので新たに作っています。 タクトスイッチが6mmのものから12mmのものに変更となったので、基板の横幅を少し広げました。
JLCPCBに発注
今回も発注はJLCPCBです。今回の基板の色は紫色です。
10cm×10cm以内で5枚だと $2 + 送料です。お安い・・

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)
実装
さてさて、今回もいくつかのトラブルに見舞われました
我が家のICがやはりおかしい
今回もどうもATmega328の様子がおかしく、シリアル通信の速度を遅くしないと書き込みができませんでした。 以前の記事ではUSBシリアル変換ICであるCH340Nがおかしいかも、と書きましたが、色々実験をしているとATmega328の方がおかしいようでした。
我が家にストックしているATmega328が偽物という可能性が出てきています・・・どうしたものか・・
ともあれ、前回と同様にだましだまし書き込むことで一応期待した動作をしています。
格安の昇圧モジュールから電源を供給すると動作が不安定
今回は、HT7750を使った昇圧回路とは別に、格安の昇圧モジュール(名称不明)を使って乾電池2本から5Vへの昇圧が出来るように設計していました。 しかし、こちらの昇圧モジュールを使った場合、どうも動作が不安定になるという事象が発生しました。
おそらく、音を鳴らす際に多くの電流を取り出そうとするために、電圧低下を起こしてしまっているのだと思います。 おとなしく前回と同じHT7750を用いた昇圧回路の方を使うことにしました。
昇圧方法を両方用意しておいてよかったです。
この格安の昇圧モジュールについては Arduino Nanoを単4電池で動かすボードを作った - inajob's blog で紹介しました
ダイオードのフットプリントが1つだけ逆向き
この基板にはスイッチの同時押しを実現するために、多数のダイオードが存在しています。 ダイオードには極性があるため、実装時には注意が必要ですが、実装を簡単にするため、同じような位置に存在するダイオードの向きは揃えておいたつもりだったのですが・・・
1つだけ並んでいるなかで向きが逆のものが残ってしまっていました。 案の定実装するときに、ほかと同じ向きに実装してしまい、キーが認識されないという問題が発生しました。
基板上には正しい向きが指定されているので、バグではないのですが、実装ミスを誘う良くない設計だと感じました。

格安の昇圧モジュールの向きが逆
昇圧モジュールは単純に2.54mm間隔ピンが3つ出ているだけなので、専用のフットプリントを作らず、汎用的なコネクタ部品とを配置し、格安の昇圧モジュールの配置を示す四角形を基板上に描画していたのですが、この四角形の配置を間違えており、実際の格安の昇圧モジュールの配置と食い違っていました。
そのままでは乾電池ケースと干渉してしまい、格安の昇圧モジュールが実装できない、という感じだったのですが、想定していた基板の面とは逆の表面に実装することで対応しました。 (上に書いたようにこのモジュールはそもそも性能不足で利用できなかったのですが・・)
電源スイッチの配線が間違っている
電源スイッチ周りの配線は、格安の昇圧モジュールからくるもの、HT7750の昇圧モジュールからくるものの両方を考慮する必要があったのですが、格安の昇圧モジュールからくるものを見落としており、こちらは電源スイッチとは関係なく導通した状態になってしまっていました。
これは一部の回路のパターンを切断し、導線を使ってジャンパすることで、修正しました。
(これも上に書いたように、このモジュールの性能不足により、利用できないのですが・・・)
ダイオードが破損
これは実装が終わってしばらく遊んでいる最中に起きたことなのですが、1つのキーが反応しなくなりました。 原因がわからずいろいろ試していたところ、キーの同時押しを実現するためのダイオードの1つが壊れていることが判明しました。
ダイオードは通常片方向からのみ電気を通す素子ですが、なぜかどちらからも電気を通さない状態になっていました。
部品を交換することで、この問題を解消しました。 ダイオードって壊れやすいんですかね?
ケースの作成
演奏しやすいように3Dプリンタでケースを作るというのもやってみました。
利用したツールはOpenSCADとLibreCADです。
モデリングを簡単にするために、KiCADから基板データをdxf形式エクスポートしたものを積極的に利用するスタイルで設計しました。
まず基板外形を使いベースとなる形を整え、それをくりぬいていくという手法です。 くりぬく範囲もKiCADのUserレイヤーを使いGUIで作成しました。
くりぬきは貫通、micro USBコネクタの高さ、筐体側2mm残しの3段階とし、それぞれのレイヤーをdxfでエクスポートし、OpenSCADを使って切り抜きました。

(この画像で黄色、薄緑、灰の3色の塗りつぶしがくりぬきを表しています)
この手法は、OpenSCADのプログラミングによる手軽な設計の良さと、KiCADで部品を見ながらくりぬき範囲を描画できるGUIの良さを両立させる手法だと感じています。
指をひっかけるための突起は、LibreCADやOpenSCADで頑張って設計しています。(ここはもうちょっとどうにかしたい)


まとめ
以前とほぼ同じ構成ですが、表面実装RakuChordの改良版を作りました。
やはり新しく作った個所で問題が起こりやすいことがわかりました。前回の物より演奏しやすくなって満足です。
格安昇圧モジュールは試してみたものの、今回の用途では性能不足であることが分かったのも収穫で、かつそのような問題があってもHT7750を使った昇圧回路を利用できるようにした「こんなこともあろうかと」の設計が役立って良かったです。
















