necomimiを改造して脳波データを取り出した

脳波で猫耳が動く「necomimi」が、なんと3000円台で投げ売りされて話題になっていました。僕も3150円で買いました。なんと中に入っている脳波チップを単体で買うより安い!(スイッチサイエンスではいま4980円)

頭に着けるための電極とセットになっているのにチップより安いだなんて!よしこれを改造してPCで脳波の値を取得できるようにしよう!

necomimiの分解・改造に関しては既に先人がいくつかのエントリーを上げておられます。まずこちら: nekomimiを分解してみた。シールを剥がすとネジが出てくるのでそれを回せば簡単に開くとの話。これはそのとおりでした。簡単でした。シールを剥がす時にノリが残ってネチョネチョにならないように慎重に剥がす必要があるけど。

上記スイッチサイエンスのページから各ピンがどういう意味かの説明PDFが見れます。Pin1が額でPin2がその線のシールド線(ケーブルがノイズを受けるのをキャンセルするためか)、Pin5が耳でPin4がそのシールド、じゃあPin3はどこにつながるんだ?Pin3も耳電極につながってるんじゃないかと思ったけども、テスターではPin5だけが耳電極と導通。耳たぶ電極は2つの金属で挟む形になっているけども、その片方だけがPin5と導通。これでいいのかなぁ。ちょっと不安。最悪の場合僕のnecomimiがのPin3の配線が断線している可能性も考えられる。手元には1個しかないので誰か他の人にPin3がどこにつながっているのか確認して欲しいところです。

あ、耳たぶ電極のことを「心拍センサ」と書いているブログを何処かで見かけましたけど、心拍センサはLEDと受光素子が向かい合わせになっている構造で、こっちは両方金属なので心拍センサでないことは明らかです。

さて次は心拍データをnecomimiの外に引っ張りだす配線をしましょう。こちらを参照:小ネタ。脳波チップTGAM1の出力はスイッチサイエンスのサイトに書いてあるとおり「UART(57600 baud、8ビット、パリティ無し、 1 ストップビット)」なので、このUARTのTXとGNDを引っ張り出します。僕は最初間違えてTXとRXを引っ張りだしてしまった…。ここのサイトのようにTXを回路から、GNDを電池ボックスから取る形に変更して、ちゃんと信号が取れるようになりました。

取り出したUARTの信号をUSB端子経由でPCで読むために、秋月のAE-UM232R(FT232RLを使ったUSB-シリアル変換基板)を使います。今回、チップは3.3Vと書いてあったので、以前自分が書いたエントリーAE-UM232Rで3.3V出力を出す方法を参考にしてジャンパピンを設定します。J1を1-2間ショートにする必要があります。

回路のクローズアップ。黒いケーブルがnecomimiのGNDにつながっていて、それが青いワイヤーでAE-UM232RのGNDにつながっています。白いケーブルがnecomimiのTXにつながっていて、これが3本のワイヤーを経由してAE-UM232RのRXD、反対側の5本目のピンにつながっています。

これで /dev/tty.usbserial とかからチップの出力が読めるようになります。おっと書き忘れていましたが僕の環境はMac OS X 10.7.5です。この出力をどうこうする上では、チップを作っているNeuroSkyがSDKを公開しているのでそれを参照するのがよいでしょう。thinkgear_connector_tgc [NeuroSky Developer - Wiki]Windows版とMac版のアプリが用意されています。アプリを起動したらそのアプリがシリアルを読みつつサーバになって、TCPで13854ポートをListenし始めるので、適当なプログラムからそこへ接続すればJSON形式でデータが送られてくる…はずなんだけどもJSON形式にする設定の仕方がわからずバイナリフォーマットで送られてきたので「Binary Socket Packet Format」を参考にして自分でパースしました。

ここでeSenseが返す「集中」と「瞑想」の値でグラフを書いてみるとなんと正弦波に。これはThinkGear Connectorを起動するときにシリアルデバイスの指定を間違っていてうまく接続できなくて、色々設定を変えて試している時にうっかり「Demo mode」をONにしてしまったからでした。デモモードをOFFにすると、今度はバイナリパケットのフォーマットは正しいのに、ペイロードが0の状態に…うむむ。よくわからないのでNeurosky提供のツールを使わないで自前でシリアル通信をしてみることにします。

あ、ちなみにnecomimiはモーター音がうるさいのでドラえもん化しました。モーターの部分も裏のシールを剥がせばネジ穴が出るので簡単です。白黒の信号線は耳電極のケーブルが出る穴を広げてそこから外へ出しています。

シリアル通信にはpyserialを使えばOK。こっちのフォーマットは上記ソケットを流れるバイナリフォーマットと似ているけども違うフォーマット(thinkgear_communications_protocol [NeuroSky Developer - Wiki]を参照)なのでパーサをまた書くのかー面倒だなーと思ったのですが、ちょっと調べてみたら既に書いている人がいました。

https://pypi.python.org/pypi/thinkgear/0.2

PyPIに上がっているので pip install thinkgear ってするだけでライブラリがインストールされます。というわけで数行のPythonスクリプトを書くだけでOK。ThinkGearRawWaveDataを表示しないで捨てているのは、これが生データのパケットなので画面があっという間に流れてしまうから。捨ててやると残りのパケットは1秒に1回の頻度で送られてくるので目視で観察するのに適当です。

import thinkgear

PORT = '/dev/tty.usbserial-A9004xwG'
for packets in thinkgear.ThinkGearProtocol(PORT).get_packets():
    for p in packets:
        if isinstance(p, thinkgear.ThinkGearRawWaveData):
            continue
        print p

このスクリプトの出力はこんな感じ https://gist.github.com/nishio/6260262

POOR SIGNAL: 26
ASIC EEG Power: EEGPowerData(delta=1087207, theta=316167, lowalpha=848603, highalpha=153512, lowbeta=225246, highbeta=115827, lowgamma=113654, midgamma=80802)
ATTENTION eSense: 0
MEDITATION eSense: 0
POOR SIGNAL: 51
ASIC EEG Power: EEGPowerData(delta=644431, theta=203717, lowalpha=354474, highalpha=333722, lowbeta=141786, highbeta=80020, lowgamma=73025, midgamma=72347)
ATTENTION eSense: 0
MEDITATION eSense: 0

脳波の強度が8つの分類ごとに表示されています。delta=644431, theta=203717, lowalpha=354474, highalpha=333722, lowbeta=141786, highbeta=80020, lowgamma=73025, midgamma=72347…と。

あれれ…やっぱりeSenseの集中と瞑想の値が0だな…。2通りのソフトウェアで両方うまく行かないってことはハードウェアの問題なのだろうか?? センサーからの信号の質を表すPOOR SIGNALは、ヘッドセットを外すと200になり、つけると26ぐらいまで下がるので良好な信号が得られているってことだと思うのだが…まさかこれが0にならないとeSenseの出力が出ないとか?

とりあえずここまでの情報でも誰かの役に立ちそうだと思うのでシェアしておきます。もしeSenseの値までとれた方がいましたら教えていただけるとありがたいです。

状況を整理するために追記

  • 分解前に普通に装着した状態で、耳はなんだかそれなりに動いていたけども、目を閉じて瞑想しようがアクションゲームをしようがはっきりわかる変化はなかった。この時点ですでに断線していた可能性が考えられるが比較対象がないのでよくわからない。
  • 脳波チップのPin3がセンサーに繋がっていないことを疑問に思っているが、比較できる別のデバイスがないので正しいのかおかしいのかわからない。誰かデバイスを持っている人に確認して欲しい。
  • ThinkGear Connecterでセンサーの値が0になってしまう現象を観測したのはドラえもん化の前。また、センサーからの信号でモーターがドライブされる回路の構造を考えても、モーターの回線を切ったことがセンサーからの出力に影響するとは考えにくい。
  • UARTから読み込んでパースするあたりが問題なく動いていることから、読み出しのための回路が壊れているとは考えにくい。回路が壊れてて「バイナリプロトコルに正しく従いつつeSenseの値だけ0」という出力が出てくる確率は低そう。
  • 「自分はeSenseの値もとれている、POOR SIGNALは0」という情報を頂きました。ということはシグナルの質が悪いのでチップがeSenseの値を出していないと可能性が高いか…その理由はなんだろう。やっぱりPin3が気になるので、これを耳センサにつないだりGNDにつないだりを試してみようかな。
  • 「PCにつないだせいでACアダプタからのノイズが脳波回路の方にまで流れてシグナルの質が下がっているのではないか、ACアダプタを抜いてバッテリー駆動にしたらどうか」というご指摘があったので試してみましたが、POOR SIGNALの値に変化はありませんでした。
  • 信号線とUART-USB変換基板の間にフォトカプラを挟んで電気的に絶縁する案も。
  • 「Pin3は耳電極の片側に導通していた」という情報を頂きました。信号の質が悪いのはPin3〜耳電極間が断線しているせい、という可能性が高まりました。次はこの修理を試してみたいと思います。