500 Can't connect to lowreal.net:443 (certificate verify failed)

まず思いつく現状の不満とかを考えて、それを盛りこんで作ろう、という方針を決めた。つまり

  • 左右分割にしたいなあ
  • UNIX 配列準拠がいいなあ
  • Bluetooth がいいなあ

あたりが最初の方針になる。


できるだけ MacBook 標準のキーボードでも十分開発できるぐらいの状態を保ちたいので、奇抜なキー配置のものは例え身体に良くても精神に悪いので使いたくない。

市販品で近いものを探すと、Kinesis freestyle2 あたりがイメージに近い。これをキーリマッパでカスタマイズすれば実用的にはいいかもなとは思った。

 -

3.0 / 5.0

あと、普通の(普通ってなんだ?)左右分割キーボードの内側のキーにも不満がある。左右分離の場合、タッチタイピングで左手に所属するキーを右手では決して打てなくなる。

しかしゆるふわタッチタイパー的には、中央付近のキーは右手でも左手でも打ちたい。つまりキーをオーバーラップさせたいが、そんなキーボードはこの世に存在していない。僕は「タッチタイピングの矯正」とか別にしたくなくて、ゆるふわでいきたい。

ErgoDox の設計の分析

まずErgoDox はキー数が少なくて UNIX 準拠にはできない。キー配列の画像を見ればわかると思うが、右側にキーが足りない。例えば HHKB なら P の右には [ と ] と DELETE があり3つのキーが続くが、ErgoDox だと1つしかキーがないので無理。ソフトウェア的になんとかするしかない。

なお ErgoDox は設計段階で左右の基板が共通となっている。両面基板をリバーシブルに使うことで両手に対応させている。これにより基板の製造コストはかなり減る (特に小ロットで外注する場合は半額にできる)。ただし、設計には左右対象であるという制約がつく。

一般的なキーボードは右手担当のキーが多く、左右非対称になっている。左右対象という制約をつけると、一般的なキーボードからかなり離れることになる。これはエルゴノミクス的には正しい気はするがよくわからない。ただ、キーが少ないのは現実的に不便だと思う。

余談だけど、右側のキーが多いことも考えると世の中のキーボードは右利き用ではないかと思った。左利きはキーボードにおいても不利を強いられていないだろうか? (僕は右利きなのでそんなこと思いもよらなかったんだけど)

仕様

そういったことを踏まえて自作するキーボードの以下のように仕様とした。

キー配列の仕様

  • UNIX キーボードを2分割した形を基本にする。つまり HHKB とほぼ同じで、Ctrl キーはAの左、ESC は 1 の左など。
  • 矢印キーはどうしても欲しい (HHKB への大きな不満のひとつ)
  • F1〜F12キーもできれば欲しい (HHKBへの小さな不満のひとつ)
  • 中央のキーを1列分オーバーラップさせる
レイアウトの詳細


HHKB からの変更点

  • スペースキーが2分割に
  • F1〜F6, F7〜F12 キーの新設
  • 矢印キーの新設

まず「ぼくのかんがえたさいきょうのキーボードはいれつ」を Inkscape で書いてレイアウトを検証した。軽く書くというよりは CAD 的にちゃんと書いた。のちのち Inkscape からエクスポートして KiCAD で読みたかったため。

備考

  • 僕は右手のスペースキーをほぼ全く使わないので、実質飾りである。
  • Caps Lock キー? そんなものはない。写真にある Caps Lock は Shift キー(キーが足りなかったので)
  • 矢印キーを置くところがなくて右手親指付近に置いている (が、これはちょっと邪魔だった。あと1キー分左にずれていたほうがいい…)

技術仕様

同時に、いくつかこうしたいという仕様も決めた

  • NiMH 単3バッテリー2本で半年ぐらい持つ (普通の製品ぐらい持つこと)
  • 左右ボード間の接続は有線
  • USB に逃げたくなったとき逃げられるようにしておく
    • 制御用のボードは分離して設計すること

一方、躯体については殆ど考えてなくて、いきあたりばったりで基板を作ってから3層構造にした。製作編で詳しく書く。

なお省電力であればあるほどいいけど、そこそこ電波が出るデバイスなので、BLE が生きるぐらいの省電力にはならないだろうという気はしてた。

左右のキーボード間も無線にしたかったが、セキュアにしようと思うと BLE Nano 2台でそれぞれHIDキーボードにしてしまうのが楽ということになってしまう。今回はそういうことはしたくなかったので、ここは有線で妥協した。

ただ、左右どちらも回路構成が完全に一緒なので、単に制御用の基板を2つ用意して取り付ければそれぞれHIDキーボードとして使うことができるようにはした。

つづく → 500 Can't connect to lowreal.net:443 (certificate verify failed)

  1. トップ
  2. tech
  3. 自作キーボードの製作 — コンセンプトとキーレイアウトおよび技術仕様編

ErgoDox ではないナニか。オープンソースかつ Bluetooth 接続のキーボード | tech - 氾濫原

回路設計

仕様とともに回路の設計もしはじめた。単にスイッチがいっぱいついてるだけなので、回路的には難しいところは一切ないといってもよい。問題はPCとのインターフェイス部分になる。

キースイッチ

キースイッチは Cherry MX 系がいいなと思った結果 Gateron (Cherry MX 互換) にした。

  • 安い
  • 品質もそれほど悪くはない (というか ErgoDox Lite に採用されてる)
  • 入手性が良い (いろんな色が ebay 経由で買える状態だった)

あたりで決定した。

BLE Nano

Bluetooth 接続したいので、技適を通っている Bluetooth モジュールを考える。ちょうど BLE Nano という製品が技適を通っていて mbed 対応だったため、これをメインMCUとして使用することとした。 mbed で公式にサポートされているUSBボードと比べて圧倒的に小さく、ライターとともに購入してもなお安いというのもあった。ただし BLE Nano は名前の通り Blueooth LE (4.0) のモジュールなので、多少の不安はあった。

I2C GPIO MCP23017

キーマトリクスのために I2C GPIO IC を使うことにした。これはMCP23017という Microchip 社のものとした。BLE Nano の GPIO は少ないので、左右で1つずつの MCP23017 を使い、この2つを同一の I2C バスに接続する。MCP23017は3bit分スレーブアドレスを変えられるようになっているので、2つのアドレスをわける。ちなみに ErgoDox にも MCP23018 というほぼ同じものが使われている。MCP23017 は秋月で取り扱いがある。

消費電力削減のためハード設計の段階で MCP23017 の割込み生成を使うこととした。MCP23017 側でピン変更を検知した場合 INT ピンを通じて BLE Nano 側に割込みを発生させる。MCP23017 は2つ使うが、割込み生成は1つで良いので、割込みピンを BLE Nano 側でプルアップし、2つのMCP23017はオープンドレインで割込みを生成するように設定する。

割り込みを使わない場合、常時I2Cで通信してキーの状態を調べなければならないが、割り込みを使えば何も変化がないときにはデバイス全体をほぼ完全にスリープさせることができる。BLEによる無線接続は必然的にバッテリ駆動となるので、これは必要だと思った。

左右キーボード間の接続コネクタ

左右分割キーボード間の接続は

  • SCL
  • SCK
  • VDD
  • GND
  • INT

と5ピン必要になった。しかし

  • 5ピン以上
  • 小型・
  • 対称・
  • ケーブルの入手性が良い

あたりを満たすコネクタというのが壊滅的に存在しない。4ピンであれば ErgoDox と同様にTRRSコネクタ(4端子ミニプラグ)が使えるが、INT ピンを入れて5ピンにするのは譲れない仕様なため困難が生じた。VDD を INT と併用するという考えも浮かんだが、キー割込みはI2C経由で読むまで解除されないので厳しいと思った。

結局のところはLANコネクタ(8P8C・RJ45)とした。USB Type-C コネクタがナウいので、可能なら使いたいと思ったが、現状では入手性が悪く、ケーブルも高価なのでやめた。LANコネクタは比較的大きいということ以外は要件を満たしている。ケーブルも安いので優秀なコネクタだと思う。

回路図やボードレイアウトの作成

Eagle だとフリー版にはボードサイズに制限があってキーボードぐらいの大きさのものは作れないので、いよいよ KiCAD に移行することとした。なので KiCAD の使いかたレベルから学習する必要があった。これについては別途エントリを書いてきた。

最初とても辛かったが、なんとか慣れてきた。いままで Eagle でやっていたことをすべて KiCAD で可能にするためにかなりヤックシェイビング的なことをした。特にPCB Millingまわりの環境再構築が大変だった。

最終的には pcb2gcode にパッチ送ったりしてなんとかなる環境をつくった。

回路図



Root.sch / Main.sch / KeyModule-L.sch / KeyModule-R.sch となっている。これはKiCAD で複数ボードプロジェクトを運用する
に詳細を書いた。

左・右のそれぞれのキーマトリクスは BLE によるファームウェアの部分と独立させたかった (つまりBLEではなくUSB接続とした場合でも基板自体の変更がいらないようにしたかった) のでメインの制御基板を別にしてある。

ボードレイアウト



Inkscape から左と右にわけてレイアウトを DXF ファイルを出力し、pcbnew にインポートした。キーの配置はこの状態から DXF のガイドにあわせて手動で移動させて行なった。

レイアウトの仕様は以下のようにした

  • PCB Milling 前提
    • 少しでも作りやすくするため、デザインルールで最小幅を0.3mmに
  • 基本1層基板 (裏面配線のみ)
  • ジャンパ部分は極力わかりやすくする

結構大きな基板になるので格安PCBサービスでも結構高額になってしまう。なので手元でできる PCB Milling (CNCフライスによる基板切削)でやることにした。

しかしこの制約はかなり厳しくて、なかなかレイアウトが決まらなかった。両面にすればよかったが、基板作成の手順が倍以上になるのでそうしなかった。

試行錯誤してオートルートさせてなんとかした。ジャンパなしはできなかったので、ある程度ジャンパを許容してオートルートさせてから、自力でジャンパしやすいように、直線にしたり100mil単位になるようにとかと修正を加えた。

基板の製作



左側

まず先に左だけ作って様子を見ることにした。左側だけでもブレッドボードに組んだ制御基板と配線すれば使うことができるため、出来を確かめることができる。

余談だけど、既存キーボードと併用して Karabiner を使えば実際に左右分割で使えるはず、と思ったが、どうもそれができなかった。修飾キーの共有が BLE キーボードだとうまくいかないみたいだった。Karabiner からもキーボードデバイスとして認識されず謎。これは未だ謎。入力はできてるけどキーボードデバイスとして認識されてない。


それはともかく、使ってみると結構基板がたわんでしまうことがわかったので、下側のプレートにナットだけを増やして力を受けるようにした。キースイッチの実装面には隙間がほとんどないので、裏側から短いビスでナットを止めて隙間を埋めて力をうける構造になっている。


最終的な構造をいまいち考えれてなかったが、結局3層を単純に重ねる形とした。つまり、化粧板・基板・裏板を15mmのビスで共締めしている。

化粧板は特に強度が必要ないので1mm、裏板には多少強度がいるので2mmとした。結果として以下のような層になった。

  • 化粧板 1mm
  • ナット 5mm
  • 基板 1.6mm
  • ナット 3mm
  • 裏板 2mm
  • ナット3mm

できるだけ薄くて机にキーが近いほうがいいけど、このぐらいが限界だった。

化粧板と裏板の切り出し

いずれも外形カットと穴開けが必要だったため、基板と同様にCNCフライスで切り出している。

この際、CAD は KiCAD の pcbnew をそのまま流用した。KiCAD のユーザー定義レイヤーが2層あるので、ここに切削ラインを書いて、ガーバーに書き出し、外形レイヤー扱いで pcb2gcode で gcode 化した。

ただし、pcb2gcode は現時点では「外形カット」しかできないので、内側に書いたラインも外側を削る挙動になってしまう。pcb2gcode 側に対応をいれたかったが面倒なので、図面の段階でエンドミル径分を考慮して線をひいた。

右側

左側を作った結果をうけていろいろ改良を加えて右側を作った。

以下らへんを改良

  • 角丸に
  • 固定用のビス穴を大幅に増やした

やっぱ角丸にしないとこういうのはきついよなと思った。左側はあとからリューターで削って角丸にしたけど、右側は切削時点で角丸になるように外形を描きなおした。

固定用の穴は多めにあったほうが圧倒的にしっかりするのでケチらないで開けたほうが良い。実際、右側は左側と比べてかなりしっかりした構造にできた。

なお右側は左側に比べてキーの数がかなり多く、基板のサイズもぎりぎりになっている。配線もこちらのほうが大変。基板の原点をちょっと適当に設定しまって、基板は上側が実は足りてない(配線的には問題なし)

作ってみて

これで左右が揃ったので、ファームウェアのクオリティはともかく、ちゃんと打てるようになった。

基本的に HHKB と完全に一緒のキー配置なので、ほとんど違和感なく使える。ただ、物理カールキーをつけたのに関わらず、HHKB のカーソルキー移動に思ったよりも慣れていることが発覚した。Fn キー相当の位置に未割当キーはあるので、ファームウェアで対応した。

カーソルキーを制限のあるなか、なんとか配置したのはよかったが、思ったよりも右手の親指と干渉してしまった。あと1キー分左にあったほうが良いかもしれないけど、ぎりぎりすぎる。右のスペースキーは僕は使うことが全くなくて飾りなので、そこに別のキーを配置してもいいかもしれない。

なお自作する場合、CNCフライスの加工限界によって基板のサイズに制限があり、左右分割でないとそもそも作るのが難しいというのを感じた。

あと細くて短いLANケーブルがなかなかなくて難儀する。多少長くても細いほうが取り回しはよさそう。あんまり長いケーブルだとI2Cのドライブ範囲を超えるのでバグりやすくなる。

つづく → 自作キーボードの製作 — ファームウェアの実装編 | tech - 氾濫原

  1. トップ
  2. tech
  3. 自作キーボードの製作 — 回路設計とアートワーク・ハードの製作編

500 Can't connect to lowreal.net:443 (certificate verify failed)

とにかくこれが一番大変だった。BLE + mbed + HID キーボードでちゃんと動くもののサンプルっていうのが見つからないので、そこそこ動くサンプルから頑張らないといけない。

ほとんど作り終わってから気付いたけど先に言っておくと、mbed のオンラインコンパイラ環境で BLE Nano の開発をするのは筋が悪い。RedBear も Keil 使って Nordic SDK 直接使って開発しろみたいなことを言ってる。ただ、今回はどうしても、キーカスタマイズとかのために開発環境をゴリゴリ用意するというのが嫌だったので、オンラインコンパイラに拘った。

依存と罠

まず、現状の mbed ライブラリと nRF のSDK のどちらにもあるヘッダファイルが競合していて、まともにコンパイルできなかった。mbed を依存からはずして、mbed-dev をインポートして、該当するヘッダファイルをリネームして対応した。しょっぱなからひどい目にあった。

BLE_HID というライブラリもあって「お、これいいじゃん」という感じだけど、500 Can't connect to lowreal.net:443 (certificate verify failed) にある通り、さっぱりペアリングできなくてハマった。

BLE_HID は結局中の構造をいじることが多かったので、プロジェクト内にファイルをコピーして依存から消している (競合するので)。

セキュリティまわり

これまたハマりまくるポイントで困る。上記のようにそもそもペアリングできないというのもあったし、普通に使えるレベルとするにはペアリング情報を覚えてて自動再接続してほしいところだけど、どうやるかさっぱりわからなかった。

結論からいうとセキュリティまわりの処理が終わったら該当デバイスをホワイトリストに入れれば良い。しかし BLE_API のホワイトリストまわり、experimental 扱いになっていて不穏な空気を感じる。

BLE と OS X

まず、よくわからないけど OS X が BLE キーボードをキーボードとしてちゃんと認識しない (具体的にはアイコンが汎用デバイス扱いになるし、バッテリーステータスもちゃんと表示されない。ちゃんと GATT で提供してるのに……)

ただ、ペアリングするとちゃんと入力できるので対応されてないわけではない。

あと、Bluetooth の環境設定が頻繁に固まる。ジョブズが生きていればこんなことには……

Apple Magic Keyboard (US配列) MLA22LL/A - アップル

アップル

2.0 / 5.0

Apple Magic Keyboard (Wireless Keyboard ではなく) は BLE 接続らしいけど、どうなってるのかよくわからない。DeviceInformationService で PnP ID を偽称してみたりしてみたけど、うまく認識しなかった。このキーボード、思いのほか高価なので試しに買ってみて調べるみたいなこともできずモヤモヤした。

BLE と Windows

Windows とのペアリングは非常にスムーズで問題がなかった。ちゃんとキーボードとして認識されるし、OS X よりマトモ。ただ Windows でもバッテリーステータスを確認する方法がわからなかった。

BLE と Android

さすがにスマフォは BLE の対応がしっかりしていて、まともにペアリングできるし、ちゃんと使える。

nRF Connect で GATT 情報を見ると OS X 上で LightBlue を使って見るよりも多くの情報を得られる。BLE に関してはスマフォも活用してデバッグしたほうが捗る。

特にハマったところ

別途エントリに起こしたけど、ここらへんでそれぞれハマってる。

あとエントリに起こしていないけど、とにかくメモリが足りなくて苦労する。現状の BLE Nano (v1.5) は 32kb RAM があるのだけど、mbed がサポートしておらず、16kb しか使えない。そして SoftDevice とかの使用を除いて 6kb ぐらいしかアプリケーションが使えるメモリ量がない。この中で抽象化された mbed の BLE_API を使うと本当にすぐにメモリが枯渇する。

メモリが枯渇してもハードフォルトでランダムに stuck したりする感じなので、おそろしく原因究明が難しい。ヒープが上書きされても致命的でなければ動き続けるわけだし、ヒープの正確な使用容量を知るよしはないし、SoftDevice の割込みのために一定量のスタックメモリも残しておかなければならないしで、とにかくつらい。32kb になれば余裕になるので、さっさと 32kb 対応してほしい。

現状のメモリ量だと、たとえばマウスをサービスしたいと思っても不可能だと思う。

消費電力の削減


最初にやったのはこれだった。製品に近いぐらいにはしたいという気持ちがあったのと、消費電力削減はテスターで見てすぐ効果が数値でわかるので好きというのもある。

別途エントリにした 16MHz HFCLK をオフにするというのが一番支配的だったけど、他にも細かいところに気をつかったつもりではある。

必要ないペリフェラルはできるだけ止めているつもり。UART だけデバッグの都合でスリープに入る前後のタイミングで止めてからスリープに入って起きたら再開するというコードになっている。ただし、UART も RX は一切行わないので止めている。

また、無接続ピンもプルアップして中途半端な状態にならないようにしている。中途半端な電位になると、他のところとの電位差で無駄に電流が流れたりするので気をつける必要がある。これは直接レジスタをいじっていて、mbed の DigitalIn とかは使ってない。メモリ節約のため。

キー入力間でチャタリング防止のつもりで5msのインターバルをいれているけど、これも安易に wait_us(5000) とかにせず、Timeout による割込みをしかけて waitForEvent して寝るという実装にしてある。CPU をスリープさせない限り消費電力は減らないので、起きている時間をとにかく短くしたい。

起きている時間をとにかく短く、という視点で、I2C の速度を 250khz に上げてある。100khz よりも2.5倍早いので、I2Cで消費する電力は半減ぐらいになる。ただ、電源電圧が低いので速度をあげると安定性が失われる。オシロで波形を見ると結構なまっている。

BLE のコネクションパラメータで一番効果が高いのは slave latency だった。このパラメータは、ホストからのリクエストを一定個数無視するというもので、スリープ中の消費電力を結構減らせる。

一方、空中線電力は下げてもそれほど効果がなかった。コンスタントに消費はあるが、極めて短時間なので平均的には支配率が低いように感じた。

安定性改善

前述したが特定の変数を宣言するだけで stuck するみたいな挙動で原因がわからずとても苦労した。結局メモリ不足でヒープが上書きくらってたみたいだけど、そんなに使ってるつもりないのに死ぬのでなかなかメモリ量が問題と思いあたらなかった。

また MIC エラーもとにかくハマっていた。メモリ使いすぎの件があったので、これもそういう系なのだと思って原因をさがしていたが、そうではなかった。500 Can't connect to lowreal.net:443 (certificate verify failed)

レイヤー

めんどくさくて最初は実装してなかったけど、思いのほかHHKB式のカーソルキーにも慣れていることがわかって、仕方なしに実装した。

レイヤーの部分はいちいち実機デバッグするのが面倒だったので、ユニットテストを雑に書いてある。

バッテリーレベルを mV で見れるようにする

カスタムUUIDを定義して、mV 単位のバッテリーレベルもとれるようにした。カスタムUUIDやってみたかったのと、やっぱ % 単位で見れても実際どうなのか不安なので……

まとめ

まだちょろちょろいじってはいるけど、ほぼ安定した。「もうこれ安定しないんじゃないか」「USB接続に方針を変えたほうがいいんじゃないか」と思うこともあったが、なんとかなったと思う。

  1. トップ
  2. tech
  3. 自作キーボードの製作 — ファームウェアの実装編

ポリスチレンはカッターで切れるのと、プラモデル用の接着剤が使えるのが良い点だなあ。

ASUS ZenFone 2 の Android M (6.0) アップグレードは遅延 | tech - 氾濫原

遅延していた OS アップデートですがようやくきました。8月31日付けで配信開始したようです。リリースノート

ただし WW のみ。JP はいつ……

  1. トップ
  2. tech
  3. ZenFone2 にようやく Android M (Mashmallow) アップデートが降ってきた

ほかにもやりたいことがあるのだが、ここ数ヶ月やってることがなかなか「これでよし」とならなくて、とりかかれない。ぶっちゃけそろそろ飽きてきたのでさっさと日記に書きだして一旦おわりにしたい。

ここ数ヶ月ぐらいキーボードを作っていた。そのためにいろいろ yak-shaving としかいいようがないことも多々していた。

いろいろ書くことが多いので、細かい設計などについては別途エントリを分ける。

  • コンセンプトとキーレイアウトおよび技術仕様の決定
  • 回路設計とアートワーク・実際の製作
  • ファームウェアの実装

あたりをそれぞれ別途詳細なエントリを書く。だいたいの人は細かいことはどうでもいいと思うので、概要のみこのエントリにまとめる。

コンセプトや特長

UNIX ベースのキーレイアウト (というかHHKBをベース) とし、違和感なしに分割キーボードとする。

キー配列

  • UNIX キーボードを2分割した形を基本にする。つまり HHKB とほぼ同じで、Ctrl キーはAの左、ESC は 1 の左など。
  • 矢印キーはどうしても欲しい (HHKB への大きな不満のひとつ)
  • F1〜F12キーもできれば欲しい (HHKBへの小さな不満のひとつ)
  • 中央のキーを1列分オーバーラップさせる (ゆるふわタッチタイピングに必要)

特長

  • Bluetooth 4.0 (Bluetooth LE) HID over GATT 接続。Windows と OS X で接続可能
  • Bluetooth 経由によるファームウェアアップデート
  • mbed オンラインコンパイラによるファームウェア開発環境
  • 全てオープンソース (MIT)
  • 1900mAh の NiMH 充電池で約6ヶ月のバッテリーライフ
    • キー入力時 3.3mA、非アクティブ時10uA〜100uA(OSの挙動による)

FOTA/DFU (Firmware On The Air / Device Firmware Update) かつオンラインコンパイラによりキーカスタマイズのために環境構築が不必要。あるいは MK20 による書きこみなので、3ピンの配線でUSBからマスストレージクラス経由で書きこみ可能。

技術的な仕様

UNIX配列のBluetoothキーボードというのが希少で前々から欲しいと思っていたので、接続インターフェイスは Bluetooth としてみた。

インターフェイスとして RedBear BLE Nano というのを使うことにした。国内技適にも通っており結構安い。mbed が開発環境に使える。名前の通り BLE (Bluetooth 4.0) 接続になる。ただ、なんというか、この選択(無線化)は割と悪夢の始まりだった。

回路設計


BLE Nano はピン数が少ないため、I2C GPIO 拡張の MCP23017 を2つ使っている。消費電力削減のため GPIO の割込みを活用している。キーの部分は単にキーマトリクスなので特におもしろいところはない。

ステータスLEDを1つだけつけている。これはペアリングステータスを示すため。キーボードにLEDあっても見ることないし消費電力の無駄なのでほとんど消灯させておく。

基板設計

KiCAD のプロジェクトは github に置いてあります。https://github.com/cho45/Keble

PCB Milling (CNCフライスによる基板切削) でやることを前提としたので、片面基板+最低限のジャンパで構成した。

複雑ではないが配線数は多いので、片面という制約をつけると結構厳しい。がオートルータでなんとかなった。製作しやすくするため、デザインルールで最小幅を0.3mmとした。

製作

とりあえず左を作ってファームウェアと共に実装を検証し、それから右側を作った。そのため、右に比べると左側のクオリティが明らかに低い。

設計がちゃんとできている前提で、無心ではんだ付けをするだけ。振動とたわみの負荷がSMDにかかるのがなんとなく嫌で全てリード部品としたため、特に難しいところはない。

基板以外に、バックプレート(2mm)とフロントプレート(1mm)をさらにプラ版から切り出している。なので、3層構造になっている。側面はない。

ファームウェアの実装

mbed レポジトリ

mercurial:

hg clone https://developer.mbed.org/users/cho45/code/keyboard/

前述の通りだけど、今回は mbed のオンラインコンパイラで全て実装した。BLE Nano + mbed でセキュアペアリングして HID デバイスとして動かす例なんてのは例がさっぱりなくて大変苦労した。

HID キーボードとして簡単に動かすぐらいまでは、既にやってる人がいるので難しくない。しかし、実用キーボードとして安定して動かすようにするまでがかなり辛かった。

70%ぐらいの完成度まではすぐできるけど、そこから90%ぐらいまで完成度を上げるには大変な労力がいる。ハマったポイントが蓄積されていて、使えるぐらいに安定して動くコードがある状態にできたので、まぁ良かった…… ハードウェアよりもファームウェアの実装の知見のほうが遥かに価値があると思う……

基本的に mbed 環境でがんばるってのが筋が悪いのだけど、なんとなくオンラインコンパイラにこだわって意固地になって苦労している感じ。

現状の実装クオリティ

主観的には90%といったところと思ってる。温度感としては「ブログ書くぐらいなら全く問題がなく、仕事で使うのにもまぁまぁ使える」ぐらい。

仕事で1日使ったところ、数回再接続(約5〜10秒ぐらい)が必要になったのと、1度完全に刺さった(WDTで復帰せず、リセットで復帰)。0dBmで送信しているので、普通の距離なら物理要因で接続が切れることはないと思うので、他の再接続もファームウェアのバグだと思うが原因不明。

自分の主観的には割と稀ぐらいまできて普通に使える、バリバリ集中してコード書きまくる人だとイライラするかもしれない。

キーマップが HHKB と同じ (Fnキーによる矢印キーも実装してある。レイヤーってやつ)なので、基本的にどっちも全く違和感なく使える。

部品とコスト

  • BLE Nano Kit: 3300円 (Red Bear Store)
  • Gateron Brown キー 108 セット: 3300円 (ebay) 余ります
  • キーキャップ 104 セット: 5700円 (ebay) 余ります (無刻印・メタキー用)
  • キーキャップ 104 セット: 3500円 (AliExpress) 余ります (有刻印)
  • 生基板 1.6×150×250 2枚: 1000円 (monotaro)
  • 1mm プラバン B00CF9RSTU : 540円 (Amazon)
  • 2mm プラバン B001Q0ZHTW : 550円 (Amazon)
  • ビス・ナットなど 500円ぐらい

キーキャップ2セット買ってるがメタキー用の無刻印のものと通常キーの刻印ありのものを分けたかったからで、1セット+必要なキーだけとかならもっと安くはできるはず。いずれにせよキーキャップの原価支配率が高い。これだけ買ってるのに右シフトキーサイズのキーが Caps Lock しかなくて、しかたなく代用している。

基板切削を自力でやっているので注意がいる。もし基板を外注するなら、左右別のデザインにするとサイズ的に5枚組み1万ぐらいはかかるはず。とはいえ、外注しても2〜3万ぐらいの原価なので、趣味で作るのはまぁまぁ現実的といえる。基板をシェアするともだち(笑)がいるならもうちょっと安くて楽をできる。(趣味で、というのは自分の作業コストをゼロとして見積るという意味です)

製作期間

ヤパチーで ErgoDox を見て触発されて、ErgoDox について調べた(買わないけど) | tech - 氾濫原 このエントリを書いた時点でさいきょうのキーボード自作の実現性について考えていたので、そこから約1ヶ月半ぐらい。ebay や aliexpress が部品調達のメインで、かなり待ち時間があるので、実働は1ヶ月ぐらいかな。休日も平日も夜中にしか開発できないので、やる気があれば半月ぐらいで形になりそう。主観的には(大変すぎて)3ヶ月ぐらいずっとやってるつもりだったけど、案外早くできたっぽい……

ぶっちゃけ1ヶ月ぐらいじっくり取り組むと飽きる。

現時点での感想

キーボード自作は結構面白い。というか奥が深いと感じる。自分が一番よく触るインターフェイスを自分である程度作れるというのは満足度が高い。

いきなりイチから盛り盛りで作ったわりには良くできたと思うが、特にハードウェア部分は製品レベルではない。自分で作って自分で使うぶんには十分といえる。

「さいきょうのきーぼーど」追い求めると沼にハマるので、ほどほどにしたほうがよさそう。

フルキーボード作るのは結構コストがかかるので、既存のキーボードと組合せる前提で、カーソルキーだけとか、ファンクションキーだけ、みたいな無線キーボードなら安く作れて良さそう。そして十分実用にできると思われる。

  1. トップ
  2. tech
  3. ErgoDox ではないナニか。オープンソースかつ Bluetooth 接続のキーボード

BLE Nano は書きこみ器セットで購入しても $32.90 とかなりお得。BLE Nano Kit - Product 単体 なら $17.90。RedBear は香港みたい。公式の通販から最低送料のオプションで買っても割とすぐ届く。

ただのビーコンとして使うには高価に感じるかもしれないが、PCとの低消費電力無線通信デバイスでこの価格帯のものは殆どない。

そしてARM かつ、mbed を開発環境につかえる。なお Arduino からも書きこめる。ナイス。

載っている BLE モジュールも nRF51822 という界隈でデファクトスタンダートみたいなやつなので比較的情報が豊富。

そして小さい。小さいのは正義。その分IOは少ないが割となんとかなる。

  1. トップ
  2. tech
  3. なぜ BLE Nano にご執心なのか

0x3d はMessage Integrity Check (MIC)が失敗した、というエラーらしい。ホスト側で発生する。デバイス側から送られてきたメッセージのセキュリティチェックエラーのようだ。

ということで、デバイススタックの SoftDevice のバグでは? と思うところだけど、そうではないらしい。どうやら mbed と相性が悪いらしい。

解決の糸口

0x3d が出るのは最初はファームウェアのバグでどこかが stuck しているからだと思っていた。しかしどうも stuck していなくても 0x3d が起こることがある。で、そろそろ Nordic スタックのバグを疑ってみる。しかしそこのバグなら既にハマっている人がいるはずなのでググる。

すると Implement BLE security · Issue #44 · lancaster-university/microbit-dal · GitHub あたりに Nordic のバグじゃね? みたいな話がでてくる。そこからサブイシューがつくられている。


MIC failures observed with secure BLE · Issue #61 · lancaster-university/microbit-dal · GitHub

Problem is caused by mbed-classic disabling interrupts when a timer interrupt is triggered. This was too long for the underlying BLE stack to code with during critical radio events.

と原因と、さらに解決策がいくつか示されている。一番簡単なのが3つめなので、このプロジェクトでは3つめが採用されたっぽい。しかし肝心のコミットへのリンクはないので頑張って探す。

Merge branch 'secure-ble' · lancaster-university/microbit-dal@3c31479 · GitHub このコミットをつらつら眺めていくと、どうやら対策コードっぽいものが見つかった。

	// configure the stack to hold on to CPU during critical timing events.
 	// mbed-classic performs __disabe_irq calls in its timers, which can cause MIC failures 
 	// on secure BLE channels.
    ble_common_opt_radio_cpu_mutex_t opt;
    opt.enable = 1;
    sd_ble_opt_set(BLE_COMMON_OPT_RADIO_CPU_MUTEX, (const ble_opt_t *)&opt);

ここで SoftDevice の API を呼んで、無線アクティビティがあるときはCPUを完全にブロックしてアプリケーションの実行を止めるらしい。簡単なコードだ。

コピペしてみるとエラーの発生がなくなった。まじ良かった……

備考:エラーのログ

Apple が提供している Bluetooth Explorer の Event Log を開きっぱなしにしておけば、接続情報について常にデバッグログに残る。

  1. トップ
  2. tech
  3. BLE Nano (nRF51) + mbed でセキュリティ付きペアリングをして 0x3d エラーがでる

仕様に書いてあるが標準だと 0.5mA になっている。これは超高輝度LEDなら直接光るかもしれない。電源電圧がそもそも低いので青色とかはやめたほうがよさそう。

なお、設定を変えると最大3ピンまで5mAのドライブ能力に拡張することができる。これは特にピンの制約はなくて、どのピンでも可能なようだ。LEDぐらいしか駆動するものがないのなら、LED ピンのドライブ能力を拡張しておくと安心できる。

設定方法は例えば以下の通りで、

	NRF_GPIO->PIN_CNF[PIN_STATUS_LED] =
		(NRF_GPIO->PIN_CNF[PIN_STATUS_LED] & ~GPIO_PIN_CNF_DRIVE_Msk) |
		(GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos);

PIN_CNF の DRIVE を変更すれば良い。この例だとソースもシンクも5mAになる。ソースとシンクは別々に設定可能。

なお mbed 環境で DigitalOut とかしている場合 PIN_CNF レジスタは変更済みなので、必要ないところは上書きしないように注意する必要がある。

  1. トップ
  2. tech
  3. BLE Nano (nRF51822) のドライブ能力を外付け部品なしで拡張する

nRF51 での FOTA の仕組み

DFUService というのが mbed の BLE_API だと提供されていて勘違いしたけど、これは実際のファームウェア書きこみ処理は一切行わない。これがやっていることは bootloader を起動するということだけだ。

FOTA の仕組みとしては

  1. クライアントは DFUService に対してリクエスト
  2. DFUService はアプリケーション抜けて bootloader として再起動する
  3. クライアントは再度 DFU を見つけて通信を行う
  4. bootloader はBLE経由でデータを受けとってFlashに書きこむ
  5. bootloader はアプリケーションを起動する

という感じですすむ。

mbed 環境でのやりかた

まず、コンパイル済みの bootloader が必要で、これを USB 経由で書きこむ。これで準備完了になるので、これ以降は FOTA だけで書く必要がある。USB 経由で書きこむと bootloader を上書きしてしまうので、FOTA は無効になる 。

bootloader はどれを使うか

https://github.com/RedBearLab/nRF51822-Arduino/tree/S130/bootloader

Arduino IDE 経由で書きこめる bootloader になっているが、FOTA の機能もついている。BLE Nano だとこれ使っておけば良さそう。他のも使ってみたがこれだけ動いた。

mbed からデフォルトでダウンロードされる hex は書けない

ただ、上記 bootloader.hex を書きこんでも、mbed のオンラインコンパイラでコンパイル・リンクして生成される hex ファイルでは基本的に書きこめずに失敗する。これは mbed 環境でコンパイルした場合、親切にも SoftDevice などをマージした状態で hex を作ってくれるから。しかし FOTA するのはアプリケーションの部分だけなので、余計な部分を取り除く必要がある。

これは nRF51_OTA_strip.py を使えばできる。単に引数に入力と出力を与えればアプリケーション部分だけの hex ファイルを吐いてくれる。

ここを変えれば FOTA 版が落とせるみたいです。気付かなかった。ここで FOTA 版を選択すると、DFUService は自動的に組込まれてコンパイルされます。

書きこみかた

できた hex ファイルをなんとかして Android か iPhone に転送する。Google Drive に突っ込むのがてっとり早い。

そして nRF Toolbox を使って DFU をする。このとき、Init packet がどうたらというダイアログがでるが No を選択する。

Device を選択して Upload をタップすれば DFU がはじまる。結構時間がかかる。

bootloader のソースコードは?

https://github.com/ARMmbed/nrf5x-dfu-bootloader

たぶんこれがそれっぽい。ビルドしてないので確認はしてない。

OS X で DFU できないの?

公式ツールは Android / iPhone だけなので、できない。

サードパーティで作ってる人がいる。https://github.com/jeremysf/nrfDFU が、手元だとうまく動かすことができなかった。追試が必要。

  1. トップ
  2. tech
  3. mbed + BLE Nano で FOTA (DFUService) を使うには?

ちっちゃな変更を3つほど送った。

add error for positive --zcut by cho45 · Pull Request #46 · pcb2gcode/pcb2gcode · GitHub

なんか pcb2gcode を実行したら刺さるので、こまったなあと思ったら設定ミスがわかった。pcb2gcode 側でせめてwarningぐらい出せや、と思ってかっとなって書いたプルリク。

Milldrill diameter (--milldrill-diameter option) by cho45 · Pull Request #47 · pcb2gcode/pcb2gcode · GitHub

メモ書き:KiCAD + pcb2gcode で pcbmilling | tech - 氾濫原 のとき書いたパッチ。pcb2gcode は --milldrill オプションをつけるとエンドミルを使ってすべての穴をあけることができる。たとえばφ0.8mm 以上の穴しかないなら、φ0.8mmのエンドミルで全ての穴をあけることができる。

ただ、このとき使われるオプションが --cutter-diameter だった。このオプションは外形カット時に使われるオプションなので、外形カットとドリルのときとでエンドミル径を変えることができなかった。

このパッチで --milldrill-diameter として穴をあけるときのエンドミル径を上書きできるようになった。

Clearly specify X/Y to G2. by cho45 · Pull Request #48 · pcb2gcode/pcb2gcode · GitHub

grbl だと G2 に X/Y がない場合、たんに無視されるという挙動をして絶望した。実際に機械を動かして穴をあけてから「あれ? ちゃんと開いてないぞ?」と気付いたので、目の前には加工途中の基板があった。原点がずれるとやっかいなので後日にすることもできず、勘でパッチを書いたら動いてくれた。grbl のコードも pcb2gcode のコードも手元にクローンしていてよかった……


ここまで既にマージ済み。めんどくさいコントリビューションルールもなく、非常にレスポンスはやくレビューしてくれて、良かった。

あとこうやってプルリク送った経緯と書いておくのは良い気がするので送ったときには書いていきたい。

  1. トップ
  2. tech
  3. pcb2gcode へのプルリク

BLE Nano をあいかわらず触っている。どうしても消費電流の削減ができず3日ぐらい悩んだので、参考までに「どうすれば効率よく消費電流を削減できそうか」をしるす。

ドキュメントを良くよむこと

nRF51822_PS v3.1.pdf と nRF51_Series_Reference_manual v3.0.pdf というのが主要なドキュメントになる。前者には nRF51822 特有のことがら全般が書かれていて、こちらに消費電力や、ピンごとの物理仕様が書いてある。後者は nRF51 シリーズのシステムのドキュメントになっており、レジスタ仕様とかが書いてある。

消費電力の観点で考えると、まず nRF51822_PS v3.1.pdf に一通り目を通して、どの回路がどのぐらいの電力消費をするかを把握しておくと良い。

当然支配的なところから解決しないとどうしよもないので、大きいところをとりあえずおさえる。具体的には

  • 16MHz HFCLK (クロックだけで約1mAぐらい食う)
  • CPU (起きているときは 4mA ぐらい食う)
  • Radio (送信出力ごとに最大電流が異なる 5.5〜16mA。かなり大きく見えるが BLE の場合送信にかける時間はかなり短いので、平均的には支配率はそれほど高くない)

スリープ中に 16MHz のクロックを切るためには

タイトルの 1mA という数字は HFCLK の消費のことを想定している。このクロックは必要ならば動くという挙動をする。CPU が動いているなら必ず動いている。

大事なのは以下の表 (nRF51822_PS v3.1.pdf から引用)

ここで HFCLK に依存しているブロックがスリープ中に一切ないようにしなければならない。nRF51_Series_Reference_manual v3.0.pdf のほうにはどのペリフェラルが HFCLK に依存しているかは書いてないので、この表はとても大事。

だいたいのブロックは必要なときだけ有効にして動かす系だけど、UART や TWI のようにだいたいオンにしてるみたいなペリフェラルもスリープ前に明示的にオフにする必要がある。というよりは必要なときだけオンにするという使いかたのほうが安全。

TWI なら

NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
do_something();
NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;

UART なら

NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
NRF_UART0->TASKS_STARTTX = 1;
NRF_UART0->TASKS_STARTRX = 1;
// dummy send to wakeup...
NRF_UART0->PSELTXD = 0xFFFFFFFF;
NRF_UART0->EVENTS_TXDRDY = 0;
NRF_UART0->TXD = 0;
while (NRF_UART0->EVENTS_TXDRDY != 1);
NRF_UART0->PSELTXD = tx;

do_something();

while (NRF_UART0->EVENTS_TXDRDY != 1);

uint32_t tx = NRF_UART0->PSELTXD;

NRF_UART0->TASKS_STOPTX = 1;
NRF_UART0->TASKS_STOPRX = 1;
NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);

みたいな感じになる。UART はなんかバグってるのかよくわからないけど、ダミーで一回書かないとちゃんと復帰しなくてこまった。mbed のライブラリにも同様のことが書いてある。

ペリフェラル以外

書きこみインターフェイス (デバッガ) で書きこんだ直後のプログラムはデバッグモードで動いていて、この状態だと上記と同じように 16MHz とデバッガ用の回路が動くようで、消費電力がまったく減らない。

この状態から抜けてノーマルモードで起動するには

  • デバッガを切断したうえで、全ての電源供給をやめて、再度電源を入れなおす
  • デバッガ起動中でもリセットピンでリセット可能にして、デバッガを切断するとともにピンリセットをかける

あたりがある。前者は若干めんどうなので、後者の方法のほうがおすすめ。

// Enable Pin-reset on DEBUG mode
NRF_POWER->RESET = 1;

と main の冒頭あたりに書いておくと、デバッグモード中でもピンリセットがかけられる。「ピンリセットってどのピン?」と思うかもしれないが、SWDIO が nRESET と共用になっているので、書きこみ気から SWDIO/SWDCLK を抜いて GND に一瞬つなげばノーマルモードで起動するようになる。

BLE Nano 固有

BLE Nano は P0_19/D13 に LED がついてる。この LED は VDD に繋っており、負論理で光る。なので、この LED を消したいときは明示的に PullUp するか出力に設定して HIGH にする必要がある。

DigitalIn unused_p0_19(P0_19, PullUp);

備考

ちなみに英語で検索するときは nRF51 power consumption とかでググるのが良いです。

  1. トップ
  2. tech
  3. BLE Nano (nRF51822) でどうしても 1mA 以上電流食うぞというとき

メーデー!9:航空機事故の真実と真相 (吹替版) - ---

---

5.0 / 5.0

メーデー!10:航空機事故の真実と真相 (吹替版) - ---

---

5.0 / 5.0

メーデー!11:航空機事故の真実と真相 (吹替版) - ---

---

5.0 / 5.0

プライムビデオでシーズン11、10と9の一部が見れるのでずっと見てる。

航空業界は事故調査がものすごく発達しているというのを感じることができる。機械的な要因からパイロットの心理的な要因まで、とことん分析される。淡々とすすむので、見ていて疲れないが、好奇心は刺激されるので見ていてメリットしかない。

なぜ航空業界にはここまで厳しい事故調査が行われるのに、他の業界ではちゃんとしたものがないのだろうと考える。一発で大量に人が死ぬってのがインパクトがあることだから、というのがあるのだろうなと思った。自動車よりも飛行機のほうが圧倒的に安全なのにも関わらず、人間は飛行機を過剰に怖がる。


ブログラムのバグも、本来なら個人の力量に帰着せず、なぜそれをフレームワークや職場環境でカバーできなかったのかとかを深く考えるべきものであるはずだけど、基本的にプログラムのバグ1個で直接物理的に人が大量に死んだりはあまりないので、そういうところまで深く考える人が少ない。つまりプログラムで大量に人が殺せればプログラムのバグは適切に対処されるようになるだろう。人間が死なないと人間は学ばない。

 -

5.0 / 5.0

Huawei MediaPad T2 7.0 Pro を買ってみた。しばらくうちにはタブレットがなかったので、ひさびさにタブレットを手に入れた。

こんな価格だけど使用感は全く問題ない。指紋認証でロックが解除できて、思ったよりこれが便利。

PDF ドキュメント読むときに使うのがかなり快適だな〜 という感じ。Zenfone 2 と比べて2インチしか変わらないけど、ぜんぜん違う。

Androud N がリリースされたようですが、ZenFone 2 には Android M が一向にきません。こないんでしょうか。

自宅のネットワーク、ちょいちょい特定のDNSがひけなくなるけど、なんなんだろうなあ。プロバイダのキャッシュサーバーがおかしいのだろうか……

『この美術には問題がある!』と『NEW GAME』が安心してみれて無限に可愛い女の子が喋る感じなのが良い

とりあえずメモだけ

Eagle の場合は pcb-gcode を使えばよかったが、これは Eagle の ULP で書かれているので KiCAD には使えない。pcb2gcode はガーバーファイルから直接 gcode に変換するのでどちらでも使える。

レイアウト

KiCAD 書き出し


pcb2gcode

以下のパッチのブランチで実行

https://github.com/pcb2gcode/pcb2gcode/pull/47

millproject

# Use standard mm
metric=true
metricoutput=1

# front=
back=Main-B.Cu.gbr
outline=Main-Edge.Cuts.gbr
drill=Main.drl

back-output=back.gcode
outline-output=outline.gcode
drill-output=drill.gcode

# https://github.com/chrysn-pull-requests/pcb2gcode/blob/graphical-documentation/man/options.svg
zwork=-0.1
zsafe=1
mill-feed=500
mill-speed=10000
mill-vertfeed=200
offset=0.07679491924311227
#offset=10
extra-passes=1

zdrill=0.9
zchange=20
drill-feed=100
drill-speed=10000
milldrill=true
# milldrill のときの直径 パッチが必要
milldrill-diameter=0.8

# for grbl
nog81=true

# 外形カット時のミル直径
cutter-diameter=1
zcut=-1
cut-feed=500
cut-speed=10000
cut-infeed=1
cut-side=back

optimise=true
zero-start=true
dpi=1000

offset には削るエンドミルの半径を入れる。たとえば 30° 0.1mm のVカッターを -0.1mm で掘る (zwork=-0.1) にする場合 φ0.153mm なので、offset=0.0767 にする。

パッチのメモ

各 gcode を --zero-start で別々に生成すると原点がずれる。しかも --cutter-diameter を変えると外形レイヤーの基準がかわってしまう。

milldrill の場合 drill 系のオプションは無意味で、全て cutter 系のオプションが適用される。

milldrill のときの mill の直径は cutter-diameter と共用のようで、外形カットと穴開けで別の直径のエンドミルにできない…

KiCAD の時点で外形を大きくしておくか、パッチ書くしかない。→ 書いた

結果

pcb2gcode は isolate な部分を全て削る設定にすることができない(と思う)。なので孤立した銅箔が生成されてしまう。 extra-passes=100 とかにすればできるだけ全て削れるっぽい。

offset を大きく設定すると voronoi アルゴリズムが有効になり、孤立した部分をなくせる (孤立した部分は近くの配線に吸収される)。配線というよりは銅箔面の領域分割という感じになる。PCB っぽくはないけどおもしろい。

まだこれは試してない。

  1. トップ
  2. tech
  3. メモ書き:KiCAD + pcb2gcode で pcbmilling

http://www.apache.org/dist/httpcomponents/httpcore/RELEASE_NOTES-4.4.x.txt

httpcore-4.4.5 (2016-06-08) では 4.4.4 ではあったアノテーションが削られています。

Please note the following annotations originally based on CC-BY licensed source have been removed 
in this release:


org.apache.http.annotation.GuardedBy
org.apache.http.annotation.Immutable
org.apache.http.annotation.NotThreadSafe
org.apache.http.annotation.ThreadSafe

httpclient 4.5.1 や 4.5.2 はこれらのアノテーションを使ってるので、うっかり 4.4.5 が入ると死ぬようです。

以下のようにバージョン指定しました。

compile('org.apache.httpcomponents:httpcore:4.4.4')
compile('org.apache.httpcomponents:httpclient:4.5.2')

1時間ぐらいハマった。Java は辛い。

  1. トップ
  2. tech
  3. Error:java: cannot access org.apache.http.annotation.Immutable class file for org.apache.http.annotation.Immutable not found