おかゆ++

IT業界の片隅で生き残るブログ

自作キーボードを作ります② ファームウェアのプロトタイピングと回路の設計

最初に、ファームウェアのプロトタイプを作るのと、回路の設計を同時に進めていきました。

参考にしたもの

ゆかりめも 様の記事を読んで、

あたりを勉強しました。というかほぼそのまま使っていく。

eucalyn.hatenadiary.jp

この記事を読まなければ自作キーボードを作ろうとは思わなかったでしょう。 無料で情報を提供していただいている ゆかり様(id:eucalyn) には感謝しかありません。

ファームウェア

記事中のサンプルコードをベースに、プロトタイプを作っていきました。

キーは 5x6 にする予定なので、配列やら何やらもそれに合わせて変更しました。

配置したいキーでキーコードがわからないものについては、 Arduinoのリファレンスなんかを見ながら追加しました。

また、最終的には Raise や Lower といったレイヤ機能が必要ですが、現時点では保留としました。 なんとなく動くようになった後で実装することにします。

回路

ほぼほぼ参考記事のままです。

実際に配線作業をするときのことを考えて、ちゃんと図に起こしたほうがいいかと思ったので、 BSch3V で書いてみました。 初めて使った上に回路図とかどう書いたらいいのか知らないのでかなり怪しいですが、 自分がわかればOKなのでそこは妥協です!

f:id:okayu-moka:20180317144950p:plain

なんとなくできてきそうなので、次は筐体を作っていきます!

さくらのレンタルサーバをやめてGitHub Pagesを使うことにした(経緯と簡易手順)

このブログの話ではなくて、 7年ほど前からやっている スタジオ蜜柑(http://studiomikan.net) のサイトの話です。

開設してからこれまでさくらのレンタルサーバを利用していましたが、 静的ページを公開するだけなのに毎年サーバ代を払うのがしんどくなってきたので、 GitHub Pagesを使うことにしました。

レンタルサーバを借りた当初は、PHPMySQLが動く→WordPressが動く、 というのが理由の一つだったのですがWordPressは管理がしんどくて使うの辞めちゃったので……

色々動くサーバがほしければVPS借りるなりすればいいので、 レンタルサーバのほうはそのうち解約すると思います。 ドメインは変えたくないので、さくらのドメインは引き続き利用していきます。

レンタルサーバなどを使う場合でも、結局ソースコードGitHubで管理すると思うので、 だったらもう最初から全部GitHubで完結するようにしておけばいいと思います。

GitHub Pagesへの乗り換え作業メモ

以下、簡単な作業手順を載せますが、2018年3月時点での話ですので、留意ください。

基本的にはGitHubのドキュメント↓に載っていたので、そちらを参考にするほうが確実。
Using a custom domain with GitHub Pages - User Documentation
Setting up an apex domain - User Documentation

GitHub Pagesの用意

元々、ソースコードはすべてGitHubで管理していたので、 Settings > GitHub Pages から設定を変更するだけでした。

今回は一応、docsフォルダを公開ページとしました。

GitHub側でのドメイン設定

軽く調べると、CNAMEファイルを作ってリポジトリに配置せよ、 と解説しているサイトが多かったですが、GitHubの設定画面から設定できるようになってました。

f:id:okayu-moka:20180309103721p:plain

Custom domain のところを設定すると、自動でCNAMEファイルをコミットしてくれるようです。

さくらのドメインでの変更

さくらの会員メニューにログイン後、 契約情報>契約ドメインの確認>ドメインメニュー>ゾーン編集 から設定していきます。

トップレベル(studiomikan.net)でアクセスできるようにしたいので、 種別「A」の変更が必要となります。

最終的にこんな感じになりました。

f:id:okayu-moka:20180309104035p:plain

あとは待つだけ

設定が反映されるまで待つだけです。

Windowsならnslookupで確認できるかと思います。

nslookup studiomikan.net

ドメイン関係の設定伝播時間とは別に、 GitHub Pages自体もリポジトリにコミットしてから反映までタイムラグがあるようなので、 ちょっと時間がかかりました。(20分くらい?)

VimとCtagsの連携設定・使い方メモ

Vim と Ctags を連携させます。

何ができるようになる?

まだ使いこなせてないので細かいところはわからないですが、 ソースコードを解析して、関数の定義元へジャンプしたりとかできるようになるハズ。

前提

Ctagsのインストール

chocolateyで入れるのが楽だと思います。

最近はuniversal-ctagsというのがあるらしいですが、chocolateyにパッケージがないみたいなので、昔ながらの?ctagsを使います。 ctagsはもうメンテされてないらしいので、ほんとはuniversal-ctagsを使ったほうがいいみたいですが。

choco install ctags

Ctagsの設定

~/.ctags に設定ファイルを配置して、JavaScript用の拡張を記載します。

Windows環境変数HOMEなどを設定していない場合は、実行ファイルと同じ場所におけばいいのかな? すみません、確認できてません……

--exclude=.git
--exclude=.hg
--exclude=log
--exclude=tmp

--languages=-javascript
--langdef=js
--langmap=js:.js
--langmap=js:+.jsx

--regex-js=/[ \t.]([A-Z][A-Z0-9._$]+)[ \t]*[=:][ \t]*([0-9"'\[\{]|null)/\1/n,constant/
--regex-js=/\.([A-Za-z0-9._$]+)[ \t]*=[ \t]*\{/\1/o,object/
--regex-js=/['"]*([A-Za-z0-9_$]+)['"]*[ \t]*:[ \t]*\{/\1/o,object/
--regex-js=/([A-Za-z0-9._$]+)\[["']([A-Za-z0-9_$]+)["']\][ \t]*=[ \t]*\{/\1\.\2/o,object/
--regex-js=/([A-Za-z0-9._$]+)[ \t]*=[ \t]*\(function\(\)/\1/c,class/
--regex-js=/['"]*([A-Za-z0-9_$]+)['"]*:[ \t]*\(function\(\)/\1/c,class/
--regex-js=/class[ \t]+([A-Za-z0-9._$]+)[ \t]*/\1/c,class/
--regex-js=/([A-Za-z$][A-Za-z0-9_$()]+)[ \t]*=[ \t]*[Rr]eact.createClass[ \t]*\(/\1/c,class/
--regex-js=/([A-Z][A-Za-z0-9_$]+)[ \t]*=[ \t]*[A-Za-z0-9_$]*[ \t]*[{(]/\1/c,class/
--regex-js=/([A-Z][A-Za-z0-9_$]+)[ \t]*:[ \t]*[A-Za-z0-9_$]*[ \t]*[{(]/\1/c,class/
--regex-js=/([A-Za-z$][A-Za-z0-9_$]+)[ \t]*=[ \t]*function[ \t]*\(/\1/f,function/
--regex-js=/(function)*[ \t]*([A-Za-z$_][A-Za-z0-9_$]+)[ \t]*\([^)]*\)[ \t]*\{/\2/f,function/
--regex-js=/['"]*([A-Za-z$][A-Za-z0-9_$]+)['"]*:[ \t]*function[ \t]*\(/\1/m,method/
--regex-js=/([A-Za-z0-9_$]+)\[["']([A-Za-z0-9_$]+)["']\][ \t]*=[ \t]*function[ \t]*\(/\2/m,method/

Vimでの操作

大体このあたりを使っていきたいです。

操作 動作
C-] カーソル位置でタグジャンプ実行
C-t ジャンプ元に戻る
g C-] ジャンプ先一覧を表示

参考

自作キーボードを作ります① きっかけ&買ったもの

きっかけ

1月ごろ、とうとうHappy Hacking Keyboard Pro2を購入しました。

ずっとRealforceのJIS配列を使っていましたが、もっとコンパクトなキーボードが欲しくなり、 どうせならってことでUS配列のHHKBを選びました。 最初は配列の違いに戸惑いましたが、今はもうほかのキーボードには戻れない身体になってしまいました。

HHKBに慣れてきたころ、TwitterやQiitaで自作キーボードの記事を見つけました。 どうやらキーボードを簡単に作れるArduinoがあって、自作キーボードがにわかに流行っているらしいですね。

ということで、自分も作ることにしました。

方針とか

自分はエンジニアではありますが、完全なソフト畑の人間で、Webアプリの知識がメイン。 電子工作は完全な初心者です。

しかしC言語は勉強したことがあるので、Arduinoの言語であるProcessingはなんとなくわかります。

基本方針は以下の通り。

  • 左右分離型
  • 60%キーボード
  • なるべく安く?
  • せっかくなのでファームウェアも自作する
  • 格子配列の5×6
  • 特に変わった機能をつける予定なし(自作すること自体が目的の半分なので……)
  • つまり劣化Helix

購入したもの

購入元は秋月電子、AliExpress、ebayAmazonなど。

はんだづけの道具なども欲しかったので色々なところから購入したけど、 道具がそろっていて、自作キーボードに必要なものだけ買うなら、 以下のショップで全て揃いそう。(値段が安いかどうかは不明)

TALP KEYBOARD

[2018/03/05 追記]
TALP KEYBOARDで買ってみました。AliExpressよりも数十円~数百円高いですが、国内発送で、注文した翌日に発送されました。 商品がすぐに手元に欲しい場合や、中華サイトが怖い場合はTALP KEYBOARDで買うのがベストだと思います。 キーキャップの色も豊富で、好きな色が買えるのがいいですね。 AliExpressだとアソートが多いので……

キースイッチ

Gateron RGB 茶軸 × 70個を購入。 60%キーボード(キーが60個のキーボード)を作るつもりだけど、余裕を見て多めに注文。 購入元はebay。AliExpress より安かったです。

あとから追加で Gateron RGB 赤軸 も買ってしまった。これは2台目に使う予定です。 赤軸のほうは AliExpress で購入。

キーキャップ

DSAのキーキャップをAliExpressで購入。 DCSのほうがいいかもしれないけど、とりあえずは使ってみながら交換していく予定です。

マイコンボード

完全な初心者なので、最初は勉強・練習用にArduino Microを2台購入。 購入は秋月電子で、1台¥2,800くらい。

Arduino Microでファームウェアの原型ができた頃に、本番用にPro Microを追加購入しました。 こっちはAliExpressで1台¥650くらいでした。

ダイオード

回路に必要なダイオードは、ネットで見ていると1N4148というのが良く使われているみたいです。

今回は秋月電子で1N4148を買ったけれど、代用品として勧められていた1SS178も買ってみました。 1N4148は50本/¥100、1SS178は100本/¥100でした。 1SS178のほうが半値で買えるので、結構良さげ。(使えないかもしれないけど)

[2018/03/05 追記]
普通に使えるんで、秋月電子で買う場合は1SS178がいいと思います。

電子工作用の道具

はんだづけの道具(はんだ、はんだごて、こて台)に加えて、 ブレッドボード、ジャンパワイヤ、タクトスイッチ等も購入。

その他に必要なもの

筐体 or プレート

キーボードの外枠として、筐体となるような箱や、アクリルプレートなどが必要です。

PlankやLet's Splitなどではアクリルプレート二枚で挟み込むタイプが多い印象。 ただ、この場合はPCBがないとマイコンや接続用端子を固定するのに工夫が必要。

今回は3Dプリンタを使って作ることにしました。 3D CADも完全初心者なので要勉強です。

PCB

キースイッチやダイオードを配置する基盤が必要です。 今回は筐体を3Dプリンタで作り、空中配線する予定なので、不要(のハズ)。

参考にしていく記事

基本的には ゆかりめも 様のブログで勉強したままに作っていく予定です。 eucalyn.hatenadiary.jp

2017年の自作キーボード Advent Calendarはいろいろな記事があって参考になりそうです。 adventar.org

時間はかかりそうですが、ぼちぼち作っていきます。

Ubuntuで/bootの容量不足でapt-get upgradeできない時の対処

Ubuntu Server 16.04 で、apt-get upgrade した時にエラーが発生。

エラーメッセージを見ると、どうも /boot の容量が 100% になってるのが原因っぽい。

参考: munibus.hatenablog.com www.mmpp.org

最終的には、/boot 配下の不要なカーネル類を削除して、容量を開けてから sudo apt-get -f upgrade で解決しました。

sudo rm -f /boot/*24*
sudo rm -f /boot/*32*
# そのほかいろいろ削除して容量を確保してから
sudo apt-get -f upgrade
sudo apt autoremove

しかし容量不足でエラーになるということは、定期的に古いカーネルを削除していったほうがいいってことですかね。 apt autoremove で消えるんであればいいですけど、明示的にapt-get removeしないと消えないのなら面倒ですね。

MSYS2でVim8をコンパイル(Windows)

前提

2017/12/28時点の情報です! なるべく更新しますが、今後もこの通りとは限りません。

+perl、+python、+python3、+lua、+rubyが有効なVimコンパイルします。

基本的にはvim-jpの記事を参考にしますが、Perl、Python2、Python3、RubyはChocolateyでインストールします。 LuaもChocolateyでインストールしますが、ソース(lua.hなど)がダウンロードされないので、 ソースだけ別途取得します。

vim-jp.org

chocolateyでのインストール

choco install -y StrawberryPerl --version 5.26.1.1
choco install -y python2 --version 2.7.9
choco install -y python3 --version 3.6.4
choco install -y ruby --version 2.3.3
choco install -y lua53 --version 5.3.3

それぞれ、以下の場所にインストールされる。

  • python2:C:\tools\python2
  • python3:C:\Python36
  • RubyC:\tools\ruby23
  • PerlC:\Strawberry\perl
  • LuaC:\ProgramData\chocolatey\lib\lua53\tools

MSYS2の準備

pacman -Suuy
# ここで一度minttyを閉じて、再度開く
pacman -Suu
pacman -S git mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain
pacman -S python3

作業用のディレクトリ作成、ソースの取得

mkdir -p ~/src/vim
cd ~/src/vim
# Lua
wget http://www.lua.org/ftp/lua-5.3.3.tar.gz
tar xzvf lua-5.3.3.tar.gz
# Vim
git clone https://github.com/vim/vim.git

ビルド

cd ./vim/src
rm -rf ./build
mkdir -p ./build/vimfiles

# メッセージファイルを生成
python3 C:/Python36/tools/i18n/msgfmt.py ./po/ja.po

# ビルド(CUI)
mingw32-make -f Make_ming.mak  \
  GUI=no \
  ARCH=x86-64 \
  IME=yes \
  MBYTE=yes \
  ICONV=yes \
  FEAT_TERMGUICOLORS=yes \
  clean
mingw32-make -f Make_ming.mak \
  ARCH=x86-64 \
  IME=yes \
  MBYTE=yes \
  ICONV=yes \
  FEAT_TERMGUICOLORS=yes \
  PERL=C:/Strawberry/perl DYNAMIC_PERL=yes PERL_VER=526 \
  PYTHON=C:/tools/python2 DYNAMIC_PYTHON=yes PYTHON_VER=27 \
  PYTHON3=C:/python36 DYNAMIC_PYTHON3=yes PYTHON3_VER=36 \
  RUBY=C:/tools/ruby23 DYNAMIC_RUBY=yes RUBY_VER=23 RUBY_API_VER_LONG=2.3.0 \
  LUA=~/src/vim/lua-5.3.3/src DYNAMIC_LUA=yes LUA_VER=53 \
  GUI=no
cp vim.exe ./build/

# ビルド(GUI)
mingw32-make -f Make_ming.mak  \
  GUI=yes \
  ARCH=x86-64 \
  IME=yes \
  MBYTE=yes \
  ICONV=yes \
  FEAT_TERMGUICOLORS=yes \
  clean
mingw32-make -f Make_ming.mak \
  ARCH=x86-64 \
  IME=yes \
  MBYTE=yes \
  ICONV=yes \
  FEAT_TERMGUICOLORS=yes \
  PERL=C:/Strawberry/perl DYNAMIC_PERL=yes PERL_VER=526 \
  PYTHON=C:/tools/python2 DYNAMIC_PYTHON=yes PYTHON_VER=27 \
  PYTHON3=C:/python36 DYNAMIC_PYTHON3=yes PYTHON3_VER=36 \
  RUBY=C:/tools/ruby23 DYNAMIC_RUBY=yes RUBY_VER=23 RUBY_API_VER_LONG=2.3.0 \
  LUA=~/src/vim/lua-5.3.3/src DYNAMIC_LUA=yes LUA_VER=53 \
  GUI=yes \
  STATIC_STDCPLUS=yes \
  DIRECTX=yes
cp gvim.exe ./build/
cp vimrun.exe ./build/

# パッキング
cp C:/msys64/mingw64/bin/libiconv-2.dll ./build/
cp C:/msys64/mingw64/bin/libintl-8.dll ./build/
cp C:/msys64/mingw64/bin/libwinpthread-1.dll ./build/

cp C:/Strawberry/perl/bin/perl526.dll ./build/
cp C:/tools/ruby23/bin/x64-msvcrt-ruby230.dll ./build/
cp C:/Windows/System32/python27.dll ./build/
cp C:/Python36/python36.dll ./build/
cp C:/ProgramData/chocolatey/lib/lua53/tools/lua53.dll ./build/
cp -r ../runtime ./build/vim80
mkdir -p ./build/vim80/lang/ja/LC_MESSAGES
cp ./po/ja.mo ./build/vim80/lang/ja/LC_MESSAGES/vim.mo

# 実行ファイル置き場に移動
mkdir ~/bin/vim/
cp -r ./build/* ~/bin/vim/

vimrcをファイル分割する&VimとNeoVimで共通化する

vimrc分割の理由

Vimを使っていれば、プラグインを追加したり、設定を変えたり等々でvimrcは長くなっていく一方です。 ということで、読みやすさと拡張性を確保するためにも当然分割したいわけです。

分割ついでに、VimとNeoVimの両方で同じvimrcを使うようにしたい。vimrcの中身が同じって意味ではなくて、同じvimrcファイルをVimとNeoVimの両方で参照するってことです。

分割の仕組みというか、sourceについて

Vimのコマンドに source というのがあります。まんま指定したVim scriptファイルを読み込むコマンドです。これを使えば複数ファイルに分割できそうですね。実際には source をラップした関数を作るのがいいんじゃないでしょうか。

今回のディレクトリ構成

以下の方針でディレクトリを分けます。

  • 全ての設定ファイルは ~/.dotfiles/vim に配置して、所定の位置にはシンボリックリンクを張る。
  • プラグイン管理には dein を使う
  • Vim で dein を使った時のファイル類や、その他のファイルは ~/.vim に配置する。
  • NeoVim で dein を使った時のファイル類、その他のファイルは ~/.nvim に配置する。
  • 設定ファイル類は *.rc.vim という名前にする。

ということで、こんな感じ。

~/
├─.vim
│  ├─dein    deinがダウンロードしたリポジトリとかが入る
│  └─rc      ~/dotfiles/vim/rc へのシンボリックリンク
├─.nvim
│  ├─dein    deinがダウンロードしたリポジトリとかが入る
│  └─rc      ~/dotfiles/vim/rc へのシンボリックリンク
└─dotfiles
    └─vim
        └─rc  色々な設定ファイル類が入る。vimrcからsourceで読み込む。

VimとNeoVimの判定

vimrcの先頭でVimとNeoVimの判定を実施して、ディレクトリパスなどをグローバル変数に入れておきます。以後はこの変数を使うようにします。

NeoVimの場合は has('nvim') がTrueになるので、これを使います。

if has('nvim')
    let g:vim_home = expand('~/.nvim')
    let g:rc_dir = expand('~/.nvim/rc')
else
    let g:vim_home = expand('~/.vim')
    let g:rc_dir = expand('~/.vim/rc')
endif

読み込み用の関数

基本的には rcディレクトリからのみ読み込むようにするので、それ用に関数を作ります。 また、VimとNeoVimではディレクトリが違うので、そのあたりもさっきのグローバル変数で吸収します。

" rcファイル読み込み関数
function! s:source_rc(rc_file_name)
    let rc_file = expand(g:rc_dir . '/' . a:rc_file_name)
    if filereadable(rc_file)
        execute 'source' rc_file
    endif
endfunction

call s:source_rc('init.rc.vim') のような感じで書けば、dotfiles/vim/rc/init.rc.vim が読み込まれます。

最終的なvimrc

最終的には以下のようになりました。

if has('nvim')
    let g:vim_home = expand('~/.nvim')
    let g:rc_dir = expand('~/.nvim/rc')
else
    let g:vim_home = expand('~/.vim')
    let g:rc_dir = expand('~/.vim/rc')
endif

" rcファイル読み込み関数
function! s:source_rc(rc_file_name)
    let rc_file = expand(g:rc_dir . '/' . a:rc_file_name)
    if filereadable(rc_file)
        execute 'source' rc_file
    endif
endfunction

"------------------------------------------------------------------------------

" 基本設定
call s:source_rc('init.rc.vim')

" エディタの設定
call s:source_rc('editor.rc.vim')

" Dein.vim
call s:source_rc('dein.rc.vim')

" カラースキーマ
call s:source_rc('color.rc.vim')

" ターミナル設定(今の所NeoVimの :terminal の設定)
call s:source_rc('terminal.rc.vim')

" neocomplete
call s:source_rc('neocomplete.rc.vim')

" unite
call s:source_rc('unite.rc.vim')

" caw.vim
call s:source_rc('caw.rc.vim')

" NERDTree
call s:source_rc('nerdtree.rc.vim')

" lightline.vim
call s:source_rc('lightline.rc.vim')

ちょっと設定ファイルを分けすぎた感もあるけど、まぁ許容範囲かなーということで。

インストール用のスクリプトも作っておく

install.sh とか install.bat とかを作っておけば、git clone して sh install.sh すれば環境が整うはず。

Unix用のinstall.shはこんな感じ。

#!/bin/sh
cd $(dirname ${0}) 

vim_home=~/.vim
mkdir -p ${vim_home}
ln -sf `pwd`/vim/vimrc ~/.vimrc
ln -sf `pwd`/vim/rc ${vim_home}/rc

nvim_home=~/.nvim
mkdir -p ${nvim_home}
mkdir -p ~/.config/nvim
ln -sf `pwd`/vim/vimrc ~/.config/nvim/init.vim
ln -sf `pwd`/vim/rc ${nvim_home}/rc

Windows場合、シンボリックリンクの作成に管理者権限で実行する必要があることだけ注意が必要です。 また、vimrcの置き場所とかも色々*1だと思いますので、以下はあくまでも例です。

@echo off
@setlocal
cd %~dp0
set current=%~dp0

set vim_home=%HOME%\.vim
mkdir %vim_home%
mklink "%HOME%\.vimrc" "%current%vim\vimrc"
mklink "%HOME%\.gvimrc" "%current%vim\gvimrc"
mklink /D "%vim_home%\rc" "%current%vim\rc"

set nvim_initdir=%userprofile%\AppData\Local\nvim
mkdir "%nvim_initdir%"
mklink %nvim_initdir%"\init.vim" "%current%vim\vimrc"

@endlocal
@echo on

*1:自分は環境変数HOMEを用意して、vimrcなんかもそこに置いてます。