HMDつくりました〜ハード編

前々から作っていたHMDがとりあえず形になったので報告します。いきなりですが、これがその写真です。


ごてごてしてますね。

96.4g*1で、正面のカメラ二台で撮った映像をPCに送って、(加工した後)QVGAのディスプレイ二枚に表示できるといういかにもAR用な仕様です。当然左右のディスプレイは独立なので立体視出来ます。今のところ画像をそのまま転送する場合で10fpsというちょっと残念な速さです。*2


その他には三軸加速度センサと二軸磁気センサが付いているので、これとkinectの深度データを合わせると頭の位置と向きが確定できます。*3


この記事では主にハードウェアを技術的な面から書こうかと思います。

概要

http://lh4.ggpht.com/_aTfNhGxuXkI/TQxowSTqfwI/AAAAAAAAAjs/u2c8UYnxEww/s800/electronics.png


図にもあるように電源はバスからとっていて*4、内部的にも各機能への信号の分配はUSBで行っています。ここは一見USB付きのマイコンを使って、マイコンが他の全ての面倒を見る方がシンプルに見えるかもしれませんが、Hi-Speedの恩恵を受けるにはかなり高性能(そして複雑)なものである必要がある上に、何らかの問題が起きてUSBのセッションが途切れると全機能が使えなくなる、どのみちwebcamはUSBで接続するのだからUSBハブは必要、等の理由でこのようにデザインしました。


今回自前で作ったのは、

  1. USBハブLCDドライバを含む主基板
  2. USB接続センサ基板
  3. 可動レンズ付きフレーム

の三点で、以下で順を追って説明します。

主基板

この基板の機能は上の図のとおりで、下流向けにUSBを分割することと、LCDの制御をすることです。

USBハブは大きさを気にしなければ市販の物が使えるわけで、開発初期にはLCD制御を中心において以下のような感じで進めて来ました。

  1. arduinoLCDを制御
  2. Strawberry Linux製のFT2232HボードとCPLDで制御(ver.1) ここでデバッグのストレスに耐えかねてロジアナ購入
  3. 重さと大きさがやばい(300gくらい)に気付き、USBハブと統合する形でのPCB化を考えはじめる。
  4. ver.2 rev.1基板完成。d:id:xanxys:20100918:1284812027 電源容量が足りてない+数カ所のミスが発覚。安定動作しないのでドライバのデバッグできず。
  5. ver.2 rev.2基板完成。ほぼ想定通りだが、パフォーマンスの問題が発生(←イマココ)

ver.2 rev.1と同じくDesignSpark PCBで設計しています。


今回使ったLCDのREL225L01はどうやら携帯電話のディスプレイのジャンクのようなのですが、ロジックに3.0VそしてLEDバックライトに5〜8V程度と変則的な電圧を要求する関係上、結果的には1.8V,3.0V,3.3V,5.0V,6.0Vの五電源が混在するややこしい回路となりました。


(注:ほとんどの値は実測ではありません)


以下ではここで使われている部品について書いていきましょう。

CY7C65630: 4ポートUSBハブ

USB 2.0のハブです。面倒なので過電流検出ピンは無効側に固定してあります。この下にHi-SpeedのwebcamふたつとFT2232H、そしてLow Speedのセンサ基板で計四つのデバイスが接続されます。四つのうち三つはHSなので、Transaction Translatorはひとつでも大丈夫です。*5

REL225L01: 18bit parallel QVGA LCD

aitendoで買ったものです。電源が残念なのと、まともなデータシートがついてないので結構苦労しました。まぁ安いから仕方ありませんね。謎のコマンドをたくさん送って初期化した後、データをパラレルに送ります。どうやらフレームバッファは内蔵されているようなのでその点は楽でした。

XC2C64A: シリアル/パラレルコンバータ (Xilinx CoolRunner 2)

FT2232Hから出るシリアルな信号を18bitパラレルに変換して、さらに!WRを生成します。XC2C128Aなどではなく、XC2C64Aをふたつ使っているのはPCB上での配線の取り回しの都合です。

FT2232H: デュアルUSBシリアルコンバータ

モードなどについて詳しくはデータシートを読んで頂くこととして、今回はMPSSEを2ポート使用しています。*6これはホストからコマンドを送ると最高30MHzでシリアルにデータが出てくるモードなのですが、ここに誤算がありました。2ポートあるからバッファがうまく働けば60Mbpsでると期待したわけですが、実際には27Mbpsぐらいしか出ずに、これで10fpsという残念なことになってしまったのです。確かにデータシートをよく見るとFIFOモードで200Mbpsと書いてあるだけで、他の場合は書いてありません。ちなみにデータの転送はbulk transferで行われます。

LM3370: 2電源同期整流Buckコンバータ

2MHzで動くDC-DCコンバータです。これはかなり優秀で、小型な上に90%以上の効率でそれぞれ600mAずつ取れます。今回はUSBの5V電源から3.3Vと1.8Vを生成しています。

方向取得

赤いのが二軸コンパスのHMC6352で、緑のは三軸静加速度センサのMMA7260Qです。これはそれぞれI2Cとアナログ出力なので、これをUSBに変換してやる必要があります。できるだけシンプルにしたかったのでQFPのATmega168AにV-USBを載せています。ソフトウェアUSBなので当然Low Speed動作です。

初期化した後、メインループではセンサ2つに対応するFSMを手動で展開してusbPoll()と並列に実行します。
データレートはHMC6352の20Hzが律速*7、それをADCに通した値とまとめて1フレームとして保存しておきます。

二種類のコマンド(リセットとデータ要求)を定義して、データ要求が来ると最新の値を1パケットにして送り返します。これは8byte以下なのでLSのcontrol transferで問題ありません。

このモジュールの仕様は最初は決まっていなかったので(そのときはkinectの情勢を知らなかった!)別基板になっていますが、小型化を考えれば主基板に統合してもいいかもしれません。

フレーム

さて、ここまでで回路的なことはひと通り説明しましたが、当然それだけでHMDができるわけではありません。これらの部品をまとめて頭に取り付けられるような形に固定したり、LCDと眼の間で何らかの光学的変換を行う必要があるわけです。

一般的*8に両眼の間隔は65mmと言われていて、これを元に設計します。・・・とはいえこの部分はかなり適当で、現物(ie.自分の顔)合わせが非常に多い場所でもあります。例えばレンズの焦点距離*9を計算するとして、水晶体の収縮やら眼球の大きさやらを考えていたらキリがないわけです。それに、こと光学部品に関してはなかなか設計値通りの物が入手できる状況でもありません。あとノーズパッド、テンプル等の形状も試行錯誤です。*10

ノーズパッド


参考までに

そもそも重さが違いますし、本物の眼鏡のような物は絶妙な形なので諦めたほうがいいです。これにはその辺に転がっていた発泡材(詳細不明・固めのスポンジのような物)がムレも少なくて適切のようでした。

レンズ/遮光フード

レンズは硬質発泡ポリウレタン製の部品を介してアクリル棒にイモネジで固定されていて、距離を可変できます。*11レンズ自体は⌀21.5,f=25の球面(ほぼ片)凸レンズ(LAK14)を使っていますが、目を覆うためには⌀25,できれば⌀30は欲しいところで、この焦点距離と合わせて考えるとフレネルレンズを採用したほうがいいでしょう。


LCDとレンズの間から光が入ると画像のコントラストが落ちますし、没入感が損なわれます。そこで間を覆う必要があるわけですが、機械的強度が不必要な箇所に堅牢な構造を持ち込むのも不恰好です。蛇腹やゴムシート等を考慮した結果、ここは手芸的にフェルトとマジックテープが良いということで落ち着きました。これは安いですし、作るのも簡単です。

拡散板

LCDは通常バックライトから出た光がプリズムシートと拡散板、そして液晶パネルを経由して出てくるので既に拡散された状態です。しかし、今回のように目に比べてディスプレイの解像度が低い場合*12、ピクセル境界が立体的に浮き上がって見えて立体視を阻害します。そこでちょうど1px分ぐらいのブラーがかかるような板を用意する必要があるでしょう。

カメラ

Logicool C500を使っていますが、これはよくある安物のwebcamのようにレンズを回して調整しなくても(実際には固定されている)、室内では十分な範囲に焦点が合うようです(AFではありません)。

ソフトウェア

ここまででハードウェアについてはだいたい説明し終わりました。しかしPCを経由している以上、ドライバについて説明・・・と思いましたが特に言うことはないです。強いて言えばHaskellからFFIで呼べるようにしてある程度でしょうか?*13

しめくくり

冒頭でも述べたとおり、このHMDkinectと合わせてARであんなことやこんなことをするために作りました。現状最も大きな問題である低いfpsは解決法の目処が立っていますし*14、冬期休暇の間にはある程度進めたいところです。

*1:参考までに私の近視用眼鏡は16.3gなのでその6倍ほどの重さ

*2:この点については後ろの方に書いてます

*3:精度の評価はこれからなので、実際にどれぐらい使いものになるかは不明です

*4:規格外です。USB 2.0では最大500mAまでで、またホストへの電源容量の申請もしてません

*5:実は最初TTのことを知らなくて、適当に選んでいました。問題がなかったのは偶然と言えるでしょう。

*6:参考記事: d:id:xanxys:20101121:1290342164

*7:Continuous modeの最大値。もしかするとこれ以上でるのかもしれません。

*8:資料のURLは失念しました・・・

*9:LCDから18mm程離して使っています。とはいえ私は凄く視力が低いので他の場合に適用できるかは知りません。

*10:とはいえ100g弱もあれば、自重で落ちてくるわけで、HMDの上からヘッドセットを付けることで固定する運用をしています。

*11:焦点距離の調整は結構シビアで、0.5mmぐらいの変位でもかなりぼやけ具合が変わるので可動できることは重要です。

*12:中心窩の解像度と比べるということ。4k*4kぐらいあれば十分

*13:ちなみにこのHMDkinectは帯域の問題で同じホストコントローラに接続できません。最近のUSBポートがたくさん付いてるMBではフロント/リアパネルで別のコントローラになっているものが多いと思います。

*14:実行するかどうかは別問題