Cookpad Pad 2 という自作キーボードノベルティをつくった話

こんにちは、高井です。みなさま Cookpad Online Summer Internship 2020、お疲れさまでした。

さて、今回はインターンのノベルティとして Cookpad Pad 2 という自作キーボードキットをノベルティとしてつくったので、その紹介と解説です。今年のインターンシップはリモート開催ということもあり、ふだんよりも豪華なノベルティをつくることができました。写真では見えませんが、裏側に Cookpad Online Summer Internship 2020 のロゴがプリントされていて、限定感を出しています。

f:id:takai_naoto:20200910181821j:plain

というわけで、本記事では Cookpad Pad 2 を例に取りながら、自作キーボードキットを作成する方法について解説します。キーボードの開発はさまざまなノウハウが公開されているため、実際のところそれほど難しくはありません。本記事ではキーボード開発についての完全な手順を説明するというよりも、有益な記事やリソースを紹介することで、全体の流れとして個々のノウハウを結びつけることを目指します。

キーボードを設計、開発するときの流れは次のようなものです。この流れに沿いながら、どのようにキーボードを開発するのかを見ていきましょう。

  • プロダクト構想
  • キーボード基板設計
    • 回路図設計
    • パーツ選定
    • プリント基板設計
  • キーボードケース設計
    • 設計
    • 検証(アセンブリ)
  • 製造
    • キーボード基板
    • キーボードケース
  • ファームウェア開発
    • QMK Firmware
    • VIA

また、Cookpad Pad 2 はオープンハードウェアとして GitHub でプロジェクトを公開しています。記事とあわせてこちらも参照してください。

https://github.com/cookpad/cookpad-pad/tree/cookpad-pad2

プロダクト構想

まず、最初に行なうのは、どのようなキーボードをつくるのか構想することです。Cookpad Pad 2 は 6 キーのマクロパッドです。デフォルトでは「C」「O」「K」「P」「A」「D」の 6 文字が打てるので、「cookpad」と打つときに便利なキーボードです。初代のモデルは、2019年頃に製作をして、ノベルティとして個人的に配布をしていました。

デザインは、この初代 Cookpad Pad を踏襲するものとします。 6 キーを格子状に配置したシンプルなデザインです。また、ケースは PCB を 2 枚のプレートで挟み込んだ、サンドイッチマウント構造にします。この構造は自作キーボードでよく採用される構造で、安価に作成できることがメリットです。

それから、コネクターとして USB Type-C を採用します。そのために、 Pro Micro というマイコンボードを利用しない方針とします。 Pro Micro は自作キーボードに必要な電子部品が実装されているので、基板の設計を単純にすることができます。一方で、Micro USB Type-Bコネクタが採用されていたり、ピンヘッダでマイコンボードを取り付けるため、設計上の制約がでてしまうという欠点があります。そこで、 Pro Micro の利用をするのではなく、直接基板に同等の機能を実装していきます。

キーボード基板設計

ここまで決まったら、基板の設計を行なっていきます。今回は構造が単純なサンドイッチマウントを採用しているため基板を先に設計しますが、アルミ切削ケースなどの場合はケースの設計から先に行なった方がよいでしょう。

基板の設計には KiCad をつかいます。 KiCad はフリーソフトウェアとして配布されているEDAツールです。独特の操作性を持つので、はじめての人であれば、「KiCadことはじめ」などを参考に、一通り触ってみてください。

回路図

キーボードの基板設計については「ai03's Keybaord PCB Designer Guide」を参照してください。 KiCad の利用方法から回路設計、PCB設計まで一通りが解説されているので、これを読むだけでもキーボード設計ができるようになります。

自作キーボードの MCU は ATmega32u4 を利用することが一般的ですが、今回は ATmega32u2 を利用しています。ATmega32u2 の方が若干フットプリントが小さいため、部品配置が楽になるかもしれないというのが選定理由です。どちらもキーボードファームウェアとして広く利用されている QMK Firmware でサポートされている MCU です。特に理由がないのであれば ATmega32u4 を採用するのがよいとおもいます。

その他、TVSダイオードによる静電気放電対策やポリスイッチによる過電流対策を行なっています。キーボードのUSB-C関連の設計については、ai03氏が中心となって公開している Unified Daughterboard Project が参考になるでしょう。今回のキーボードでは、それよりも簡略化された実装にしています。

回路図シンボルなども ai03氏が公開しているものを利用するのが便利です。ai03氏、いったい何者なんだ……。

実際の回路図は下記のようなものになります。左上がMCU関連、右上がキーマトリクス、左下がUSB関連、右下が電源関連となります。

f:id:takai_naoto:20200910181904p:plain

なお、このサイズのキーボードであれば、MCUのピンとスイッチを一対一で対応させればよいので、本来ならばキーマトリックスは不要です。このプロジェクトを拡張することで、好きなキーボードつくってもらえるようにという意図を込めてキーマトリクスを採用しています。そのとき、「KICADの他のプロジェクトから回路をコピーする」のやり方でコピーすると便利でしょう。

パーツ選定

プリント基板設計に進むにあたって、パーツの選定をします。今回は基板製造を Elecrow へ依頼するつもりでしたので、Elecrowが在庫しているElecrow Parts Libraryや、部品の取り寄せができるDigi-Key Electronicsなどから部品を選定します。

パーツの選定は既存のキーボードで利用されている部品から選定するのがよいでしょう。ai03氏のリポジトリからUnified Daughterboard ProjectKBD8X MKIIOrbit などを参考にしています。USB-C のコネクタは TYPE-C-31-M-12 を採用します。この部品は、USB2.0にのみ対応したコネクターで、その分安価です。

それから、コンデンサや抵抗など一般的な部品は、Elecrowの方で代替品に差し替えてもいいかと確認されることがあります。そちらの方がコスト的にもメリットがあるので、それらのパーツについては仕様を示すくらいの気持ちで選定しています。

Component Package Footprint URL
Ceramic Capacitor, 22pF 0603 Capacitor_SMD:C_0603_1608Metric Elecrow Parts Library
Ceramic Capacitor, 1uF 0603 Capacitor_SMD:C_0603_1608Metric Elecrow Parts Library
Ceramic Capacitor, 0.1uF 0603 Capacitor_SMD:C_0603_1608Metric Elecrow Parts Library
Ceramic Capacitor, 10uF 0603 Capacitor_SMD:C_0603_1608Metric https://www.digikey.com/product-detail/en/murata-electronics/GRM188R61E106KA73D/490-18214-2-ND/9867922
Diode, Generic SOD-123 Diode_SMD:D_SOD-123 https://www.digikey.com/product-detail/en/micro-commercial-co/1N4148W-TP/1N4148WTPMSCT-ND/717311
TVS Diode, 5.5V SOT143B random-keyboard-parts:SOT143B https://www.digikey.com/product-detail/en/nexperia-usa-inc/PRTR5V0U2X215/1727-3884-1-ND/1589981
Polyfuse, 500mA hold, 1A trip 1206 Fuse:Fuse_1206_3216Metric https://www.digikey.com/product-detail/en/bel-fuse-inc/0ZCJ0050AF2E/507-1803-1-ND/4156312
Resistor, 5.1k 0805 Resistor_SMD:R_0805_2012Metric https://www.digikey.com/product-detail/en/panasonic-electronic-components/ERA-6AEB512V/P5-1KDACT-ND/1465964
Resistor, 22 0805 Resistor_SMD:R_0805_2012Metric https://www.digikey.com/product-detail/en/panasonic-electronic-components/ERA-6AHD220V/P123893CT-ND/9467822
Resistor, 10k 0805 Resistor_SMD:R_0805_2012Metric https://www.digikey.com/product-detail/en/panasonic-electronic-components/ERA-6AEB103V/P10KDACT-ND/1465971
Low Profile Tactile Switch 5.2x5.2mm  5.25.21.5mm random-keyboard-parts:SKQG-1155865 https://www.digikey.com/product-detail/en/c-k/RS-187R05A2-DS-MT-RT/CKN10361CT-ND/2747199
ATMEGA32U2 Microcontroller 32-TQFP 7x7mm Package_QFP:TQFP-32_7x7mm_P0.8mm https://www.digikey.com/product-detail/en/microchip-technology/ATMEGA32U2-AU/ATMEGA32U2-AU-ND/2187167
Crystal, 16MHz 3.2x2.5mm, 4 pad Type-C:HRO-TYPE-C-31-M-12-Assembly https://www.digikey.com/product-detail/en/CX3225SB16000D0GZJC1/1253-1698-1-ND/5995245/
HRO-TYPE-C-31-M-12 8.94x7.3mm Crystal:Crystal_SMD_3225-4Pin_3.2x2.5mm https://lcsc.com/product-detail/USB-Type-C_Korean-Hroparts-Elec-TYPE-C-31-M-12_C165948.html

プリント基板設計

回路が決まり、部品も決まりましたので、あとは PCB に配置していくだけです。配線をしているとパズルを解いているような気分になります。どのようにしたら効率的で美しい配線ができるのか、工夫の見せどころです。KiCad Pcbnew をつかって設計をしていくのですが、細かい操作方法についてはここでは説明しません。前述の「KiCadことはじめ」や「ai03's Keybaord PCB Designer Guide」を参照してください。

最初に ai03 - Keybaord Plate Generator をつかって、スイッチプレートを生成します。 Keyboard Layout Editor の Raw Data をコピーアンドペーストするだけでスイッチプレートを生成することができます。ファイルは DXF 形式でダウンロードできます。

次に、 KiCad Pcbnew にスイッチプレートファイルをインポートします。プレートにあわせてキースイッチのフットプリントを配置していきます。それから、その他の部品を配置します。USB 周辺や MCU 周辺から配線をしていくとよいでしょう。最後に、キーマトリクスをつくっておしまいです。このプロセスは、あまりキーボードに特有なことはありません。電源とGNDのパターンは太くする、水晶発振器はできるだけMCUに近いところに配置する、バイパスコンデンサは電源ピンの近くにする、USBは差動ペア配線なのでパターンを可能な限り平行に行なう、などに注意をして配線します。

f:id:takai_naoto:20200910181942p:plain

その他、ちょっとしたノウハウとなりますが、キー数が多いときにはスイッチ毎にダイオードを配置するのが面倒なときがあります。KiCad PcbnewはPythonでのスクリプティングが可能ですから、次のようなスクリプトをつくって配置しています。定数を変更してつかってみてください。

import pcbnew

START    = 1
STOP     = 42

X_OFFSET = 5937250
Y_OFFSET = 4857750
ORIENTATION = 90 * 10

board = pcbnew.GetBoard()

for i in xrange(START, STOP + 1):
    mx = board.FindModuleByReference("MX%d" % i)
    mx_pos = mx.GetPosition()

    new_pos = pcbnew.wxPoint(mx_pos.x + X_OFFSET, mx_pos. y + Y_OFFSET)

    diode = board.FindModuleByReference("D%d" % i)
    diode.SetPosition(new_pos)
    diode.SetOrientation(ORIENTATION)

    print("D%d moves to (%d, %d)" %(i, new_pos.x, new_pos.y))

pcbnew.Refresh()

キーボードケース設計

設計

次にサンドイッチマウントのケースをつくっていきます。サンドイッチマウントとは、PCBをスイッチプレートとボトムケースで挟み込むような構造です。キーボードのマウント方式については「Cheat sheet: Custom keyboard mounting styles 」がよくまとまっています。

今回は、サンドイッチマウント構造でもPCBを2枚のプレートによって挟み込む、よりシンプルな構造です。当初、プレートにはアクリルを採用しようと考えていたのですが、ご時世によりアクリルが品薄になっていたため、プリント基板(FR4)で製作することにしました。

ケースの設計は Autodesk Fusion 360 をつかいます。 Fusion 360 の基本的な操作については「Fusion 360 で簡単なケースを作る(初心者向け) - Self-Made Keyboards in Japan」などを参照してください。また、公式サイトの 入門セミナー も参考になるでしょう。

まず、スイッチプレートのDXFファイルを読み込み、プレートを支えるための M2 スペーサーのスペースをつくります。廣杉計器 M2 スペーサー の直径は 4mm ですので、キースイッチと干渉しないようにします。

f:id:takai_naoto:20200910182015p:plain

それから、「押し出し」て、 M2 ねじを通すために 2.2mm くらいで「穴」を作成し、「フィレット」で角を丸めます。できた面にスケッチを作成して、それを DXF としてエクスポートすればスイッチプレートの完成です。ボトムプレートも同じような構造ですので、コピーをして履歴を編集すれば簡単に作成することができます。

f:id:takai_naoto:20200910182038p:plain

検証(アセンブリ)

PCB とケース用のプレートの設計が完成したので、実際に組み立てて問題が起こらないか確認してみましょう。KiCad では基板の3Dデータを STEP ファイルを出力することができます。これを Fusion 360 に取り込み、先程つくったプレートファイルと組み合わせます。

スイッチプレートとPCBの間隔は 3.4 mmです。これは、Cheryr MX シリーズのデーターシート を確認するとボトムハウジングの高さは 5 mm ですので、ここからプレートの厚みである 1.6 mmを引いた数字です。ボトムプレートとPCBの間隔は、PCBに実装されている USB-C コネクターの高さが 3.21 mmですから、それ以上あればよさそうです。 9 mm のスペーサーを利用することを考えて 4mm にします。

完成したら、部品の干渉など問題が発生していないことを確認します。

f:id:takai_naoto:20200910182057p:plain

製造

キーボード基板

基板の製造と電子部品の実装は Elecrow に発注します。 Elecrow は深圳にある工場で、品質と価格のバランスが良いことから、製品の製造のときにはいつも利用しています。発注にあたっては、 KiCad でガーバーフォーマットのデータを作成します。オプションを次の画像のように選択します。さらに、ドリルファイルも作成します。

f:id:takai_naoto:20200910182121p:plain f:id:takai_naoto:20200910182144p:plain

さらに、 Elecrow では生成されたファイルの拡張子を変更する必要があります。この作業は面倒で間違いやすい作業ですので、私はちょっとしたスクリプトを利用して拡張子の変更を行なっています。拡張子を変更したら、ガーバーデータをZip形式でアーカイブします。

#!/bin/bash

PROJECT=$1
OUTPUT=elecrow

mkdir "$OUTPUT"

cp "$PROJECT"-F_Cu.gtl      "$OUTPUT"/"$PROJECT".GTL
cp "$PROJECT"-B_Cu.gbl      "$OUTPUT"/"$PROJECT".GBL
cp "$PROJECT"-F_SilkS.gto   "$OUTPUT"/"$PROJECT".GTO
cp "$PROJECT"-B_SilkS.gbo   "$OUTPUT"/"$PROJECT".GBO
cp "$PROJECT"-F_Mask.gts    "$OUTPUT"/"$PROJECT".GTS
cp "$PROJECT"-B_Mask.gbs    "$OUTPUT"/"$PROJECT".GBS
cp "$PROJECT"-Edge_Cuts.gm1 "$OUTPUT"/"$PROJECT".GML
cp "$PROJECT"-PTH.drl       "$OUTPUT"/"$PROJECT"-PTH.TXT
cp "$PROJECT"-NPTH.drl      "$OUTPUT"/"$PROJECT"-NPTH.TXT

次に Excel で発注書をつくります。 Elecrow でも 発注テンプレート を用意していますし、実際に発注するときに利用したファイルもリポジトリに入れておきますので、参考にしてください。

Zip形式でアーカイブしたガーバーファイル、Excelの発注書を添付して service@elecrow.com へメールで発注をします。このとき、配送方法についても指定をするとよいでしょう。英語については自信がないのですが、下記のような文面でいつも送っています。

To whom it may concern,

I'd like to order PCBA service. Could you give me a quotation for attached files? The shipping address is as follows. I would prefer OCS as a shipping method.

XXXXX XX-XX-XX, XXXX, Tokyo XXX-XXX, Japan

Best Regards,

ほどなく担当者から見積が来るので、内容に問題がなければ PayPal で支払いをします。製造には、だいたい1ヶ月くらいかかるようです。製造のプロセスで何か問題が見付かれば、それも連絡してくれます。私は、ガーバーファイルでのフットプリントと部品のパッケージが一致しないミスをよくします。

キーボードケース

今回は FR4 、つまり PCB でプレートをつくるので、 KiCad でデータを作成します。 DXF ファイルをインポートするときにグラフィックレイヤーで Edge.Cuts 指定すれば、外形情報として取り込むことができますので、そのデータをもとにガーバーフォーマットのデータを書き出します。

発注は Elecrowのフォーム から行ないます。プレートの厚さはデータシート上で 1.5mm なので、PCBではその厚さに近い 1.6mm を選択します。こちらは1週間ほどで届きます。

アクリルプレートを発注するときは、レーザー加工サービスによって指定のテンプレートがありますので、そのフォーマットに従って発注をします。個人的な利用であれば工房Emerge+のレーザー加工サービスを利用することが多いです。Illustrator形式ファイルのテンプレートにDXFファイルを取り込み、データを作成します。アクリルは 2mm のものを選びます。フォームから見積を依頼したうえで支払いをすると、こちらも1週間ほどで届きいます。

ファームウェア開発

ハードウェアができたらファームウェアをつくっていきましょう。今回は最低限キーボードとして動作するための実装を目指し、 QMK Firmeware や VIA のリポジトリに取り込んでもらうことを考えないようにします。

QMK Firmware

ファームウェアはフリーソフトウェアとして開発されている QMK Firmware を利用します。QMK Firmware の開発は、事前にセットアップが必要です。公式ドキュメントの「Setting Up Your QMK Environment」を読み、セットアップをしてください。

QMK Firmware のトップディレクトリで util/new_keyboard.sh を実行すると、 keyboards ディレクトリ以下にテンプレートができますので、そのファイルを編集していきます。Cookpad Pad 2 の差分 を例にとりながら、編集する部分を見ていきましょう。

config.h:23-28 ではUSBのベンダーID、プロダクトIDを定数として定義します。USBのベンダーID、プロダクトIDについては衝突しないことが求められていますが、テスト目的のIDなどは定義されていません。なので、「いい感じにする」必要があります。詳しくは「 USBのベンダーIDとプロダクトIDの話 」などを参照してください。

#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x9009
#define DEVICE_VER 0x0002
#define MANUFACTURER Cookpad Inc.
#define PRODUCT Cookpad Pad
#define DESCRIPTION A six keys macro pad made by Cookpad.

config.h:31-45 では、キーマトリクスの定義を行ないます。Cookapd Pad は 2行 × 3列 のマトリクスですので、そのように定義をします。さらに回路図を確認し、ピンとの対応も定義します。

#define MATRIX_ROWS 2
#define MATRIX_COLS 3

...

#define MATRIX_ROW_PINS { C6, C7 }
#define MATRIX_COL_PINS { B7, B6, B5 }

Cookpad Pad 2 は MCU として ATmega32u2 を利用していますので rules.mk:2 の部分も変更します。 ATmega32u4 であれば変更は必要ありません。

MCU = atmega32u2

cookpad_pad.h:29-36 はキーボードの物理配列の定義です。キーボードによっては、行と列の二次元配列として定義されているキーマトリクスの全てが入力可能というわけではありません。そこで、キーボードの物理配列とキーマトリクスを対応させるためのマクロを定義します。

#define LAYOUT( \
    K00, K01, K02, \
    K10, K11, K12  \
) \
{ \
    { K00, K01, K02 }, \
    { K10, K11, K12 }  \
}

keymaps/default/keymap.c:18-23 で、キーボードの論理配列のデフォルト値を定義します。キーコードについては「Full List」を参照してください。

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [0] = LAYOUT(
        KC_C, KC_O, KC_K,
        KC_P, KC_A, KC_D
    )
};

変更が完了したらビルドが通るかどうかを確認してください。ファームウェアを書き込むには工場出荷時に書き込まれているブートローダのDFU機能をつかって、USB経由で書き込みをします。

$ make cookpad_pad:default
$ make cookpad_pad:default:dfu

VIA

VIA は QMK を前提につくられたキー設定ツールです。それまで、 QMK Firmware でキーレイアウトを変更するためには、プログラムを修正してコンパイルする必要がありました。 VIA を使うと、 GUI でコンパイルなしにキーマップを変更することができます。

f:id:takai_naoto:20200910182237p:plain

キーボードを VIA に対応させるためには QMK Firmware で VIA に対応したキーマップを作成する必要あります。対応する方法については公式サイトの「Configuring QMK」や「(設計者向け)VIA対応のファームウェアを作ろう」などを参照してください。

Cookpad Pad 2 でいうとkeymaps/via/rules.mk が VIA 対応となります。主だったものは VIA_ENABLE だけです。その他は、 VIA では対応していない機能を無効にしたり、ファームウェアのサイズを減らすためのオプションとなります。

VIA_ENABLE = yes
LINK_TIME_OPTIMIZATION_ENABLE = yes
EXTRAKEY_ENABLE = no
MOUSEKEY_ENABLE = no
CONSOLE_ENABLE = no
MIDI_ENABLE = no

それから、 VIA でつかう cookpad_pad.json も用意します。便宜上、 QMK のリポジトリに含めていますが、このファイルを含んだままプルリクエストを送ると、余分なファイルがあるとレビューで指摘されるので注意してください。

{
    "name": "Cookpa Pad",
    "vendorId": "0xFEED",
    "productId": "0x9009",
    "lighting": "none",
    "matrix": { "rows": 2, "cols": 3 },
    "layouts": {
        "keymap": [
            ["0,0","0,1","0,2"],
            ["1,0","1,1","1,2"]
        ]
    }
}

まとめ

本記事では Cookpad Pad 2 を事例として、キーボードの基板設計からケース設計、製造、ファームウェア開発について簡単に解説をしてきました。実際のところ、まだまだ細かな解説をする部分はありますが、大まかな流れについては理解いただけたのではないでしょうか。

Cookpad Pad 2 は オープンハードウェアとして公開 していますので、このプロジェクトを改変して新しいキーボードをつくってみることにチャレンジしてみてください。