03-07-2020 03:07 PM - edited 03-07-2020 05:47 PM
草稿です。添付するサンプルファイルは「返信」で入れます。 VIをzipしても添付できなかったので、後日環境が整ってからということにしましょう。コメントは「返信」で入れてください。あるいは文字色を変えて追記・挿入してもらうのもわかりやすいかもしれません。
----------------------------------第7章の草稿----------------------------------
第7章 半導体センサを使ってみる
Arduinoをセンサのインターフェースとして、LabVIEWでスマートフォンや自動車などに使用されている半導体センサーを使う方法を紹介します。
[キーワード] 半導体センサ、心拍センサ、MAX30102 、I2C、SDA、SCL、プルアップ抵抗、スレーブアドレス、データシート、レジスタ、シリアルポート、キュー、生産者消費者デザインパターン、シングルトーン情報抽出 VI
7.1 スマートフォンや自動車に使われている半導体センサ
皆さんがお使いのスマートフォンには多くの半導体センサ、半導体アクチュエータが使われています。昔から使われている原理を使っていますが半導体の微細加工技術で小型で精度が高く、さらに周辺回路との一体化によって小さくて軽いセンサーやアクチュエーターになりました。スマートフォンを縦に持つと縦長画面、横に持つと横長画面になったり、スマートフォンの振り方でアプリを起動したりする機能は3軸加速度センサや3軸ジャイロセンサが使われています。カラオケで手にするマイクの大きさからは想像しにくい小さなマイクも半導体の微細加工技術が使われています。通信回路に使われるRFスイッチも半導体の微細加工技術が使われ始めました。自動車にも3軸加速度センサ、3軸ジャイロセンサ、圧力センサ、流量センサ、環境(大気圧/温度/湿度)センサ、空気質センサ、車載レーダーなど多くの種類のセンサが使われているとのことです。
小さくて高性能な半導体センサは、昔の電気部品のように自分でハンダ付けして使うことは難しくなりましたが、周辺回路と合わせてピンヘッダで利用できるモジュールとして購入することができます。加速度センサや環境(大気圧/温度/湿度)センサについてはArduinoでの使用例が豊富ですので簡単に使うことができると思います。
この章ではパルスオキシメータといって皮膚を通して動脈血酸素飽和度(SpO2)と脈拍数を測定するための機器に使われている半導体センサMAX30102を使ってみます。MAX30102は写真7-1の右側の基板中央の素子で、表面にガラスが貼られています。
7.2 心拍数を測定するセンサ
心拍センサは血流中の酸素と結合したヘモグロビンの割合で特定の光の波長の反射率が異なることを利用して心拍を検知しています。アナログ出力のセンサー(写真7-2)はArduinoで簡単に読み取れるために入門用として人気があります。指先や耳たぶに当てて心拍を計りますがきれいな信号が取れる場所を探り当てるのに手間取ることがあります。最近は同程度の価格でMAX30102を購入できるため使ってみることにしました。発光素子と発光光量を設定する機構、受光素子、AD変換、フィルター処理、通信インターフェースを統合した高性能な半導体センサです。動脈血酸素飽和度(SpO2)も測定できるセンサですが、今回は心拍だけを測定します。機会があれば動脈血酸素飽和度(SpO2)も測定してみてください。同梱されたピンヘッダをハンダ付けして使う必要がありますので半田ごて、ハンダが必要になります。どうしても、ハンダ付けをしたくない場合はスルーホール用テストワイヤで一時的にテストすることもできます。
7.3 Arduino用サンプルプログラムで動作確認
Arduino用のライブラリとサンプルプログラムを使って、MAX30102基板が正常で配線も間違っていないことを確認します。
ライブラリのインストールはArduino IDEの”スケッチ”メニューから”ライブラリのインクルード”さらに”ライブラリの管理…”を選択すると、”ライブラリマネージャ”ウィンドウ(図7-1)が表示されます。”検索をフィルタ・・・”と書かれている欄に”max3010x”と入力すると図7-2のように”SparkFun MAX3010x Pulse and Proximity Sensor Library”が表示されるので”インストール”をクリックする。”ライブラリマネージャ”を閉じてライブラリのインストールを終了します。
“ファイルメニュー”の”スケッチ例”から”SparkFun MAX3010x Pulse and Proximity Sensor Library”の"Example4_HeartBeat_Plotter.ino”を開きます(図7-3)。このサンプルスケッチは心拍データをシリアルポートに出力してArduino IDEの”シリアルプロッタ”で表示するプログラムです。Arduinoへの書き込みを行います。
ArduinoをUSBポートから外します。MAX30102をArduino UNOに接続します(表7-1)。ピン名はMAX30102の裏側に印刷されていますのでひっくり返して見ている間に右左を間違えがちです。図7-4を見ながら注意して配線してください。
ArduinoをUSBポートに取り付けて、ツールメニューからシリアルプロッタを選びます。センサーに指を当てると大きなDC成分の上に心拍パルスを見ることができます。パルスを見ることができたら一安心です。
7.4 データシートを手に入れよう
米粒ぐらいのセンサーですが高機能です。データシートを手に入れましょう。”MAX30102 datasheet”で検索するとすぐに”MAX30102.pdf”を見つけることができるでしょう。ここに基本的な使い方の情報が書かれています。英語が面倒臭いと思う人は翻訳サイトで日本語に変換しましょう。
“Typical Application Circuit” (図7-5)という回路の模式図をdatasheetから転記しました。これを見ると外部のプロセッサーとはI2C通信を介してデータレジスターと読み書きすることがわかります。左端には赤色LEDと赤外LEDがあり、光センサーが1個だけあります。光センサーのアナログ電圧をデジタルデータに変換するADCがあります。
これで少しだけMAX30102のことがわかりました。LINXにはI2C通信の関数がありますから理詰めでこのデータシートに従って読み書きすれば動脈血酸素飽和度(SpO2)と心拍データを得ることができます。あるいはデータシートを読み解くときのヒントとしてArduinoのライブラリをたどって理解を深めるという方法もあります。ライブラリは”ドキュメント”>”Arduino”>”libraries”>”SparkFun MAX3010x Pulse and Proximity Sensor Library”の中にあります。もしも見つからない時には“MAX30105”で検索すると良いでしょう。
”Example4_HeartBeat_Plotter.ino”はすでに動作していますから、プログラムのサンプリング速度の設定を少し変えて、意図通り変化するかどうか見てみたり、他のサンプルプログラムで動作させてみたりしながらMAX30102に親しんで行くことができます。データシートの設定表(表7-2)に従い、ADC分解能が高くサンプリング速度も高い設定を選び、”my_HeartBeat10ms.ino”のセッティングとしました(表7-3)。コードの不要部分を削除し、micros()というマイクロ秒で経過時間を返す関数を使って10msec間隔で動作するようにしました。
プログラムフォルダーから”my_HeartBeat10ms.ino”を開いてArduinoに書き込んでください。書き込みが終了したらシリアルモニタを開いて115200bpsで受信してみてください。
7.5 LabVIEWシリアル受信プログラムの作成
LabVIEWには多くのサンプルプログラムがありますが、その中にArduino IDEのシリアルモニタのような機能を持ったものがあります。NI エグザンプルファインダでDirectory Structureを選択してください。目的のVIは、”Instrument IO” >” Serial”にある”Continuous Serial Write and Read.vi”です(図7-6)。ダブルクリックで開いて、プログラムを作成するフォルダ保存してください。Arduinoが使用しているポート番号とボーレート"115200"に変更して実行ボタンを押します。Readボタンを押すとシリアルモニタのように文字列が表示されるはずです(図7-7)。このサンプルVIは機能が多いのでブロックダイアグラムは複雑そうに見えます(図7-8)。今回使わない機能を削除して”Continuous Serial Read.vi”として保存します(図7-9)。この数字の文字列を数値に変換すれば加減乗除やグラフに表示することができます。
Arduinoから10msecごとに最大6桁の数値と2文字分の改行コード(CRとLF)が送られてきますので、シリアル通信に必要な時間を表7-4で見積もってみるとおよそ0.7msecでした。シリアル通信でよく使われる9600bpsという通信速度の場合を計算してみてください。その場合は少ししか余裕がなくなってしまいます。データを受け取りながらデータ処理やデータ保存していると、場合によっては時々データを受け取りそこなうこともでてきます。そのような状況の時には生産者消費者デザインパターンを使います。データを受け取る仕事とデータ処理する仕事を分けることで、お互い独立して仕事ができるような仕組みです。
今回のMAX30102を使った心拍測定プログラムでは余裕がありますが、生産者消費者デザインパターンを使ってみましょう。ファイルメニューからNewを選んでFrom Templete>>Frameworks>>Design Patternsの中の"Producer/Consumer Design Pattern (Data).vi"を開きます。ブロックダイアグラム(図7-10)には2個のWhileループがあり、上のループで受信した文字列をキューで下のループに伝えています。キューは人気店の前の行列みたいなもので、下の処理ループが時々滞っても行列が少し長くなるだけで、取りこぼしなく処理することができます。処理ムラに対応するだけなので、平均的に処理に時間がかかりすぎる場合はいずれ破綻しますが、グラフ表示などのUIを操作した時に処理が遅くなってしまうような一時的な遅れには対応できます。
“max30102ChartDisplay.vi”という名前でプログラム作成フォルダに保存します。 ”Continuous Serial Read.vi”から”VISA Configure Serial Port”、”VISA Read”、”VISA Close”を接続されている制御器、表示器ごと上のループにコピー&ペーストしてください。図7-11のようになります。このままでもVIは動作しますが、下のループとは無関係に動作するだけですので、3か所変更します。
(1)”VISA Read”から出力された文字列を受け取っている部分を下のループの”No Error”ケースストラクチャに移動してください。”Dequeue Elemrnt”から出力されている文字列に配線してください。
(2)VISA Readの接続されていない出力”return count”は読み取った文字数を出力するので0より大きい時に”Queue Element”が入っているケースが選択されるようにケース端子に”Greater Than 0?”を接続します。
(3)”Wait(ms)”に接続された定数を5に変更します。
図7-12のようになります。VIを実行させてみてください。生産者消費者デザインパターンで動作しています。ここまでは数字の文字列で送られてきたものをそのまま文字列で表示しているだけです。フロントパネルに”Graph”パレットから”Waveform Chart”をドラッグドロップしてください。
ブロックダイアグラムで数字の文字列を数値に変換します。”String”パレットの”Number/String Conversion”にある”Decimal String To Number”(図7-13)をドラッグドロップして図7-14のように配線します。実行すると図7-15のように血流パルスが表示されます。
このプログラムはしばらく実行していると動作がギクシャクしてくると思います。”Response”という文字列表示器に文字がたまりすぎてしまうためです。データは”Waveform Chart”で見ることができるので”Response”は削除してしまいます。エラークラスターの配線を1系統にまとめて、図7-16で一区切りです。
ここで、”STOP”ボタンを押した時にどんな順番で停止するか、”Hilight Execution”を押して停止のメカニズムを観察してください。
7.6 心拍数測定プログラムの作成
“max30102ChartDisplay.vi”の下のループに心拍数を求める処理を追加しますので、“MAX30102_Plot.vi”という名前で保存してください。心拍数は1分間のパルス数ですが、10秒間のデータを配列にして周波数解析により基本周波数を求めて1分間のパルス数を推定したいと思います。周波数解析をするためにはデータがサンプリングされた間隔が必要になります。Arduinoからは10msec間隔でデータが送られてきますのでサンプリング間隔”dt”は0.01secとなります。10秒分のデータ数は1000個ですので、要素数1000の配列を用意します。新しいデータを配列の先頭(要素0)に入れて、過去のデータは順番に後ろにずらします。一番古い1000個目のデータは捨ててしまいます。このような操作で配列には常に最新の1000個のデータが入っているようにします。このような使い方はリングバッファと呼ばれています。
図7-17が要素1000個の配列を作ってシフトレジスタに接続した状態です。表示されていない”Error”にもワイヤーを配線しています。図7-18は”Rotate 1D Array”で要素を1ずつずらし、一番最後の要素を先頭に持ってきました。この関数のアイコンはアイコンを見れば機能がわかる良い例です。”Replace Array Subset”を使って先頭の要素(一番古いデータ)を新着のデータで置き換えています。図7-19ではサンプリング間隔とデータ配列から波形データを作って”Waveform Graph”に接続しました。VIを実行すると図7-20のように表示されます。波形データを”Extract Single Tone Information.vi”に入力すると周波数解析を行って一番顕著な周波数を出力します。60倍することで1分間の心拍数を得ることができます(図7-21)。図7-22が表示画面です。
03-13-2020 12:55 AM - edited 09-25-2024 10:25 PM
03-13-2020 01:19 AM
杤木が担当する1章から3章の間で、Arduino IDEのインストールと詳細について解説したほうが良いでしょうか?
それとも4章以降で紹介されますか?
第5章でArduino IDEのインストールとLチカについて書きました。3/10にデータ便で送ったのですが、受け取れていないのであれば直メールで送ります。
03-13-2020 01:38 AM