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(表面実装)

よく見かけるソケットです。ピンの幅が狭く、実装の難易度が高そうに見えます。 はんだごてで実装するとすぐにブリッジ思想だったので、ホットエアーを使って実装しました。

フットプリントは以下の記事を参考にして、いくつかのパッドを長くすることで、はんだ付けしやすいようにしました。

inajob.github.io

心配しましたが、こちらも動作することを確認しました。

自動書き込み回路の動作確認

最後に、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 で遊んでみることにしました。

inajob.hatenablog.jp

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つ取り付けました。

ここに写っている部品のみでOK

書き込み

書き込みは開発ボードを使った時と同様にWCH-LinkEという専用の書き込み機を使いました。 ソフトウェアは前回の記事で紹介したch32v003funを利用しました。

専用書き込み機を使わずに書き換える方法

WCH-LinkEを使わないと書き換えられないのが少し気になって、調べてみると、WCH社が公式のサンプルとしてUART経由でプログラムを書き換えることが出来るサンプルプログラムを公開していることを知りました。

github.com

UARTを使って書き換えるといえば、よく知られている例だとArduino UNOなどの方式です。

この方式は、素朴ですが、ボード上にUSBシリアル変換ICを搭載することで、そのボード単体で開発が完結するという点で魅力的です。 (もちろん一番初めにこのプログラムを書き込むためにWCH-LinkEが必要なのですが、一度書き込んでしまえば以降はUARTで書き換えることが出来ます。)

さらに、このWCH社が提供しているサンプルの細かい問題点を解消したものを74thさんが作っているのを発見したので、今回はこちらを利用しました。

github.com

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 の試しに録音してみた を始めました。なんだかんだでほぼ毎週配信できています。

open.spotify.com

ポッドキャスト仲間とのコミュニケーションが出来たり、音声編集のテクニックが身についたり得るものが多くありました。

また、ポッドキャストをよく聞くようにもなり、お気に入りのポッドキャストもたくさんできました。 副次的な効果として、日記をしっかり書くようになり、日々をより噛み締めて生活できるようになり、人生を濃くすることが出来ていると感じます。

ChatGPTを活用し始めた

このブログではあまり紹介していませんでしたが、自分の日記をChatGPTに分析させたり、omoikaneに参加して、ChatGPTを使ったSFプロトタイピングを体験したりしました。

このあたりの話は以下のポッドキャストのエピソードでも話しています。

open.spotify.com

PASMOがバズる

誤ってPASMOを洗濯機に投入してしまい、破片しか残らなかったエピソードがバズりいくつかのメディアで記事にしてもらいました。 平和な内容でバズるのはまぁインターネットと言う感じで面白かったです。

nlab.itmedia.co.jp

ステータス

  • 今の家に引っ越してから7年目
  • 会社に入ってから14年目
  • 結婚して7年ちょっと
  • 娘が生まれて3年目

子供がいる生活にもだんだんと慣れてきて、そういった環境でもできる新たな挑戦などにも取り組めていると思います。引き続きやっていこう!

今年学んだスキル

今年は技術的なところというよりは、家族周りのスキルアップも多かった年でした。 親の介護なんていう次なる課題も見えてきて、色々と考える機会となりました。

今年買ったもの

ハンドソープディスペンサー(娘の手洗いがずいぶん楽になりました)

ヘッドセット(ポッドキャストの録音はこれで行っています。リーズナブル!)

電気圧力鍋(料理で大活躍)

ロボットペット(親の方が欲しかった、クリスマスプレゼント)

レゴ(親も楽しい、誕生日プレゼント)

ScanSnap S1500(全然使える、中古で買った)

コンパクトなキーボード

感想

昨年から模索している非同期コミュニケーション手段の1つとしてScrapboxに加えてポッドキャストの配信を始めたというのが一番大きな変化です。

最新の技術であるChatGPTを触ることが出来ているのも良かったです。

朝ジョギングを始めるなど、健康維持についても行動できているので、継続していきたいです。

娘も3歳となり、一緒に技術展示のイベントに参加したり、宿泊を伴う旅行に連れて行けるようになったりと、行動の幅が広がったのも良かったです。引き続き、英才教育・・という名の親の趣味に付き合わせていきたいなと思っています。

月別生データ

1月

  • 親子2人で電車でお出かけ
  • 動画で子守するのを解禁
  • 凧揚げ
  • 内窓を設置
  • 前半は風邪、後半は胃腸炎

ひらがなおもちゃを作る

RakuChordのSMD版を作る inajob.hatenablog.jp

2月

  • 節分
  • 水族館にいく
  • 成田空港にいく

おしたくボード改

MakePython Audio Expansionレビュー inajob.github.io

HandiPiを作る inajob.hatenablog.jp

事前に議事録を作る方式について qiita.com

3月

なぜなぜ分析

おもちゃの分解

Web Assembly qiita.com

ChatGPTに英語記事の要約を頼む実験

OLEDの不良品を激安のロジックアナライザーで分析 scrapbox.io

オーディオコメンタリーメーカーを作る github.com

inajob.hatenablog.jp

3Dプリンタの寸法チェック用モデル

蛇口延長用アダプタ

ESPHomeを試す(が結局プログラミングすることに・・)

4月

レタスの発芽(失敗)

PASMOがバズる

電子メモパッドのレビュー inajob.github.io

小型のフルカラーLEDのテスト基板 inajob.hatenablog.jp

モノクロ液晶の試食

ESP32で動く日本語入力対応Wiki的なもの

5月

枝豆・トマトを植える

埼玉県近代美術館

電気圧力釜を買った

DIYこいのぼり

粘土に夢中

自動ハンドソープディスペンサー購入

トイレの最中

ケースづくり

ESP32搭載のDIY時計ガジェットキットレビュー inajob.github.io

ペン型マルチメーターレビュー inajob.github.io

乾電池駆動のArduino Nanoボード inajob.hatenablog.jp

Vision Five2試食

ダイソーで買ったおもちゃ

6月

  • 長靴を買った
  • 七五三の前撮り
  • KEY PALETTOを購入
  • omoikane参加
  • blueskyを始める

ノートパソコンのバッテリーが膨らむ

ジャガイモを収穫

スカイツリーを見に行く

Raspberry Pi Picoを使った携帯ゲーム機 inajob.hatenablog.jp

7月

  • 地域のソーメン流し参加
  • ブルーベリー狩り
  • 打ち上げ花火を見る
  • Threadsに参加
  • (今更)Twitter API V2を試す
  • ヘッドセット、ロジクールH111rを買った
  • SNSを同期する仕組みの作成

トマト、枝豆の収穫

絵を描いて教える

お金やさん

8月

Raspberry Pi Pico搭載のマクロパッド inajob.hatenablog.jp

バタフライピー

ビリヤニ

ポップコーン

市販キーボード用のマウンタ

ログ機能付きの電流計自作

フレキシブルHDMIケーブル

inajob.hatenablog.jp

9月

  • 写真データをGoogle Photosから自宅のNASに移行
  • synthioを試す
  • Raspberry Pi Picoで遊ぶ
  • MSX0で遊ぶ
  • NS8002オーディオアンプ実験
  • CH32V003で和音実験
  • 遊園地に行く

自作キーボード inajob.hatenablog.jp

10月

  • 上野動物園、ジャグリング鑑賞
  • 地元の秋祭り
  • 自転車が壊れる
  • コテンラジオを聞き始める
  • 安い骨伝導イヤホンを買った(いまいち)
  • LISTENトーク(仮)に参加
  • パパ友とバーベキュー会主催
  • 七五三撮影

RP2040実装練習

inajob.hatenablog.jp

11月

  • 幼稚園の入園面談
  • 国立科学博物館に行く
  • ChatGPT with Voiceで子守してみる
  • サーキュレーターを買った
  • 加湿器を買った
  • 喰い切りニッパーを買った
  • Milk-V Duo試食
  • CadQueryを学ぶ

娘を連れてNT東京2023を見に行った

不良品と思われるATmega328の調査

inajob.hatenablog.jp

12月

コストコ入会

クリスマスオーナメントを作る

クリスマスツリーを作る

Loona購入

inajob.hatenablog.jp

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円です

akizukidenshi.com

プログラムメモリ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というGUIIDEと公式のSDKを使う手があるのですが、どうも大げさな開発環境で、肌になじまなかったので、シンプルなch32v003funを使うことにしました。

github.com

ch32v003funはシンプルな実装ですが、このくらいの規模のCH32V003の開発には必要十分で、サンプルも豊富です。 いくつかのサンプルを組み合わせることで目的のプログラムを作ることが出来ました。

  • blink
    • まずはLEDをチカチカします
    • これで最低限の雰囲気をつかみました
  • tim2_pwm
    • 音を鳴らすために利用するPWMの機能
    • LEDをフェードイン・フェードアウトするような使い方にも利用できます
  • systick_irq
    • 音源のオシレータを一定時間ごとに進めるためにタイマ割込みの機能
  • i2c_oled
    • I2C接続のOLEDの制御
    • ホビー電子工作でよく利用するSSD1306向けの描画ロジックが便利です

ch32v003funを使うにあたっては以下のブログ記事が非常に参考になりました。

74th.hateblo.jp

つぎはぎですがソースコードはこんな感じです (ch32v003funのi2c_oledのexampleを以下のように書き換えて、ビルドしました)

gist.github.com

まとめ

安価な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++を使うのがよさそうです。

ということで、できました。

押したキーに対応する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でも音を鳴らすところまではプログラムを作り、それなりに遊んだりもしました。

こういう過去があっての今回のigetaの製作につながっています。

ってこれやってたの2021年5月とかですね、、意外と歴史があります。

表面実装部品版RakuChordの改良版を作った

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

JLCPCBとは

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)

JLCPCBとは、プリント基板製造などで有名な香港の企業です。

日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。

値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。

この記事の作例もJLCPCBに基板を発注して実現しました。

表面実装版RakuChordとは?

RakuChordというのはinajobが開発している電子楽器です。

inajob.github.io

ワンタッチで和音を演奏できるボタンがあり、だれでも比較的簡単に演奏ができるという電子楽器で、少しずつバージョンアップをさせながら、電子工作キットとしての販売をしています。

以前RakuChordの表面実装版を作ったことがありましたが、今回はこれの更なる改良版です。

inajob.hatenablog.jp

今回の表面実装版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を使った昇圧回路を利用できるようにした「こんなこともあろうかと」の設計が役立って良かったです。

自作キーボードHanamuguriを作った

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

JLCPCBとは

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)

JLCPCBとは、プリント基板製造などで有名な香港の企業です。

日本からでもWebページでポチポチするだけでKiCADなどで作成した基板データの製造を依頼できます。

値段もかなりお手頃で、ホビー電子工作ユーザーの間では広く利用されています。

この記事の作例もJLCPCBに基板を発注して実現しました。

自作キーボード「Hanamuguri」とは

Hanamuguriはinajobの2つ目に設計した自作キーボードです。

いわゆる40%キーボードと呼ばれるレイアウトで、コンパクトながら実用的なキー配列となっています。一般的なパソコンのキーボードとしても利用できますが、どちらかというと、Raspberry Piなどを使って作られたコンパクトな自作モバイル端末を実現するための部品の一つとして利用できるものを目指しています。

前作はALLPCB39というキーボードを作りました。こちらもコンパクトなキー配列のキーボードです。

ALLPCB39はオーソリニアと呼ばれる格子状のキーボードだったのですが、今回のHanamuguriはロウスタッガードと呼ばれる、行ごとに少しずつキーがずれている、いわゆる一般的なキーボードの配列のキーボードと同じ配列を選択しました。 加えて、ALLPCB39はCherry MX互換キーボードスイッチを採用しましたが、HanamuguriはGateronのLowProfileを利用できるようにして、より薄くなりました。

これも含めて以下のような特徴があります

  • 49キー(配列はいわゆる40%キーボード的)
  • 独立カーソルキー
  • 固定用のねじ穴がたくさんある
  • ユニバーサル基板っぽい領域がキーボード上部にある
  • 対応キーボードスイッチ
    • Gateron LowProfile
    • Gateron LowProfile Hot swap
    • Cherry MX(not LowProfile)
  • キーボードスイッチはパネルマウント
  • 128*64 OLED
  • 開発ボードはRP2040-Zero
  • キーボードマトリクス、未使用ピンのための拡張ピンヘッダ

Hanamuguriをいきなり作るのは心配だったので、まず オリジナルのマクロパッドを作ってみた - inajob's blogを使ってキーボードスイッチまわりのフットプリントの使い方に問題がないかを検証しています。そのため、キーの数が多いことを除いては、以前作ったマクロパッドと同じような構成となっています。

RP2040-Zero

今回のキーボードのキモともいえるこのマイコンボード。コアとなるMCUはRP2040で、Raspberry Pi Picoと同じものですが、RP2040-Zeroの方が基板がコンパクトであることや、USB Type-C端子であることに魅力を感じ、こちらを選択しました。

コンパクトな分利用できるGPIOは少ない、、と思いきや裏面に細かいピッチでパッドが並んでいるので、この部分をはんだ付けできればより多くのGPIOを利用できます。(Hanamuguriではこの部分のピンは今後の拡張のために引き出しているだけで、利用していません)

www.waveshare.com

基板の設計

基板の設計と書きましたが、以前のALLPCB39を作った時と同様、Keyboard Layout Editorのデータから基板のデータを半自動的に生成します。

ということで、まずキーレイアウトを作成しました。

keyboard-layout-editorのデータから回路図を作るツールについて、KiCADのバージョンを上げたせいか、以前使ったツールはうまく動かなくなっていたので、今回はKiCADのアドオンであるGitHub - adamws/kicad-kbplacer: KiCad plugin for automatic keyboard's key placement and routingを使いました。

使い方はkicad-kbplacerのREADMEに従いましたが、ちょっとわかりにくかったので、ここでも説明します

まず、キーボードマトリクスの論理回路図を作成します。今回はキーの数が44キーなので、Rowが7ピン、Columが7ピンのマトリクスレイアウトを採用します。結果として49キー利用できるので、キーボードの配列とは別に5つのキーを利用できるように設計することとします。

で、この論理回路図の部品に番号を振ります

annotation機能を実行すれば番号を振れるのですが、その際に以下の画像のように設定します。

おそらくここを変な形で設定しても、ファームウェアでうまいこと設定すれば対応できそうですが、今回はおとなしく指示に従いました。 その後、フットプリントを割り当てます。

Gateron LowProfileのキーのフットプリントは以前作成したものがあるので、これを使います。

次にKiCADの基板エディタで、ネットリストを読み込みます。 読み込んだ直後は以下のようになっています。

さて、ここでこの部品たちをkeyboard-layout-editorで設計したキー配列のように並べるのがkicad-kbplacerの役割です。

keyboard-layout-editorで作成したjsonをkle-serial形式に変換する必要があるので、以下のツールを利用しました

adamws.github.io

その後ツールバーにあるkbplacerをクリックし、設定画面を開きます

kle-serial形式のjsonファイルを指定して、OKをクリックすると以下のように、部品がkeyboard-layout-editorで設定したものと同様の配列になりました。

なお、今回は45キーのレイアウトだったので、余っている5キーについては手動で配置します。

ここまででキーボードスイッチとダイオードについてはレイアウトが決定しました。

その他の部品や基板外形はいつもの回路設計と同様に行います。

RP2040-Zeroのフットプリントは GitHub - crides/kleeb: Collection of Kicad 6.0 symbols, footprints and 3D models useful in keyboard creationを利用しました。

キーボードの上部にユニバーサル基板のような領域を作ってみました。

これを作るにあたってはKiCadのレイアウトエディタ(Pcbnew)で半田付けパッドを自由に追加する方法(viaを利用する) - PCB Design Tutorial - PCBwayで紹介されているviaとソルダーマスクを使用する方法を利用しました。 ただしこの方法を愚直にやるとfreeroutingで自動配線するときにviaをfreeroutingが認識せず、自動配線がユニバーサル基板領域と重なってしまう問題が起きました。

そのため、まずはユニバーサル基板領域を配線禁止エリアとし、自動配線後にviaとソルダーマスクを並べる手法でユニバーサル基板風の基板を作りました。

続いて、トッププレートも作成します。作り方は以前のオリジナルのマクロパッドを作ってみた - inajob's blogと同じです。

基板の発注

発注はもちろんJLCPCBです。

jlcpcb.com (↑こちらは日本語版のログインページで、お得なクーポンも配布されています。)

10cm×10cm以内の基板が激安なのは、今まで紹介してきたとおりですが、今回の基板はそれより大きいです、さて、いくらくらいかかるのか・・?

大きさは、本体基板が 242.6 mm × 127 mm、トッププレートが242.6 mm × 92.2 mmです。 注文後にメールが1つきて「配線が含まれない基板があるけどデータが間違っているのでは?」(英語)と確認されました。こちらはキーボードのトッププレートなので、配線なしで合っているので、問題ないので進めてくださいと返しました。

その後さらにAn additional charge will be applied to your order[JLCPCB] というメールが来て、「細かい穴が多いので追加で$7.5支払ってほしい」と連絡がありました。これも問題ないので追加で支払いを行いました。

具体的にはこのあたりが追加料金となった原因とのことでした。(まぁ、確かに細かい穴が多い)

ということで5セット作ってもらうのに、お値段は下記に加えて追加の$7.5、送料の$13.77がかかりました。(別にもう1種類基板を発注していたので、送料はそれも込みのものとなっています)

部品の発注

Gateronのロープロファイルのキーボードスイッチ、これに対応したホットスワップソケット、RP2040-Zero、128*64のI2C接続のOLED、ダイオード、キーキャップが必要でしたが、今回はこれらの部品は家のストック部品を利用しました。

Gateronのロープロファイルキーボードスイッチの2Uのスタビライザーは家になかったのでAliExpressで購入しました。

今回のミス

スペースキーが横に長い(2.75U)ため、スタビライザーを取り付けられるように溝を付けたのですが、そのフットプリントのサイズが誤っており、そのままでは取り付けられないものとなりました。

やはり、新しい部分があると、そこでミスしますね・・ 今回は取り敢えず、スタビライザーなしで組み立てることとしました。

部品実装

RP2040-Zeroは端面スルーホール部品なので、基板を重ねて実装することが出来るのですが、とりあえず後で着脱が出来るようにピンヘッダ・ピンソケットを介して実装しました。OLEDも同様にピンヘッダ・ピンソケットを介して実装しました。

後はダイオードと、ホットスワップソケットです。単純な部品なのですが、何しろ44個もあるので、実装が大変でした。特にホットスワップソケットは、はんだがパッド面ではなくソケットの溝の方にばかり流れ込んでしまい、一見はんだが乗っているように見えるが、パッドと部品が接続されていないという状態になるケースが多発し、苦労しました。

加えて、とても初歩的なミスですが、ダイオードの向きを一部間違えて実装してしまい、これも修正が面倒でした。

ファームウェア実装

ファームウェアKMKfw | KMKを使いました。 これはCircuitPython上に実装された、自作キーボード向けのファームウェアで、非常に簡単に利用することが出来ました。

実装したファームウェアはこんな感じです

  • 日本語キー配列(KMKは日本語キー配列もサポートしていました)
  • レイヤーは2つ
    • 通常レイヤー(キートップに刻印されているアルファベット)
    • 数字レイヤー (一般的なキーボードの1行目にあるキーや、一部の記号)
  • OLEDにレイヤーの状態を表示

これだけの記述でカスタマイズできるのはとても便利だと感じました。またCircuitPythonはインタプリタとして動いているので、修正・確認のフィードバックループを素早く回すことが出来たのも良かったです。(その分実行速度は遅いですが、今回の用途ではその遅さが気になることはなかったです)

import board

from kmk.kmk_keyboard import KMKKeyboard
from kmk.keys import KC
from kmk.scanners import DiodeOrientation

# レイヤーを利用する
from kmk.modules.layers import Layers

# 日本語対応
import kmk.extensions.keymap_extras.keymap_jp

# OLED対応
from kmk.extensions.peg_oled_display import Oled,OledDisplayMode,OledReactionType,OledData


keyboard = KMKKeyboard()

# ピンアサイン
keyboard.col_pins = (board.GP11, board.GP12, board.GP13, board.GP14, board.GP15, board.GP26,board.GP27)
keyboard.row_pins = (board.GP4, board.GP5, board.GP6, board.GP7, board.GP8, board.GP9, board.GP10)
keyboard.diode_orientation = DiodeOrientation.COL2ROW

# レイヤー
keyboard.modules.append(Layers())

# OLED用のピンアサイン
keyboard.SCL=board.GP3
keyboard.SDA=board.GP2

# OLEDの設定
oled_ext = Oled(
    OledData(
        corner_one={0:OledReactionType.STATIC,1:["layer"]},
        corner_two={0:OledReactionType.LAYER,1:["1","2","3","4"]},
        corner_three={0:OledReactionType.LAYER,1:["base","raise","lower","adjust"]},
        corner_four={0:OledReactionType.LAYER,1:["qwerty","nums","shifted","leds"]}
        ),
        toDisplay=OledDisplayMode.TXT,flip=False,oWidth=128, oHeight=64)
keyboard.extensions.append(oled_ext)

# よく使うキー
LOWER = KC.MO(1)
_______ = KC.TRNS

# キーマップ
keyboard.keymap = [
        # layer0
        [
            KC.ESC, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC,
            KC.TAB, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.ENT,
            KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.UP,LOWER,
            KC.LCTRL, KC.LGUI, KC.LALT, LOWER, KC.MINUS, KC.SPC, KC.DOT, KC.LEFT, KC.DOWN, KC.RIGHT,
            KC.N0, KC.N1, KC.N2, KC.N3, KC.N4
            ],
        # layer1
        [
            KC.GRAVE, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSLASH,
            _______, _______, _______, KC.CIRC, KC.JYEN, KC.AT, KC.SCLN, KC.COLN, KC.LBRC, KC.RBRC, _______,
            _______, _______, _______, _______, _______, _______, KC.SLASH, KC.BSLS, _______, _______,LOWER,
            _______, _______, _______, LOWER, LOWER, _______, _______, _______, _______, _______,
            KC.N0, KC.N1, KC.N2, KC.N3, KC.N4
            ],
]

if __name__ == '__main__':
    keyboard.go()

まとめ

自分としては2つ目の自作キーボードを設計・実装しました。 kicad-kbplacerを使った自動配置、ロープロファイルキーボードスイッチ、KMKなど、以前とは違う手法・構成を使い、多くの学びを得ました。

前回のときも感じましたが、自作キーボードは、趣味の電子工作のジャンルの中でもとてもポピュラーなものとなってきており、周辺ツールや文書が潤沢にあるため、非常に入門しやすく、簡単に作り上げることが出来ると感じました。

Hanamuguriは、まだキーボードとして最低限動作するところまでしかできていないので、今後ケースの作成、キーマップの充実、OLEDやカラーLEDの活用、これを組み込んだモバイル端末の作成など、まだまだやりたいことがたくさんあります。

また進展があれば、ブログ記事などで紹介しようと思います。