1. はじめに
特許「特開平4-208842」「平1-301147」によれば赤外線を分光解析することで糖度がある程度測定できるらしい。いわゆる非破壊検査みたいなものである。ということはこの原理を人体測定に利用すれば何かしらの生体情報が測定できるかもしれない。ということで赤外線領域のミニ分光器を作ってみることにした。ちなみに赤外線は0.7 – 2.5μmの近赤外線から波長がおよそ4 – 1000μmの遠赤外線があるが、今回はセンサーの測定領域である640nm-1050nmの近赤外線領域の分光装置となる。
2. 分光器の原理
いわゆる三角プリズムで光を分光してその分光された先にリニアイメージセンサーを置いてその強度を測定すればいい。最近の小型分光器は三角プリズムの代わりに非常に細かい格子(グレーティング)によりプリズムと同じ役目を行っているらしい。グレーティングはCD表面に光を当てたとき虹色に見られる現象と同じなので、CDを使ってもいいけど、それでは精度が出ないので今回浜松ホトニクスのミニ分光モジュールを利用することにした。
図 2 1に浜松ホトニクスのミニモジュール(C11010MA)の分光実装イメージ図を示します。
ガラスボディ上に実装されている反射型グレーティングにより光を分光させ、イメージセンサーでその色成分の強度をセンシングします。
3. H/W
3.1 ブロック図
今回は分光モジュールを用いてUSBのHID IF変換程度のことを行うだけなのでUSB IFとして使い勝手がいいPSoC(CY8C24794)を使用することにする。HIDのプロファイルはキーボード・マウスなどのユーザーインターフェスデバイス用いられるため最初からドライバーが入っており、どのようなPCでも基本動作する。
4. S/W
4.1 PC間インターフェス
USBのHIDプロファイルを使用する。PCソフトはBorlandのC++ Builder 6.0を使用する。USBライブラリは自作のUSB HIDコンポーネントライブラリを使用する。
エンドポイントバッファのサイズは以下の通り。
エンドポイント | バッファサイズ |
---|---|
IN(デバイス→HOST) | 22byte |
OUT(HOST→デバイス) | 8byte(実質2byteしか使用していない) |
4.1.1 デバイス→HOSTデータフォーマット
測定結果は600nm(オレンジ)~1100nm(赤外)間の波長を256等分する。1画素あたり14bit出力となるため1スキャンあたり512byteのデータとなる。USB HIDインターフェースを使用する。512byte分のデータを一度に転送することはできないため以下のようなフォーマットにする。
オクテット | INDEX | 内容 |
---|---|---|
1 | 0 | index(max255) |
2 | 1 | ADData1(high:13-8) |
3 | 2 | ADData1(low:7-0) |
4 | 3 | ADData2(high:13-8) |
5 | 4 | ADData2(low:7-0) |
6 | 5 | ADData3(high:13-8) |
7 | 6 | ADData3(low:7-0) |
8 | 7 | ADData4(high:13-8) |
9 | 8 | ADData4(low:7-0) |
10 | 9 | ADData5(high:13-8) |
11 | 10 | ADData5(low:7-0) |
12 | 11 | ADData6(high:13-8) |
13 | 12 | ADData6(low:7-0) |
14 | 13 | ADData7(high:13-8) |
15 | 14 | ADData7(low:7-0) |
16 | 15 | ADData8(high:13-8) |
17 | 16 | ADData8(low:7-0) |
18 | 17 | Temperature |
19 | 18 | DATA0LOW(Type0:可視光) |
20 | 19 | DATA0HIGH(Type0:可視光) |
21 | 20 | DATA1LOW(Type1:赤外光) |
22 | 21 | DATA1HIGH(Type1:赤外光) |
分光器センサーの出力は256通りである。1データあたり14bitのADコンバータにより量子化されるため、1データあたり2byte必要となる。
例えばindex=0のパケットデータではデータindex 0~7まで送ることになる。
従って次のパケットデータのindexは8となる。0,8,16,24,32・・・248までの32パケットで1つのスペクトラムデータとなる。18オクテット目の温度データは常に入るが、あまり変わらないデータとなるが、固定長で送った方が扱いやすいのでこのようなフォーマットにした。
4.1.2 HOST→デバイスデータフォーマット
オクテット | INDEX | 内容 |
---|---|---|
1 | 0 | Sensor Gain 0:Auto,1:HIGH,2:LOW |
2 | 1 | 照度センサーのGAIN 0:1倍 1:2倍 2:64倍 3:128倍 |
4.1.3 温度センサー
このミニ分光器の内部にDALLASの温度センサー(DS1775)が内蔵されており、I2Cインターフェースで温度情報を読み出すことができる。
デバイスアドレスは0x48。Configurationレジスタがあり、温度分解能、サーモスタット使用での温度閾値設定など設定できるが、今回すべてデフォルト値で使用することにした。デフォルトでは温度分解能が9bit(0.5℃)である。もともとこのセンサーの絶対精度が±2.0℃とのことなのでキャリブレーションを行わない限り温度分解能を高めても意味がないとの判断である。
温度情報は図 4 1および表 4 3に示す。デバイスからHOST PCには1byte(8bit)で温度情報を通知するため、表 4 3中の赤の点線で囲んだ部分の8bitデータをホストに通知することにする。
±64℃(0.5℃ステップ)となるが、通常この範囲であれば問題ないとの判断。温度は0℃基準の符号付き変数値として扱えば問題なさそう。
この温度データはPC側で2で割ることで0.5℃単位のデータとなる。温度情報は9bit設定の場合150msecの測定変換時間を要するため、PSoCマイコンからは200msec周期でデータを取り込むことにする。
4.1.4 照度センサー
可視光、赤外光両方に対応する。(センサーが2つ入っている)
4.1.5 VIDEOセンサー情報取り込み
イメージセンサーからはマイコンからのクロック(CLK)同期で画素アナログ値を順次出力する形となっている。必要な物理線はマイコンからセンサーに対してはST,CLKのみでセンサーからはVideo出力値(アナログ値)と測定終了を示すEOS信号となっている。
ここでポイントとなるのが「クロックパルスースタートパルスタイミング」(t(CLK-ST))であり、このタイミングで光電荷蓄積時間を決めるらしい。ただ、この設定時間の尤度が400ns~5msecとかなり広い!この値は適宜使用環境に応じて調整するような感じだと解釈した。そこでPSoCの内部タイマーのベースを125usecとし、図 4 3に示すようにタイミングベースにST0~ST5の状態を作りこれを元にイメージセンサー用の信号を作り出すことにした。
イメージセンサーの光電荷蓄積時間を決めるST3の状態は約125usec単位で調整可能となる。とりあえずはデフォルト125usecに設定して試験を行った。
4.1.6 感度Gain設定
このイメージセンサーはGainの設定(High/Low)があり、適宜最適な方を使用する。
4.1.7. 感度特性パラメータ
イメージセンサーは一般的に波長によってその感度特性が異なる。従って同じ強度の光を当てても出力値が異なるのでその感度による正規化を行う必要がある。そこでメーカーから図 4 4のようなデータをもらったのだが、実にこれが見にくい!縦軸が一見リニアに見えたけど、よく見るとどうも対数っぽい。測定をわけのわからん担当者に測定させたのがありありと判る。こんなデータを出してくるようではメーカーの信頼性がないなぁー┐(´~`;)┌といってもこのデータしか特性を特定するものがないので、これをもう少しちゃんとしたデータに置き直してみる。
いったんこれを印刷して定規でY軸上のデータを読み取り、対数値とリニア変換を考慮しながら特性を解読してみた。
今回モジュールに使用されているCMOSセンサーは256ポイントであり、このAD index値と波長との関係は近似式で
Wavelen = 1.7011*(index + 1) + 639.21 (nm)となる。・・・(式1)
ただし0 ≦ index ≦ 255
また、波長とセンサー感度を考慮した出力値はセンサーの一番感度が高いところ(AD index値18:約669.83nm)を基準”1”としてその他の波長での感度を とし、その波長での補正オフセット値を とする一次関数で表現できる。
Sout = a * Wavvelen + b ・・・(式2)
(式2)に(式1)を代入して
Sout = aindex * (1.7011(index + 1) + 639.21) + bindex ・・・(式3)
ここで aindex, bindexはそれぞれADindex値(波長)による正規化するための固有の値となる。
光が無い時のADの出力値はほぼ3500となっており、これを基準に正規化するためのパラメータを求めると
A/D index | 波長(nm) | 特性カーブ | 正規化係数(a) | 3500との差分(b) | |
---|---|---|---|---|---|
1 | 640.9111 | 1.88621698 | 1.06531434 | 3728.6002 | -228.6002 |
2 | 642.6122 | 1.90188290 | 1.05653929 | 3697.8875 | -197.8875 |
3 | 644.3133 | 1.91633365 | 1.04857210 | 3670.0023 | -170.0023 |
4 | 646.0144 | 1.92960368 | 1.04136099 | 3644.7635 | -144.7635 |
5 | 647.7155 | 1.94172688 | 1.03485924 | 3622.0073 | -122.0073 |
6 | 649.4166 | 1.95273659 | 1.02902460 | 3601.5861 | -101.5861 |
7 | 651.1177 | 1.96266564 | 1.02381881 | 3583.3658 | -83.3658 |
8 | 652.8188 | 1.97154629 | 1.01920711 | 3567.2249 | -67.2249 |
248 | 1061.083 | 0.67070347 | 2.99597972 | 10485.9290 | -6985.9290 |
249 | 1062.784 | 0.67717974 | 2.96732740 | 10385.6459 | -6885.6459 |
250 | 1064.485 | 0.68422096 | 2.93679105 | 10278.7687 | -6778.7687 |
251 | 1066.186 | 0.69184792 | 2.90441576 | 10165.4552 | -6665.4552 |
252 | 1067.887 | 0.70008183 | 2.87025589 | 10045.8956 | -6545.8956 |
253 | 1069.588 | 0.70894437 | 2.83437473 | 9920.3115 | -6420.3115 |
254 | 1071.289 | 0.71845765 | 2.79684404 | 9788.9542 | -6288.9542 |
255 | 1072.991 | 0.72864425 | 2.75774357 | 9652.1025 | -6152.1025 |
256 | 1074.692 | 0.73952721 | 2.71716033 | 9510.0611 | -6010.0611 |
この補正を行うことで感度の正規化を行うことができる。その一方、感度の低い部分は演算により無理矢理増幅しているため、ちょっとノイジーになる。(仕方ないことだけど・・・)
5. 評価・動作確認
5.1 白熱電球
白熱電球を測定したときの波形。「Sens Norm」は感度正規化「あり・なし」の設定。
赤外領域でもエネルギーが分布していることがわかる。
5.2 太陽光
5.3 赤外線LED
5.3 蛍光灯
可視光版の分光器(C11009MA)もあったのでついでにこの帯域の分光装置も製作しました。
それで近くにある蛍光灯を測定してみます。
6. まとめ
赤外線領域およびついでに可視光領域の簡易分光器ができたのでこれをどうやって使っていくかを考えていく必要がありそうだ。ある物体の赤外線の吸収特性を測定することでいろんなことが見えてくるらしいのだが、そのリファレンスとなるなるべく均一な赤外線成分を含んだ光源を用意してやる必要があり、ハロゲンランプあたりが良さそうな気もする。
今回の測定ソフトでは単に特性をリアルタイムでグラフ化する機能しかないが、物体の赤外線吸収特性を測定するのであれば相対的な値を表示する機能が必要になってきそうだ。