ぶていのログでぶログ

思い出したが吉日

OpenStackのlive-migrationをSlackに通知するくんを作った

OpenStackにはlive-migrationと言う機能がある。 この機能を使うと、インスタンスが稼働中のまま他の母艦に移動することができる。 ハードウェア障害やカーネルアップデートなどで、母艦のシャットダウンが必要になった場合に、稼働中のインスタンスを問題のない別の母艦に移動するのによく使っている。

live-migrationはopenstack-cliやWebUI(Horizon)などから実施することができるのだが、1つ問題がある。 それは live-migrationが終わったことに気がつくことができない*1 いつlive-migrationが終わるのかを意識しつづけなければならないのはつらい…。 そこで、live-migrationの実行・終了を監視、Slackに状態を通知するスクリプトを作成した。

github.com

使い方

今のところ環境変数で設定を渡すようになっているので*2、RabbitMQやSlackのWebHook URLを環境変数にセットする。

$ export RABBITMQ_HOST=<rabbitmq host>
$ export RABBITMQ_PORT=<rabbitmq port>
$ export RABBITMQ_USER=<rabbitmq user>
$ export RABBITMQ_PASSWORD=<rabbitmq password>
$ export SLACK_WEBHOOK_URL=<webhook url>

環境変数にセットしたら、あとは notifier.rb を実行すれば動くはず。

$ bundle install
$ bundle exec ./notifier.rb

通知される内容は以下のような感じ。

f:id:buty4649:20180530145019p:plain

仕組み

f:id:buty4649:20180530142904p:plain

conductorから各agentへの通知はRabbitMQを使って*3通知される。 live-migration-notifierは、RabbitMQに流れるキューを監視して、live-migrationに関わるキューが来た場合に通知処理を行う。

最初、conductorやagentに手を入れて実装しようとしたが、バージョンアップによりコードが変わるとそれに追随してソースを変更しないといけなくなりつらくなるので今のような実装にした。

おわりに

live-migration-notifierを作ったおかげで、live-migrationの状態が可視化されてとても便利になった。 また、導入以前にlive-migrationがエラーに終わったことも通知されず、毎度 nova migration-list してステータスを取らないとわからない状態でストレスになっていたが、それもわかるようになってとてもストレスフルだ! 利用者の方々からもとても便利になった!!!最高!!!!抱いて!!!!っと好評です(当方調べ)。

とりあえず動く!を目指して作ってしまったため、コードがかなり雑なのでこれを何とかしたい…というのが直近の目標。 リファクタしたらrubygemsにパブリッシュする予定です。

*1:openstack-cliなら、 --wait オプションを付けることで、live-migrationが終了するまでコマンドを待機させることができるので、それを終了をトリガーに通知するような仕組みを作ればできなくはないが、利用者に環境をそろえてもらうのが大変

*2:雑に作ってしまったので、そのうちちゃんとconfigファイルから設定を読み込むように変更したい

*3:ZeroMQやQpidなども選べるが弊社環境ではRabbitMQを使っているし、live-migration-notifierの実装はまだRabbitMQにしか対応していない

自作キーボードHelixにトラックポイントを付ける その2

前回の記事では、トラックポイント基板の準備まで書いた。 今回は、Helix/QMKにトラックポイントを接続するところまでを書く。

PS/2の接続モード

トラックポイント基板から出るPS/2信号をQMKが取り込む方法として、ドキュメントには以下の3つのパターンが示されている。 このうちの1つを使って、トラックポイント基板と接続する必要がある。

  1. Busywaitモード
  2. Interruptモード
  3. USARTモード

1のBusywaitモードについては、ドキュメントにnot recommendedと書いてあるので、この方法はよっぽどのことが無い限り使わない方が良い*1。 ベストな方法として書かれているのは、3のUSARTモードである。 この方法を使いたいのだが、クロック用としてD5ピンをデータ用としてD2ピンを使用する必要がある。 ProMicroではD5ピンをオンボードのLEDとして使っているためUSARTモードを使うことが出来ない。。 したがって、必然的に2のInterruptモードを利用することになる。

Interruptモードで使用するピンは、D2をクロック、D5をデータとして使う例がドキュメントに載っているが、クロック側はINTまたはPCINTが使えるピン、データ側はどこのピンを選択しても良いようだ。 先述した通りドキュメントの例の通りにピンを選択することはできないので、別のピンを選択する必要がある。

接続ピンの選択

まず、空いているピンを探すのだが、これについてはおまけに書いた。 その結果、(ProMicroに書いてある)ピン9(B5)と10(B6)が使われておらず、また、両方ともPCINTが使えるので、ピン9と10を使うことにした!(下図の青丸部分) また、ピン9をクロック、ピン10をデータ用のピンにした。

f:id:buty4649:20180417005613p:plain

Helixソースの修正

Helixのデフォルトファームのままでは、もちろん扱えない。 ドキュメントに書いてある通り、rules.mkとconfig.hに設定を追加する必要がある。

設定を変更する前に、右手用と左手用でkeymapsディレクトリを分ける必要がある。 これは、なぜかというとトラックポイント基板がついていない左手側でPS/2 Mouse機能を有効化してしまうと、正しくキー入力ができなくなってしまうためである*2。 とはいえ、右手と左手で差分があるのはrules.mkだけであるため、私はrules.mkのみ両方のディレクトリに作成し、それ以外のファイルは右手側をマスターとして左手側はシンボリックリンクにしている。

$ cd keyboards/helix/rev2/keymaps/
$ ls -l right/
total 28
-rw-r--r-- 1 *** *** 2387  3 28 14:52 config.h
-rw-r--r-- 1 *** *** 8033  3 28 14:53 keymap.c
-rw-r--r-- 1 *** ***  430  3 13 20:53 readme.md
-rw-r--r-- 1 *** *** 1296  3 13 21:40 rules.mk
$ ls -l left/
total 4
lrwxr-xr-x 1 *** ***   17  3 13 20:53 config.h -> ../right/config.h
lrwxr-xr-x 1 *** ***   17  3 13 20:53 keymap.c -> ../right/keymap.c
lrwxr-xr-x 1 *** ***   18  3 13 20:53 readme.md -> ../right/readme.md
-rw-r--r-- 1 *** *** 1298  3 13 20:53 rules.mk

rules.mkの変更

以下の設定を右手側の rules.mkに追加する。なお、この設定を行うとそこそこファームウェアサイズが増えるので、OLEDやバックライトLEDを有効にしていた場合はファームウェアサイズに注意した方が良い。

PS2_MOUSE_ENABLE = yes
PS2_USE_INT = yes

config.hの変更

次にconfig.hを変更する。この変更は両手に書いても問題ない。 以下では、ピン9(B5)をクロック、ピン10(B6)をデータ用のピンとしている。

/* Select hand configuration */

//#define MASTER_LEFT          // ①MASTER_LEFTをコメントアウトして
#define MASTER_RIGHT           //   MASTER_RIGHTのコメントをはずす
// #define EE_HANDS

-- -- (省略) -- --

#ifdef PS2_USE_INT
#define PS2_CLOCK_PORT  PORTB  // ②クロックピンの設定
#define PS2_CLOCK_PIN   PINB   //         〃
#define PS2_CLOCK_DDR   DDRB   //         〃
#define PS2_CLOCK_BIT   5      //         〃
#define PS2_DATA_PORT   PORTB  // ③データピンの設定
#define PS2_DATA_PIN    PINB   //         〃
#define PS2_DATA_DDR    DDRB   //         〃
#define PS2_DATA_BIT    6      //         〃

#define PS2_INT_INIT()  do {    \  // ④割り込みの設定
    PCICR |= (1<<PCIE0);        \  //       〃
} while (0)                        //       〃
#define PS2_INT_ON()  do {      \  //       〃
    PCMSK0 |= (1<<PCINT5);      \  //       〃
} while (0)                        //       〃
#define PS2_INT_OFF() do {      \  //       〃
    PCMSK0 &= ~(1<<PCINT5);     \  //       〃
} while (0)                        //       〃
#define PS2_INT_VECT   PCINT0_vect // ⑤利用する割り込みベクタの設定
#endif

各設定について解説する。なお、すべてを正しく理解しているわけではない!ので間違っているかもしれない…*3

①Helixにどちら側にUSBケーブルを刺すのかを決定する。 ここでは、必ずMASTER_RIGHTに変更しなくてはならない。 この変更を行ってもキーマップが反転することはないが、OLEDを使用している場合、右手側に情報が出て、左側にHelixロゴがでるようになる。

②、③ではクロックとデータピンを設定する。 PORTB/PINB、DDRBが何を示しているのかは正しく理解していないが(!)、おそらくArduinoにおけるピンの定義だろうという雰囲気を感じている。 ピン9,10はそれぞれB5、B6としてArdruinoにマッピングされているのでそんな感じに設定する(ふんわり)。

④割り込みを初期化/有効化/無効化するマクロを設定する。 ドキュメントではINTを使うようになっているが、私はPCINTを使うので有効にするレジスタを変更している*4。 なお、私はここが一番工夫したところだと思っている!

⑤利用する割り込みベクタを設定する。

動作確認

rules.mkとconfig.hの設定を変更し、無事にビルドができたらPro Microにファームウェアを書き込む。 Pro Microにファームウェアを書き込んだら、一旦Helix基板から取り外し、ブレッドボードにPro Microと前回作成したリセット回路付きトラックポイント基板を接続して動作確認すると良いと思う。 接続は以下の通り行う。

Pro Micro リセット回路付きトラックポイント基板
RAW or VCC <--> VCC
ピン9 <--> CLK
ピン10 <--> DATA
GND <--> GND

USBケーブルをPro Microに刺し、トラックポイントを動かすとマウスカーソルが動く!!!!!!!!!!・・・・はず。 動かない場合はリセット回路を見直すのがよい。

ここまでのまとめ

QMKの設定を変更して、トラックポイント基板と接続することができた。 次回は、Helixに組み込む方法について書きたい。

おまけ: どうやって空いているピンを調査したか

まずはじめに、ProMicroの回路図とにらめっこした。 Pro Microの回路図(PDF)

基板のピンアウトは下図のとおり。 ここにある、D2~D10、A0~A3、SCK、MISO、MOSIが回路図右側のATMEGA32U4の各ピンにつながっていることがわかる*5

f:id:buty4649:20180417021456p:plain

ATMEGA32U4の各ピンにはPD2だったり本記事でも出てきたPB5、PB6などと書いてある。 これは何かというと、答えはデータシート(PDF)に書いてある。 各ピンごとに機能が違い、使用できるピンごとにA~Fまでグループに分かれているのである。 詳しくはデータシートの2.2 Pin Descriptionを参照。

物理的なピン配置がわかったので、次はソフトウェア部分を見ていく。 キーマトリクスに使われいるピンはそれぞれ、MATRIX_COL_PINSMATRIX_ROW_PINSで定義されている。 5行版だとそれぞれ以下のように定義されている。

#define MATRIX_ROW_PINS { D4, C6, D7, E6, B4 }
#define MATRIX_COL_PINS { F4, F5, F6, F7, B1, B3, B2 }

このD4だったりC6というのが、Atmega32u4上の各ピンに該当している。 これで各々がどうつながっているかがわかったので、表にまとめた。 それぞれHelixでの用途、Pro Micro上のシルクプリントとATmega32u4上のピンになる。

Helix Pro Micro ATmega32u4 ATmega32u4 Pro Micro Helix
RGB? TXO PD3 - RAW Vcc
Serial? RXI PD2 - GND GND
GND GND - - RST RST
GND GND - - Vcc Vcc
SDA(I2c) 2 PD1 PF7 A3 COL4
SCL(I2c) 3 PD0 PF6 A2 COL3
ROW1 4 PD4 PF5 A1 COL2
ROW2 5 PC6 PF4 A0 COL1
ROW3 6 PD7 PB1 15 COL5
ROW4 7 PE6 PB3 14 COL6
ROW5 8 PB4 PB2 16 COL7
- 9 PB5 PB6 10 -

おまけで、5行版のデフォルトのキーマップとピン番号の対応表も書いておく。

        PF4    PF5    PF6    PF7    PB1    PB3   PB2    PB2    PB3    PB1    PF7     PF6    PF5   PF4
     ,-----------------------------------------.             ,-----------------------------------------.
PD4  |   `  |   1  |   2  |   3  |   4  |   5  |             |   6  |   7  |   8  |   9  |   0  | Del  |  PD4
     |------+------+------+------+------+------|             |------+------+------+------+------+------|
PC6  | Tab  |   Q  |   W  |   E  |   R  |   T  |             |   Y  |   U  |   I  |   O  |   P  | Bksp |  PC6
     |------+------+------+------+------+------|             |------+------+------+------+------+------|
PD7  | Ctrl |   A  |   S  |   D  |   F  |   G  |             |   H  |   J  |   K  |   L  |   ;  |  '   |  PD7
     |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
PE6  | Shift|   Z  |   X  |   C  |   V  |   B  |   [  |   ]  |   N  |   M  |   ,  |   .  |   /  |Enter |  PE6
     |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
PB4  |Adjust| Esc  | Alt  | GUI  | EISU |Lower |Space |Space |Raise | KANA | Left | Down |  Up  |Right |  PB4
     `-------------------------------------------------------------------------------------------------'

*1:名前から察するに、入力の待ち受けにsleepを使うのだろうか。それによって、システム全体が止まるので、キー入力に影響があると思われる。

*2:9,10ピンが浮いているので変にノイズが入って、それが割り込み処理をひきおこしているせいなのだろうかという憶測

*3:雰囲気でQMKをいじっている

*4:INTはLレベル、論理変化、立ち下がり、立ち上がりで割り込めるがポートが少ない。PCINTは論理変化のみだがポートが多いという違いであると知った

*5:改めてみるとPro Microはその小ささゆえに未使用なピンが多いことに気がつく

自作キーボードHelixにトラックポイントを付ける その1

諸君、私はトラックポイントが好きだ!!!! 初めてThinkpadを使ってからトラックポイントにはまり、今の会社に入ってからトラックポイントキーボードを2枚買い、そして自宅にもサーバ管理用に1枚ある! で、先日作成したHelixに付けたくなりできたのが↑の写真であるw

Helixにわざわざトラックポイントを付けようという人はいないだろうけど、Twitterでそこそこ反響があったのでブログにまとめておこうと思う。 なお、長くなったので何回かに分けて書く予定。

はじめに

実は、当初はトラックポイントを付けるつもりはなかった。

しかし、HHKBにトラックポイントを追加している先人がいることを知り、トラックポイントを後付けできることを知ったのだった。 この記事がなかったら、トラックポイントを付けようと思わなかったので感謝しかない 🙇‍♂️

itjo.jp

トラックポイントが後付けできることを知ったので、Helixにも付けられるはず!となり調べたら、Helixが使っているQMKというファームウェアトラックポイントを使う方法が書いてあることを見つけたので、改造を行った次第。

PS/2 Mouse Support

また、ここで紹介している手順や方法は私が試行錯誤した結果であって、他によりよい方法があるかもしれないので参考程度に見てもらえるとありがたい。

副作用

トラックポイントは最高なのだか、Helixはトラックポイントをつける設計になっていないため、以下の副作用が発生する。

  1. キー入力の取りこぼしが発生する
  2. コンパクトさが若干失われる
  3. OLED/バックライトLEDと同時に利用できない

特にこの中で1が一番致命的である。 全く入力出来ないことはないが、かなりタイピング速度が遅くなる。 さすがに、実用にはほど遠くなるのだが最近QMKをいじることでかなり改善したので、私は気にならなくなった(これについては後ほど詳しく書く)。 なお、トラックポイントをUSB接続した場合はこの問題は起こらない。

2は、トラックポイント基板をHelix PCBと底面フレームの間に設置する関係上、4mmスペーサでは隙間がたらないため7mmスペーサに交換する必要がある。 そのため、背が高くなりコンパクトさが失われる。

3は書いた通りだが、使用しないコードやレイヤを削除してファームウェアシュリンクすれば両立することはできる。 QMKをいじる知識がないと出来ないのでハードルが高い。 なお、これもUSB接続の場合は発生しない。

以上がトラックポイントを使う上での副作用だが、ほとんど解決可能な問題であり、かつ、問題の修正や副作用を考慮してもトラックポイントは最高という結論に至った!

トラックポイント基板の入手と接続方法の検討

副作用があることを理解して早速制作を開始!の前に、Helixにはトラックポイント機能はないのでどうにかしないとならない。 そうなると、必然的にトラックポイントの基板を入手することになるが、悲しいことに基板単体を入手することは不可能である*1。 そこで、トラックポイントキーボードから基板を取り外す必要がある。 基板を外したらそのキーボードは使用できなくなるので、生け贄にしていいものを選ぶと良い。 先述したとおりトラックポイント基板とHelixの接続にはPS/2とUSB接続の2種類があり、どちらで接続するかによって利用する基板が異なるので注意が必要だ。 私は、PS/2を使って接続することにしたので、ヤフオクでThinkpadT40の交換用キーボード(FRU:13N9801)を購入した。

トラックポイントの接続方法

Helixとトラックポイント基板を接続する方法について改めて説明する。

  1. USBで接続する方法
  2. PS/2で接続する方法

1は先人たちが行っている方法で、内部的にUSB接続を行っているトラックポイント基板を使い、キーボード本体とトラックポイント基板をUSBハブでつなぐ方法である。 この方法をとる場合のメリットは、HelixのPCBに手をくわえる必要がないところにある。 先人たちはマウスボタンを使うためにキースイッチ部分のメンブレンを切り出して使用しているが、QMKにはMOUSEKEY機能があるためこれを有効化すればそのような手間はない(MOUSEKEYを有効化するとファームウェアのサイズが大きくなり、一部機能が使えなくなるデメリットもある)。 また、副作用でも書いたようなキー入力の取りこぼしもない。

2はトラックポイント基板とQMKをPS/2で接続する方法である。 USB接続の場合と違い、QMK側でコントロールできるということと、トラックポイント基板のマウスキー入力が使えるためにQMKのMOUSEKEY機能を有効化する必要がないというメリットがある。

このように書き出すとUSB接続にした方がよいように思える。 しかし、USB接続タイプのThinkapdキーボードはそこそこ高価で、生け贄にするには少し躊躇する。 また、MOUSEKEY機能が使えるとはいえ、64キーしかないHelixのうち3キーを消費するし、MOUESKEYでミドルクリックを押した状態でマウスを移動してもスクロール状態にならない*2トラックポイントでこれができないのは、個人的には大きなマイナスである。

そんなことで私は2のPS/2で接続する方法をとった*3

なお、トラックポイントの基板の製造時期によってはPS/2だったりUSBだったりするようだ。 確実にPS/2で接続したい場合は、以下のページに載っている基板を搭載した交換用キーボードを入手すると良いと思う。

トラックポイント基板を設置する

f:id:buty4649:20180326134924p:plain

基板が入手できたら次に設置位置を決める。

まずはトラックポイントの位置をきめるのだがオリジナルでは、GHBNの間にトラックポイントがある(上図の青丸あたり)のだがHelixでは、アクリル板の足があるため断念した。。 しかし、その隣のHJNMの間にちょうどよい穴が空いていた(赤丸部分)ので私はここにした*4。 この部分のアクリル板の穴はPCBの穴より小さいため、後述するトラックポイントの延伸を行うために、アクリル板の穴をPCBの穴程度に広げた。

ネジ止め

f:id:buty4649:20180327012639p:plain

トラックポイントの位置をきめたらトラックポイント基板を固定する。 私の使ったトラックポイントの基板にはちょうどよくネジ穴があったため、底面側のアクリル板に穴を開けてM2 6mmネジで固定している*5。 わかりづらいが上図の赤丸部分になる。

4mmスペーサ -> 7mmスペーサへ変更

トラックポイント基板を固定した後、Helixのスペーサを4mmから7mmに変えた。 4mmスペーサでは、HelixのPCBと底面側のアクリル板の隙間にトラックポイント基板が配置できないためである。 7mmを使ったのはHelixのキットについてきたからという単純な理由である。

トラックポイントの軸を伸ばす

トラックポイント基板を設置したら、次はトラックポイントの軸を伸ばす。 いい感じに、Helixのキートップトラックポイントの頭がツライチになるようにする。 延伸する方法は、先人が行っているように真鍮パイプを使う方法を取った(詳しい手順は先人のブログを参照)。

真鍮パイプは、ウェーブ社が販売しているNEW パイプ Cセットを使った。 大きさもちょうどよく、かつ、段々にできるように各大きさがそろっているのがよかった。

ウェーブ NEW C・パイプCセット (1.5/2.0/2.5/3.0)

ウェーブ NEW C・パイプCセット (1.5/2.0/2.5/3.0)

真鍮パイプを入手したらいい感じの長さに切断するのだが、先人も書かれているとおりパイプの切断は本当に難しかった…。 先人の失敗を読み、パイプカッターを買ったのだが、気がはやってキツキツにネジを締めカットしてしまい切断面が折れ曲がり、その結果内径が縮まり1段階細いパイプが通らなくなってしまった。。 これはもうどうしようも無いので、綺麗に切れるまで試行回数を増やしたり、縮まった切断面を鉄ヤスリで削るなどの方法で回避した。

パイプの接着にはエポキシパテを使った。

コニシ ボンド ハイスピードエポ 15gセット #15123

コニシ ボンド ハイスピードエポ 15gセット #15123

で、いい感じに延伸したものが↓これ

f:id:buty4649:20180327020457p:plain

キートップを削る

延伸しただけではキートップがはめられないので削る。 ↓が削ったものである。

f:id:buty4649:20180327020733p:plain

それっぽい感じになっているが、よくよくみると雑に削ったために対称に削れていなかったりする…。

リセット回路の作成

最後にリセット回路を作成する。これがないと正しく動作しないようだ。 リセット回路は、以下の画像を参照。 CLK/DATA/RSTというラインは、トラックポイント基板でいうところのTP_CLK/TP_DATA/RSTに該当する。

https://raw.githubusercontent.com/alonswartz/trackpoint/master/images/collage-reset.jpg

↓が実際に私が作成したリセット回路である。

f:id:buty4649:20180327021722p:plain

右側にある回路は最初に作ったものである。 参考画像のように電解コンデンサを使ったのだが、これが思った以上にでかくHelixを組み立てた時にコンデンサ部分が収まらない状態になってしまった*6。 7mmのスペーサから変更することも考えたが、これ以上背が高くなるのは避けたかったので、積層コンデンサを使った左側の回路に作り直した*7

ここまでのまとめ

ここまででトラックポイント基板を設置・延伸し、リセット回路の作成ができた。 次回は、QMKにトラックポイントを認識させる方法について書きたい。

*1:入手できる方法を知っていたら教えて欲しい

*2:macOSでMOUESKEYを設定したHelixと、普通のマウスで試したが意図した動作はしなかった

*3:本当はUSB接続タイプの基板も用意していたのだが、好奇心でトラックポイント部分の基板を分解したら帰らぬ人になってしまったのだった。てへぺろ

*4:@pluis9さんは私がトラックポイントを付けることを見抜いていた?!

*5:当初両面テープで固定しようと思ったが、何度も試行錯誤するたびに取り外していたので結果としてネジ式にしてよかった

*6:ちょうど、Helixの中央あたりが膨らんでしまったためキーを入力するとカタカタいうようになってしまった。。

*7:抵抗器も小型のものに変更している

OpenStack Octavia-1.0.1 で、VIPポートがadminになるバグ

バグフィクスされたバージョンが出たら記事にしようと思ったけど、こないままQueensが出てOctavia-2.0.0になってしまった…。

タイトルの通りなのだが、Octavia-1.0.1を含んでそれ以前までには、LBが作成するVIP用のポートが、LBを作成したユーザのプロジェクトにはならず、必ずadminになってしまう不具合があった。 これで何が困るかというと、Floating IPをVIP用のポートに関連付けようとするとエラーになる。 なぜかというと、関連付け用とするFloating IPとポートの所属しているプロジェクトを合わせないとイケないからだ。 これではさすがに使い物にならないので、ワークアラウンドとして、ロードバランサーを作る前にVIP用のポートを手動で作っておき、ロードバランサー作成時に作成したポートのIDを指定する方法をとっていた。

ある日、OctaviaのRelase Noteを見ていたらこれが直っていることを知った。

Neutron LBaaS was assigning the VIP port it created the user’s project-id, thus allowing the user to attach Floating-IPs to the VIP port. Octavia, on the other hand, was assigning the Octavia project-id to the port, making it impossible for the user to attach a Floating IP. This patch brings Octavia’s behavior in line with Neutron LBaaS and assigns the user’s project-id to the VIP port created by Octavia. https://docs.openstack.org/releasenotes/octavia/pike.html#id1

1.0.1-13とバージョンが打たれているのと、過去の経験から1.0.2としてリリースされるのかと思っているのだが、特にそんなことはなかった…*1。 このFixされたバージョンを使う場合は、git cloneしてセルフパッケージングするしかない。 幸い、stable/pikeタグには修正コミットが含まれているのでこのタグを使うと良いと思う。

github.com

修正コミットはこれ

なお、この修正は、Newton移行のNeutronでないとエラーになる。 会社のOpenStackはMitakaなので*2、forkして修正して利用している。

github.com

*1:今後出る可能性はある

*2:近いうちにNewtonにする!!!

文鎮化したPro Microを復活させた

早速やらかしました。Pro Microが文鎮化しました! ことの発端は、QMKのMouse Keysページを見ていて、便利そうじゃんっと思っておもむろに有効化したことだった…。 ファームウェアのサイズが大きくなりすぎて、ブートローダ領域をぶっ壊しうんともすんとも言わなくなったのであった。

途方に暮れていたら、以下の記事を見つけた。 幸いHelixは2つのPro Microを使うのと、片側はまだ正常であったために、試してみることにした。

qiita.com

AVR ISPとは

まずなんでこんなことしないといけないかということから調べた。 Helix(QMK)のファームウェアは、直接これがブートされるわけではなくて、Arduinoブートローダが前段にいる。 電源が入るとこのブートローダが呼び出されて、Helix(QMK)のファームウェアが起動される。 リセットを押すと、LEDが点滅してファームウェアが書き込めるようになるのもArduinoブートローダがよしなにやっているからなのであった。 このブートローダは、Helix(QMK)が置いてあるフラッシュメモリ領域に保存されているため、Helix(QMK)のサイズが大きくなるとブートローダ領域に浸食しぶっ壊れるのであった。

で、ブートローダが壊れるとUSBをPCに刺してもうんともすんとも言わなくてなる。。 こうなると、直接AVRマイコンにアクセスしてファームウェアを書き換えるしかにない。 この書き換えには、AVRライターが必要になるのだが、AVRマイコンをライター化するファームウェアがAVR ISP(In-circuit Serial Programmer )である。 Pro MicroをAVR ISP化して、文鎮化したPro Microに直接ファームウェアを書き込もうというのが、先述の記事である。

母艦Pro MicroのAVR ISP

ここからが本題。 作業の前に必要なものは以下の通り

  • 正常なPro Micro(母艦)
  • 文鎮化したPro Micro
  • ブレッドボード
  • ジャンパワイヤ
  • PC
  • Arduino IDE

まず、Arduino IDEをDL。ファームウェアとavrdudeがあれば不要ではあるが、AVR ISPファームウェアがどこにあるか分からなかったので、Arduino IDEを使った。 なお、DLにはかなり時間がかかる。

https://www.arduino.cc/en/main/software

DL後実行したら、まず、母艦Pro MicroをAVR ISP化する。 メニューの[ファイル]->[スケッチ例]->[11.AurduinoISP]->[AruduinoISP]を選択する。すると、新しいウインドウが開いて中にスケッチ(コード)が書かれている。

次にデバイスの設定を行う。 デフォルトではPro Microのボード情報は入っていない?ので追加する必要があると公式ドキュメントに書いてあるのでそれに従う。 メニューから環境設定画面を開き、[追加のボードマネージャのURL]に以下のURLをコピーする。

https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json

入力を完了したら、スケッチ画面に戻りメニューより[ツール]->[ボード]からSpark Fun Pro Microを選択する。 一覧にない場合は同メニューのボードマネージャからPro Microを選択すると、メニューに追加される。 ボードを選択したら、同じく[ツール]メニューの[プロセッサ]からATmega32U4(5V,16MHz)を選択する。

ここまでできたら、母艦Pro MicroをPCにつなげ、一旦リセットを押す。 ファームウェア書き込み用のUSBモデムが見えている間に、メニューの[ツール]->[シリアルポート]から母艦Pro Microのポートを選択する。

選択が出来たらファームウェアを書き込む。 メニューの[スケッチ]->[マイコンボードに書き込む]を選択すると書き込みが開始される。 初回はファームウェアのビルドが走るので少々時間がかかる。 ビルドが終わり、ファームウェアの書き込みが走る直前に、再度母艦Pro Microのリセットを押す。 このタイミングが絶妙すぎるので、いい感じに調整する…。

無事書き込みが出来るとLEDが何度か点滅する。 そして、リセットボタンを押さなくてもUSBモデムが見えている状態なっているはず。

文鎮Pro Microへのブートローダ書き込み

ここまで来たらあとは簡単。 一旦母艦Pro MicroをPCから外し、以下のように配線する。

母艦Pro Micro 文鎮Pro Micro
VCC VCC
GND GND
14 14
15 15
16 16
10 RST

問題がなければ、再度母艦Pro MicroをPCに接続する。 Aruduino IDEに戻り、メニューの[ツール]->[書き込み装置]からAruduino as ISPを選択したら、同メニューよりブートローダを書き込むを選択すると、書き込みが開始される。 問題がなければ正常に文鎮Pro Microにブートローダが書き込まれるはず。

おわりに

文鎮化したPro Microを復活することができてよかった! 組み立てて一週間も経たずに壊すところであったw

とはいえ、どのくらいのサイズまでならOKであるか知りたい…! っと思っていたらavr-sizeというズバリそのものなコマンドがあった。 このコマンドを使うとHexファイルが実際に何byteになるのかわかるのであった。 たとえば、以下はHelixデフォルトのファームウェアで試した例である。

$ avr-size .build/helix_rev2_default.hex
   text    data     bss     dec     hex filename
      0   17540       0   17540    4484 .build/helix_rev2_default.hex

17540byteであることがわかる。 ちなみに、Arduinoブートローダ(Caterina-promicro16.hex)は4090byteである。

$ avr-size Caterina-promicro16.hex
   text    data     bss     dec     hex filename
      0    4090       0    4090     ffa Caterina-promicro16.hex

Helixに使われているPro Microは32KBのフラッシュメモリを積んでいるので、ブートローダ分を除外すると28,678byteつかえることがわかる。 今後はファームウェアアップデート前にavr-sizeを確認して、この数値を超えていないかチェックするようにしようと思ったしだい。

2018/03/06 追記

qmk_firmwareを最新にしたらファームウェアサイズのチェックがされるようになっていた! これで文鎮化する人が減るんやなって・・・

f:id:buty4649:20180306134317p:plain

メモ: HelixをJIS配列で使ったときのキーマップ

  /* Qwerty
   * ,-----------------------------------------.             ,-----------------------------------------.
   * |  ` ~ |  1 ! |  2 " |  3 # |  4 $ |  5 % |             |  6 & |  7 ' |  8 ( |  9 ) |   0  | Del  |
   * |------+------+------+------+------+------|             |------+------+------+------+------+------|
   * | Tab  |   Q  |   W  |   E  |   R  |   T  |             |   Y  |   U  |   I  |   O  |   P  | Bksp |
   * |------+------+------+------+------+------|             |------+------+------+------+------+------|
   * | Ctrl |   A  |   S  |   D  |   F  |   G  |             |   H  |   J  |   K  |   L  |  ; + |  : * |
   * |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
   * | Shift|   Z  |   X  |   C  |   V  |   B  |  @ ` |  [ { |   N  |   M  |  , < |  . > |  / ? |Enter |
   * |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
   * |Adjust| Esc  | Alt  | GUI  | EISU |Lower |Space |Space |Raise | KANA | Left | Down |  Up  |Right |
   * `-------------------------------------------------------------------------------------------------'
   */

  /* Lower
   * ,-----------------------------------------.             ,-----------------------------------------.
   * |   ~  |   !  |   "  |   #  |   $  |   %  |             |   &  |   '  |   (  |   )  |   0  |      |
   * |------+------+------+------+------+------|             |------+------+------+------+------+------|
   * |   ~  |   !  |   "  |   #  |   $  |   %  |             |   &  |   '  |   (  |   )  |   0  |      |
   * |------+------+------+------+------+------|             |------+------+------+------+------+------|
   * |      |  F1  |  F2  |  F3  |  F4  |  F5  |             |  F6  |   =  |   ~  |   `  |   +  |  }   |
   * |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
   * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  )   |   0  |  F12 |      |      | Home | End  |      |
   * |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
   * |      |      |      |      |      |      |      |      |      |      | Next | Vol- | Vol+ | Play |
   * `-------------------------------------------------------------------------------------------------'
   */

  /* Raise
   * ,-----------------------------------------.             ,-----------------------------------------.
   * |   `  |   1  |   2  |   3  |   4  |   5  |             |   6  |   7  |   8  |   9  |   0  | Bksp |
   * |------+------+------+------+------+------|             |------+------+------+------+------+------|
   * |   `  |   1  |   2  |   3  |   4  |   5  |             |   6  |   7  |   8  |   9  |   0  | Del  |
   * |------+------+------+------+------+------|             |------+------+------+------+------+------|
   * |      |  F1  |  F2  |  F3  |  F4  |  F5  |             |  F6  |   -  |   ^  |   @  |   [  |  ]   |
   * |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
   * |      |  F7  |  F8  |  F9  |  F10 |  F11 |      |      |  F12 |      |      |PageDn|PageUp|      |
   * |------+------+------+------+------+------+------+------+------+------+------+------+------+------|
   * |      |      |      |      |      |      |      |      |      |      | Next | Vol- | Vol+ | Play |
   * `-------------------------------------------------------------------------------------------------'
   */

HelixはUS配列がデフォルトなので、OS側でJIS配列として使うとドキュメントにあるキーマップと全然違うので焦る。

なぜこんなことが起こるかというとキー配列によってキーコードの解釈が違うから。 例えば、Helix(QMK)からKC_AT(@)を出力した場合、US配列ではそのまま@としてOSに認識されるが、JIS配列の場合"(ダブルクォート)として認識される…(なんでこんなことになったの)。 そのため、JIS配列でOSに認識させたいキーに対応した、QMK上で定義されたキーコードをいい感じに並べ替えないと、JIS配列として使えないのであった。。

とはいえ、私は今までJIS配列で生きてきた人間なので、なんとかしてJIS配列で違和感のないキーマップにしたい。 幸いにも公式ドキュメントに各キー配列とキーコードの対応表が用意されているのでこれを見て組み替えたい。

なお、JIS用の配列定義を作る場合は、↓の記事にあるように別名をつけてあげると設定を書くときに楽になりそうだ。

qiita.com

Let's split互換のキーボードHelixを作った

f:id:buty4649:20180207192244j:plain

最近電子工作を始めて、いろいろ記事を書いてきたが、次は自作キーボードだねみたいな謎の圧を感じながらも興味は持っていた。 そんな中、同僚がHelixのGroupBuyに申し込んでいるのを知ったので、私もそれに乗っかってみた!

HelixはLet's split(レツプリ)ベースのカスタムキーボードで、ロープロファイルのキーも選択できるのがウリです。また、開発者の方が日本人であるため、私みたいな自作キーボード初心者には安心して購入できるのも大きかったです!

GBは12月に行われ、実際に部品が来たのは2月頭くらいでした。そこから、組み立てて完成したのが冒頭の写真です。 完成後は、今まで使っていたトラックポイントキーボードを封印して使い始めています。 キー配列やレイヤーの概念になれず、PC初心者のような入力速度になっていますがw

Helixの組み立てやファームウェアについては、日本語ドキュメントが用意されていて自作キーボード初心者の私でも簡単に組み立てられました。 しかし、いくつかハマりどころがあったので以下にそれを備忘録がてら書いておきます。

組み立てについて

組み立ては半田付けが必須です。 電子工作を行なったことがあるなら、必要な機材は揃っていると思いますが、以下のような機材を用意しておくと良いと思いました。

  • 温度調整機能付き半田ごて
  • 半田吸い取り線
    • キースイッチのランドがはみ出したときに吸い取る
  • テスター
    • ダイオードの向きチェックとキースイッチのランドはみ出しチェック
  • ピンセット

パーツ実装については、ダイオードの半田付け、キースイッチの半田付けが終わった後間違っていないことをテスターを使って確認しました。 ダイオードの確認は、丸側のランドにテスターの+極を、四角側にー極を当てると確認しやすかったです。

f:id:buty4649:20180207203053p:plain

個人的には、キースイッチの半田付けがとても大変でした。。 Helixはロープロファイルとフルサイズのキーの両方が選択できるため、両方のランドがあります。 しかし、ロープロファイルのキースイッチの右側のランド(青矢印右側)と、赤矢印右側のランドの隙間がほとんど無く半田が少しでもはみ出すと短絡します。 しかも、このランドは、ロープロファイルキースイッチの反対側の端子にもつながっているので、短絡してしまうと常にキーが押されてしまう判定になってしまうのでした。 はみ出した場合は、半田吸い取り線で半田を吸い取り再度半田付けを行うことで、なんとか乗り切りました。

f:id:buty4649:20180207203917p:plain

ファームウェアについて

ファームウェアについても日本語ドキュメントが用意されています。 しかし、ここに書いてあるとおりqmkのソースコードをダウンロードして make helix:defaultしてもビルドできません。 ビルドするためには、ビルドツールをインストールする必要があります。 何をインストールするかはQMKのFAQに書いてあります。

Install Build Tools

この中でも、avr-gccのインストールが非常に遅く*1、私の環境では半田付けしている時間より長かったです。。。

ビルドツールをインストールしても、 make helix:defaultしただけでは、Pro Microのファームウェアはフラッシュされません。 ファームウェアのフラッシュを行うには make helix:default:avrdude する必要があります。 これも最初わからずハマりました。。

dockerを使ってビルドする

QMKのリポジトリにはdockerfileが含まれていて、ファームウェアのビルドをdockerで行うことができるようです。 私の環境で試したところ以下のようなコマンドでファームウェアのビルドができました。

$ docker build -t qmk .
-- -- snip -- --
$ docker run --rm -e keyboard=helix -e subject= -e keymap=default -v $(pwd):/qmk qmk

☆実行が完了するとhexファイルができているはず
$ ls -lh .build/helix_rev2_default.hex

ファームウェアのフラッシュはdockerからはできないので、これはPCでやる必要があります。 フラッシュにはavrdudeコマンドが必須なのでこれをインストールしておきます。 インストールが完了したら、Helixのリセットボタンを押して 7秒以内に*2以下のコマンドを実行します(macOS環境を想定)。

$  sudo avrdude -p atmega32u4 -c avr109 -P /dev/tty.usbmodem* -U flash:w:.build/helix_rev2_default.hex

なぜ時間制限があるかというと、リセットボタンを押すと数秒だけttyデバイスが生える仕様になっているためです。 最初これに気がつかず、手動フラッシュできなくて悩みました 😓 ちなみに、 make helix:default:avrdude では /dev/tty.usbmodem* が生えるまでsleep 1してループしているようです。

設定ファイル

私はLED Underglowが使えるような構成にしていたため、ファームウェアのソースを修正する必要がありました。 修正する部分はドキュメントに書いてあるので、それに従って修正するだけなのですが、修正を行う rules.mkが複数個あり間違ったファイルを修正していたため、Underglowが光らずかなりハマりました。。

最初私が修正したのは keyboards/helix/rules.mk でしたが、正解は keyboards/helix/rev2/keymaps/default/rules.mk です。。 どちらにも同じ設定が書かれていて、 git grep で変更対象の定数名を探したため最初に出てきたrules.mkを修正したみたいな感じでした。。 他のqmkプロジェクトがどうなっているかちゃんと見ていませんが、ここら辺は少しわかりづらいなぁっと思いました。

最後に

ハマりどころはありましたが、無事に完成して、そして、完動するキーボードができて感動しています! 初心者の私でも、簡単に作成出来る素晴らしいキーボードをこの世に出していただいいた製作者様には感謝しかありません 🙇‍♂️

先述したとおり会社で使っていますが、キーマップが手になじんでいません。。 しかし、自分の思い通りのキーマップに変更できるのも自作キーボードの強みだと思います! ガシガシファームウェアをカスタマイズして、自作キーボード沼にどんどん潜っていきたいと思います 😇

*1:avr-glibcのビルドがかなり重い

*2:正確には何秒かは知らない。7秒は実測値