Android+ポケモンキーボードでモバイルLinux環境を作る
Android+ポケモンキーボードでモバイルLinux環境を構築する話です。当然root化とbusyboxのインストールが必要です。
今回はGalaxy Nexusにインストールした。他のAndroid端末でも同じようにインストールできると思うけど、手順どうりにやってもうまく動かないことがあるのでその時はググるなりしてください。
chroot環境の構築
まずArch Linux ARMのフォーラムを参考にchroot環境を構築します。
Arch Linux ARM • View topic - Installation in an Android Chroot
私はArchLinux派なので、ArchLinuxをインストールしていますがDebianなど他のディストリビューションがいい。もうすでにインストールしてるよって人は、他のディストリのインストール方法をググるなり読み飛ばすなりしてください。
まずAndroid上で以下のコマンドを実行してArchLinuxをインストールします。
途中ddコマンドで750MBのイメージファイルを作成していますが、容量は各自で適当に決めてください。私はいろんなパッケージをインストールするつもりなので2GBの容量で作成しました。
su cd /sdcard mkdir arch dd if=/dev/zero of=alarm.img seek=749999999 bs=1 count=1 mke2fs -F alarm.img mknod /dev/loop1 b 7 0 losetup /dev/loop1 alarm.img mount -t ext2 /dev/loop1 arch/ cd arch wget http://archlinuxarm.org/os/ArchLinuxARM-armv5te-latest.tar.gz tar xzf ArchLinuxARM-armv5te-*.tar.gz rm ArchLinuxARM-armv5te-*.tar.gz cd .. umount /sdcard/arch losetup -d /dev/loop1
これでArchLinuxARMのインストールは完了。
次に起動スクリプトを/sdcard/startarch.shとして配置します。
この起動スクリプトはarchlinuxarmのフォーラムの書き込みを参考に作成しました。
startarch.sh
perm=$(id|cut -b 5) if [ "$perm" != "0" ]; then echo "This script requires root! Type: su"; exit; fi echo "Starting up ArchLinux" if [ ! -b /dev/loop1 ]; then mknod /dev/loop1 b 7 0 fi losetup /dev/loop1 alarm.img mount -t ext2 /dev/loop1 arch/ cd arch mount -o bind /dev/ /sdcard/arch/dev mount -t devpts devpts /sdcard/arch/dev/pts mount -t proc proc /sdcard/arch/proc mount -t sysfs sysfs /sdcard/arch/sys mount -o bind /mnt/sdcard /sdcard/arch/media/sdcard busybox sysctl -w net.ipv4.ip_forward=1 echo "nameserver 8.8.8.8" > /sdcard/arch/etc/resolv.conf echo "nameserver 8.8.4.4" >> /sdcard/arch/etc/resolv.conf echo "127.0.0.1 localhost" > /sdcard/arch/etc/hosts echo "Arch is configured that can be accessed from the IP:" ifconfig wlan0 echo " " PATH_=$PATH export PATH=$bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin:/bin:/usr/local/sbin export TERM=xterm export USER=root export HOME=/root export SHELL=/bin/bash /system/xbin/busybox chroot . /bin/bash export PATH=$PATH_ cd .. umount /sdcard/arch/media/sdcard umount /sdcard/arch/dev/pts umount /sdcard/arch/dev umount /sdcard/arch/proc umount /sdcard/arch/sys umount /sdcard/arch losetup -d /dev/loop1 echo "Shutting down ArchLinux"
準備が終わったのでいよいよArchLinuxを起動してみます
ArchLinuxを起動するには
su
cd /sdcard
sh startarch.sh
で起動できます。
あとは普通のArchLinuxとして操作できます。pacman -S vim などで好きなパッケージを入れてください。ArchLinuxのパッケージマネージャはpacmanです、pacmanの詳細はArchLinuxのwikiを読んでください。
何度も言いますが、端末によってはうまく動かないので、そのときは各自で起動スクリプトを書き換えるなどしてください。
ポケモンキーボードと接続
さて、これでLinuxのインストールはできたので。スクリーンキーボードでコマンドを打って操作することはできるようにはなった。ただ使いづらくて仕方ないのでキーボードを接続します。
今回はDSのゲーム、ポケモンタイピングに付属するキーボードを使った。このキーボードはBluetooth接続でiPhone, PCなどにも普通に接続でき、スタンドまで付属していてamazonで2000円程度。他のbluetoothキーボードと比べても安い方だ。接続方法はFnキーを押したまま電源スイッチをオンにして、AndroidやiPhone, PCからBluetooth機器を検索すればNintendo Wireless Keyboardとして認識されるのでそのまま接続。次に画面に出る数字をキーボードに入力してEnterを押せば接続が完了する。
Androidにポケモンキーボードを接続すると。USキーボードとして認識されるのでJISキーボードとして認識してもらうためにキーアサインを変更しないといけない。
Androidのキーアサインについては以下のサイトを参照してください。
.klと.kcmファイルを用意すれば未知のキーボードにも対応できそうだ。
ポケモンキーボードでの注意点はESCキーだ。ESCキーは全角/半角キーと一緒になっていてESCを入力するときはFn+全角/半角を押さないといけない。これはvimを使用するときには不便なので、全角/半角キーの機能を殺して全角/半角キー = ESCキーとして動作するようにキーアサインを変更した。
というわけでキーアサインを変更する以下の2つのファイルを@hiromo6さんの作成されたファイルをベースに作成しました。
それぞれのファイルを
- /system/usr/keylayout/Nintendo_Wireless_Keyboard.kl
- /system/usr/kaychars/Nintendo_Wireless_Keyboard.kcm
となるようにコピーする。このとき/systemはデフォルトでは書き込みできないので。/systemを書き込み許可にして再マウントしなきゃいけない。Galaxy Nexusの場合は以下のコマンドで/systemを再マウントできる。
mount -o remount,rw /dev/block/platform/omap/omap_hsmmc.0/by-name/system /system
他のandroid端末の場合は別のコマンドになるので各自調べて下さい。
ターミナルエミュレータ
ターミナルエミュレータにはConnectBotの強化版であるVX ConnectBotを使った。が、ctrlキーの挙動が変(ConnectBotの仕様?)なのでソースコードを一部書き換えた。もちろんソースコードを変更するのでandroidの開発環境が必要です。
まずvx / connectbotからソースコードを落としてきてsrc/sk/vx/connectbot/service/TerminalKeyListener.javaの133行目付近のhardKeyboardHiddenをtrueに変更する。
diff --git a/src/sk/vx/connectbot/service/TerminalKeyListener.java b/src/sk/vx/connectbot/service/TerminalKeyListener.java index a5a7af9..555d42c 100644 --- a/src/sk/vx/connectbot/service/TerminalKeyListener.java +++ b/src/sk/vx/connectbot/service/TerminalKeyListener.java @@ -130,7 +130,7 @@ public class TerminalKeyListener implements OnKeyListener, OnSharedPreferenceCha */ public boolean onKey(View v, int keyCode, KeyEvent event) { try { - final boolean hardKeyboardHidden = manager.hardKeyboardHidden; + final boolean hardKeyboardHidden = true; // Ignore all key-up events except for the special keys if (event.getAction() == KeyEvent.ACTION_UP) {
正直に言うとなぜtrueにするとうまく動くのかわかってないです。詳しく書くと、hardKeyboardHiddenがctrlキーの挙動に関わっているようで、これがtrueだとctrlキーは正しく動く。Android起動直後にVX ConnectBotを起動した時はtrueなのですが、一旦HOMEに戻ってもう一度VX ConnectBotを起動するとfalseになっているという謎挙動をするので、強制trueにしています。これで今のところ大きな問題は出てないので大丈夫だと思います。
これで持ち運びできるLinux環境の完成です。Galaxy NexusはUSBホストも持っているのでUSB変換コネクタを接続すれば、Androidに対応していないUSB機器でもArchLinux側が対応していればArchLinux側から操作できます。たとえばAndroid上で動作しているArchLinuxからUSBメモリにアクセスするには
mount /dev/block/sda /mnt
でUSBメモリの中のファイルにアクセスできます。
ポケモンキーボードを使うことでほぼPCと同等のLinux環境をAndroidで実現することができました。これならRaspberry piにも負けない小型PCとして使えるのではないでしょうか。
iPhoneやiPadの充電器の自作について
普通に5V供給してやるだけでは、充電してくれないようなので。充電モードにするのにどんな細工が必要かちょっと調べてみた。
軽くググったら以下のサイトがUSB端子の各電圧について書いてある。
- Apple iPod, iPhone (2g, 3g), iPad Dock connector pinout and connections @ pinouts.ru
- Choosing USB Pin Voltages for iPhones and iPads – Update for iPhone 5 | Voltaic Systems – Solar DIY and Device Charging
- How to make your own iPad 2 USB Charger (DIY iPad 2 USB Charger)
各サイトの示すUSB端子電圧には多少ばらつきがあるけど、だいたいD-は2.75V D+は2.0Vで良さそうだ。
D+ | D- |
---|---|
2.0V | 2.75V |
まだ実際にテストしてないので試すときは自己責任で
追記
英語版wikipediaのUSBのページにiPod/iPhoneの充電電流について書かれていた。
(D-)=(D+)=2.0Vの時500mA
(D-)=2.8V (D+)=2.0Vの時1000mAになるようだ。
LPC1343のデバッグ環境の構築
ねむいさんのブログにSTM32VL-DiscoveryをVersaloon化する記事があったので、Versaloon化したSTM32VL-DiscoveryでLPC1343のデバッグをしてみようとした。まあ結局記事に書いてある方法と同じように試したけど、うまく行かなかったので自己流で最新のVersaloonファームウェアの用意からopenocdのビルド、インストールまでやりました。ちなみにUbuntu11.10上で行なっています
まずSTM32VL-Discoveryの改造
やってることはねむいさんのブログの記事と同じです
UARTブートローダを有効にするためのジャンパーの配線とUARTの配線
ファームウェアの書き込みが終わったらジャンパーは外します
firmwareの準備と書き込み
ここからやり方が変わります
STM32VL-DiscoveryのST-Linkに書き込むファイルの準備
svn checkout -r 1054 http://vsprog.googlecode.com/svn/trunk/ vsprog-read-only
バージョンによってうまく動かないことがあります。私はrev1054を使いました。とりあえずうまく動いてます
makefile を書き換え
vsprog/dongle/firmware/Projects/Versaloon/GCC/makefile 18行目 HW_BOARDの値を変更
HW_BOARD = STM32VL_Discovery
ブートローダーを使わないのでリンカスクリプトを書き換える
vsprog/dongle/firmware/Projects/st-discovery.ld 17行目 0x8002000 から 0x8000000 に変更
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 56K
makeでVersaloon_GCC-STM32VL_Discovery-0x0000.binが生成される
あとは生成されたファイルをFlashLoaderDemonstratorを使って書き込みます。書き込み方法はねむいさんのぶろぐ | SWD専用Versaloonクックブックを参照
openocdのインストール
insightを使うためのarmv7mx.patchを用意
ねむいさんのぶろぐ | ARMマイコンをInsightとOpenOCDを使ってデバッグする環境を整える(2013年度前半版)からopenocd_misc.zipをダウンロードする
展開すると3つファイルがありますが使うファイルはarmv7mx.patchのみです
openocdインストールスクリプトとパッチの用意
Versaloonの旧フォーラムからoocd-16-aug-2011.tar.gzをダウンロードして展開
armv7mx.patchを展開したフォルダoocd-16-aug-2011に移動
openocd_update_0.5.0の書き換え
patch -p1 < ../armv7mx.patch;openocd_update_0.5.0を実行
sudo sh openocd_update_0.5.0うまくいけばopenocdのインストールまで勝手にやってくれます。 openocdのcfgファイルもねむいさんの(ryからダウンロード insightのダウンロードと設定もねむ(ry insightでデバッグ 最後に、ねむいさんのブログがものすごく役に立ちました。ねむいさんありがとう
GCCでLPC1343用のバイナリをビルドする
結構前に買ってずっと放置されていたlpcxpresso nxp 1343をそろそろ使ってみる。OSを何度も変更する自分にとってはlpcxpressoIDEのプロダクトコードの入力とかめんどくさいので、GCCでlpc1343のバイナリを作成します。
Lチカサンプルコードと必要なファイルの入手
http://ics.nxp.com/support/lpcxpresso/からLPC1300 Seriesの下のリンクからExample Projectsをダウンロード
適当なフォルダ(ここではblink)を作って、examples.lpc13xx.zipからLチカに必要な以下のファイルをコピー
- CMSISv1p30_LPC13xx/src/core_cm3.c
- CMSISv1p30_LPC13xx/src/system_LPC13xx.c
- CMSISv1p30_LPC13xx/inc/core_cm3.h
- CMSISv1p30_LPC13xx/inc/system_LPC13xx.h
- CMSISv1p30_LPC13xx/inc/LPC13xx.h
- blinkly/src/blinkly_main.c
- blinkly/src/clkconfig.c
- blinkly/src/clkconfig.h
- blinkly/src/config.h
- blinkly/src/gpio.c
- blinkly/src/gpio.h
- blinkly/src/timer32.c
- blinkly/src/timer32.h
あといくつかのファイルを以下のリンクから持ってきてblinkにコピー
- https://github.com/microbuilder/LPC1343CodeBase/blob/master/lpc1xxx/linkscript.ld
- https://github.com/microbuilder/LPC1343CodeBase/blob/master/lpc1xxx/LPC1xxx_startup.c
- https://github.com/microbuilder/LPC1343CodeBase/blob/master/lpc1xxx/LPC13xx_handlers.c
firmware.binをUSB経由で書き込み、動作させるためにlpcrcを用意しblinkに配置
GCCでビルドしたfirmware.binはそのままでは問題があるようでlpcrcでfirmware.binを書き換えないといけない。書き換えるとうまく動作した。よく調べてないので理由はよくわからないけど動いているから問題はないはず。
Makefileはhttps://github.com/vsergeev/mbed-cmsis/blob/master/Makefileを修正した
以下のMakefileをblinkに保存
Makefile
# LPC1343 make Sample PROJECT=lpc13xx_blink OBJECTS=LPC1xxx_startup.o LPC13xx_handlers.o core_cm3.o system_LPC13xx.o blinky_main.o clkconfig.o gpio.o timer32.o LSCRIPT=linkscript.ld OPTIMIZATION= 0 DEBUG= -g # Compiler Options GCFLAGS = -Wall -fno-common -mcpu=cortex-m3 -mthumb -O$(OPTIMIZATION) $(DEBUG) GCFLAGS += -D__RAM_MODE__=0 #GCFLAGS += -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch #GCFLAGS += -Wredundant-decls -Wreturn-type -Wshadow -Wunused LDFLAGS = -mcpu=cortex-m3 -mthumb -O$(OPTIMIZATION) -Wl,-Map=$(PROJECT).map -T$(LSCRIPT) ASFLAGS = $(LISTING) -mcpu=cortex-m3 --defsym RAM_MODE=0 # Compiler/Assembler/Linker Paths GCC = arm-none-eabi-gcc AS = arm-none-eabi-as LD = arm-none-eabi-ld OBJCOPY = arm-none-eabi-objcopy REMOVE = rm -f SIZE = arm-none-eabi-size ######################################################################### all: $(PROJECT).bin $(PROJECT).bin: $(PROJECT).elf $(OBJCOPY) -O binary -j .text -j .data $(PROJECT).elf $(PROJECT).bin mv $(PROJECT).bin firmware.bin ./lpcrc-linux firmware.bin #$(PROJECT).hex: $(PROJECT).elf # $(OBJCOPY) -R .stack -O ihex $(PROJECT).elf $(PROJECT).hex $(PROJECT).elf: $(OBJECTS) $(GCC) $(OBJECTS) $(LDFLAGS) -o $(PROJECT).elf stats: $(PROJECT).elf $(SIZE) $(PROJECT).elf clean: $(REMOVE) $(OBJECTS) $(REMOVE) $(PROJECT).hex $(REMOVE) $(PROJECT).elf $(REMOVE) $(PROJECT).map $(REMOVE) $(PROJECT).bin $(REMOVE) $(OBJECTS) $(REMOVE) firmware.bin ######################################################################### # Default rules to compile .c and .cpp file to .o # and assemble .s files to .o .c.o : $(GCC) $(GCFLAGS) -c $< .cpp.o : $(GCC) $(GCFLAGS) -c $< .S.o : $(AS) $(ASFLAGS) -o $@ $< #########################################################################
ファイルの修正
いろんなところからファイルを集めてきたのでファイルを少し修正します
スタートアップコードの修正
LPC1xx_startup.cはmain()を呼ぶ前にSystemInit()を呼び出すように変更
38と39行目の間にextern void SystemInit (void);を追加
extern void SystemInit (void);
60と61行目の間にSystemInit();を追加
SystemInit();
リンカスクリプトの修正
linkscript.ldの30行目あたりにMEMORYの記述を追加
MEMORY { flash(rx): ORIGIN = 0x00000000, LENGTH = 32k sram(rwx): ORIGIN = 0x10000000, LENGTH = 8K }
あとはmakeコマンドでバイナリが作成されます。
書き込み
firmware.binの書き込みはhttp://hp.vector.co.jp/authors/VA000177/html/LPCXpresso.htmlに書いてあるのでそれを参考に、USBコネクタ取り付けて、firmware.binを書き込む
やっと動きましたー。やったね!
ここまで書いてあれだけど、こんな面倒なことをしなくてもhttps://github.com/microbuilder/LPC1343CodeBaseに別のサンプルソースコードがあるのでそれ使ってもいいと思います。
エアコンをネットから操作するデバイスを作ってみた
冷房が効いた部屋に入るときの涼しさのために、エアコンをネットから操作するデバイスを作ってみた。まあもう気付いたら秋になってしまったのですが。とりあえず完成したので、公開してみます。
動画はこちら
参考サイトやプログラム
- AVR-Ethernet - スイッチサイエンス
- tuxgraphics.org: Introduction to the tuxgraphics TCP/IP stack, 3rd generation
- RemoteIR
- ELM - 赤外線リモコンの通信フォーマット概要
- PSP IR wave viewer
AVR-Ethernetのページにのっている回路を参考に赤外線LEDを追加したものです
コードはtuxgraphics.orgのeth_tcp_client_server-4.3をベースにRemoteIRを追加したような感じになっています。
webから操作
iPhoneなどから操作出来るようになっています。これで外出先からでもエアコンのon/offが可能。
ダイキンのエアコンに対応させる
自室で使っているエアコンはダイキン製で当然RemoteIRは対応していません
テレビのリモコンのフォーマットはすでにいろんなサイトで情報が載っていますが、エアコンのリモコンはテレビとは違うもフォーマットなので、いくら調べても情報が出てきません。
そこでまずリモコンから出ている信号の解析から始めました。ロジックアナライザがあれば簡単に解析できそうですがロジックアナライザは持ってないので、他に解析する方法はないか調べたらPSP-1000で動作するPSP IR wave viewerを発見。これを使ってリモコンの信号の解析をしました。
これをPCに取り込んで信号を解析してみると、テレビのリモコンのフォーマットに似ていた。フォーマットは似ていたのでRemoteIRをちょっと改造してリモコンがら出ているデータと同じ信号がでるようにしてやるとうまくエアコンが動いてくれました。これで赤外線系は完成。メーカーによってフォーマットが全然違うから他のエアコンに対応させるのはちょっと大変だ。
ソースコードはGithubにUPしてみました。
https://github.com/strobo/eth_air_controller
ちなみに開発環境はFedora15 avr-gccのバージョンは4.5.3
あとMake: Tokyo Meeting 07行きたい
sparkfunのBluetoothモジュールBluetooth Mateのメモ
大阪の日本橋に行ってきたときに衝動買いしたBluetooth MateをUbuntu11.04と接続してみる。忘れないようにメモしておく。
参考サイト
- sparkfunのBluetooth Mateのページ下のDocuments
- Ubuntu/Bluetoothシリアルポート - DebugIto's
- SparkFunのBluetoothモジュールのコマンドモードへの接続手順です。 | dietposter's blog
BluetoothMateはデフォルトでSPPスレーブとして動作します。
ubuntu11.04で接続した時のメモ
rfcomm bind 1
このコマンドでBluetoothMateと接続
- /dev/rfcomm1を使って通信できます
- 電源投入後60秒間コマンドモード移行待ち状態でその間にペアリングして"$$$"と送信してやるとコマンドモードに入り設定の変更ができます。コマンドはRN-41 AT Command Set(PDF)を参照。
- 60秒過ぎると"$$$"でコマンドモードには入れなくなる。
- コマンドモードから抜けるには"---
" - ビットレートはデフォルトで115200
- UART経由でも"$$$"でコマンドモードに入れる。こっちはいつでも"$$$"でコマンドモードに入れるみたい。ただしbluetoothでどことも接続していない時のみ。
screen /dev/rfcomm1 115200
この方法では接続できなかった。参考サイトの「Ubuntu/Bluetoothシリアルポート」のように、minicomを使えばうまく接続することができた