2020年11月28日土曜日

ChocV2 で Type-C 左右分離キーパッドを作ってみた

今回制作した左右分離型10キー キーパッドの右手側

前回の Breakout 基板を作ってから色々忙しくなってしまい、なかなか進捗が出せていなかった。 けど、ようやくキーパッドを作れたのでまとめておきたい。しかし、こういう時のために設計した 前回の Breakout 基板 だったはずなのに、今回はキーボードを薄型にしたいと思って、マイコン直載せにしたので使わなかった(汗)

そう、何かを作る準備ばかりしていて、いつまで経っても本番の作業が始まらない・・・。 今も自分なりのキー配置の 60% キーボードを作りたいのだけど、そのための要素技術を 100x100mm PCB で確かめておこうという試み。 でもそういうのは、今回で最後にしたい!ぞ!!

コンセプト


さて、左右分離型の自作キーボードについて、いくつか気になっていて、今回は少し変えてみたいところがある。


ProMicro マイコン2個持ち?


これはファームを変更した時に、マイコン2個とも書き換えないといけないのがいつも面倒だなぁ、と思っていた。 USB ケーブルを外して、TRRS ケーブルも抜いて、USB ケーブルをつないで、ファームを書き込んで、USB ケーブルを抜いて、TRRS ケーブルをつないで、USB ケーブルをつなぐ、みたいなことを毎回している。

いや、自分が知らないだけで、実は楽に書き換える方法があるのだろうか?

と思って今調べてみたら、実は qmk_firmware では、MASTER 側を書き換えるだけでよかったらしい・・・。 そうなの?もう作っちゃったよ?

気を取り直して、今回はマイコンは1つだけにして、反対側のキー状態は、I2C 接続の I/O エクスパンダで読み取るようにしてみたいと思った。 マイコン同士の通信プログラムもいつかは書いてみたいけど・・・。


TRRS ケーブル?


こちらは、オーディオケーブルは信号用だから、電源を送るのはちょっと・・・、と見るたびに思っていた。 キーボードを USB につないだまま TRRS ケーブルを抜き差しするのは NG だと思うから、 時々、必要があって抜き差しする時には、USB ケーブルが抜いてあることを確実にすることを忘れてはいけない。

いつも何となくヒヤヒヤしてしまうので、両側 micro-b コネクタの USB ケーブルを自作して両側をつなごうか? でも micro-b コネクタにケーブルをハンダ付けするの難しいんだよな、・・・。 それとも、keyboardio のように LAN ケーブルでつなぐか。でもコネクタでかいんだよな・・・。

という逡巡の末、今回は左右を USB Type-C ケーブルで接続することを考えてみた。 そこで 24 ピンタイプの Type-C コネクタをお試しで秋月で買ってみたけど、自分のハンダ付け力ではまず無理だと判明・・・。

上がフルの 24 ピンタイプで、裏面にも端子がある。下は 16 ピンタイプ

こういう時、リフロー環境があれば 24 ピンタイプも大丈夫なのだろうか? アイロンでリフローというのもあるみたいだけど、自信無いので、今回は 16 ピンで行くことにする。

必要な線としては、電源の 2 本、I2C の 2 本、そしてフルカラー LED の信号線 1 本で、計 5 本。 16 ピンタイプで使えるのは、

VBUS, GND, D+, D-, CC1, CC2, SBU1, SBU2

の 8 本まで。リバーシブルで使えるように SBU1/2 はつないでしまって、これを LED の信号線にあてよう。 しかし、SBU1/2 を使おうとすると、この端子までちゃんと配線されている Type-C ケーブルは、 映像出力可と書いてあるフルスペックの USB 3.1 ケーブルという、何とも無駄に矛盾した感が満載・・・。


ロープロファイル キースイッチ?


そうこう考えている時に、ChocV2 というロープロファイルのスイッチを Aliexpress で購入してみたのだけど、これがめっちゃ薄い! この薄さは抗い難い魅力がある・・・。今回はこのスイッチを使ってみたい!

届いた Choc V2(左)と Kailh Box Silent Pink (Linear) (右)

でも twitter を見てると、どうもデータシートの推奨 PCB パターンが正確ではないらしい!? そこで、自分でもデータシートの寸法から図面を描いてみて、写メと合わせてみた。まずデータシートはこちら。

これを元に図を描いて、写メの上に重ねてみる。

データシートの寸法と写メを合わせたところ。左下が fix ピン

確かに左下の fix ピンがズレている? そこでノギスでも測ってみたのだけど、やっぱり fix ピンの位置が少し左右に(上下に?)ずれているようだ。

ノギスで測ってみた値(0.05mm 刻み)

しかし、そもそもノギスで正確に測るのがなかなか難しい。挟んで測るわけではなくて、 お尻の細い棒をギュッと当てて測る感じなので、微妙に斜めってしまったりすると、毎回計測値が変わってしまう・・・。

それなら挟んで測れるところを測って、あとは計算だ! というのもやってみたけど、斜めに挟むところと真っ直ぐに挟むところと両方あって、 それぞれでノギスが違う側面に当たっているからか、やっぱり正確には求まらない!?

ピン間の距離から余弦定理などで求める

最終的は、こちらの KiCAD フットプリントを参考にさせて頂きました。



あと、前から気になっていた、キースイッチのスルーホールの径・・・。

MX スイッチのフットプリントの穴って結構大きくて、いつもハンダがどばどばどば〜っと吸い込まれる。 こんなに穴大きくしなくてもいいんじゃね?と常々感じていたので、今回は少し狭目にしてみた。 0.6mm もあればいいんじゃないだろうか?

で、実際そうしてみたらどうなったかというと、キースイッチを取り付ける時にピンが穴にスッと嵌まらず、引っかかってちょっと大変でした・・・。 なるほどこういう理由か〜! スイッチの足って簡単に曲がっちゃうから、嵌めやすいように、大きめの穴にしてあったんだなぁ、と学習。次回は気持ち広げてみよう。


デバウンス回路?


最後に、去年、初めて作ったキーパッドでデバウンス回路を入れてみたけど、後から考えると失敗回路だった。 今回はその反省を元に、ちゃんと動く回路にリベンジしたい!


設計


外形デザイン


キーパッドの形はどうしよう?とりあえず名刺サイズにするか、Suica サイズにするか?と迷ってたんだけど、 いつもお世話になってる美容師さんとの会話で、「自分は黄金比か、和の白銀比にすることが多いですね〜」 と仰っていたので、100mm サイズの白銀比の長方形にしてみようと考えた。

そしてキーの配置は、今度作ろうと思っているキーボードの最下段を取り出した感じにしたのだけど、 それだと結構 PCB がスカスカなので、フラクタル的に3分の1の相似形を切り欠いたコの字型にして、少しハードルを上げてみた。

コの字型デザイン。角っこの計6箇所のスペーサ用穴は六角形にしてみた


基板構造


一番悩んだのがここ。PCB のサンドイッチ構造にするとして、ChocV2 の寸法をどう収めるか。スペーサーの高さやネジの長さも関係してくる。

最終的には、4mm の六角スペーサーを、1.6mm 厚のトッププレートと、1.2mm 厚のボトムプレートで挟むことにした。 また、部品をハンダ付けする PCB は 1.2mm 厚にして、ボトムプレートはとの隙間は 1.0mm + 1.2mm の PCB 2 枚で埋める。

PCB 5 枚重ね。隙間は 0.6mm なので、もう1枚 PCB を入れられたと後で気付いた

ChocV2 の軸の高さは 3.3mm ある。上の設計だと、3.4mm の隙間に 3.3mm だからかなりギリギリ。

同じようにもう一つ注意が必要だったのが、I/O エクスパンダの MCP23017。 なるべく小さくと思って SSOP パッケージを選択したけど、高さは 2mm あったので、今回の表面実装部品の中では一番背が高い。 これが引っかからないようにするために、メインの PCB は厚み 1.2mm にして、ボトムプレートとの間を 2.2mm 確保するようにした。

あと、これまでは PCB の両面に部品を実装してたけど、今回はトッププレートとの間は 0.6mm しか隙間がないので、片面実装にした。


ネジ


ネジについては、M2 ネジだと締め付け力が不安だったので、M3 ネジを使おうと思った。 1.6mm 厚のトッププレートは 4mm のネジで、1.2mm 厚のボトムプレートは 3mm のネジで止める。 6.8mm の厚みに計 7mm のネジ長で、ちょっと余りそうだけど、まぁたぶん大丈夫?適当だ。

でも低頭の M3 ネジというと、黒のステンレスがよかったんだけど、1本単位で購入できる 3mm のものはなかなか見つからない。 ネジ山の巻数が少なくなるから、締め付け力や強度の点で問題があるのかもしれない。

そこで、間を取って M2.5 / M2.6 の方を探してみると、スペーサーについては、M2.6 だと種類が色々用意されているけど、M2.5 になると急に選択肢が狭まる。 一方で、Aliexpress でネジを探してみると、M2.6 ネジはほとんど見つからず、M2.5 がほとんどのよう。

う〜ん、あちらを立てればこちらが立たず。ここもめちゃくちゃ悩んだけど、結局、3mm 黒の鉄ネジを注文した。 4mm の方は黒ステンレスのものがあったのでそちらを注文。

あと、六角スペーサを通す穴を前回はただの円形にしていたのだけど、六角形にすることで、スペーサーが引っかかってねじ止めし易くしてみた。 これはやってみるとかなり便利でよかった。


回路図


コの字型にすると、そこそこ狭い。片面実装だし、微妙に部品を置くスペースがない!

マイコンのパスコンは、いつもデータシート通りに、デジタルの Vdd, Gnd の2組にはそれぞれ 0.1uF, 4.7uF の計 4 個、 アナログの Vdda, Gnd には 0.01uF, 1uF の 2 個の合計 6 個と取り付けていた。 今回はこれが場所取るなぁ、と思い、NUCLEO-F042K6 ボードの回路図を見てみたら、 0.1uF がそれぞれ 1 つずつの、合計 3 個付いているだけだった・・・。

なんだと?!今回はアナログ入出力はないので、同じく 0.1uF x3 だけでいってみることにした。

左手(マイコン)側の回路図

右手(I/O エクスパンダ)側の回路図

トッププレートとボトムプレート


何か自キ界隈の皆さまは、Gnd ベタに色んな模様を並べたりしてカッコよくて羨ましい・・・。 自分も何かやってみたいとは思うのだけど、やり方が分からない。 それならせめて、配線のないトップ・ボトムプレートには何かデザインを入れてみようと思って考えてみた。

さて、上述の白銀比とは、1:√3 の比のことで、って、あれ?これは白金比=プラチナ比では!? これを書く今の今まで間違えていたらしい。白銀比は 1:√2 でした・・・。 っていうか、美容師さんとのやり取りのくだりは何だったのか(汗)

えっと、気を取り直して、プラチナ比も和柄にはたくさん見られる。麻の葉とか青海波、亀甲などなど(フォロー)。 こういうのもよいなぁとか、コの字型の切り欠きを合わせると綺麗に揃うデザインとか出来ないかなぁとか。 あるいはシェルピンスキーガスケットのような、フラクタルも面白そう・・・。

・・・。

迷走しまくって、シンプルなボーダーに落ち着きました。 エルゴノミックな配置のつもりのキーの角度に平行なボーダー柄にする。 そして、外形やネジ穴にボーダーの線がかぶらないようにしたい。

色々試行錯誤して、最終的に以下の手順で、まず外形やネジ穴からの距離画像を作成した。
  1. KiCAD で Edge.Cuts を SVG で出力する(輪郭(contour)出力をしないようにすること!)
  2. Python の cairosvg パッケージを使って、254dpi(1ピクセル=0.1mm)の解像度でビットマップの線画に変換する
  3. 閾値 64 で二値化
  4. opencv の cv2.connectedComponents() で中心位置での flood fill =有効領域を取得する
  5. cv2.distanceTransform() を使って、その反転領域から有効領域内への距離変換をする
  6. 距離画像をcsv形式でテキストファイルに書き出す

あとは、このテキストファイルを KiCAD の Python から読み込む。

外形からの距離画像


ボーダーの線は、1~2mm 程度の区分的折れ線に分割して、その線の太さと、この距離画像とを見て、 外形やネジ穴にかぶらないように再分割して引いていく。

トッププレート

ボーダー線は、上から下へグラデーション的に太さを変えてみた。また、表と裏で、太さを逆に変化させている。 なんだけど、意外によく見ないと、この太さのグラデーションはぱっと見では気付かない。

完成後のボトムプレート

組み立て


これまでは PCB は pcbgogo さんにお願いしていたけど、つや消し黒というのを試してみたくて、今回は jlcpcb に発注してみた。 そして、届いたのがこちら。よき!

ミッドプレートは、同じ形で厚みが 1.0mm と1.2mm の2種類

さあ、作るよ〜。と意気込んだけど、最初の Type-C コネクタ 3 個のハンダ付けでいきなり苦戦(汗) 溶けたハンダの表面張力で自動的に位置調整、とかは無理だと悟る。 マステでちゃんと仮止めしてからハンダ付けするようにしたら、何とか付けることができた。

左右両側に Type-C コネクタ

あとのハンダ付けはそんなに難しくはないので、どんどんやっていく。 MCP23017 の SSOP パッケージはそれなりにピッチが狭いので、これもマステで位置決めした方がハンダ付けしやすかった。


LED までハンダ付け完了〜

ミッドプレートは左右共通になってて、左手側は、USB コネクタの部分をノコギリで切り落とす。
ミッドプレート左手側

縦に 3 つ抵抗とコンデンサが並んでいるのが、row 線の終端のデバウンス回路。そして、それに形を合わせたミッドプレート。
ミッドプレートを乗せたところ


ファーム書き


探してみるとやはり、今回使っている STM32F042K6 でも qmk_firmware を動かしている人はいるようだ。

https://github.com/gesinger/qmk_firmware/tree/dragonwell/keyboards/dragonwell
https://github.com/qmk/qmk_firmware/issues/6783

でも今回はデバウンスや I2C に対応したりするし、以前 qmk に emacs モードを実装してみた時に、



qmk が色んなところで register_code() / unregister_code() を呼んでいるのが気になって、 一度 queue ベースで実装してみたいと思っていたので、勉強のために自分で書いてみることにする。

デバウンス用のウェイトは、大体 1ms 程度。一方で、USB のホストからのポーリング間隔も最短で 1ms。 なので、col 線を HI に上げたら、row 線を読み出すまでの 1ms の間は、 例えば LED の計算と PWM 信号送出など、他のタスクをするようにした方がよい。

そうすると、一度に 1 つの col 線のみ HI にするから、col の本数 ms のスキャン時間がかかることになる。 一方 SK6812 の LED は、1 個当たりの設定に 30us かかるので、1ms だと 30 個ぐらいが限度になる。 60%キーぐらいのキーボードを作りたい時は、PWM 出力を 2 系統用意するなどをした方がよさそうだ。

また、キーの押下・解放は queue を使うようにして、メインループが 1 回回る時に、キューから 1 つだけ拾って送るようにする。 NKRO も実装。 今のところ単純なキーパッドとしては動作しているけど、この辺りは今後本格的にレイヤー機能などを実装していくと、また色々楽しめそうだ。


RGB LED


そして、ファームと言えば、RGB LED のエフェクトだ?!

qmk のようにレインボーとか、Knight2000 とかはベタに作って、そのあとは何を作ろう?

押した回数だけ熱拡散的にじわ〜っと広がるもの。

そして、波動方程式的にぴゅ〜っと進むもの。 特にこちらは両端での反射が出ないように、2階の微分方程式を左進波と右進波の1階の微分方程式に因数分解して実装してみた。

あとは、ロウソク風に、1/f 揺らぎでユラユラする感じも作ってみた!!



動作不良?


あれれ、右手側のキーパッドの位置を動かしていると、時々その後右手側が一切反応しなくなってしまう!? USB ケーブルのコネクタ部分で接触が一瞬外れたりして、I2C 通信がその後正しく行えなくなったりしているのだろうか? MCP23017 の NRST をマイコンから制御するか(現在は Vdd に接続)、 あるいはファームウェアで、I2C がタイムアウトした時に、何かできるだろうか・・・?

要検討である!