2016/04/22

マウスパッド表面評価のためのセンサー可視化デバイス

はじめに

ADNS-3090とADNS-9800というゲーミングマウスのセンサが、マウスパッドをどのように「見て」いるのか、というセンサの視界を人にも見える化するシステムを作りました。こういったシステムがあると、ソール厚に関する知識を深めたり特定のマウスパッドへの相性問題を解決したりモヤモヤした画像を見て悦に入ったりと色々なことが出来ます。
要するに、マウスとマウスパッドの間に問題が起きた時にデバッグしたり、更にマウスの性能を引き出したりする時に手助けとなる道具です。ただ闇雲にデバイスを買って試すのではなく、色々な道具を作って科学的/工学的な観点でデバイスを評価するのも私は良いと思うのです。

前の記事との差分としては、現役で活躍しているゲーミンググレードのレーザーセンサとLEDセンサの双方で「見る」ことが出来るようになったのは意義があるでしょう。記事のような色々なマウスパッドの表面画像についてはそのうちまとめます。

ハードウェア

まずはセンサとMCUについてハードウェアの面で説明します。

ADNS-9800

ADNS-9800は色々と訳あってセンサモジュールを購入しました。
ADNS-9800のセンサモジュール with ジャンパワイヤ
代理店を介さずにゲーミンググレードのセンサを購入できる場所は少ないです。結構探したのですがこのサイトしかありませんでした。送料が$60という恐ろしい数字だったので非常に痛い出費ですが、個人に売ってくれるだけありがたいです。
送料分を取り返すためにモジュールに加えてバニラなセンサとレンズのセットを数組購入しましたが、使用予定は・・・In progressということで。

センサモジュールはピンアサインがはっきりしているので説明通りに繋ぐだけで大丈夫です。
このモジュールは探せばArduinoのサンプルもあるので、Arduino持っていれば誰でも動かせると思います。

ADNS-3090

ADNS-3090はELECOM M-XG3Gのセンサを使用しました。
3000円程度で完動するセンサモジュールが手に入るのは素晴らしい・・・(とか考えてるのは日本で私くらいしか居ないのかもしれません。)

購入した時はマウス自体のMCUがセンサのマスタになっているので、データパスを切る必要があります。
ADNS-3090のSROMがなかなか見つからないのでデータパスを切る前にSROMを事前に吸い出す予定でしたが、「ADNS-3090は部品としては手に入らないセンサなのでSROMを持っておく必要もないのかな」と考えてデータパスをぶった斬りました。RIP。
データパス切断の図。中央の傷の部分でレジストごと配線を切っています。
切る必要があるのは、NCS、MISO、SCLK、MOSI、RESET、NPDです。
最近のマウスはほとんどが両面基板なのでビアを追うのが面倒ですが、センサ付近から追っていって切りやすい部分で切ればいいと思います。

外観はゴミを寄せ集めたみたいな手作り感溢れるアットホームな感じです。自分のMCUからの配線はセンサの足に直付けしています。こうすると基板の上側から配線を引き出せるので非常に便利です。
システム外観。

MCU

センサを制御してもらうMCUはいつものCY8CKIT-042 PSoC 4 Pioneer Kitです(上写真右の赤いボード)。
プログラマ不要の開発ボードで、秋月で税込み3000円で買えます。Arduinoみたいなピンアサインで、しかもリセットしてもCOMポートの接続が切れないのでとても便利です。
センサから生やしたジャンパワイヤをしかるべき所に繋ぐだけで準備完了。


ソフトウェアの実装

あんまり面白いことはしていないのですが、概要は下のようになります。
  1. MCUがセンサにFrameCaptureをリクエスト
  2. センサが画素データを返す
  3. MCUが画素データのバイナリをUART→USB経由でPCに転送
  4. ホストのアプリがバイナリを受け取り、グラフとして描画
  5. 1~4を繰り返す

ホスト(PC)のプログラム

ホスト側はネイティブアプリを書くのも面倒なのでPythonのserialモジュールと、matplotlibモジュールでお茶を濁していくスタイル。matplotlibは動画も撮れたり、画像の補完方法も豊富なので結構便利ですね。

MCUのファームウェア

MCU側はフンハフンハ言いながら実装するとできます。いくつかセンサを触った経験から言うと、とりあえずProductIDを取得出来るようにする→大体の事は出来るようになる。という感じなのでデータシートをよく読みながら実装すればよいでしょう。

注意する点としては、ADNS系のセンサはNCSの扱いが特殊なので、そこに工夫が居る点です。
MCUからのレジスタアドレスとして1バイトの送信が終わってNCSをHIGHにしていまうと、うまく動きません。なので、NCUはMCUのSPIの処理とは別に制御する必要があります。
PSoCの場合は、SPIのNCS(SS)はSPIコンポーネントには接続せず、別にDigital Output Pinを用意すれば良いです。
基本となるRead/Write Operationsコードはこんな感じになります。ここでは、NCSとしてSSというピンを用意して、適宜HIGHにしたりLOWにしたりしています。
--------
void Write_Operation(uint8 address , uint8 value )
{
    address = address | 0b10000000; //MSBを1にしてWriteだと伝える
    SPIM_ClearRxBuffer(); //バッファクリア
    SPIM_ClearTxBuffer();
    SPIM_ClearFIFO();
    
    SS_Write(0); //NCSをLOWに。送信開始
    CyDelayUs(1); //ディレイが必要。時間はセンサによる。
    
    SPIM_WriteTxData(address); //書き込み先のレジスタアドレス送信
    
    SPIM_WriteTxData(value); //書き込み先のレジスタに書き込む値を送信
    while(!(SPIM_ReadTxStatus() & SPIM_STS_SPI_DONE)){}; //終わるまで待つ
    CyDelayUs(1);
    SS_Write(1); //NCSをHIGHに。送信終了
    SPIM_ReadRxData(); //SPIのRxに入ったゴミデータを捨てる
    SPIM_ReadRxData(); //SPIのRxに入ったゴミデータを捨てる
    CyDelayUs(120u); //ディレイが必要。時間はセンサによる
}

uint8 Read_Operation(uint8 address)
{
    address = address | 0b00000000; //MSBを0にしてReadだと伝える
    SPIM_ClearRxBuffer(); //バッファクリア
    SPIM_ClearTxBuffer();
    SPIM_ClearFIFO();

    SS_Write(0); //NCSをLOWに。送信開始
    CyDelayUs(1); //ディレイが必要。時間はセンサによる

    SPIM_WriteTxData(address); //取得先のレジスタアドレス送信
    while(!(SPIM_ReadTxStatus() & SPIM_STS_TX_FIFO_EMPTY)){}; //送信が終わるまで待つ
    CyDelayUs(100); //ディレイが必要。時間はセンサによる

    SPIM_WriteTxData(0x00); //0x00を送る間にデータが帰ってくる
    while(!(SPIM_ReadTxStatus() & SPIM_STS_TX_FIFO_EMPTY)){}; //送信が終わるまで待つ
    while(!(SPIM_ReadRxStatus() & SPIM_STS_RX_FIFO_NOT_EMPTY )){}; //RxFIFOに1個目のデータが来るまで待つ
    SPIM_ReadRxData(); //一個目はゴミなので捨てる
    while(!(SPIM_ReadRxStatus() & SPIM_STS_RX_FIFO_NOT_EMPTY )){}; //RxFIFOに2個目のデータが来るまで待つ
    SS_Write(1); //NCSをHIGHに。送信終了
    CyDelayUs(120u); //ディレイが必要。時間はセンサによる
    return  SPIM_ReadRxData(); //レジスタから取得したデータを呼び出し元に返す
}
--------
弱いコードですが大目に見て下さい。
ちなみにFrameCaptureを動かすだけならSROMは必要ないので色々なセンサで試すことが出来るでしょう。


動かしてみた

画像や動画はCOUGAR Control Mouse Padの滑走面を撮影したものです。

ADNS-3090の画像

ADNS-3090は画素が0~63の値をとるようなので、ADNS-9800(0~127)の値から2倍になるようにしています。
ADNS-3090
ADNS-5090(下図)を高解像度化したような印象です。センサ素子がADNS-5090は19x19ですが、ADNS-3090は30x30になったためですね。視野の範囲などの考察はまたいずれ。
ADNS-5090


ADNS-3090の動画

動画にするとこんな感じです。適当に動かしています。後半でマウス全体を一度持ち上げていますが、3090ではシャッター値がMAXになると白飛びに近い状態になるようです。



ADNS-9800の画像

ADNS-9800はこんな感じに映ります。
ADNS-9800
見た印象だと全然同じマウスパッドに見えません。これはLED式センサと比較すると、見えている範囲がものすごく小さいためです。LED式センサでは「山」が2個くらい画面内に映るのですが、「山」ひとつでフレームアウトするような感じです。詳細な比較はまたいずれ。

また、ADNS-5090やADNS-3090のようなLEDセンサと比較すると、「のっぺり」とした印象になります。これは、レーザの射角が滑走面に対して深いためです。LED式センサではほぼ真横にLEDが付いていて、それをレンズで屈折させて滑走面を照射しており射角が浅いのですが、レーザ式の場合はセンサダイの真横にレーザ素子があり、そこから下図のようにレンズで屈折させて射角が深くなっています。射角が深いため、「影」となる部分が少なく、LED式と比較してコントラスト比が小さくなると考えれます。
Pixart ADNS-6190-002 データシートより
他にも「レーザースペックルがどうのだからDPIが・・・」みたいな考察もあるので、もう少し裏を取ってから別記事で上げたいと思います。

2 件のコメント:

  1. デバイス勢待望のハイエンドセンサーでの実装お疲れ様です。

    映像が高解像度で滑らかなのが見易くて素晴らしいですね。
    手持ちのマウスパッド全部見てみたいです。
    リフトオフするとシャッター解放値にり白飛びする、という映像も見れて良かったです。
    ADNS-9800のキャプ映像がLED-Based系と全然違うのも興味深いですね。
    VCSEL型とLED-Based型でトラッキング面との相性の傾向が違うのは
    体感的には認知されている案件ですが
    それを視認できる面白さは堪らないですね:)

    将来このような綺麗なリアルタイムセンシング映像を見れる機能を搭載した
    マウスウェアを開発する気合の入ったメーカーの登場を心待ちにしています:)
    そしてセンサー純正レンズでなく、スマホのような薄型オートフォーカスレンズを搭載し
    ボタン一つでSQUAL最大となるように焦点距離を自動調整してくれるような
    ゲーミングオートフォーカスとか
    Enthusiast向けとして、マウスウェア上でセンサーからの映像を見ながら
    焦点距離をマニュアルフォーカスさせてくれるオプションとか登場して欲しいです。
    トラッキングの信頼性向上にどこまで貢献するかはさて置いてガジェット的に楽しめますから:p

    systema様の開発によって色々と妄想が捗りました:)

    返信削除
  2. rafa様、
    コメントありがとうございます。

    レーザとLEDで光の当たり方が違うことと、視野の広さの差で画像が全く違うものになりました。
    今後、もう少し掘り下げて調査して、双方の特性の違いやメリット・デメリットを議論したいと考えています。

    フォーカスに関してはかなり興味深いです。現状で動かしている3センサについてフォーカスを整理すると、

    ①E-Blue Mazer Type-R(ADNS-5090)の筐体はソールなしでも滑走面に対してレンズが高すぎる
    ②ELECOM EX-G(ADNS-3090)の筐体はソールなしで少しレンズが低い(おそらくソールありでぴったり)
    ③Perixx MX-2000IIBにADNS-9800のモジsュールを付けた筐体はソールなしでも滑走面に対してレンズが高すぎる

    というようになっています。
    これは意図的な設計なのか、それとも設計ミスなのかという検証も必要そうです。
    ソール張り替えや,マウスパッドの変更によって適切なフォーカス位置は変化しうるので,自動調整できる機構や,ユーザが調整できる機能があれば便利になりそうですね.

    返信削除