Comments
Description
Transcript
位置情報管理システム~センサネットワークの試作
卒 業 研 題 目 究 位置情報管理システム -センサーネットワークの試作報 告 者 1060233 多 木 勝 彦 指 導 教 員 岩 下 克 教授 平成 18年 2月 21日 高知工科大学工学部 電子・光システム工学科 第1章 序論..................................................................................................................... 2 1.1 研究背景 ................................................................................................................. 2 1.2 研究の目的 ............................................................................................................. 2 第2章 研究の概要.......................................................................................................... 4 第3章 実験系 ................................................................................................................. 5 3.1 全体の構成 ............................................................................................................. 5 3.2 使用する機材の主な説明 ........................................................................................ 5 (1)赤外線センサー ......................................................................................................... 5 (2)A/Dコンバーター(PCIボード)................................................................................... 7 (3)PIC............................................................................................................................ 8 (4)PIC開発環境 ............................................................................................................. 8 (5)Xport......................................................................................................................... 8 (6) VisualBasic.net ..................................................................................................... 10 3.3 センサー設置のための出力測定 ........................................................................... 10 3.3.1 センサーの設置パターン............................................................................... 10 3.3.2 センサー出力測定結果 .................................................................................. 13 3.4 ノード作成 ........................................................................................................... 15 3.4.1 送信パケット構造 ......................................................................................... 15 3.4.2 ノード回路図と構成説明............................................................................... 16 3.4.3 処理フローチャート ...................................................................................... 18 3.5 センサーネットワーク作成 .................................................................................. 22 3.5.1 Comm Port Redirectorを使用したセンサー出力パケット取得 .................... 22 3.5.2 パケット診断プログラムを使用したパケット取得 ....................................... 23 3.6 第4章 センサーノード設置模式図(簡略版、直線T字路モデル) ...................................... 26 測定結果 ........................................................................................................... 27 4.1 完成したセンサーノード概観と動作 .................................................................... 27 4.2 ハイパーターミナルと親ノードの通信 ................................................................ 28 4.3 パケット診断プログラム ...................................................................................... 28 4.4 人体位置情報検知................................................................................................. 30 第5章 考察................................................................................................................... 32 第6章 まとめ ............................................................................................................... 33 謝辞 .................................................................................................................................... 34 参考文献 ............................................................................................................................. 35 付録 .................................................................................................................................... 36 付録 1 使用した機材の性能一覧............................................................................... 36 <1>赤外線センサー ..................................................................................................... 36 <2>A/Dコンバーター(PCIボード)............................................................................... 36 <3>PIC........................................................................................................................ 37 <4>Xport..................................................................................................................... 39 付録 2 赤外線センサー出力測定プログラム(A/Dボード制御) .................................. 39 付録 3 赤外線センサー出力処理、送信プログラム(PIC制御) .................................. 44 付録 4 ノード出力受信処理プログラム(Main&モジュール) ................................... 69 Main............................................................................................................................ 69 モジュール................................................................................................................... 88 1 第1章 1.1 序論 研究背景 私達を取り巻く生活空間は、パソコンや携帯電話などの情報端末の一般への普及、 インターネット回線のブロードバンド化及び価格の定額化などに伴って、大きく変わ って来た。近年それらを活用した情報家電と呼ばれるユビキタスネットワーク化に対 応する商品の開発が行われてきている。 ユビキタスネットワークとは、「『いつでも、どこでも、何でも、誰でもアクセス が可能』なネットワーク環境」[1]と定義されている。ユビキタスネットワーク化は既 存のパソコンだけではなくテレビ、洗濯機や冷蔵庫など一般的な家電製品をネットワ ークで結び、互いに通信を行い今までになかった機能や利便性の向上を図ることを目 的としている。 ユビキタスネットワークを一般家庭等に構築する上で、センサーネットワークの開 発は必要不可欠となってくる。センサーネットワークとは元来、単体では限られた機 能しか持たなかったセンサーを、ネットワークに繋げ機能向上を図るシステムである。 ユビキタスネットワークの「目」とも言えるセンサーでネットワークを構築し、パソ コンや情報家電がデータをやり取りすることで詳細な人体の位置情報を得て、より良 いサービスを提供することが可能となる。 人体の位置情報検知にはGPSや無線LAN、RFID、防犯カメラなどを使用した事例が報 告されている。しかし検知精度や個体識別の有無など、実装する用途や現場によって 求められる性能が異なっている。例えば、個体識別が必要な場合にはRFIDなどが使用 される。実用例として「RFID豚トレーサビリティ」[2]や「社員証、学生証への導入」[3]、 「物品ラインへの導入」[3]などがあり、それぞれ生産情報管理、防犯、効率化と精度 向上などのために実用化されている。 しかし、RFIDは各個人にタグを携帯してもらう必要があるが、公共の場所や家庭内 では個人識別の必要性がない場合がある。よって用途に応じて個人識別を必要とせず 安価な位置情報検出手段が必要となる。 1.2 研究の目的 本研究ではセンサーとして安価で定評のある赤外線センサー複数使用し、センサー ネットワークを作成することによって人体の位置情報検知を行いたいと考えている。 まず使用する赤外線センサーの特性の計測を行い、実際にセンサーを効率的に設置す るかを検討する。 本実験で使用する赤外線センサーとは、自動ドア、ATMなど単体で広く利用されて 2 いるものを指す。単体では、センサーの検知範囲内に人が居るか居ないしか検知する ことができないが、このセンサーを複数個ネットワークに接続し管理することによっ て、人の位置や移動方向、速度を検出することができる。センサーネットワークが必 要とされてくる中で、確かに性能の良いセンサーを各所に配置すればより完璧なセン サーネットワークが出来上がるが、将来様々なセンサーが混在するセンサーネットワ ークの構築に向けて、まずは簡単な動作をし、世間一般に最も普及していると考えら れる赤外線センサーを用いて人体移動検知がどこまで行えるかについて実験を行う。 3 第2章 研究の概要 センサーネットワークによって得られた位置情報を他の製品に活用する場合、例え ば光無線LANのアクセスポイントに人の位置情報を渡した場合、各ノードの近くに人 が居るか、また近寄りつつあるかが分かり通信の効率化や省エネなどに活用できる。 また、防犯カメラに情報を送ってやれば同じ場所を撮り続けるのではなく、位置情報 にあわせて被写体を追尾しながら撮影、記録が可能となる。そしてどこにでもある照 明やブラインド等に送ってやれば、部屋の中に誰も居ない場合に人の居ない区画の電 気を消したりブラインドを閉めたりすることも出来る。 本研究では図 2-1のように居室に複数のセンサーを設置し、得られた位置情報を PCで管理し他の電化製品等に渡し活用することを可能とするための実験を行う。最初 は平面状ではなく、直線的にセンサーを設置し一人の被験者を歩かせることによって 位置情報検知を行う。 図 2-1 センサーの設置例 4 第3章 実験系 3.1 全体の構成 センサーネットワークを作成しPC上で管理を行うにあたり、赤外線センサーひとつ ひとつに通信機能を設けるのではなく幾つかをまとめて統括するノードの作成を行 う。図 3-1に位置情報管理システムの全体の構成を図示する。私が手がけるのは破 線部分で囲まれたハードウェア中心のセンサーネットワークの部分で、それ以外のソ フトウェア中心の管理システムは共同研究者が手がける。しかし、私の方で作成した パケットが正しいものかを判断するために、独自にパケット診断プログラムを作成す る。 図 3-1 位置情報管理システムの構成 3.2 使用する機材の主な説明 (1)赤外線センサー センサーは図 3-2の松下電器製焦電型MPモーションセンサーNaPiOn(AMN13111)を 使用し、付録に性能の概略を示す。 5 図 3-2 実験に使用した AMN13111 の概観 赤外線を利用したセンサーには今回使用した焦電型とサーモパイルと呼ばれるも のがある。原理は、サーモパイルが熱電対の原理を応用した簡単なセンサーで、熱電 対を微少な面積の中に直列に並べた物である。熱電対、すなわち2種類の金属で回路 を作成しその2つの接合部分が異なる温度に保たれた時に熱起電力が生じて電流が流 れる「ゼーべック効果」の原理を使用している。 また、焦電型は焦電物質を用いてあらゆる物体から放出される赤外線エネルギーを 検出することができる。この型のセンサーは波長依存性がないため光学フィルターを 使い分け、波長を選別してやることによって様々な温度センサーを作ることが可能で ある。AMN13111は温度差(±4℃)を検出可能なため体温を持つ人体の検出に最適とさ れている。 全体の検出範囲は図 3-3のような縦1.4m横2.0mの長方形となっているが、実際に は24個の各セルに被験者が侵入した場合にのみ出力(Vdd-0.5V)されることとなる。 6 図 3-3 使用した赤外線センサーの検出セル配置 (2)A/Dコンバーター(PCIボード) A/Dコンバーターは、センサーからのアナログ信号をデジタル信号変換しパソコン 上で記録するために使用した。今回使用したA/Dコンバーターは図 3-4に示す interface社製PCI-3163である。パソコンのPCIスロットに装着し使用するボードタイ プの物で12bit分解能2ch同時A/Dコンバートが可能でありBNCコネクタによって接続 を行う。付録にPCI-3163の基本仕様を明記する。 図 3-4 実験に使用した PCI-3163 の概観 7 (3)PIC PICとは所謂マイコン(マイクロ・コントローラー) と呼ばれる物で、電気的な「何 か」を制御するためのコンピューターの一種だと考えることが出来る。例えば炊飯器 や洗濯機などの電化製品に内蔵され、予めPIC内にプログラムされた手順に沿って付 属のI/Oポートの入出力制御を行うことにより、ご飯を炊いたり洗濯を行ったりする ことを可能としている。PICがパソコンと異なる点は、パソコンが様々な動作が可能 な様汎用的に組み立てられているのに対し、PICはランプを点灯させたりモーターを 駆動させたりと制御面に特化している。図 3-5に使用したPIC 16F628Aの概観、付 録に基本仕様を示す。 図 3-5 実験に使用した 16F873A の概観 (4)PIC開発環境 PIC内のプログラムを記述するには、アセンブリ言語を使用する。アセンブリ言語は 低水準言語と呼ばれ、今回使用するPICでのアセンブリ言語の命令数は他の高級言語な どと異なり35個しかない。命令の数が少ないということは覚えることが少なく理解しや すいということになるが、これらの命令とレジスタを活用してC言語等、高級言語で行 われるような算術、比較、繰り返しなどの処理を行わなければならず、プログラムは一 見して分かりにくい物となる。今回アセンブリ言語を処理するアセンブラには Microchip社の開発支援ソフトのMPLAB IDE内のMPASMを使用した。 (5)Xport 図 3-6のXportを用いることでPIC等、シリアル通信に対応したデバイスを比較 的簡単にネットワークに対応させる事が出来る。そしてPICの出力をネットワークを 8 介して管理し、PC側からPICを制御することが可能となる。付録にXportの基本仕様を 明記する。 図 3-6 実験に使用した Xport LANTRONIX社Xportは「超小型シリアル-イーサネット変換デバイス」として開発さ れている。対応するI/Oピンに対しシリアル通信機器を繋ぐ事によって簡単にネット ワークへと対応させてやる事が出来、ネットワークが通っている場所なら何処からで も監視、制御が可能となる。また通信の暗号化や電子メールの送信、内蔵webサーバ ーによるWebページの配信やJAVAアプレットによるブラウザでの接続機器の状態監視 などにも対応可能となっている。また、Xportには使用者が簡単にシリアル接続対応 の機器をネットワークに対応させられる様、Comm Port Redirector というソフトが 公表されている。図 3-7にその概略を図示する。実際はXportとPC間はLANケーブル で結ばれておりデータのやり取りするために接続の確立やデータの処理方法などを 別にプログラムを作成して処理してやらなければならない。しかしこのソフトを使用 した場合には、初期導入時にのみ設定を行うことでPC側にRS232CのCOMポートを仮想 的に作成し、本来XportのIPアドレスを指定して接続を確立してやらなければならな い所を、PCのCOMポートに対しシリアル通信対応の機器が接続されているように扱え る。よってOSに標準装備されているハイパーターミナルで接続、出力パケットの取得 が可能である。 9 図 3-7 Xport 付属ソフト Comm Port Redirector 図 3-7では研究室内にて設置したXportに192.168.11.101というローカルIPアド レスを割り振り、同IPへの3001番ポートを使用した接続をRS232CのCOMポート2として 仮想的に定義している。 (6) VisualBasic.net センサーの特性を取得するプログラム、パケットを診断するプログラムを作成する にあたり、言語はVisualBasic6かVisualBasic.netどちらを使うかという問題に至っ た。センサーの特性を取得するプログラムのみならばVisualBasic6を用いたが、パケ ット診断プログラムを作成するにあたり、ネットワーク関連の機能が強化された VisualBasic.net[7]を使用することとなった。ネットワーク関連のプログラミング[6] とADボードの制御[6]に関して参照した書籍等は参考文献に後述する。 3.3 センサー設置のための出力測定 3.3.1 センサーの設置パターン 赤外線センサーを設置するにあたりこのセンサーの出力特性を取得し、最適な設 置方法を検討する必要がある。センサーの出力をA/Dボードに入力し図 3-8の Visual Basic.netで作成した制御プログラムによってA/Dボードを制御[9]しデータ を取得した。研究では最初に精度を出すために図 3-9のようにセンサーを互いにオー バーラップさせて設置を行ったと同時に、プログラム側でもある程度の出力波形のオ ーバーラップに対応できるようにプログラミングを行っていた。しかし、使用した赤 10 外線センサーは立ち上がりには問題はないものの、出力の立下りが遅く予測よりも大 幅に出力波形がオーバーラップを起こしプログラム側でこれを補正することが難しく なった。よって図 3-10の様にセンサーを隣接した場合や、図 3-11の様に各センサー間 に十分な空きスペースを確保してやる場合などのいくつかのパターンを設けてセンサ ーの設置実験を行った。 そして、結論として図 3-11のように各センサー間を 2.1mの距離を空けて設置してや ることによってオーバーラップを低減し、プログラム側で補正してやることが可能と なった。 図 3-8 A/D ボード制御、計測値記録プログラム概観 11 図 3-9 センサー設置モデル(オーバーラップ) 図 3-10 図 3-11 センサー設置モデル(隣接) センサー設置モデル(マージンを取る) 12 3.3.2 センサー出力測定結果 3.3.1 の結果を踏まえて 図 3-12 の様にセンサーを 2 つ 2.1mおきに高さ 2.9mの天井 へと 2 つ設置した。高さ 2.9mというのは今回実験を行ったスペースの天井の高さからこの ようになっている。そして 図 3-8 で紹介したプログラムを使用して、この2つのセンサ ー間を身長 185cmの被験者Aに行きはセンサー1→センサー2 となる様、青い矢印の方 向に移動し、数秒後に帰りはセンサー2→センサー1となる様、赤い矢印の方向に移動 を行った結果 図 3-13 のような出力を取得できた。 図 3-12 センサーの設置例 13 図 3-13 赤外線センサーの出力特性 この出力波形より、センサーの立ち上がりの順番から被験者の歩行した方向が分かる。 また各センサーの最初の立ち上がり間の時間と実際にセンサーを設置した距離との 関係から被験者の移動速度が算出できる。次に、この算出された速度が信用出来る物 かを検討するために実験を行った。図 3-14 に2人の被験者(身長185cm、身長170 cm)を個別に速度を変化させ歩行させ、実測速度とセンサーによって計測した速度 の関係を図示する。試行回数は往路、復路を区別せず共に15回試行した。 14 図 3-14 実測速度とセンサーで検知した速度のグラフ 縦軸がセンサーで検知、算出を行った被験者の移動速度(km/h)、横軸が実際の速度 (km/h)となる。またグラフ内の1.8km/hと5.4km/hの罫線は、データシートで見たこの 赤外線センサーの検出可能速度0.5m/s~1.5m/sに対応する場所に設けている。結果と して実速度とセンサーによって計測された速度との誤差は±21%の間に分布し、人の 速度と移動方向が算出できることが分かる。 3.4 ノード作成 3.4.1 送信パケット構造 XportからPCに送られるデータは図 3-15のような構造となっており、Xportを介し てTCPセグメントとして送信されPC側で処理する。PICはセンサーの出力波形を10ms 毎に読み取っているがこれを全てパケット化して送信するのではなく各センサーの 出力のON/OFFが前回と異なる場合のみパケット化して送信を行う。パケットは7文字 (56bit)で構成しておりどの部分のセンサーが反応したかを格納するSensor番号 (1Byte)部分、センサーのON/OFFの状態(1Byte)を格納する部分、反応時間(4Byte)を 格納する部分、改行コード(1Byte)となる。タイムスタンプをつけるのはネットワー 15 クを経由するためなにか遅延が発生した場合にも対応出来るようにするためである。 図 3-15 送信パケットの構造 3.4.2 ノード回路図と構成説明 センサーの出力波形を処理し、パケット化したデータをPC上のプログラムとやり取 りするノードを作成する。作成したノードの回路図を図 3-16に図示する。 16 図 3-16 作成したセンサーノード(親・子)の回路図 17 ①全体の配置 ノードは親と子に分別され、親ノードにはXportとセンサー、各センサーからの出 力信号を処理するためのPIC、動作確認用のLCD(液晶)が付属させる。子ノードは基本 的にセンサー部分のみで給電及び、センサー出力の伝送にはRJ45ケーブル(Ethernet に用いられるLANケーブル)を用いて親と子を結んでいる。 ②給電方法 回路への給電はXportが標準で装備しているACアダプターから行う。Xportの動作電 圧は3.3Vで供給されたおよそ6Vの電圧はXportの内部の三端子レギュレータによって 電圧を落とし使用する。またXportからの端子には降圧前の6Vの流れているポートが あるので、この部分からPICやLCD、赤外線センサーの駆動に必要な5Vの電圧を同じ様 にして、三端子レギュレータによって降圧し得ている。 ③Xportとの接続 XportのDTOピンをPICのUSART通信用ポートRxに接続、PICからのTx出力は駆動電圧 の違いから抵抗を使用して5V⇒3.3Vに降圧させてDTIピンへと入力する。 ④その他 クロックは内部でRTCC(リアルタイムクロックカウンタ)が必要となるため、精度の 高い20MHzのクリスタルクロックを使用した。付録表 1に示すように1年経過した段 階でもその誤差は±5ppm(5μ秒)となっておりRTCCとして最適になっている。また、 LCDは4bitのパラレル伝送を使用しているため液晶へのデータ伝送のために4本、制御 用に3本がPICからLCDへ入力している。 付録表 1 使用したクリスタル(20MHz)の特性表 周波数偏差(25℃) ±50ppm 温度依存(-10℃~60℃) ±50ppm 経時変化(1年) ±5ppm Max 動作温度範囲 -20℃~+70℃ 処理フローチャート 図 3-17にメインルーチン、図 3-18に割り込み処理と受信データ判別処理につ 3.4.3 いてのサブルーチンを記述する。 18 図 3-17 メイン処理のフローチャート ①PICに対して電源を投入後、使用する変数とレジスタの関連付け宣言、各ポートの 入出力指定、シリアル接続についての設定、液晶の初期化及び初期メッセージの表示 19 などを行う。 ②PICのPortAに対してセンサーの出力が入力されているため、ポートの状態を取得し 保存、比較しながらXport側へとパケットとして送りだして行く。まず電源投入後初 期のPortAの状態を取得、前回のセンサー状況(SenSorBeFoR:SSBFR)に格納する。 ③RCIFレジスタをチェックしPC側からの受信データがないかを確認する。(RCIFはRx ピンに対して通信が行われバッファがフルになると1にセットされる) 受信データ があった場合は後述する図 3-18での「データ判別」ルーチンを呼び出し、PC側から の受信データがなかった場合は、そのままメインの処理が続けられる。 ④PortAの状態を取得し、現在のセンサーの状態レジスタ(SenSorNOW:SSNOW)に格納 し 、 SSBFR と SSNOW の XOR( 排 他 的 論 理 和 ) を 取 得 し 、 結 果 を 比 較 結 果 レ ジ ス タ (SenSorReSuLT:SSRSLT)に格納する。PortAの状態はビットごとに入力がHighなら1に セットLowなら0にクリアされるので、例えばPortAの1と3に入力があった場合は 00001010 という感じに0~7bitまでのうち1bit目と3bit目が1にセットされる。つま りSSBFRとSSNOWをビット毎に排他的論理和を取ることによって前回のポートの状態 とことなっている部分だけを1にセットし、結果にSSRSLTとして保存している。 ⑤保存したSSRSLTからどのポートの状態が変化したかを判別し、対応するセンサー番 号をSENSORレジスタに格納する。またSSRSLTの変化により現在ポートが1(センサー ON)なのか0(センサーOFF)なのかを判別、ON_OFFレジスタにON(1)OFF(0)として格納し ている。 次にMFLGが1にセットされるのを待って(図 3-18の解説で後述)MFLGをクリアした後 SENSOR+ON_OFF+現在の時刻(秒2桁,ミリ秒2桁)を液晶に表示、Xport側へ送り出す。送信 終了後にメインループへの先頭へとReturnする。 20 図 3-18 割りこみ、サブルーチンのフローチャート 割り込み処理 割り込み処理はTMR0を使用し、クロックが20MHzのためこれを1/4のサイクルタイム、 プリスケーラー4倍でカウントアップを行う。 20MHzクロック⇒1/4のサイクルタイム5MHz(20MHz/4)で使用 プリスケーラー4倍⇒1024(256回×4)のカウントアップ完了ごとに割り込み 5MHz÷1024=4882.8125Hz 10ミリ秒毎に時計をカウントアップさせたいため、 4882.8125Hz×0.01秒≒48回 48回の割り込みをカウントした時点で10m秒と見なす。 しかし、このままでは48回カウントアップ完了ごとに約163psの誤差がでるため 0.8125Hz×64=52Hz 64Hzごとに次回カウントアップ回数の格納を48回ではなく通常の48回+52回、合計 100回分のカウントアップを指示する。 およそ205μ秒毎に割り込みが入り、プログラム内の割り込み処理へとジャンプす る。ジャンプ先で今まで行っていた作業状況と作業位置のセーブを行った後、現在何 回目か割り込みであるかの判断を行う。もし割り込みが48回目ならMFLGをセットし、 内部時計の10ミリ秒カウンタをカウントアップする。48回に満たない場合は割り込み 処理を抜ける。MFLGはカウントアップが完了したことを示すレジスタで、内部時刻カ 21 ウンタにおいて書き込みと読み込みが競合しない様に、内部時刻カウンタに対して処 理を行う場合にはMFLGのセットを待って処理を行う。また参照した後は必ずMFLGをク リアする必要がある。 受信データ判別処理 ①データが受信された場合にメインループより呼び出される。まず受信データが特殊 なキャラクタ“S”か“R”であるかを判別し、どちらにも当てはまらない場合はここ でメインループへとReturnする。 ②もし受信したキャラクタが“R”の場合はPCからのリセットコードが送られて来た として処理を行う。MFLGのセットを待って秒カウンタ(SECD)と10ミリ秒カウンタ (TENM)をクリアし、リセット完了後に液晶上に時刻カウンタの秒と10ミリ秒カウンタ がクリアされたとして“Reset!”と表示する。 ③もし受信したキャラクタが“S”の場合は PC からの時刻セットコードが送られて 来たとして処理を行う。まず割り込みを禁止し内部時間カウンタを全てクリアし、そ して PC 側から現在の時刻を受信した後に内部時間カウンタにその値を反映させ割り 込みを許可する。液晶上には時刻のセットが完了したとして現在時刻である“時:分: 秒”の 8 桁が表示される。 センサーネットワーク作成 3.5 3.5.1 Comm Port Redirector を使用したセンサー出力パケット取得 センサー設置及び、出力特性が取得できたため、実際にノード一つにセンサーを接 続して作成された、センサー出力パケットをPCで受信してみる。後述するパケット診 断プログラムを作成する前に図 3-19のようにComm Port Redirectorによって仮想 RS232C COMポートを作成し、OSに標準で装備されているハイパーターミナルを使用 してXportとの接続を確立、出力パケットを受け取った。 22 図 3-19 センサーノードネットワーク化概略(仮想 COM 使用) 3.5.2 パケット診断プログラムを使用したパケット取得 VisialBasic.netを用いて図 3-7で記述したComm Port Redirectorを使用せずに、 Xportとの通信を行うためにプログラムを作成し、ノードを複数にした 図 3-20 の ようなセンサーネットワークからの出力パケット取得を行った。プログラムの概観は 図 3-21に図示する。また動作のフローチャートを図 3-22に示す。 23 図 3-20 図 3-21 センサーネットワークの概略図 センサー出力取得プログラム(ネットワーク経由版) 24 図 3-22 パケット診断プログラムのフローチャート ①プログラムが開始されると各選択ボックスへの選択肢の追加やセンサーの設置座標が 読み込まれる。 ②接続ボタンが押されると、2台のXport(以下親ノード)に対して接続の確立が試みら れる。 ③2つの親ノードの接続が確立されたら、現在時刻を取得PIC側へと送信を行いPIC内 の現在時刻を合わせる。その後、Xportに蓄積されていたパケットを5秒という処理時 間を設けて破棄している。これは診断プログラムが接続を行う前のパケットがXport に蓄積されているため、現在のパケットを取得するために破棄を行っている。 ④パケットを受信し、センサー番号の比較処理を行う。もしセンサー番号が不一致だ 25 った場合隣接するセルに移動したものとして速度の算出を行う。算出を行った速度が 速度がセンサーの検出可能速度範囲に納まっている場合のみ、画面に表示を行う。セ ンサー番号が一致した場合や算出を行った速度が不正な場合は、処理を中断し次のパ ケットを受信する。 3.6 センサーノード設置模式図(簡略版、直線 T 字路モデル) 作成したノード2個、センサー8個を図 3-23のようにしてT字路の形に設置を行っ た。各センサーはノードによって管理されており、斜線が引かれている場所がノード CとノードGとなっている。検出セルA,B,C,EとD,F,G,HはそれぞれノードCとノードG に統合され通信を行っている。被験者A(身長185cm)を 図 3-23内においてH⇒D、D⇒ Hの検知範囲を往路、復路の区別なく約25回歩行の速度を変化させ測定、比較を行っ た。 図 3-23 センサーネットワーク 26 T 字路モデル 第4章 測定結果 4.1 完成したセンサーノード概観と動作 図 4-1に作成した親ノードの概観を図示する。電源投入直後に「START Sensor SYS!」というメッセージをLCDに表示している。図 4-2にセンサーに反応があった 場合のLCDの画面を図示する。表示内容は 図 3-15 に記述した送信パケットの構造 に対応しており、1文字目にセンサー番号、2文字目にON_OFF(1or0)、3 文字目以 降はタイムスタンプが表示される。 図 4-1 図 4-2 ノード 完成図 検知時の LCD 画面 27 4.2 ハイパーターミナルと親ノードの通信 1 台のノードに搭載しているXportをComm Port Redirector(図 3-7)にてPC上の COMポートに関連づけ、接続すると出力が図 4-3のように送られてくる。ハイパー ターミナル上では 1 件表示後画面がクリアされてしまうのでテキストに保存した。テ キスト画面上「■」は改行コードである。 図 4-3 親ノードへのハイパーターミナルを使用した接続(1 対 1) 4.3 パケット診断プログラム 3.5.2 にて記述したLAN経由センサー出力取得プログラムの動作画面を図 4-4に 図示する。取得したセンサーの出力は随時画面上に表示され、出力の変化が生じた時 点で比較演算操作を行い、画面上に速度と移動方向を表示している。またプログラム 内で平行してセンサーの出力と割り出した移動区間と移動速度を保存している。各ノ ードには実時間をカウントするカウンタを搭載しており、センサー出力パケットに対 してタイムスタンプを付加する。しかし複数のノードが混在するセンサーネットワー ク内において、各ノードが同じ実時間を刻み続ける必要性があるため、PCソフトウ ェア側と連携して実時間を取得、PICに反映させる機能とPIC内部の実時間時計カウ ンタの秒以下のリセットを行う機能を実装している。また、図 4-5に実時間のPIC反 映時のLCDが画面、図 4-6にリセットを受信した場合のPIC側のLCDを図示する。こ 28 れらの機能はこのセンサー出力取得プログラムからの各ノードへの接続確立時、及び 手動でCodeを選び要求を行った場合に実行される。 図 4-4 センサー出力プログラム動作画面 29 図 4-5 時間セット時のプログラムと親ノードの LCD 画面 図 4-6 4.4 リセットコード送信時の LCD 画面 人体位置情報検知 図 4-7にセンサーノードからのパケットを受信プログラムによって算出した速度 と、実際の移動速度との関係グラフを図示する。 30 図 4-7 センサーノード検知速度と実速度のグラフ 縦軸がノードで検知、算出を行った被験者の移動速度(m/s)、横軸が実際の速度 (m/s)となる。またグラフ内の罫線は、データシートで見たこの赤外線センサーの検 出可能速度0.5m/s~1.5m/sに対応する場所に設けた。 結果、ノード検知速度と実速度の誤差は±16%の範囲に分布している。 31 第5章 考察 赤外線センサーによって人の位置・方向・速度を検出することが可能であり、既存 の LAN を使用したセンサーネットワークの試作を行えた。 実験より、センサーの 設置間隔は検知範囲を隣接又は、オーバーラップさせるのではなく少なくとも検知範 囲の半分以上の間隔をあけてやることが必要とされることが分かった。今回測定のた めに作成したセンサー出力プログラムでも、センサーの出力データが時間軸上でオー バーラップした場合であっても、正しく速度と方向を表示出来る様にプログラミング を行っているが、それをもってしても改善が難しいためセンサー間の距離を 2.1mに することによって出力のオーバーラップを低減した。 今回の実験では、センサーネ ットワーク内に二人以上の動体が進入した場合に、センサーネットワークでこれを検 知することは可能だが、プログラム側で二人以上の進入があり尚且つ、追尾すること は困難であった。 32 第6章 まとめ 世間一般に自動ドアや防犯カメラ、ATM などに単体で使用されている赤外線センサー を複数もちいてセンサーネットワークを構築する。これにあたりまず使用する赤外線セ ンサーの特性を理解し、最適な設置間隔を調べるために A/D ボードを用いて赤外線セン サーの出力を得て試行錯誤を行い、実験の結果からセンサー間は 2.1mの間隔をおいてや るのが最適という結果になった。また同時にセンサーの波形の立ち上がりから人の移動 方向と移動速度を予測することが出来ることが分かった。この結果を踏まえてセンサー を設置し、作成したノードと結びセンサーの出力波形を最適化したパケットの形に加工 を行った。センサーの出力パケットはネットワーク介し、作成したプログラムによって 画面上に人の現在位置、移動方向、移動速度を算出し表示することが出来た。 今回使用した赤外線センサーは物体が放出する赤外線を検知、リアルタイムで監視 し赤外線の変化量から人体の検知を行っている。赤外線センサーを使用した理由とし て「安価である」「世間一般に広く使われている」「簡単な動作を行う」などがある。 他の RFID や画像処理など高価で個人を識別できる機材を使用しなかったのは、今回 の目的として人体位置情報管理を行うにあたり、簡単な検知情報を送信してくる赤外 線センサーを用いてどの程度可能なのか、またどういった場所に実装可能なのかを検 証するという目的があったためである。今回赤外線センサーを用いてセンサーネット ワークを作成また、今後異なるセンサーを使用するにあたり、種類ごとにプログラム 側で処理方法を変えてやることでこれに対応できると考える。 33 謝辞 本研究を行うにあたって、常日頃からご指導、その多大なる知識のご教示を賜った 電子・光システム工学科 岩下 克 教授に深く感謝致します。 回路実装時における PIC や回路実装でお世話になった 綿森研究室 車 載仁さん に深く感謝致します。 日頃から素晴らしい研究環境を作っていただいた同研究室メンバー 乾 梨紗さん 翔さん ん 小松 昇さん 山本 宣幸さん 島村 卓嗣さん 恒安 宏一さん また同研究室先輩方である 坂本 貴章さん 中島 公亮さん 田口 渡邊 利成さ と 3 年生の皆様に感謝意を表したいと思います。 また個別に、共同研究者である乾 梨紗さんには互いに諦めず最後まで研究を行っ てくださったことに対し、再度お礼を申し上げます。 34 参考文献 [1] 総務省:情報統計データベース http://www.johotsusintokei.soumu.go.jp/whitepaper/ja/cover/index.htm [2] オムロンソフトウェア 豚トレーサビリティ 豚トレーサビリティとは http://www.omronsoft.co.jp/rfid/pork/about.html [3] オムロンソフトウェア RFID開発キット活用事例 http://www.omronsoft.co.jp/rfid/kit/case.html [4] 櫻井 他 信学会 [5] 滝本 他 信学会 [6] “センサネットワークによる人の行動認識のための実験系の検討” 総合全大A21-12 p.369(2005) “無線センサネットワークを用いた動線検出システムの試作” ソサエティ大B-15-4 p.614(2003) インターフェイス社 チュートリアル Visual Basic によるAD 入門書 [7] Ver.1.4 秀和システム やさしいPICマイコンプログラミング&電子工作 著:高橋 隆雄 [8] 日経BPソフトプレス Visual Basic.NET 実践講座 Vol.1 基礎編 Vol.2 活用編 著:Michael Halborson Visual Basic.NET 実践講座 著:Michael Halborson [9] MYCOM Visual Basicではじめる ネットワークプログラミング 超入門 著:ソケたん製作委員会 35 付録 付録1 使用した機材の性能一覧 <1>赤外線センサー 付録図 1 実験に使用した赤外線センサー 付録表 1 赤外線センサー性能一覧 <2>A/Dコンバーター(PCIボード) 36 付録図 2 実験に使用した A/D ボードの概観 付録表 2 A/D ボード性能一覧 <3>PIC 37 付録図 3 実験に使用した 16F873A の概観 付録表 2 16F873A の基本仕様 38 <4>Xport 付録図 4 実験に使用した Xport 付録表 3 付録2 Xport の基本仕様 赤外線センサー出力測定プログラム(A/Dボード制御) '各メソッドで共有される変数の宣言 Dim nRet As Integer ' 関数戻り値 Dim lpszName As String ' デバイス名 39 Dim hDeviceHandle As Integer ' デバイスハンドル Dim Config(1) As ADSMPLCHREQ 'ADSMPLCHREQ構造体 Dim SmpData(1) As Short 'サンプリング結果格納配列 Dim Counter1 As Integer = 0 '繰り返し用カウンター Dim Counter2 As Integer = 0 '繰り返し用カウンター2 Dim Volts1 As String 'Volt値格納変数1~2 Dim Volts2 As String '[接続]ボタンを押したときの処理 Public Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click '変数の宣言 Dim smpNum As Integer Try '[接続]ボタンを無効化(2度押し防止) StartButton.Enabled = False Config(0).ulChNo = 1 Config(1).ulChNo = 2 Config(0).ulRange = AD_5V Config(1).ulRange = AD_5V MyPrint("サンプリング条件設定") ' 読み取りアクセス可能な状態でファイルを開く FileOpen(1, "Sensor1.csv", OpenMode.Output) FileOpen(2, "Sensor2.csv", OpenMode.Output) MyPrint("書き込みファイルオープン") '[切断]ボタンを有効化 smpNum = CInt(SmpBox1.Text) MyPrint("") 40 MyPrint("サンプリング件数" & smpNum & "件") MyPrint(DelayBox.Text & "秒後にサンプリングを開始します") Thread.Sleep(CInt(DelayBox.Text) * 1000) 'サンプリング開始Delay StopButton.Enabled = True Counter1 = smpNum Do 'サンプリング条件設定 nRet = AdInputAD(hDeviceHandle, 2, AD_INPUT_SINGLE, Config, SmpData) If nRet <> AD_ERROR_SUCCESS Then MsgBox("AD一件取得に失敗しました1", MsgBoxStyle.Exclamation, "警告") Exit Sub End If '外部ファイルに値を出力 Volts1 = Format(10 / (2 ^ 12 - 1) * SmpData(0) - 5, "#0.000") Volts2 = Format(10 / (2 ^ 12 - 1) * SmpData(1) - 5, "#0.000") MyPrint("1ch=" & Volts1 & "V 2ch=" & Volts2 & "V") 'ファイル書き込み Print(1, Volts1, TAB(), Volts2) '改行コード WriteLine(1) Counter1 = Counter1 - 1 If Counter1 < 1 Then Exit Do End If Loop MyPrint("") MyPrint("サンプリング終了") FileClose() MyPrint("ファイルをCloseしました") '[開始]ボタンを有効化 41 StartButton.Enabled = True Catch ex As Exception 'エラー処理 MyPrint("* " & ex.Message) EndSession() End Try End Sub '[停止]ボタンを押したときの処理 Public Sub StopButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StopButton.Click Try '[切断]ボタンを無効化(2度押し防止) StopButton.Enabled = False 'サンプリングストップ nRet = AdStopSampling(hDeviceHandle) If nRet <> AD_ERROR_SUCCESS Then MsgBox("サンプリングの停止に失敗しました", MsgBoxStyle.Exclamation, "警告") End If Catch ex As Exception 'エラー処理 MyPrint("* " & ex.Message) EndSession() End Try 'ファイルクローズ FileClose() MyPrint("ファイルをCloseしました") End Sub 42 '各メソッド共通の終了処理 Sub EndSession() MyPrint("") StopButton.Enabled = False StartButton.Enabled = True End Sub 'ログウィンドウに1行表示 Sub MyPrint(ByVal str As String) logBox.Items.Add(str) logBox.TopIndex = logBox.Items.Count - 1 logBox.Refresh() End Sub Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load lpszName = "FBIAD1" hDeviceHandle = AdOpen(lpszName) If hDeviceHandle = -1 Then MsgBox("ボードの初期化に失敗しました", MsgBoxStyle.Exclamation, "警告") End If MyPrint("ボード" & lpszName & "をOPENしました。") 'サンプリング件数BOX選択肢追加 SmpBox1.Items.Add("1000") SmpBox1.Items.Add("2000") SmpBox1.Items.Add("4000") SmpBox1.Items.Add("8000") SmpBox1.Items.Add("16000") 'サンプリング開始DelayBOX選択肢追加 DelayBox.Items.Add("0") DelayBox.Items.Add("5") DelayBox.Items.Add("10") DelayBox.Items.Add("15") End Sub 43 Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed ' 終了処理 nRet = AdClose(hDeviceHandle) If nRet <> AD_ERROR_SUCCESS Then MsgBox("ボードのクローズに失敗しました。", MsgBoxStyle.Exclamation, "警告") End End If End Sub End Class 付録3 赤外線センサー出力処理、送信プログラム(PIC制御) list p=16f873a #include <p16f873a.inc> __CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF ;_CP_OFF プログラム読み出しプロテクトオフ ;WDT_OFF ウオッチドック無効 ;BODEN_ON ブラウンアウト有効 ;PWRTE_ON パワーアップタイマ有効 ;HS_OSC オシュレータ 高速クリスタル/レゾレータ ;WRT_OFF フラッシュへの書き込みOFF ;LVP_OFF LVP有効 ;CPD_OFF EEPROMの読み出し許可 TEMP EQU 0x20 ;作業用Temp SECD EQU 0x21 ;秒カウンター TENM EQU 0x22 ;ミリ秒カウンタ(10ms) MINI EQU 0x23 ;分カウンタ MFLG EQU 0x24 ;ミリ秒カウントアップフラグ HOUR EQU 0x25 ;時カウンタ RTCLOW EQU 0x26 ;RTCC counter lower CNT1 EQU 0x27 ;タイマーカウンター1 44 CNT2 EQU 0x28 ;タイマーカウンター2 CNT3 EQU 0x29 ;タイマーカウンター3 CNT4 EQU 0x2a ;タイマーカウンター4 RESET_CHAR EQU 0x2c ;タイマーカウントクリア"S" TMP_DATA EQU 0x31 TMP_DATA_B EQU 0x32 TMP_CNT EQU 0x33 CCNT EQU 0x34 ; 文字数カウンタ LCNT EQU 0x35 ; 行番号フラグ WR_SV EQU 0x70 ;save Wreg STA_SV EQU 0x71 ;save status ; busyチェック用 ;センサー出力処理関数 SSBFR EQU 0x38 ;前回のセンサー出力格納 SSNOW EQU 0x39 ;現在のセンサー出力格納 SSRSLT EQU 0x3a ;SSBFR XOR SSNOW の結果を格納 N_TENM EQU 0x3b N_SECD EQU 0x3c SENSOR EQU 0x3d ON_OFF EQU 0x3e N_MINI EQU 0x3f ;瞬時のMINI N_HOUR EQU 0x40 ;瞬時のHOUR EQU 0x41 ;Sirial通信用 SEND_TEMP SET_CHAR EQU WHAT_CHAR EQU DEX_TEMP EQU 0x42 ;現在時刻セットコード 0x43 ;内部時間要求コード 0x44 ;ASCII→16進 ;Symbols For LCD #define LCD_DATA PORTB #define LCD_DDIR TRISB #define LCD_RS PORTB,0 #define LCD_RW PORTB,1 #define LCD_E PORTB,2 #define BUSY_BIT 7 45 #define ROWS d'16' ; 横方向は16文字 ;********************************************************************** ORG 0x000 ; processor reset vector clrf PCLATH ; ensure page bits are cleared goto INIT ; go to beginning of program ORG 0x004 ; interrupt vector location GOTO INTRPT ;************************************************************************ ;PortA &PortB初期化 ;タイマー初期化 ;PortA ; RA012345入力 ;PortB ; RB4567:LCD出力 ; RB012:LCD制御 ;PortC ; RC67:Sirial通信 ;************************************************************************ INIT ;-------------Portモード設定--------------bcf INTCON,GIE ;割り込み不許可 bsf STATUS,RP0 ;page1に移動 movlw b'11111111' movwf TRISA ; PORTAを入力に clrf LCD_DDIR ;LCDデータポートを出力に movlw b'10111111' ; RC7/RX(入力),RC6/TX(出力) movwf TRISC ; PORTC の設定 ;-------------Timerモード設定-------------movlw 0x81 ;プリスケーラー=4 movwf OPTION_REG ;タイマーモードセット ;-------------Sirial通信設定-------------movlw b'00100100' ; 8BIT,送信許可,非同期,高速 movwf TXSTA ; TXSTA レジスタの設定 movlw 81H ; ボーレート 9600bps (20MHz:高速設定時) 46 movwf SPBRG ; SPBRG レジスタの設定 bcf STATUS,RP0 ; Bank 0 へ戻す movlw b'10010000' ; シリアル,8BIT,継続受信許可 movwf RCSTA ; RCSTA レジスタの設定 ;-------------デジタルモード設定-------------BSF STATUS,RP0 MOVLW 07H MOVWF ADCON1 BCF STATUS,RP0 clrf ADCON0 ;全てディジタルモードにする ;A/D未使用にする ;---------------LCD初期化----------------call lcd_init ; LCD初期化 ;---------------Timerスタート---------------clrf TMR0 movlw 0x30 movwf RTCLOW ;48回 ;--------------Timer例外AJUST-------------movlw 0x40 movwf CNT4 ;64回 ;-------------各パラメーターリセット-------------clrf HOUR clrf MINI clrf SECD clrf TENM clrf SSBFR clrf SSNOW clrf SSRSLT clrf N_TENM clrf N_SECD clrf SENSOR clrf PORTA clrf RESET_CHAR clrf SET_CHAR clrf WHAT_CHAR clrf ON_OFF clrf SENSOR 47 clrf DEX_TEMP ;----------------------------------------bcf LCD_RS ; bcf LCD_RW ; LCDの制御信号をゼロに bcf LCD_E ; clrf LCD_DATA ; call dly_10m ; 念のため10mS待つ call lcd_init ; LCD初期化 call dly_10m movlw b'00001100' call cmd_send call dly_10m clrf CCNT ; キャラクタ数カウンタをリセット clrf LCNT ; 行フラグをリセット clrf TMP_CNT ; テンポラリカウンタをクリア movf TMP_CNT,w ;文字列出力 call INIT_MSG addlw 0x00 btfsc STATUS,Z goto msg_out call chr_out incf TMP_CNT,1 goto str_out1 ;カーソルオフ、左から右へ表示 str_out1 ;ゼロだったなら終了 msg_out movlw d'100' movwf TMP_CNT ;初期メッセージ1秒表示 msg_loop call dly_10m decfsz TMP_CNT,1 goto msg_loop ;初期メッセージ表示遅延 48 call disp_clr goto MAIN ;表示クリア ;******************************************************** ;メイン ;******************************************************** MAIN bsf INTCON,T0IE ;RTCC mask enable bsf INTCON,GIE ;割り込み許可 movf PORTA,0 ;初回センサー状態取得 movwf SSBFR ;SSBFRに格納 ;**************メイン ループ***************** MAINLOOP btfsc PIR1,RCIF call RV_DATA btfss MFLG,0 goto MAINLOOP CLRF MFLG ;clear secondup flag movfw TENM ;10msカウンタから取得 movwf N_TENM ;瞬時の10msカウンタの値 movfw SECD ;秒カウンタから取得 movwf N_SECD ;瞬時の秒カウンタ値 movfw PORTA ;センサー状態取得 movwf SSNOW ;SSNOWに格納 movfw SSBFR ;wレジ格納 xorwf SSNOW,0 ;SSBFR XOR SSNOW movwf SSRSLT ;XOR結果を格納 movlw b'00001111' ;下位選定 andwf SSRSLT,1 ;選定結果はSSRSLTへ btfsc SSRSLT,0 ;センサーA-D判定&分岐 ;Secondflag カウントアップ完了? 49 call SSASND btfsc SSRSLT,1 call SSBSND btfsc SSRSLT,2 call SSCSND btfsc SSRSLT,3 call SSDSND movfw SSNOW ;次ループのための処理 movwf SSBFR ;SSNOW→SSBFR goto MAINLOOP ;*********************************************************** ;センサー反応後処理 ;番号、状態取得→液晶表示→データ送信 ;*********************************************************** SSASND movlw 'A' ; movwf SENSOR ;センサー番号A格納 btfsc SSNOW,0 ;SSNOW0ビット目は1? goto A_ON ;ON bcf ON_OFF,0 ;OFF goto A_ON_OFF_END bsf ON_OFF,0 A_ON A_ON_OFF_END call DISP call SEND_T return ;----------------------------------SSBSND movlw 'B' 50 movwf SENSOR ;センサー番号B格納 btfsc SSNOW,1 ;SSNOW1ビット目は1? goto B_ON ;ON bcf ON_OFF,0 ;OFF goto B_ON_OFF_END bsf ON_OFF,0 B_ON B_ON_OFF_END call DISP call SEND_T return ;----------------------------------SSCSND movlw 'C' ; movwf SENSOR ;センサー番号C格納 btfsc SSNOW,2 ;SSNOW2ビット目は1? goto C_ON ;ON bcf ON_OFF,0 ;OFF goto C_ON_OFF_END bsf ON_OFF,0 C_ON C_ON_OFF_END call DISP call SEND_T return ;----------------------------------SSDSND movlw 'D' ; movwf SENSOR ;センサー番号D格納 btfsc SSNOW,3 ;SSNOW3ビット目は1? goto D_ON ;ON 51 bcf ON_OFF,0;OFF goto D_ON_OFF_END bsf ON_OFF,0 D_ON D_ON_OFF_END call DISP call SEND_T return ;******************************************************* ;Display表示関連関数 ;DISP:メイン表示 ;NUDISP:アスキー変換後送信 ;disp_clr:表示クリア ;******************************************************* DISP call disp_clr movfw SENSOR ;センサー番号送信 call chr_out ;NUDISPにてアスキーコード変換&送信 movfw ON_OFF ;ON_OFF送信 call NUDISP swapf N_SECD,w call NUDISP movf N_SECD,w call NUDISP movlw ':' call chr_out swapf N_TENM,w ;秒上位ビット ;秒下位ビット ;10mカウンタ上位ビット 52 call NUDISP movf N_TENM,w call NUDISP ;10mカウンタ下位ビット return NUDISP ANDLW 0x0F ADDLW 0x30 CALL chr_out ;to ASCII code RETURN ;表示クリア disp_clr movlw b'00000001' call cmd_send clrf CCNT clrf LCNT ; 表示クリア return ; 1文字出力 ; wに表示したい文字をセット chr_out call data_send incf CCNT,f movlw ROWS subwf CCNT,w btfss STATUS,Z goto chr_done ;ROWSと同じではないので終了 clrf CCNT ;文字数カウンタをリセット btfss LCNT,0 ;現在は1行目か? goto chr_ld1 movlw b'10000000' call cmd_send bcf LCNT,0 ;出力した文字数を+1 ;もしもROWSと同じになったら line_chg ;1行目にアドレスをセット 53 goto chr_done chr_ld1 ; 2行目にアドレスをセット movlw b'11000000' call cmd_send bsf LCNT,0 chr_done return INIT_MSG addwf DT PCL,1 "START SenserSYS!",0x00 BINHEX addwf DT PCL,1 "0123456789ABCDEF",0x00 ; 液晶を初期化 ; 4bitモード lcd_init call dly_10m call dly_10m movlw b'00110000' call cmd_send4 call dly_10m movlw b'00110000' call cmd_send4 call dly_10m movlw b'00110000' call cmd_send4 call dly_100u movlw b'00100000' call cmd_send4 call dly_100u call busy_check movlw b'00101000' call ;初期化データ1 ;初期化データ2 ;初期化データ3 ;4bitモードにセット ;初期モード設定 cmd_send 54 movlw b'00001000' call cmd_send movlw b'00000001' call cmd_send movlw b'00000110' call cmd_send ;ディスプレイオフ ;液晶をクリア ;エントリモードをセット return ; 液晶にコマンドを送出 ; wレジスタ=コマンド ; Fレジスタ: TMP_DATA cmd_send ; CMD=w movwf TMP_DATA andlw 0xf0 movwf LCD_DATA bcf LCD_RW bcf LCD_RS bsf LCD_E nop nop bcf LCD_E swapf TMP_DATA,w andlw 0xf0 movwf LCD_DATA bcf LCD_RW bcf LCD_RS bsf LCD_E nop nop bcf LCD_E call busy_check 55 return ; 初期化用4bit幅コマンド送出 ; wレジスタ=コマンド(上位4bit) ; Fレジスタ : TMP_DATA ; ビジーチェックできない期間用 cmd_send4 movwf TMP_DATA andlw 0xf0 movwf LCD_DATA bcf LCD_RW bcf LCD_RS bsf LCD_E nop nop bcf LCD_E return ; 液晶にデータを送出 ; wレジスタ=データ ; Fレジスタ: TMP_DATA data_send movwf TMP_DATA andlw 0xf0 movwf LCD_DATA bcf LCD_RW bsf LCD_RS bsf LCD_E nop nop bcf LCD_E swapf TMP_DATA,w andlw 0xf0 movwf LCD_DATA 56 bcf LCD_RW bsf LCD_RS bsf LCD_E nop nop bcf LCD_E call busy_check return ;****************************************** ; 液晶ビジーチェック ; Fレジスタ:TMP_DATA_B ;****************************************** busy_check bsf STATUS,RP0 movlw 0xf0 movwf LCD_DDIR bcf STATUS,RP0 ; bank=1 ; bank=0 busy_chk1 bcf LCD_RS bsf LCD_RW bsf LCD_E nop movf LCD_DATA,w andlw 0xf0 movwf TMP_DATA_B bcf LCD_E nop nop bsf LCD_E nop ; 下位4ビットは無視 nop bcf LCD_E btfsc TMP_DATA_B,BUSY_BIT goto busy_chk1 bcf LCD_RW 57 bsf STATUS,RP0 movlw 0x00 movwf LCD_DDIR bcf STATUS,RP0 ; bank=1 ; bank=0 return ;**************************************************** ;USART受信用ルーチン ;**************************************************** RV_DATA BTFSC RCSTA,FERR ;フレーミングエラーチェック GOTO F_ERROR ;エラー時移動 BTFSC RCSTA,OERR ;オーバーランエラーのチェック GOTO O_ERROR ;エラー時移動 movlw 'R' ;PCからのResetコード movwf RESET_CHAR movlw 'S' movwf SET_CHAR movlw 'W' movwf WHAT_CHAR MOVF RCREG,W subwf RESET_CHAR,f btfsc STATUS,Z goto TIME_RESET subwf SET_CHAR,f btfsc STATUS,Z goto TIME_SET subwf WHAT_CHAR,f btfsc STATUS,Z goto TIME_SET ;PCからの時間Setコード ;PCからの内部時間要求コード ;レジスタから受信データの読み込み ;タイマーリセット分岐へ ;タイマーセット分岐へ ;タイマーセット分岐へ return 58 F_ERROR MOVF RCREG,W ;wレジに格納するとFERRはクリア BCF RCSTA,CREN ;クリアによりリセット BSF RCSTA,CREN ;受信許可 return O_ERROR return ;**************************************************** ;USART送信用ルーチン ;**************************************************** SEND_T movf SENSOR,w call TX_TXT movf ON_OFF,w call EX_SEND swapf call N_SECD,w ;センサー番号 ;センサーON_OFF ;秒上位ビット EX_SEND movf call N_SECD,w ;秒下位ビット EX_SEND swapf call N_TENM,w ;10mカウンタ上位ビット EX_SEND movf N_TENM,w call EX_SEND movlw 0x0d call ;10mカウンタ下位ビット ;アスキーCRコード TX_TXT SEND_DLY movlw d'5' movwf TMP_CNT ;50mです DLY_LOOP call dly_10m decfsz TMP_CNT,f 59 goto DLY_LOOP return TX_TXT movwf SEND_TEMP ; 送信するデータを変数(SEND_TEMP)に格納 bsf STATUS,RP0 ; Bank 1 へ切替 LPTX ; btfss TXSTA,TRMT ;送信可能であるかチェック(1:可能, 0:禁止) goto LPTX ; 禁止であれば LPTX のラベル間を繰り返す ; bcf STATUS,RP0 ; Bank 0 へ戻す movf SEND_TEMP,W ;格納していた送信データをWregにロード movwf TXREG ; 送信データはTXREGレジスタを通してシリアル出力 return ; メインルーチンへ戻る EX_SEND ANDLW 0x0F ADDLW 0x30 CALL TX_TXT ;to ASCII code RETURN ;**************************************************** ;時間遅延ルーチン クロック20MHz用 ;**************************************************** ; 100マイクロ秒遅延 ; Fレジスタ: CNT1 dly_100u ; 100uS movlw d'100' movwf CNT1 dly_100u1 nop nop ;1uS@1path nop nop decfsz CNT1,f goto dly_100u1 return 60 ; 10ミリ秒遅延 ; Fレジスタ:CNT1 dly_10m ; 10mS movlw d'10' movwf CNT1 dly_10m1 call dly_1m decfsz CNT1,f goto dly_10m1 return ; 1ミリ秒遅延 ; Fレジスタ:CNT2,3 dly_1m ; 1ms movlw d'4' movwf CNT2 dly_1m1 movlw d'250' movwf CNT3 dly_1m2 ; 250us Loop nop nop nop nop decfsz CNT3,f goto dly_1m2 decfsz CNT2,f goto dly_1m1 return ;**************************************** ;タイマーリセット分岐処理 ;**************************************** TIME_RESET btfss MFLG,0 goto TIME_RESET ;10Msflag カウントアップ完了? 61 clrf TENM clrf SECD call disp_clr movlw 'R' call chr_out call TX_TXT movlw 'e' call chr_out movlw 's' call chr_out movlw 'e' call chr_out movlw 't' call chr_out movlw '!' call chr_out movlw ;PC側に返信'R' d'100' movwf TMP_CNT ;初期メッセージ1秒表示 msg_loop2 call dly_10m decfsz TMP_CNT,1 goto msg_loop2 call disp_clr goto ;表示遅延 ;表示クリア MAIN return ;********************************************** ;タイマーセット分岐 ;********************************************** TIME_SET bcf INTCON,T0IE bcf INTCON,GIE clrf HOUR clrf MINI clrf SECD clrf TENM ;割り込み不許可 62 D_1 btfss PIR1,RCIF goto D_1 MOVF RCREG,w btfss PIR1,RCIF goto D_2 MOVF RCREG,w btfss PIR1,RCIF goto H_SET_H MOVF RCREG,w movwf DEX_TEMP movlw 0x30 subwf DEX_TEMP,w movwf HOUR swapf HOUR,f btfss PIR1,RCIF goto H_SET_L movf RCREG,w movwf DEX_TEMP movlw 0x30 subwf DEX_TEMP,w addwf HOUR,f btfss PIR1,RCIF goto M_SET_H movf RCREG,w movwf DEX_TEMP movlw 0x30 subwf DEX_TEMP,w movwf MINI swapf MINI,f ;USART受信割り込みFLGチェック D_2 ;USART受信割り込みFLGチェック H_SET_H ;USART受信割り込みFLGチェック H_SET_L M_SET_H ;USART受信割り込みFLGチェック 63 M_SET_L btfss PIR1,RCIF goto M_SET_L movf RCREG,w movwf DEX_TEMP movlw 0x30 subwf DEX_TEMP,w addwf MINI,f btfss PIR1,RCIF goto S_SET_H movf RCREG,w movwf DEX_TEMP movlw 0x30 subwf DEX_TEMP,w movwf SECD swapf SECD,f btfss PIR1,RCIF goto S_SET_L movf RCREG,w movwf DEX_TEMP movlw 0x30 subwf DEX_TEMP,w addwf SECD,f clrf TENM bsf INTCON,T0IE bsf INTCON,GIE call disp_clr swapf HOUR,w call NUDISP S_SET_H ;USART受信割り込みFLGチェック S_SET_L ;割り込み許可 64 movf HOUR,w call NUDISP movlw ':' call chr_out swapf MINI,w call NUDISP movf MINI,w call NUDISP movlw ':' call chr_out swapf SECD,w call NUDISP movf SECD,w call NUDISP movlw d'100' movwf TMP_CNT ;秒上位ビット ;秒下位ビット ;秒上位ビット ;秒下位ビット msg_loop3 call dly_10m decfsz TMP_CNT,1 goto msg_loop3 call disp_clr ;表示遅延 ;表示クリア return ;********************************************** ;内部時間送信分岐 ;********************************************** Send_time btfss MFLG,0 goto Send_time ;10Msflag カウントアップ完了? 65 call movfw TENM movwf N_TENM movfw SECD movwf N_SECD movfw MINI movwf N_MINI movfw HOUR movwf N_HOUR swapf N_HOUR,w ;時カウンタ上位ビット EX_SEND movf call EX_SEND swapf call N_SECD,w ;秒上位ビット EX_SEND movf call N_MINI,w ;分カウンタ下位ビット EX_SEND swapf call N_MINI,w ;分カウンタ上位ビット EX_SEND movf call N_HOUR,w ;時カウンタ下位ビット N_SECD,w ;秒下位ビット EX_SEND return ;*********************************************** ;タイマー割り込み処理 ;*********************************************** INTRPT ;**** save レジスタ ******* movwf WR_SV ;save wreg swapf STATUS,W ;save status movwf STA_SV ;**** last pulse check **** 66 bcf INTCON,T0IF ;int flag reset decfsz RTCLOW,F ;RTC lower counter-1 goto POPRTN ;**** count up 10 Mirisecond *** bsf MFLG,0 ;second flag on call TIMEUP ;Timerをカウントアップ decfsz CNT4,f goto ADDCNT movlw 0x40 ;64? 66? movwf CNT4 ; movlw 0x65 ;48+53=101 movwf RTCLOW ;AJUSTカウントセット goto POPRTN movlw 0x30 movwf RTCLOW ADDCNT ;last count is adjustable ;******** レジスタを戻す **** POPRTN swapf STA_SV,W ;get status MOVWF STATUS SWAPF WR_SV,F SWAPF WR_SV,W ;get wreg RETFIE ;*********************************************************** ;時間カウント+ ; ;*********************************************************** TIMEUP ;***** カウントアップ 10m秒****** TENM_UP INCF TENM,F ;TENM+1 MOVLW 0x0f andwf TENM,w ;下位ビット取得 sublw 0x09 ;9-TENM 67 btfsc STATUS,C ;0A? return ;9以下ですリターン movlw 0x06 ;+6 addwf TENM,f ;0A+6=10 ;*******1000ms チェック****** movlw 0x9a subwf TENM,w btfss STATUS,C return clrf ;1000ms? ;1000mに達しない リターン TENM ;リセット00ms ;******カウントアップ 秒 ********* S_UP INCF SECD,F ;SECD+1 MOVLW 0x0f ; ANDWF SECD,W ;get lower SUBLW 0x09 ;over 9 BTFSC STATUS,C ;0A? RETURN ;not over 9 exit MOVLW 0x06 ADDWF SECD,F ;0A to 10 ;**** 60sチェック ****** S_check MOVLW 060H SUBWF SECD,W BTFSS STATUS,C RETURN CLRF ;60sec? ;not 60 exit SECD ;reset to 0 second ;****** カウントアップ 分 ***** M_UP INCF MINI,F ;MINT+1 MOVLW 0FH ANDWF MINI,W ;get lower SUBLW 09H ;over 9 68 BTFSC STATUS,C ;0A? RETURN ;not over 9 exit MOVLW 06H ADDWF MINI,F ;0A to 10 ;**** 60分チェック ****** H_check MOVLW 060H SUBWF MINI,W BTFSS STATUS,C ;60min? RETURN CLRF MINI ;reset to 0 minute ;**** カウントアップ 時 ***** H_UP INCF HOUR,F MOVLW 0FH ANDWF HOUR,W SUBLW 09H BTFSC STATUS,C ;HOUR+1 return GOTO D_check MOVLW 06H ADDWF HOUR,F ;24h check ;**** 24時間 チェック ***** D_check MOVLW 024H SUBWF HOUR,W BTFSS STATUS,C ;24H check RETURN CLRF HOUR ;reset to 0 hour RETURN END 付録4 ノード出力受信処理プログラム(Main&モジュール) Main 69 Imports System.IO Imports System.Net Imports System.Net.Sockets Imports System.Text Imports System.Threading '共有変数宣言 Dim mySocket As Socket 'ソケット情報記憶変数 Dim myStream As NetworkStream 'ストリーム Dim myReader As StreamReader 'ストリームからのデータ読みだし変数 Dim myWriter As StreamWriter 'ストリームへのデータ書き込み変数 Dim myThread As Thread 'スレッド変数 Dim mySocket2 As Socket 'ソケット情報記憶変数2 Dim myStream2 As NetworkStream 'ストリーム2 Dim myReader2 As StreamReader 'ストリームからのデータ読みだし変数2 Dim myWriter2 As StreamWriter 'ストリームへのデータ書き込み変数2 Dim myThread2 As Thread 'スレッド変数2 Dim myRecvData As String = "0" '受信データ格納 Dim myRecvData2 As String '受信データ格納2 Dim ON_OFF As String 'センサーON/OFF格納 Dim SSZero As String 'センサー出力格納配列 Dim RecvLen As Integer '受け取った出力の文字長格納変数 Dim OpenF As Boolean = False 'FileOpen確認フラグ Dim SensorArea(7, 1) As Integer 'センサー座標格納配列 '比較サブルーチン用宣言 Dim TheBigin As Boolean = False '初期フラグ Dim Sensor1 As String '前センサー出力格納 Dim Sensor2 As String '現在センサー出力格納 Dim Time1_Str As String '前の検知時間(文字列) Dim Time2_Str As String '現在の検知時間(文字列) Dim Time1 As Integer '前の検知時間(ms) Dim Time2 As Integer '現在の検知時間(ms) Dim TimeS As Integer 'センサー間移動時間1 70 'センサー間移動 Dim TENM_H As String '10ミリ上位 Dim TENM_L As String '10ミリ下位 Dim W_X As Integer = 0 'X1の幅 Dim W_Y As Integer = 0 'Y1の幅 Dim Speed As Single '移動速度 Dim DelyTime As Integer '受け取りデータ破棄時間 Dim StopTime As Integer = 0 '範囲アウト時間 Dim Init As Boolean = False '初期化完了フラグ Dim mySendData As String '送信データ格納変数 Dim Hour As String '時間格納変数 Dim Mini As String '分格納変数 Dim Secd As String '秒格納変数 Dim i As Integer 'ループ用のi Dim Hour_H As String '時間桁HHigh Dim Hour_L As String '時間桁Low Dim Mini_H As String '分桁High Dim Mini_L As String '分桁Low Dim Secd_H As String '秒桁High Dim Secd_L As String '秒桁Low Dim H_Len As Integer '時の文字桁数 Dim M_Len As Integer '分の文字桁数 Dim S_Len As Integer '秒の文字桁数 '[接続]ボタンを押したときの処理 Public Sub ConectButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConectButton.Click '変数の宣言 Dim myHostEntry As IPHostEntry 'IPホスト格納変数 Dim myAddress As IPAddress 'IPアドレス格納変数 71 Dim myPort As Integer '接続に使用するポート番号を格納 Dim myEndPoint As EndPoint 'ネットワーク アドレスを識別 '変数宣言2 Dim myHostEntry2 As IPHostEntry 'IPホスト格納変数2 Dim myAddress2 As IPAddress 'IPアドレス格納変数2 Dim myPort2 As Integer '接続に使用するポート番号を格納2 Dim myEndPoint2 As EndPoint ''ネットワーク アドレスを識別2 Try '[接続]ボタンを無効化(2度押し防止) ConectButton.Enabled = False 'ソケットを作成する mySocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) MyPrint("ソケットを作成しました1") mySocket2 = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) MyPrint("ソケットを作成しました2") '指定したホストのポートに接続する myHostEntry = Dns.Resolve(hostBox.Text) myHostEntry2 = Dns.Resolve(hostBox2.Text) myAddress = myHostEntry.AddressList(0) myAddress2 = myHostEntry2.AddressList(0) myPort = 14002 'Host1 myPort2 = 14001 'Host2 myEndPoint = New IPEndPoint(myAddress, myPort) myEndPoint2 = New IPEndPoint(myAddress2, myPort2) mySocket.Connect(myEndPoint) mySocket2.Connect(myEndPoint2) MyPrint("Host1に接続完了") MyPrint("Host2に接続完了2") 'ソケットを読み書きする準備 72 myStream = New NetworkStream(mySocket) myStream2 = New NetworkStream(mySocket2) myReader = New StreamReader(myStream, Encoding.UTF8) myReader2 = New StreamReader(myStream2, Encoding.UTF8) myWriter = New StreamWriter(myStream, Encoding.UTF8) myWriter2 = New StreamWriter(myStream2, Encoding.UTF8) myWriter.NewLine = vbNewLine 'Chr(13) + Chr(10)のこと myWriter2.NewLine = vbNewLine myWriter.AutoFlush = True myWriter2.AutoFlush = True '読み出し処理を別スレッドで開始する myThread = New Thread(AddressOf RecvLoop) myThread2 = New Thread(AddressOf RecvLoop2) myThread.IsBackground = True myThread2.IsBackground = True myThread.Start() MyPrint("受信スレッド1を起動しました") myThread2.Start() MyPrint("受信スレッド2を起動しました") '[切断]/[送信]ボタンを有効化 closeButton.Enabled = True sendButton.Enabled = True Catch ex As Exception 'エラー処理 MyPrint("* " & ex.Message) MyEndSession() End Try End Sub 73 '受信スレッド Sub RecvLoop() Try Do 'データを受信する SyncLock myRecvData myRecvData = myReader.ReadLine() 'センサー保存⇒比較分岐へ SensorIn(myRecvData) End SyncLock '受信したデータを表示する 'MyPrint("受信Host1 >> " & myRecvData) If IsNothing(myRecvData) Then MyPrint("サーバーがシャットダウンを伝えてきました") myRecvData = "0" Exit Do End If Loop '終了処理 MyPrint("受信スレッド2を終了しました") MyEndSession() Catch ex As Exception 'エラー処理 Select Case MyGetSocketErrorCode(ex) Case 10004 'WSAEINTR 'ReadLine()の受信待ち中に自分でソケットを閉じた 74 MyPrint("受信スレッドを終了しました<Host1>") MyEndSession() Case 10053 'WSAECONNABORTED '自分でソケットを閉じた後にReadLine()が開始された MyPrint("受信スレッドを終了しました<Host1>") MyEndSession() Case 10054 'WSAECONNRESET 'サーバーが落ちた MyPrint("* ホストが落ちました<Host1>") MyPrint("受信スレッドを中断しました<Host1>") MyEndSession() Case Else '上記以外は予想外のエラーである MyPrint("* " & ex.Message & "<Host1>") MyPrint("受信スレッドを中断しました<Host1>") MyEndSession() End Select End Try End Sub '受信スレッド2 Sub RecvLoop2() Try Do 'データを受信する myRecvData = myReader2.ReadLine() '受信したデータを表示する() 'MyPrint("受信Host2>> " & myRecvData) 'センサー保存⇒比較分岐へ 75 SensorIn(myRecvData) If IsNothing(myRecvData) Then MyPrint("サーバーがシャットダウンを伝えてきました") myRecvData = "0" Exit Do End If Loop '終了処理 MyPrint("受信スレッド2を終了しました") MyEndSession() Catch ex As Exception 'エラー処理 Select Case MyGetSocketErrorCode(ex) Case 10004 'WSAEINTR 'ReadLine()の受信待ち中に自分でソケットを閉じた MyPrint("受信スレッドを終了しました<Host2>") MyEndSession() Case 10053 'WSAECONNABORTED '自分でソケットを閉じた後にReadLine()が開始された MyPrint("受信スレッドを終了しました<Host2>") MyEndSession() Case 10054 'WSAECONNRESET 'サーバーが落ちた MyPrint("* ホストが落ちました<Host2>") MyPrint("受信スレッドを中断しました<Host2>") MyEndSession() Case Else 76 '上記以外は予想外のエラーである MyPrint("* " & ex.Message & "<Host2>") MyPrint("受信スレッドを中断しました<Host2>") MyEndSession() End Select End Try End Sub '[送信]ボタンを押したときの処理 Sub sendButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles sendButton.Click Try 'Emuにデータを送信する(Emu使用時ON) 'mySendData = ComboBox1.Text 'myWriter2.WriteLine(mySendData) 'Resetコード送信(両Host) If inputBox.Text = "PICカウンターReset<R>" Then mySendData = "R" myWriter.WriteLine(mySendData) myWriter2.WriteLine(mySendData) MyPrint("送信<<PICカウンターResetCode") 'MsgBox("PICカウンターResetCode送信", , "操作") 'Setコード送信&現在時刻送信(両ホスト) ElseIf inputBox.Text = "PIC内部時間設定<S>" Then mySendData = "S" myWriter.WriteLine(mySendData) myWriter2.WriteLine(mySendData) Hour = Date.Now.Hour.ToString Mini = Date.Now.Minute.ToString Secd = Date.Now.Second.ToString H_Len = Hour.Length 77 M_Len = Mini.Length S_Len = Secd.Length '送信用桁合せ(規定の桁に届かない場合桁あわせ) If H_Len = 1 Then Hour = ("0" + Hour) End If If M_Len = 1 Then Mini = ("0" + Mini) End If If S_Len = 1 Then Secd = ("0" + Secd) End If '時、分、秒の上位、下位をキャラクタごとに読み出し Hour_H = Hour.Chars(0) Hour_L = Hour.Chars(1) Mini_H = Mini.Chars(0) Mini_L = Mini.Chars(1) Secd_H = Secd.Chars(0) Secd_L = Secd.Chars(1) '読み出したキャラクタをそれぞれ送信 myWriter.Write(Hour_H + Hour_L + Mini_H + Mini_L + Secd_H + Secd_L) MyPrint("送信<<PIC内部時間設定Code Host1") myWriter2.Write(Hour_H + Hour_L + Mini_H + Mini_L + Secd_H + Secd_L) MyPrint("送信<<PIC内部時間設定CodeHost2") MsgBox("PIC内部時間設定Code送信" & (Chr(13)) & (Chr(13)) & "現在時刻" & Hour_H + Hour_L & "時" & Mini_H + Mini_L & "分" & Secd_H + Secd_L & "秒", , "操作") End If Catch ex As Exception 'エラー処理 MyPrint("* " & ex.Message) 78 MyEndSession() End Try End Sub '[切断]ボタンを押したときの処理 Sub closeButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles closeButton.Click Try FileClose() ' エクセルファイルクローズ. '[切断]ボタンと[送信]ボタンを無効化(2度押し防止) closeButton.Enabled = False sendButton.Enabled = False '送信の終了をサーバーに伝える mySocket.Shutdown(SocketShutdown.Send) mySocket2.Shutdown(SocketShutdown.Send) MyPrint("サーバーへの送信をシャットダウンしました") '交信スレッドの終了を2秒(=2000ミリ秒)待つ If myThread.Join(2000) Then 'スレッドが正常終了した場合、なにもする必要がない Else 'スレッドが終了しない場合、ソケットを閉じて強制終了させる MyPrint("サーバーが応答しないので勝手に終了します") mySocket.Close() End If Catch ex As Exception 'エラー処理 MyPrint("* " & ex.Message & "切断ボタン") MyEndSession() 79 End Try End Sub '例外発生の原因になったソケットエラーのエラー番号を調べるメソッド Function MyGetSocketErrorCode(ByVal ex As Exception) As Integer If IsNothing(ex) Then Return -1 ElseIf TypeOf ex Is SocketException Then Return CType(ex, SocketException).ErrorCode Else Return MyGetSocketErrorCode(ex.InnerException) End If End Function Sub SensorIn(ByVal myRecvData As String) '初期化処理 If OpenF = False Then ' '時刻設定コードを送信 mySendData = "S" myWriter.WriteLine(mySendData) myWriter2.WriteLine(mySendData) '現在時刻を取得 時、分、秒格納変数へ Hour = Date.Now.Hour.ToString Mini = Date.Now.Minute.ToString Secd = Date.Now.Second.ToString 'MyPrint(Date.Now.Second.ToString) '時、分、秒の各キャラクター数を取得 H_Len = Hour.Length M_Len = Mini.Length 80 'デバック S_Len = Secd.Length '送信用桁合せ(規定に届かない桁数の場合桁を調整) If H_Len = 1 Then Hour = ("0" + Hour) End If If M_Len = 1 Then Mini = ("0" + Mini) End If If S_Len = 1 Then Secd = ("0" + Secd) End If Hour_H = Hour.Chars(0) Hour_L = Hour.Chars(1) Mini_H = Mini.Chars(0) Mini_L = Mini.Chars(1) Secd_H = Secd.Chars(0) Secd_L = Secd.Chars(1) myWriter.Write(Hour_H + Hour_L + Mini_H + Mini_L + Secd_H + Secd_L) myWriter2.Write(Hour_H + Hour_L + Mini_H + Mini_L + Secd_H + Secd_L) 'PIC内時間カウンタリセットコード送信 myWriter2.Write("R") myWriter.Write("R") MyPrint("PIC内部時間設定Code送信") 'MyPrint(Date.Now.Second.ToString) 'デバック OpenF = True Init = True '初期化完了フラグ DelyTime = Date.Now.Second '現在時刻取得 81 True End If '最初5秒はデータを廃棄 While Date.Now.Second < DelyTime + 5 And Init = True Return End While Init = False '測定用デバック 'MyPrint(myRecvData.Chars(0)) If myRecvData.Chars(0) = "A" Or myRecvData.Chars(0) = "B" Or myRecvData.Chars(0) = "C" Or myRecvData.Chars(0) = "E" Then Return End If 'SSZeroへ受け取ったデータを格納 SSZero = myRecvData '文字長を取得 RecvLen = Len(SSZero) '文字長=6文字 & センサー出力ONのみのデータを判別して外部ファイルに出力 If RecvLen = 6 And SSZero Like "?1????" Then FileOpenS() Thread.Sleep(10) PrintLine(2, SSZero) FileClose() Thread.Sleep(10) MyPrint(SSZero) OutputComp() 'センサー出力比較処理へジャンプ End If 82 End Sub 'センサー出力比較処理 Sub OutputComp() '最初のセンサーの出力を格納する If TheBigin = False Then 'Sensor座標の再指定(外部Module) IntoSensorArea() Sensor1 = SSZero BeforS = Sensor1.Chars(0) 'センサー番号格納 Time1_Str = (Sensor1.Remove(0, 2)) '時間データを文字列で取得 Secd_H = Time1_Str.Chars(0) Secd_L = Time1_Str.Chars(1) TENM_H = Time1_Str.Chars(2) TENM_L = Time1_Str.Chars(3) Time1 = CInt(Secd_H) * 10000 + CInt(Secd_L) * 1000 + CInt(TENM_H) * 100 + CInt(TENM_L) * 10 '被験者進入経路に合わせた初期座標の変更 Select Case BeforS Case "A" AjustAreaX = -38 AjustAreaY = 0 Case "E" AjustAreaX = 38 AjustAreaY = 0 Case "H" AjustAreaX = 0 AjustAreaY = -54 End Select 83 TheBigin = True '初期のセンサー完了フラグ ON Return End If Sensor2 = SSZero NowS = Sensor2.Chars(0) 'センサー番号格納 Time2_Str = (Sensor2.Remove(0, 2)) '時間データを文字列で取得 Secd_H = Time2_Str.Chars(0) Secd_L = Time2_Str.Chars(1) TENM_H = Time2_Str.Chars(2) TENM_L = Time2_Str.Chars(3) Time2 = CInt(Secd_H) * 10000 + CInt(Secd_L) * 1000 + CInt(TENM_H) * 100 + CInt(TENM_L) * 10 TimeS = Time2 - Time1 '時間計算式補正 If TimeS < 0 Then TimeS = (Time2 + 60000) - Time1 '60000ms追加して計算しなおし End If If TimeS > 3000 Then '無反応3秒経過(初期化) '空白代入 FileOpenS() Thread.Sleep(10) PrintLine(2, "") FileClose() Thread.Sleep(10) Time1 = Time2 BeforS = NowS MyPrint("初期化処理(現在の検知位置が初期化されました。)") 84 Return End If '前のセンサー状態Xor現在センサー状態の不一致ならば比較する If BeforS <> NowS Then TimeS = Time2 - Time1 '時間計算式補正 If TimeS < 0 Then TimeS = (Time2 + 60000) - Time1 '60000ms追加して計算しなおし End If '移動開始位置代入(外部Mocule) IntoSensorAjust() 'X幅、Y幅 W_X = x2 - x1 W_Y = y2 - y1 'スピード算出 Speed = CSng((((((W_X) ^ 2 + (W_Y) ^ 2) ^ 0.5) / TimeS) * 1000) / 54) '秒 速/m '速度規制(規定速度外の移動はイレギュラーとしてスルー) If 0.45 < Speed And Speed < 1.55 Then MyPrint(BeforS & "⇒" & NowS) MyPrint(CStr(Speed) & "m/sにて移動") FileOpenS() Thread.Sleep(10) PrintLine(3, BeforS & "⇒" & NowS) 85 PrintLine(3, Time1) PrintLine(3, Speed) PrintLine(3, " ") FileClose() Thread.Sleep(10) BeforS = NowS Time1 = Time2 End If End If End Sub '各メソッド共通の終了処理 Sub MyEndSession() If Not IsNothing(mySocket) Then mySocket.Close() MyPrint("ソケットを閉じました") End If MyPrint("") closeButton.Enabled = False sendButton.Enabled = False ConectButton.Enabled = True End Sub 'ログウィンドウに1行表示 Sub MyPrint(ByVal str As String) SyncLock logBox logBox.Items.Add(str) logBox.TopIndex = logBox.Items.Count - 1 logBox.Refresh() End SyncLock 86 End Sub 'フォームロード時実行 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load 'PICの制御Code選択肢追加 inputBox.Items.Add("PICカウンターReset<R>") inputBox.Items.Add("PIC内部時間設定<S>") 'センサーの座標設定(外部Modlue) IntoSensorArea() 'コンボボックスへの選択肢追加(Emulatorへのパケットパターン要求) ComboBox1.Items.Add("パターン1(A~E)") ComboBox1.Items.Add("パターン2(E~A)") ComboBox1.Items.Add("パターン3(A~D~H)") ComboBox1.Items.Add("パターン4(H~D~A)") ComboBox1.Items.Add("パターン5(E~D~H)") ComboBox1.Items.Add("パターン6(H~D~E)") 'ホストBoxへの選択肢追加(Host1 Host2 同PC内での動作確認) hostBox.Items.Add("192.168.11.9") hostBox.Items.Add("localhost") hostBox.Items.Add("192.168.11.102") hostBox2.Items.Add("192.168.11.9") hostBox2.Items.Add("localhost") hostBox2.Items.Add("192.168.11.101") End Sub 'Ver情報ボタン Private Sub MenuItem6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem6.Click 87 MsgBox("センサー出力測定プログラム Ver1.0", MsgBoxStyle.Information, "Version 情報") End Sub '終了ボタン Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click Close() End Sub End Class モジュール Module Module1 Public SensorArea(7, 1) As Integer 'センサー座標格納配列 Public GotoGO(8, 5) As String '行き先テーブル Public AjustAreaX As Integer = 0 '侵入位置補正X座標 Public AjustAreaY As Integer = 0 '侵入位置補正Y座標 Public x1 As Integer 'x座標1 Public y1 As Integer 'y座標1 Public x2 As Integer 'x座標2 Public y2 As Integer 'y座標2 Public BeforS As String '前センサー番号格納 Public NowS As String '現在センサー番号格納 Public GotoFlag As Boolean = False '通行許可フラグ 'ファイルオープン Sub FileOpenS() FileOpen(1, "Sensor.csv", OpenMode.Append, OpenAccess.Default, OpenShare.Shared) ' Open file for output. FileOpen(2, "Sensor-Z.csv", OpenMode.Append, OpenAccess.Default, OpenShare.Shared) ' Open file for output. FileOpen(3, "Speed.txt", OpenMode.Append, OpenAccess.Default, OpenShare.Shared) End Sub 88 'Sensor座標設定 Sub IntoSensorArea() 'AのSensorArea SensorArea(0, 0) = 164 SensorArea(0, 1) = 111 'BのSensorArea SensorArea(1, 0) = 240 SensorArea(1, 1) = 111 'CのSensorArea SensorArea(2, 0) = 316 SensorArea(2, 1) = 111 'DのSensorArea SensorArea(3, 0) = 392 SensorArea(3, 1) = 111 'EのSensorArea SensorArea(4, 0) = 468 SensorArea(4, 1) = 111 'FのSensorArea SensorArea(5, 0) = 392 SensorArea(5, 1) = 219 'GのSensorArea SensorArea(6, 0) = 392 SensorArea(6, 1) = 327 'HのSensorArea SensorArea(7, 0) = 392 SensorArea(7, 1) = 435 End Sub '開始座標修正 Sub IntoSensorAjust() Select Case BeforS Case "A" x1 = SensorArea(0, 0) + AjustAreaX 89 y1 = SensorArea(0, 1) + AjustAreaY Case "B" x1 = SensorArea(1, 0) + AjustAreaX y1 = SensorArea(1, 1) + AjustAreaY Case "C" x1 = SensorArea(2, 0) + AjustAreaX y1 = SensorArea(2, 1) + AjustAreaY Case "D" x1 = SensorArea(3, 0) + AjustAreaX y1 = SensorArea(3, 1) + AjustAreaY Case "E" x1 = SensorArea(4, 0) + AjustAreaX y1 = SensorArea(4, 1) + AjustAreaY Case "F" x1 = SensorArea(5, 0) + AjustAreaX y1 = SensorArea(5, 1) + AjustAreaY Case "G" x1 = SensorArea(6, 0) + AjustAreaX y1 = SensorArea(6, 1) + AjustAreaY Case "H" x1 = SensorArea(7, 0) + AjustAreaX y1 = SensorArea(7, 1) + AjustAreaY End Select Select Case NowS Case "A" x2 = SensorArea(0, 0) + AjustAreaX y2 = SensorArea(0, 1) + AjustAreaY Case "B" x2 = SensorArea(1, 0) + AjustAreaX y2 = SensorArea(1, 1) + AjustAreaY Case "C" x2 = SensorArea(2, 0) + AjustAreaX y2 = SensorArea(2, 1) + AjustAreaY Case "D" x2 = SensorArea(3, 0) + AjustAreaX 90 y2 = SensorArea(3, 1) + AjustAreaY Case "E" x2 = SensorArea(4, 0) + AjustAreaX y2 = SensorArea(4, 1) + AjustAreaY Case "F" x2 = SensorArea(5, 0) + AjustAreaX y2 = SensorArea(5, 1) + AjustAreaY Case "G" x2 = SensorArea(6, 0) + AjustAreaX y2 = SensorArea(6, 1) + AjustAreaY Case "H" x2 = SensorArea(7, 0) + AjustAreaX y2 = SensorArea(7, 1) + AjustAreaY End Select End Sub End Module 91