Comments
Description
Transcript
在室確認システムの設計と製作
特 別 研 究 報 告 題 目 在室確認システムの設計と製作 報 告 者 1105309 多 木 勝 彦 指 導 教 員 岩 下 克 教授 平成 20年 2月 18日 高知工科大学 大学院 工学研究科基盤工学専攻 電子・光システムコース 目次 第1章 序論.................................................................................................................. 3 1-1 研究背景 .............................................................................................................. 3 1-2 研究の目的........................................................................................................... 3 第2章 研究概要........................................................................................................... 5 2-1 センサネットワーク概要...................................................................................... 5 2-2 在室確認システム ................................................................................................ 5 2-3 全体の構成........................................................................................................... 7 2-4 使用する機材の主な説明...................................................................................... 7 (1) PIC .................................................................................................................... 7 (2) AVR ................................................................................................................... 8 (3) 赤外線センサ..................................................................................................... 8 (4) フレネルレンズ ................................................................................................. 9 (5) 距離センサ .......................................................................................................10 (6) ステッピングモータ .........................................................................................12 (7) サーボモータ....................................................................................................13 (8) XBee .................................................................................................................13 2-5 センサノード部...................................................................................................15 2.5.1 ハードウェア設計 ............................................................................................15 (1) PWM ................................................................................................................15 (2) ADC..................................................................................................................16 (3) 各種割り込み....................................................................................................16 (4) 通信デバイス切り替え .....................................................................................16 2.5.2 センサーノードフローチャート .......................................................................17 2.5.3 パケット構造....................................................................................................22 2-6 在室確認ソフト部 ...............................................................................................23 2.6.1 在室確認システムフローチャート ....................................................................24 2-7 在室状況のWeb公開............................................................................................30 2.7.1 Web公開システムのフローチャート .................................................................31 2-8 センサ設置のための出力測定 .............................................................................32 2.8.1 モーションセンサ ............................................................................................32 2.8.2 距離センサ .......................................................................................................33 第3章 3-1 測定結果..........................................................................................................37 センサノード作成 ...............................................................................................37 3.1.1 センサノード構成 ............................................................................................37 1 3-2 距離センサの相互干渉 ........................................................................................41 3-3 電圧読み込み精度向上検証 .................................................................................42 3-4 人の検出アルゴリズム ........................................................................................43 3-5 作成したシステムの外観.....................................................................................48 3-6 実用化実験..........................................................................................................50 3-7 判断不可能な事例 ...............................................................................................52 3.7.1 熱源の移動 .......................................................................................................52 3.7.2 検知箇所の狭窄化によるデメリット ................................................................53 第4章 考察.................................................................................................................54 第5章 まとめ .............................................................................................................55 謝辞 ..................................................................................................................................56 参考文献 ...........................................................................................................................57 管理ソフトウェア プログラムリスト ..........................................................................85 管理ソフトウェア プログラムリスト(モジュール) ....................................................109 2 第1章 序論 1-1 研究背景 私達を取り巻く生活環境は、パソコンや携帯電話などの情報端末の一般への普及、インタ ーネット回線のブロードバンド化及び価格の定額化などに伴って、より一般的に、より高 速大容量へと大きく変わって来た。近年それらを活用した情報家電と呼ばれるネットワー クに接続された家電の開発が行われてきている。 ユビキタスネットワーク[1] とは、総務省によると「『いつでも、どこでも、何でも、誰で もアクセスが可能』なネットワーク環境」と定義されている。ユビキタスネットワーク化 は既存のパソコンだけではなくテレビ、洗濯機や冷蔵庫など一般的な家電製品をネットワ ークで結び、互いに通信を行い今までになかった機能や利便性の向上を図ることを目的と している。 ユビキタスネットワークを一般家庭等に構築する上で、センサネットワークの開発は必要 不可欠となってくる。センサネットワークとは元来、単体では限られた機能しか持たなか ったセンサを、ネットワークに繋げ機能向上を図るシステムである。ユビキタスネットワ ークの「目」とも言えるセンサでネットワークを構築し、パソコンや情報家電がデータを やり取りすることで詳細な人体の位置情報や、様々な環境情報を得て、より良いサービス を提供することが可能となる。 人 体 の 位 置 情 報 検 知 に は GPS(Global Positioning System) や RFID(Radio Frequency IDentification) 、防犯カメラの使用が考えられる。しかし検知精度や個体識別の有無など、 実装する用途や現場によって求められる性能が異なっている。例えば、個体識別が必要な 場合にはRFIDなどが使用される。実用例として「RFID豚トレーサビリティ」[2] や「社員証、 学生証への導入」[3] 、「物品ラインへの導入」[3] などがあり、それぞれ生産情報管理、防 犯、効率化と精度向上などのために実用化されている。 しかしながら、公共の場所や家庭内では個人識別の必要性がない場合がある。よって、用 途に応じて個人識別を必要とせず安価な位置情報検出手段が必要となる。 1-2 研究の目的 大学構内で要望が出た「教員に面会を求める際に前もって在室状況が分からない か?」というものである。 教員室は各教員に対して割り振られており、ドア部分に は手動で行う「行き先表示ボード」が設置されている。しかし、手動で行われる「行 き先ボード」では人の手によるものなので忘れられる事が多い。また、教員室前に行 った場合にその在室状況が判ってもメリットは少なく、訪問する前に在室状況を確認 したい。 まず、RFIDやGPSの携帯を考えた場合、デバイスを持ち歩かなければならず、また、 忘れる事も多い事が推測される。他の手段として一般的なのは監視カメラの設置であ 3 るが、高価であり、プライベートを著しく侵害する可能性がある。そこで、研究室で 作成した既存の位置情報管理システムを転用し在室確認を行えないかと考える。本研 究ではセンサとして安価で定評のある赤外線センサを使用し、人体の位置情報検知を 行いたいと考えている。そして、既存のシステムはそのメインとなった赤外線センサ の特性から検知範囲内で静止している対象に対し安定した検知が困難である。したが って、この問題の解決を解決し、実際に「在室確認システム」を作製し、教員室に設 置、実用可能か検証を行う。また実際に得られた情報は、その利用を考え、Webペー ジ上へと公開を行う。 実験で使用する赤外線センサとは、自動ドア、ATMなど単体で広く利用されている ものを指す。センサネットワークが必要とされてくる中で、確かに性能の良いセンサ を各所に配置すればより完璧なセンサネットワークが出来上がるが、ユーザーのプラ イバシーを侵害せず、また専用のデバイスを携帯させることなく位置情把握を行いた い。また、通常人体検知には用いないセンサを検証、使用し、システムの機能向上に 努める。 4 第2章 研究概要 2-1 センサネットワーク概要 センサネットワーク概略を図 2-1に図示する。 server LAN Energy saving 01001110 NIC NIC Sensor node Sensor node Functional 図 2-1 位置情報管理システム概略 システムは、サーバー側の管理プログラムと、各種センサを搭載したセンサノード部分に 分けられる。実験では私たちの生活空間にモーションセンサを複数設置し、各センサから のデータを元に人の位置情報の検知を試みた[6] [7] 。得られた位置情報は、省エネ、防犯な ど既存の電化製品への新たな機能追加などに役立てる事が可能である。 2-2 在室確認システム 在室確認システムとは、オフィスなど広範囲な場所で運用することを目的とはせず、限 られたスペース(教員の居室、パーテーションで区切られた個人スペース)に対しての運用を 考えており、図 2-2の様な構想となっている。 5 居室 EV LAN Cor サーバ 図 2-2 在室確認システム構想 各部屋のセンサノードで得られた情報をサーバーで収集管理を行う。 使用するモーションセンサは自身の検知範囲の温度変化を監視しているため、静止した人 体は検出困難である。よって、モーターを用いて、図 2-3の様に限られた検知範囲を掃引さ せてやる事によって静止した人体の検知を可能とする。 検知範囲 回転 図 2-3 センサ感知範囲の拡張案 また、他のセンサにも言える事であるが、センサの検知範囲外の探索は行えず、センサネ ットワーク複数個のセンサの設置を余儀なくされる。しかし、検知範囲内を掃引させてや れば、最小限のセンサで人の位置情報を得ることを可能となる。 6 2-3 全体の構成 まず、使用するセンサは赤外線センサ単体ではなく、距離センサも用いる。これら 2 つ のセンサの相関を得る事によって 「モーションのみでは熱源が検知可能だが、人か物かの区別が出来ない」 「距離センサでは物体の有無は確認可能だが、人か物かの区別が出来ない」 このそれぞれの問題に対して対処可能であると考える。 図 2-4に製作を行う『在室確認システム』の概要を示す。システムは大きく2つに分けら れる。 設置場所の環境データを取得するセンサノード部と、センサノード群より送られ てきたデータを取得、在室確認するソフト部分に分けられる。 センサーノード センサー PC モータ 管理ソフト MCU HTML パケット NIC NIC 図 2-4 在室確認システム概観 センサノード側には、センサの検知範囲を掃引するためにはモーターが必要となる。得 られた環境情報の判別は外部ソフトウェアで行おうと考えているが、センサの出力管理及 び PC 側との通信管理を行うためセンサノード上に MCU (Micro Control Unit)を搭載する。 管理ソフトウェア側では、センサノードより得られた情報を元に、在室確認を行う。ま た得られた情報は HTML 文書として内部で生成し、Web 上へと公開を行う。 2-4 使用する機材の主な説明 (1) PIC PIC とは所謂マイコン(マイクロ・コントローラー) と呼ばれる物で、電気的な「何か」 を制御するためのコンピューターの一種だと考えることが出来る。例えば炊飯器や洗濯機 などの電化製品に内蔵され、予め PIC 内にプログラムされた手順に沿って付属の I/O ポー トの入出力制御を行うことにより、ご飯を炊いたり洗濯を行ったりすることを可能として いる。PIC がパソコンと異なる点は、パソコンが様々な動作が可能な様汎用的に組み立て られているのに対し、PIC はランプを点灯させたりモーターを駆動させたりと制御面に特 化している。 7 (2) AVR AVR とは Atmel 社の開発した 8bitRISC タイプの MCU(Micro Controller Unit)で、PIC などと同様に、CPU,メモリ(フラッシュ、RAM)、不揮発メモリ、I/O が一つのチップ上に 収められている。PIC などと異なり 1996 年に発表された後発の MCU である。従って、PIC の不足部分を補うような形で洗練された商品となっている。結果的に、PIC と AVR の両方 を比べた上で AVR を選択したが、機能的な面について比較紹介する。 まず、両 MCU は RISC タイプであり命令長が固定バイトとなっている。それぞれ、16Byte* 長となっており、命令数はそれぞれ、35 個(PIC)、131 個(AVR)となっている。命令数が多 い分、多彩な要求に答える事が可能となっている。また PIC は 1 クロック=4 サイクルとな っており、最短の 1 クロックの命令コードの実行時間であっても 2μs(20MHzクロックの 場合)かかる。対して、AVR ならば、1 クロック=1 サイクルであるため、最短の命令実行 時間が 1/4 となる 0.5μs で実行可能です。また汎用レジスタが 32 個(PIC で言うところの Working レジスタ個数が 32 倍)、リニアなメモリ空間(バンク切り替えが要らない)、割り込 みベクタが割り込みの種類ごとに設定されている、(PIC では割り込み要因を手動で判断し なくてはならない)などを代表して挙げたいと思う。結局の所、一番のポイントは前述した 命令数の多さからの拡張性の高さが決め手となった。 *PIC18F シリーズと仮定 (3) 赤外線センサ センサは図 2-5の松下電器製焦電型MPモーションセンサNaPiOn(AMN13111)を使用し、 付録に性能の概略を示す。 図 2-5 実験に使用した AMN13111 の概観 赤外線を利用したセンサには今回使用した焦電型とサーモパイルと呼ばれるもの がある。原理は、サーモパイルが熱電対の原理を応用した簡単なセンサで、熱電対を 8 微少な面積の中に直列に並べた物である。熱電対、すなわち2種類の金属で回路を作 成しその2つの接合部分が異なる温度に保たれた時に熱起電力が生じて電流が流れる 「ゼーべック効果」の原理を使用している。 また、焦電型は焦電物質を用いてあらゆる物体から放出される赤外線エネルギーを 検出することができる。この型のセンサは波長依存性がないため光学フィルタを使い 分け、波長を選別してやることによって様々な温度センサを作ることが可能である。 AMN13111は温度差(+4℃)を検出可能なため体温を持つ人体の検出に最適とされてい る。 全体の検出範囲は図 2-6のような縦1.4m横2.0mの長方形となっているが、実際には 24個の各セルに被験者が侵入した場合にのみ出力(Vdd-0.5V)されることとなる。 図 2-6 使用した赤外線センサの検出セル配置 (4) フレネルレンズ 赤外線センサの検出範囲を明確に、なおかつ狭窄化させるため、レンズを用いる。 用いたレンズは図 2-7に示すフレネルレンズを用いる。 9 図 2-7 フレネルレンズ概観 フレネルレンズは同心円状に切り厚みを減らしたレンズで、断面はノコギリ状にカ ットされている。性能としては凹レンズ、凸レンズ等と変らぬ効果を持ちながら、そ の厚みが解消されており、レンズの軽量、コンパクト化に成功している。 使用したフレネルレンズは今回使用した赤外線センサと同系統のセンサに最適化さ れている。よって、焦点の位置合わせが不要で後部に差込、固定することで実装可能 であり、専用のフォルダを用意する必要がなく、生産性が高い。検知範囲は図 2-8に図 示する。 260cm フレネルレンズ 130cm 86cm 5m 10m 20m 30m 検出範囲 43cm 図 2-8 フレネルレンズを用いた理論検知範囲 (5) 距離センサ 図 2-9に使用した、距離センサの概観を示す。(写真は 150cm距離センサ、500cmの 物は割愛する。) 10 図 2-9 距離センサ概観 このセンサはメカトロ分野でのロボットの周囲環境把握用の眼として、また工場ラ イン上での製品の流れを把握する為などに用いられる。測定物までの距離に応じて出力電 圧を返すが、このセンサを用いて人の位置情報検知を行いたい。このセンサの動作原理は図 2-10に示すように、内部に赤外線LEDとPSD(Position Sensitive Detector)を内蔵しており、 被測定物に対して赤外線LEDを照射し、その反射光をレンズでPSD素子上へと収束させて いる。PSDは素子上に照射された光スポットの重心を、その光パワーより把握する事が可 能である。そして、測定物までの距離が変化する度、重心がPSD上で変位するため、対象 物までの距離として検出可能である。 変位 レンズ LED駆動回路 LED 信号処理回路 測定物 PSD 図 2-10 距離センサの構造及び、動作原理 11 (6) ステッピングモータ 使用を検討しているモーターの一つとしてステッピングモータを挙げる。ステッピン グモータの概観は図 2-11に示す。 図 2-11 ステッピングモータ概観 このモーターは外部からのパルス制御によって駆動が行われる。具体的には図 2-12の様に 4 種のパルスを順番に信号線に与えてやる事によって正転、逆転に回転を行える。 CW CCW 青 0 0 1 1 黄 1 1 0 0 赤 0 1 1 0 白 1 0 0 1 CW CCW 青 0 0 1 1 黄 1 1 0 0 赤 0 1 1 0 白 1 0 0 1 図 2-12 0=0V 1=Vcc ステッピングモータ駆動パターン このモーターの欠点は今現在の角度を基準として何ステップ進むか?という処理しか行え ないため、電源投入時に初期角度を手動で設定してやる必要性がある。また、駆動中に外 部からの要因で角度がずれても補正する事はモーター単体では不可能である。 12 (7) サーボモータ この研究で使用したサーボモータについて記述する。サーボモータ概観は図 2-13に示す。 図 2-13 サーボモータ概観 サーボモータは先に紹介したステッピングモータと同じくパルスによってその回転角度が 制御されている。しかしながらステッピングモータとは異なり。図 2-14の様に周期的なパ ルスのデューティ比を変化させる事によって回転角度の制御を行っている。 デューティ比 15ms(固定) 小さく GND 1.5ms Vcc 中心 Pulse 大きく 図 2-14 サーボモータの制御方法 周期は 15ms を固定として、ハイレベル部分が 1.5ms を中心として±0.5ms 動かしてやる ことによって回転角度を制御可能である。 サーボモータは、いくつか種類があるが一般的には回転角度に制限があり、今回使用し た物も、約 180 度強の回転角度しか持たず、これを振り切ろうとした場合、過電流による レギュレータ等の破損が考えられるので注意が必要である。 (8) XBee 図 2-15に使用した無線通信デバイス、XBeeの概観を示す。XBeeモジュールは低消費電力 13 のワイヤレスセンサーネットワークを構築するために設計されており、内部のファームウ ェアを書き換えることによって、ZigBee又は、IEEE802.15.4 としての動作が可能である。 このXBeeは図 2-16の様な評価基盤が付属しており、XBeeを評価基盤に接続、電源投入す る。その後USBもしくは、RS232CケーブルでPCと接続し、ハイパーターミナル上からコ マンド対話形式でモジュールの制御が行える。また制御コマンドは私達ユーザー側の希望 する独自のコードを開発することが可能である。表 2-1にXBeeの簡単な仕様を明記する。 表 2-1 XBee 簡略化性能表 XBee802.15.4 OEM RF Module 250kbps 通信速度 30m 屋内通信距離 送信Power 1mW (+0dBm) 2.4GHz 周波数帯 2.8~3.4V DC 電源 電流 (受信/送信) 50mA / 45mA 128-bit AES 暗号化 I/O 8 (10bit ADC 7本) 名称 14 図 2-15 無線通信デバイス XBee 概観 図 2-16 XBee 開発ボード(USB) 2-5 センサノード部 センサノードは、モーターの回転、ネットワーク送受信、センサ出力の加工などの管理 を行っている。 2.5.1 ハードウェア設計 (1) PWM PWM とは Pulse Width Modulation の略でパルス波のデューティ比を変化させ I/O ピン 15 より出力可能である。使用した ATmega48 では 6 箇所の PWM 出力が可能で、16Bit タイ マカウンタを用いた PWM を使用する。PWM によって得られたパルスは前述の通りサーボ モータの駆動に使用します。 (2) ADC 各センサ及び、Cds セルの検出抵抗にかかる電圧を AD 変換するために ADC を使用して います。ATmega48 では 10bit 分解能を持った ADC が 6 チャンネル使用可能で、距離セン サ 2 種、Cds セルの合計 3 本を使用しています。ADC の基準電圧は比較電圧として Vref ピンが用意されていますが、各センサの出力特性から回路駆動電圧 Vcc 3.3V をそのまま使 用しています。 また、ADC 精度向上のために、ADC 開始後 SLEEP に入り、ADC 完了割 り込みをもって SLEEP の解除を行っています。 (3) 各種割り込み 前述の様に AVR では割り込みベクタがそれぞれ個別に指定されており、使用している割 り込み要素は、タイマカウンタ 1 比較 B 一致(PWM のデューティ比更新のための割り込み)、 USART RX(通信機能 USART の受信完了割り込み)、ADC 割り込み(ADC 完了割り込み)の 3 種を使用している。 (4) 通信デバイス切り替え 製作するセンサノードはRs232cとXBeeを経由した無線通信の 2 つの機能を持たせてい る。AVRからのTx、Rxピンをそれぞれの通信デバイスのRxとTxに繋いだ場合、各々の通信 デバイスのピンの入出力がバッティングする事となる。よって論理ゲートチップを用いて の図 2-17様に切り替えを行っている。 74HC244AP Tx Rx Rx Tx AVR RS232C RS232C使用 AVR In Out 図 2-17 XBee使用 XBee 論理ゲートを用いて使用通信デバイス選択 16 2.5.2 センサーノードフローチャート 図 2-18、図 2-19にセンサノードBのフローチャートを示す。 SubMain ルーチン スタート 制御コード受信 Mode1 PWM幅指定 初期化 150cmセンサ ON メイン 割込み待 Yes Wait 各種 Mode選択 150cmセンサ 出力取得 No SRAM格納 照度確認 500cmセンサ ON Wait 照度確認 ルーチン Cds電圧値 取得 閾値比較 Yes Mode2 500cmセンサ 出力取得 SRAM格納 モーションセンサ 出力取得 SRAM格納 NO 回数比較 Yes NO Return Return 図 2-18 センサノード B フローチャート NO.1 ノードは基本的に電源投入後、初期化を経て、メインルーチンへと突入する。しかし、 メインではノード上のCdsの照度を確認しているだけで他に作業を行っておらず、外部 からのシリアル通信による対話形式にて各種機能を選択、実行している。動作モードは デバッグがしやすい様に 6 つに細分化されており。各モードについて表 2-2の様に定め ている。 17 表 2-2 センサノードモード別機能表 モード名 Mode0 機能 手動回転 Mode1 ソフトウェアリセット Mode2 Sleep Mode3 回転&センサ出力送信 Mode4 SRAM内容送信 Mode5 各ADC結果取得 Mode6 テスト 「照度確認」サブルーチン Cds セルに直列で繋がれている検出抵抗にかかる電圧値より、センサノード設置環境の照 度比較を行っている。Cds とは照度センサの一種で照射される光量によって抵抗値が変化 する素子である。内部であらかじめ定めた閾値を ADC 結果が下回った場合において、セン サノード設置環境が消灯状態になったとして「Mode2」を呼び出す。それ以外の場合はル ーチンを抜けている。 18 Mode0開始 Mode1開始 Mode2開始 Mode3開始 メッセージ表示 メッセージ表示 メッセージ表示 メッセージ表示 角度受信 SRAMクリア 各種センサ OFF 制御コード受信 PWM幅反映 Return Cds電圧 取得 SubMain 呼出 PWM許可 NO Return 閾値より上? メッセージ表示 Yes メッセージ表示 Return Return Mode5開始 Mode6開始 メッセージ表示 メッセージ表示 150cmセンサ ON Return Wait Mode4開始 150cmセンサ 出力取得 メッセージ表示 SRAM内容 送信 500cmセンサ ON SRAM呼出 Wait NO アドレス比較 500cmセンサ 出力取得 Yes モーションセンサ 出力取得 Return Return 図 2-19 センサノード B フローチャート NO.2 「Mode0」サブルーチン ここでは、対話ユーザーによるモーターの手動回転が行える。ルーチンに入るとまず 「Mode0」で在る旨が送信された後に、回転希望角度に相当する 3byte 文字列の受信待 19 機状態へと移る。その後、得られた設定値を元に PWM 値のデューティ比の変更を行っ た後、ルーチンを抜ける。 「Mode1」サブルーチン Mode1 は MCU のソフトウェアリセットであり、作成したセンサノードにはリセット スイッチを付属させているが、遠距離からのリセットを行う必要が想定されるのでこの 機能を設けている Mode1 がコールされると、マイコン上の SRAM の内容をクリアし、 初期化ルーチンに戻る。 「Mode2」サブルーチン Mode2 は、強制 Sleep 待機動作を行う。センサノードは、各動作の間、定期的に ADC ピンに接続された Cds セルの監視を行っている。ノード内部で閾値電圧を設定し、Cds にかかる電圧が降下した場合に、搭載されているセンサの一部の電力をカットし、その 後、閾値を電圧が越える場合、センサノード設置部屋が点灯状態になったとして Sleep より復帰する。 「Mode3」サブルーチン モード 3 は最も多用されると思われるモードで、管理システムから送られてくる制御 コードを元にサーボモータ回転を行う。制御コードの内訳は 図 2-22にて後述する。 Mode3 が呼び出されると、制御コードの受信待ち状態となる。制御コードが受信完了し た時点で「SubMain」サブルーチンをコールする。処理が戻ってきた後、ルーチンより 抜ける。 「Mode4」サブルーチン モード 4 は、マイコン内部のSRAMに格納されているデータの一覧を送信する。こ れらをターミナルで受信した場合図 2-20の様に表記される。Mode4 が呼び出されると、 まず、受信側で読みやすい様に横軸に 3 桁のSRAMアドレスのうち下位 1 桁が、送信途 中ではSRAMデータに規則的に上位 2 桁のSRAMアドレスを付加していく。SRAMの終 了アドレスに達した場合ルーチンを抜ける。 20 レジスタアドレス モーションセンサ 150cm距離センサ 500cm距離センサ 図 2-20 モード 4 送信データ内容 使用した MCU には 512Byte の SRAM が搭載されており、先頭から順に 110Byte ず つ「モーションセンサ出力」「150cm 距離センサ出力」、「500cm 距離センサ出力」の順 番に 2 桁の 16 進数で保存されている。 「Mode5」サブルーチン 現在センサが向いている正面の測定物に対して、各センサの出力を図 2-21の様に表記す る。Mode5 が呼び出されると、まず 150cm距離センサの電源をONにする。安定化時間を 待った後、出力電圧を取得、送信する。同様に 500cm距離センサも出力を取得、送信、モ ーションセンサのON/OFFの情報を取得した後送信を行っている。その後ルーチンを抜ける。 図 2-21 Mode5 出力文字列 送られてくるデータは ADC の結果をそのまま送信しているため、8bit の AD の出力として 256 段階となるため、16 進数で表記すると 00~FF の間の2Byte で表記される。 「SubMain」サブルーチン 21 SubMain では、制御コードで与えられた設定を元にサーボモータを回転し、角度毎にそれ ぞれのセンサの出力の SRAM への格納を行っている。 まず、SubMain が呼び出されると、 回転開始角へと移動するために PWM のデューティ比が変更される。 希望回転角に到着し、 使用するセンサの電源 ON→安定化時間待機→センサ出力取得→SRAM に格納が行われて いる(150cm 距離センサ終了後、同手順で 500cm 距離センサ)また上記手順とほぼ同じだ が、モーションセンサについては安定化時間が7s 前後存在し、尚且つ、駆動中でも 0.5mw の消費電力であるため電源管理は行わない。 2.5.3 パケット構造 図 2-22 9Byte 制御コード にセンサノード側からの送信パケット構造図を示す。 Max 331Byte 出力データ 1Stepあたり6Byte モーション 距離センサ 距離センサ データ分割 センサ1件目 150cm 1件目 500cm 1件目 コード 回転方向 1Byte スタート位置 回転Step数 3Byte 2Byte 図 2-22 回転速度 データ分割 コード 2Byte 1Byte ・・・ ENDコード 送信パケット構造図 パケットは大きく、制御コード部と出力データ部に分けられる。制御コードとはセンサノ ードに搭載されているサーボモータの回転制御コードである。コード部は更に細かく 4 つ に分けられる。まず、正転、逆転を選択する「回転方向」部分、回転の開始部分を決定す る「スタート位置」部分、回転開始から何度回転するかを決定する「回転 Step 数」部分、 そして、1Step 回転後の停止時間から「回転速度」を設定する部分となる。 スタート位置は 16 進数表記 4D~13F の間の約 242 ポイントを指定可能である。回転ステ ップ数はディフォルトでは 1 ステップ 4 ポイント移動として、55 ステップに設定してある。 回転速度は 1 ステップ毎の移動終了後の待ち時間を指すため、100ms と指定した場合には 回転開始から終了まで 5.5 秒程必要となる。 次に、出力データ部分では、モーションセンサ⇒距離センサ(150cm)⇒距離センサ(500cm) の順にセンサの出力を数値化して送っている。また、各ステップのデータの区別しやすい 様に分割用のコードの付加を行った。最後に、END コードを付加する事によって PC 側か らパケット送信の終了を認識する。 22 2-6 在室確認ソフト部 在室確認ソフト部構想を図 2-23に示す。在室確認システムでは、ネットワークを介して センサノードより得られたパケットを選別、在室の判定を行う。また得られた結果をディ スプレイ上に視覚的に判りやすく表示、実際の運用の観点からWeb上での公開用ページ作成 を行っている。 出力データ 00593710,0808F,07F9 6,00F89,0738E,0279E ,10099,10096,1008F,1 0073,11158,00198,10 023,10133,10173, ・・・ 管理ソフト Webページ 変換表示 15度 17度 18度 20度 = = = = 100cm 120cm 115cm 330cm ・ ・ ・ Webページ生成 在室管理公開ページ 更新日時 ノードA 在室 ノードB 不在 グラフ化 PC 図 2-23 在室確認ソフトウェア構想図 23 2.6.1 在室確認システムフローチャート 作成した管理システムのフローチャートを図 2-24~図 2-27に記述する。 スタート 初期設定 Yes 各種イベント 待ち NO 回転データ 送信 通信開始 Text Clear Graph Clear コマンド 送信 Return pos MsCom イベント 自動運転 タイマ 環境情報 更新チェック NO 終了ボタン Yes 終了 回転データ 送信 Text Clear Graph Clear 自動運転 タイマ 回転開始 Delay テキストBox クリア グラフ領域 クリア イベント発生 Mode3選択 Return Return Mode3 move 回転制御 送信 Return Pos 通信開始 Return Return 直前回転方向 取得 Comポート オープン Text Clear 直前回転開始 箇所算出設定 Return テキストBox クリア 制御コード 送信 コマンド送信 Return Return 送信テキスト BOX内送信 Return 図 2-24 在室確認ソフトフローチャート 1 ソフトウェアが起動されると、各種初期化が行われた後、各種イベント待ち状態へと遷 移する。イベントは主に、画面上のボタンに対するクリックイベントであるが、その他、 24 Mscomm の Oncomm イベント、タイマコントロールの Tick イベントが 2 種含まれている。 各種ルーチンについて説明していきたいと思う。 「通信開始」クリックイベント 「回転データ送信」クリックイベント “3”を送信し Mode3 を選択する、その後メッセージが送られてくるため受信終了時ま でディレイを挿入している。画面上の各種制御 Box より回転制御コードを作成し送信を行 う。 「通信開始」クリックイベント Com ポートをオープンにし送受信可能状態とする。オープン時にエラーが発生した場合 は画面上にエラー内容が明記される。 「コマンド送信」クリックイベント コマンド送信と書いてあるが直ぐ左のテキストボックス内の内容を直ちに送信を行う。 この機能は、すべての動作を手動で行いたい場合などのために用意されている。 「Text Clear」クリックイベント 中央のメインテキストボックス内容を手動クリアする。 「Graph Clear」クリックイベント 在室確認システムタブ上に存在する 2 つのグラフ描画領域を手動クリアする。 「Return Pos」クリックイベント 直前の回転開始まで速度等を同じ条件で移動を行う。イベントが発生した場合に、まず直 前の回転方向が取得される。その後、現在地から前回転開始位置まで逆方向に回転する形 の制御コードを生成し送信する。 「自動運転タイマ」Tick イベント 設定タブ内で定められた繰り返し時間が来ると発生するイベントである。イベント発生 後「Mode3 Move」を呼び出す事によって、実質自動運転という形を実現している。 25 環境情報 更新チェック Yes No 更新時刻か? 次回更新時刻 +5分後 Mode2か? NO Yes 環境情報 更新 Return センサ出力 計算 NO Yes 平均化回数 ≧1 出力平均化用 配列に格納 Yes 逆転データか? 配列内 昇降入れ替え NO 既存出力に新規 分データを加算 Yes 平均化回数 取得終了 NO Mode3 move センサ出力を 電圧値へ変換 配列を平均回数 で乗算 Return 受信データを 出力格納配列へ Yes 逆転データか? 配列内 昇降入れ替え NO センサ出力を 電圧値へ変換 出力電圧値 テキスト保存 NO Yes ファイル オープン テキスト 書き込み ファイル クローズ 距離算出 距離リミッタ 算出データ 列挙 ① 図 2-25 在室確認ソフトフローチャート 2 26 5分後に 再確認 ② 算出距離 テキスト保存 NO Yes ファイル オープン テキスト 書き込み ファイル クローズ モーションセンサ描画 初期位置反映 Mode3 move モーションセンサ出力 描画 距離センサ描画 初期位置反映 Mode3選択 150cm距離センサ 出力描画 Delay300ms 制御コード 送信 500cm距離センサ 出力描画 Return 実距離選定 NO 初期値格納 フラグ Yes 環境情報初期値 としてDefEnv()へ 初期化格納フラグ Ture 現在の環境情報 としてNowEnv()へ 選別後実距離 を描画 Mode10選択 Return 図 2-26 在室確認ソフトフローチャート 3 「環境情報更新チェック」Tick イベント 1 分ごとに発生し、設定タブ内で定めた時刻との比較を行っている。もし、一致し、なお かつ、現在 Mode2(センサノード設置場所が消灯中)であればモーションセンサの反応にかか わらず環境初期情報の更新を行います。更新時刻でありながら Mode2で無かった場合は設 置環境内にまだ人が居るであろうことを考慮し、次回の環境更新比較時刻を現在の値より +5 分する。 「センサ出力計算ルーチン」サブルーチン 取得したセンサの出力が配列に格納し終わった後に呼び出され、距離に変換された後に 画面描画、テキスト保存などが実行される。まず、呼び出されると、平均化回数について 27 比較が行われる。平均化を行う必要性があるならば分岐したのち、保存されていた前出力 に加算される。平均化を行える分のデータが揃ったのならば平均を算出し、その値を現在 のセンサの出力として処理を続けていく。もし、平均化を行うに十分なデータを取得して いなければ 「Mode3Move」を呼び出し続けてモーターにて回転を行う。加えて、最初か ら平均化を行う必要性の無い場合は、受信データを配列に格納したのち、電圧値に変換→ 距離に変換を行う。算出した距離は各センサの検知範囲外のデータを取り除き、テキスト ボックス内に角度ごとに列挙する。その後、画面上にモーションセンサの出力は下の描画 ウインドウへ横軸は角度、縦軸は距離として描画される。その後、150cm と 500cm 距離セ ンサの出力は、 「実距離選定」ルーチンにより選定、統合され 1 種の距離データとして保存 される。選定後の距離データは初期値格納が行われていなければ、設置環境の無人時の比 較データとして DefEnv()配列へと格納される。その後初期値格納が終了したことを示すフ ラグを真として「センサ出力計算」のメインへと戻る。もし初期値格納が完了しているな らば、選定後の距離データは現在の環境の値として NowEnv()配列へと格納される。次に、 「選別後実距離を描画」にて選定によって統合された実距離を描画ウインドウ上に太めの 白線で描画を行う。サブルーチンを終了する前に、Mode10 を選択する。 「Mscomm」Oncomm イベント MicrosoftCommunicationControl にて、RS232C 経由で送受信、エラーが発生した場合 に発生する。各種エラーはエラーメッセージを表示したのち、ルーチンを抜ける。受信イ ベントが発生した場合にのみ。定義された処理を行っていく。まず、受信した文字列から 「Mode」という文字列の検索を行い、Mode 数の判別を行い Mode 数に応じた処理へと分 岐を行う。例外として Mode10 は受信した文字列をただ、メインテキストボックスへと列 挙するのみにとどまる。また、分岐条件である「Mode」の探索において発見されなかった 場合はルーチンを抜けるものとする。 「Mode2 処理」サブルーチン Mode2 はセンサノード設置環境が消灯中である場合に継続されるモードである。 まず、受信した文字列から「Quit」文字列の検索を行う。Quit が発見されたならば、Mode2 が終了したとして、Sleep が解除された旨をメインウインドウへ表示する。受信文字列は初 期化された後、Mode10 に設定され処理を抜ける。 「Mode3 処理」サブルーチン 受信文字列内から「END」文字列の検索を行う。もし発見されたなら「センサ出力計算」 サブルーチンを呼び出す。それ以外の場合においてはルーチンを抜ける。 「Mode4 処理」サブルーチン 28 ここでは、センサノード内でのSRAM内容の画面への表示を行っている。表示パターン 等については前述した図 2-20を参照してもらいたい。 「Mode5 処理」サブルーチン このモードでは受信した各種センサの出力である 16 進数を画面上へ変換して理解しやす く表記しなおしている。具体的には、まず、受信文字列内から「Quit」文字列の検索を行 う。発見された場合、Mode5 にて送られてくるデータ群(図 2-21参照)より必要データを計 算用配列へと格納を行う。その後、各距離センサについては電圧、距離の 2 種類に変換を 実行し、メインウインドウへの表記を行う。モーションセンサの出力に関してはそのまま 0 or 1で表記している。その後Mode10 を選択しルーチンを抜ける。初期文字列検索分岐で 「Quit」が発見されなければ直ちにルーチンを抜けている。 29 MsCom イベント Yes NO 受信文字列内 「Mode」検索 Mode数認識 No Mode10? Mode2 処理 Yes 受信文字列を TextBoxへ Mode3 処理 Mode4 処理 Mode5 処理 Return Mode2 処理 Yes 受信文字列内 「Quit」検索 NO 受信文字列 初期化 SLEEPが 解除されました Mode10 選択 Return Mode3 処理 Mode4 処理 Yes 受信文字列内 「END」検索 NO Yes 受信文字列内 「Quit」検索 NO センサ出力 計算 Return Return Mode5 処理 Yes 受信文字列内 「Quit」検索 NO 取得データを 計算用配列へ 電圧値変換し 格納 各種センサ 変換後の値 Mode10 選択 Return 図 2-27 在室確認ソフトフローチャート 4 2-7 在室状況の Web 公開 在室確認システム部分において得られた、各部屋の在室状況を Web 上にて参照可能と するために、ソフトウェアからページの作成、更新を行う。Web ページは基本的に HTML タグによって作成されており、JavaScript を組み込むことによってページ内テーブルの 内容を定期的に変更している。しかし、システム側で 1 から HTML 文書を生成しなお 30 すのでは手間がかかる。よって、良く変更する箇所のみを JavaScript の外部ファイル(Js ファイル) として作成し、外部ファイルのみを変更する事とする。 Js ファイルの更新によって、画面内の在室状況更新時刻、教員名、在室状況、不在開始時 間などが順次書きかれられる事となる。 2.7.1 Web 公開システムのフローチャート 図 2-28にWeb公開システムのフローチャートを示す。このフローチャートは 前述した在室確認ソフト内部に組み込まれており、別タブに機能が搭載されている。 外部Jsファイル 編集 保存 HTML表示 ファイル オープン 外部Jsファイル オープン ブラウザ起動 ファイルより 1行づつ取得 ユーザー数 書き込み 在室管理ページ EOFに到達 ユーザー名 書き込み Return NO Yes 文字列を”;” 毎に分割保存 文字列から “を除外し保存 ファイル クローズ ノード数読取り 保存 在室状況 書き込み テキスト 更新時間格納 変更後テキスト Return ノード名読取り 保存 TextBox上に 列挙 Return 図 2-28 Web 公開システムのフローチャート まず、 「外部 Js ファイル編集」は在室確認ソフトの初期化部分に含まれる手順であるが、 この節で記述を行う。このサブルーチンは外部 Js ファイルを読み込み込んだ後、Web 公開 システムタブ内のテキストボックススペースにその内容の列挙を行っている。また画面上 に列挙するだけではなく、ユーザー数を収める Numeric Box やユーザー名を格納する各 31 Text Box に値の反映を行っている。 「保存」ルーチンでは、画面上の「保存」ボタンのクリックイベントの処理が書かれてい る。外部 Js ファイルをオープンした後、画面上のユーザー数とユーザー名を元に Js ファ イル内配列の内容を書き換えている。また、在室状況更新時間を HTML 文書上に記述する ために、Js ファイル書き込み時間の保存を行う。その後、外部 js ファイルをクローズし変 更後の Js ファイル内全文を画面上に再度読み込み直している。 「HTML」ルーチンでは、画面上の「HTML 表示」ボタンのクリックイベントにより実行 される。ブラウザを起動し、実際に作成された在室公開ページ HTML 文書を表示する。 2-8 センサ設置のための出力測定 使用したセンサは前述したとおり、AMN13111 焦電センサ(以下モーションセンサと 記述)、150cm 距離センサと 500cm 距離センサの 3 種類を起用する。使用したセンサの 出力特性をシステム設計のために取得する。 2.8.1 モーションセンサ 実験に使用したモーションセンサは前述のとおり、環境の温度変化を監視してお り、+4 度以上の温度変化があった場合に、TTLレベルでのVccに相当する電圧を出 力する。また、反応が無い場合は内部で開放状態となり、出力は 0Vとなる。モーシ ョンセンサの検知範囲については図 2-6に前述した。これを踏まえた上で、モーショ ンセンサを天井に設置し出力測定を行った、しかし、実際の検出範囲はデータシー トに記載されているものとは異なり、曖昧である事が判った。加えて、このセンサ は赤外線を照射するタイプではなく、受ける事によって温度差を取得しており、尚 且つ、反応があった場合の矩形波の立ち上がりに数百ミリの遅延があるため、その 検出範囲の明確な測定は困難である。よって、前述した図 2-7のフレネルレンズを使 用する事によって検出範囲を可能な限り狭窄化させる事とした。 このセンサは検知範囲がセル化されており、検知範囲内において周囲と温度差の ある物体が横切った場合に図 2-29の様な矩形波が、横切ったセル分もしくは、複数 個出力される。また、立ち上がり、立下り遅延時間の関係から実際に人が通過し終 わった後も数秒間延びして出力される事となる。 32 検出範囲 検出セル 移動 Td(立ち下がり遅延) 電圧(V) Tr(立ち上がり遅延) 時間(s) 図 2-29 モーションセンサの出力特性 2.8.2 距離センサ 使用した距離センサは、被測定物の材質、言うなれば反射率に関係なく距離を算出可 能で有るとデータシートに記載されている。図 2-30に使用した距離センサ(150cm・ 500cmレンジ)の距離と出力電圧のグラフを図示する。測定は見通しがよく、空調の風や 日光などの照射がない室内にて行った。測定は同センサのデータシートより、それぞれ の検知可能範囲とされる 20-150cm(150cmセンサ)、100-500cm(500cmセンサ)付近を中 心に測定を行った。 33 3.5 150cmセンサ 出力電圧(V) 3 500cmセンサ 2 1 0 0 100 図 2-30 200 300 400 対象物までの距離(cm) 500 使用する距離センサの出力特性 (cm-V) また、被測定物の材質をコンクリート、繊維、鉄板などで続けて出力特性を取得し たが、図 2-31の様に出力に変化が生じる事はなかった。よって、このセンサが被測定 物に因らず距離を算出可能だとし、以後の研究で使用を行う。 3 コンクリ 鉄 繊維 出力電圧(V) 2.5 2 1.5 1 0.5 0 0 50 100 150 200 距離 (cm) 図 2-31 材料別距離センサ特性(150cm センサ) 次に、図 2-32に 150cm距離センサの出力特性取得(モータ移動時)のための実験構成 を示す。 34 1.5m 1.2m センサーノード 図 2-32 センサ回転時の出力測定 センサノードを幅 1.2mの屋内廊下に設置し、モーターを用いて 15 度~165 度、約 2.7 度おきに 55 点取得した。その出力取得結果が図 2-33となる。 500 実距離 回転出力 距離(cm) 400 300 200 100 0 0 30 60 図 2-33 90 120 回転角度(Deg) 150 180 センサ回転時の出力グラフ この図は点線部が、角度を元に算出した壁までの距離、実線が出力された電圧値を元 に得られた壁までの距離である。このセンサは前述した様に、計測物への光の入射角な どの変化から、光の反射パワーに変化があった場合にも計測可能である。しかし、グラ フから参照可能な様に 165 度付近において実距離と計測距離の著しい乖離が見られる事 があるが、同角度にて測定を繰り返しても一定してレンジ外の出力が取得できるため、 作成するシステムでは大きな問題とはならない。 出力電圧から距離を算出する方法として、図 2-30の出力特性グラフからエクセルによって 35 近似式を求める。線形ではなく、二次曲線でも近似は難しいよって多項式近似を用いるも のとして、図 2-34に近似項数ごとの近似曲線を図示する。 160 6次式 5次式 4次式 3次式 2次式 実測 距離(cm) 120 80 40 0 0 1 2 3 電圧(V) 図 2-34 多項近似式考察 この結果より、項数が少ない場合に電圧から正しい距離が算出出来ないため、6 次項近似方 程式を使用する。また近似線を求める際に、検出可能距離の近傍距離側の上に凸となって いる部分は除外した。 36 第3章 測定結果 3-1 センサノード作成 センサノードは 2 種類試作を行った。1つは、PIC 及びステッピングモータを用いた もの、2 つ目は AVR 及びサーボモータを使用したものである。最終的に採用した 2 つ目 のセンサノードについてのみ記述する。 3.1.1 センサノード構成 センサノードは、MPUとしてAVR、モーターはサーボモータを採用している。また、 センサは 150cm距離センサ及び、500cm高レンジの距離センサ、モーションセンサを搭 載、加えて、PCとセンサノード間の通信にXBeeを用いて無線化を行っている。センサ ノードの回路図を図 3-1に示す。 37 図 3-1 AVR 使用センサノード 38 5 4 3 2 1 6V VCC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 A Xbee 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 RS232C_Conv A GND USBRxD GND 50kΩ 3.3V U TA48M033F 0.1u 100u IN GND OUT RxD USBTxD B B 2 3 4 5 6 7 8 9 19 3.3V OE2 1A1 2Y4 1A2 2Y3 1A3 2Y2 1A4 2Y1 OE1 1Y1 2A4 1Y2 2A3 1Y3 2A2 1Y4 2A1 U 74244 1 18 17 16 15 14 13 12 11 C C GND 33kΩ 22kΩ 3.3V 15p 15p PUSHSW TxD RxD 10K D XTAL(8M) D 14 13 12 11 10 9 8 7 6 5 4 3 2 1 PB0 PD7 PD6 PD5 PB7(XTAL2) PB6(XTAL1) GND Vcc PD4 PD3 PD2(INT0) PD1(TXD) PD0(RXD) PC6(RESET^) ATMEGA48 PC3 PC4 PC5 E PB1 PB2(OC1B) PB3(MOSI) PB4(MISO) PB5(SCK) AVcc AREF GND PC0(ADC0) PC1(ADC1) PC2(ADC2) E GND LED 15 16 17 18 19 20 21 22 23 24 25 26 27 28 130Ω 0.1u 0.1u GND 0.1u 0.1u 800Ω 800Ω 800Ω F 10kΩ CDS 22u 2 1 2 1 2 1 F 3.3V PC-TR 3 4 PC-FET 3 4 PC-FET 3 4 6V GND GND G G 6 5 4 3 2 1 SERVOMORTAR GND Vdd Pulse OUT GND Vdd AMN13111 OUT GND Vdd GP2Y0A700k0F OUT GND Vdd GP2Y0A02YK0F ProgramPin 1 2 3 3 2 1 3 2 1 3 2 1 H H 5 4 3 2 1 ステッピングモータ使用時における問題点である外的要因による角度の変化は、サーボで はほぼ解消される、ステッピングモータと異なり、どの様な状態であっても、角度に応じ たパルス幅の信号を与える事によって、目的の角度へモーターを指向させる事が可能だ。 しかし「問題がほぼ解消される」と記述したのは、回転途中などにおいて、外的要因によ って圧力がかかりモーターが停止したとしても、モーター本体、もしくは MCU で異常事態 を知る事は出来ないためである。消費電力は回転角を維持するのに 18mW、駆動する場合 には瞬間的に 100mA 程度流れるので 600mW かかると仮定する、実際にモーターを駆動す るのは標準で 1 分に 1 回 12 秒程度なので、モーターの消費電力だけに限定した場合その値 は約 120Wh+14.4mWh=134mWh となる。駆動モータにステッピングモータを使用した場 合は、駆動時と回転角を保持する時に同等の電流を必要とするため、消費電力は 480mWh となる。 これらの条件から、作成するノードにはステッピングモータを搭載する。また、 実際に製作を行ったセンサノードの完成系が図 3-2に示す。 150cm距離センサ 500cm距離センサ モーションセンサ サーボモータ 図 3-2 センサノード概観 ノードは無線化を行っており、通信線については付属しなくても通信可能であるが、電 源は AC アダプタより供給されている。 次に内部回路について外観を図 3-3に示す。 39 フォトモスFET センサ&モータI/O センサ&モータI/O プログラム用 I/O ATmega48 論理ゲート XBee 図 3-3 図 3-4 センサノード内部回路(表) センサノード内部回路(裏面) 40 3-2 距離センサの相互干渉 150cm と 500cm の距離センサを同時に用いて実験を行う段階で、互いに内蔵されている LED の光が干渉しあうという問題が発生した。この問題に対応するには ①センサの出力を取得する時だけ、素子に電圧を印加する。 ②センサの出力が干渉しない様、あらかじめ一定の角度を設けてセンサを固定する。 の 2 つの案が考えられる。 第一案を起用した場合に図 3-5に示すような流れで電圧が印加される。 PWMパルス幅変更MAX時間 1Step移動時間 モーター 距離センサ (150cm) 15ms 5ms 移動終了 安定化時間 電源ON Max52.9ms ADC終了 電源OFF 距離センサ (550cm) 電源ON Max25.2ms 電源OFF 20ms 52.9ms ADC終了 25.2ms Total≒100ms 図 3-5 センサ出力干渉に伴う電源管理図 この図は最初にモーターが1STEP 回転したのち、2 センサーンサーの電源管理を行った うえで出力電圧の ADC が完全に終了するまでの流れを示している。まず、モーター制御部 ではサーボの挙動を管理している PWM 波形のパルス幅更新時間が 15ms 周期に 1 度とな っており、これに加えてデータシートより 2.72 度回転するのにおよそ 5ms の時間を要する。 次に、150cm と 500cm のセンサでは互いに電源が OFF の状態から ON に移行し、出力が 安定状態となるまでに、最大で上記の時間を要する。これを総合した場合にモーター1 STEP 当たりの時間は最低限約 100ms となる。 第 2 案を起用した場合、図 3-6の様に各距離センサ間に傾斜をつけた板を挟むことによ 41 って距離センサからの赤外LEDの照射範囲をオーバーラップさせない様にする。 結果、1m 時点において赤外線スコープを用いて LED 照射範囲を観察したところ、○○の ように検知範囲がオーバーラップしていない事が確認できる。しかしながら、センサ間に 角度を付けた場合に、回転ステップ毎に、各センサの被測定物が異なるという事態が発生 してしまう。また、1m 地点ではオーバーラップを回避するに十分な角度であっても、測定 物までの距離が伸びた場合に、再度オーバーラップしてしまう可能性が考えられる。 よって、これらの検証により、距離センサ間の相互干渉の回避には第 1 次案を採用する。 光の重心 正面 上部 光路角度差 図 3-6 相互干渉回避案 2 3-3 電圧読み込み精度向上検証 マイコンのADCの精度を向上させるためには、「ADC時Sleepモードを取り、外的要 因を極力減らす」、 「ADC比較用電圧をコンデンサ、コイル等で安定化を図る」などの方 法がある。これ以外の方法として各角度のAD変換結果を平均することによって、値の急 峻な変化に対応することが出来ると考える。よってセンサを同じ環境で複数回振り、出 力が安定化するか検証を行う。実験構成は図 2-32と同じく、幅 1.2mの屋内廊下におい て、15 度~165 度間を、2.7 度間隔で 55 点取得を行う。得られた結果について 1 回~4 回平均化を行い図 3-7に実距離との誤差を図示する。 42 平均なし 平均1回 平均2回 平均3回 10% 誤差 (%) 5% 0% -5% -10% 0 30 60 90 120 150 180 回転角度 (Deg) 図 3-7 平均化による誤差収束検討 得られたグラフからわかる様に、「平均なし」データ 50 度、60 度付近の値が平均回 数 1~3 回の場合と比較し精度が向上している事が判る。しかしながら、全体の誤差の平 均の向上は見られないため、平均化は行わない事とする。 3-4 人の検出アルゴリズム 作成したセンサノードをモデルケースとして図 3-8のような個人の居室に設置、実 験を行った。 43 3.5m 机 イス 5m 机 回転 入口 センサノード 図 3-8 センサノード設置モデルケース 上記設置モデルにて無人時のデータを基準として、検知可能なパターンを示す。 図 3-9の様に人が検知範囲内に侵入した場合、図 3-10の様な出力がえら得られる。 44 人 回転 回転 入口 センサノード 入口 センサノード 無人状態 図 3-9 在室中 無人→人が侵入した場合 距離 (cm) 500 無人時 人有り 400 300 200 100 0 検知 モーションセンサ 未検知 0 30 60 図 3-10 90 角度 (Deg) 120 150 180 人の検出の決定例 出力結果グラフの破線部分から参照可能な様に、人は退席を持っているため、距離セン 45 サに反応し、また、熱を持っているためにモーションセンサで検知が行えている。この事 から、両センサで変化が起こった場合にのみ「人が在室している」という結論を下す事とし ている。このアルゴリズムを用いれば、例えば、図 3-11の様な部屋内の体積の変化が無い が、熱源が発生した場合、モーションセンサに反応があり、検知した物体を物と断定でき る。出力波形は図 3-12に図示する。 暖房器具 暖房ON 回転 回転 入口 センサノード 入口 センサノード 無人状態 図 3-11 熱源発生 不在→熱源発生した場合 46 距離(cm) 500 無人時 熱源発生 400 300 200 100 0 検知 モーションセンサ 未検知 0 30 60 図 3-12 90 角度(Deg) 120 無人→熱源発生した場合の出力 47 150 180 3-5 作成したシステムの外観 本ソフトは機能別にタブで切り替える事が可能となっており、図は動作中の画面とな る。他の HTML 作成部分は後述する。 図 3-13 在室確認システム概観 在室公開Webページ作成のためのJsファイル作成部分は、在室確認ソフトウェアのタブ 部分を切り替えた場所にあり、図 3-14の様になっている。 48 図 3-14 在室確認ページ生成タブ概観 また、実際に出力される在室公開ページは図 3-15に図示する。 49 図 3-15 Web 在室状況ページ 3-6 実用化実験 実際に数時間の運転をし、在室確認システムとして運用できるかの検証を行う。 作成したソフトには、1 分ごとの在室状況が外部にテキスト形式で保存さる様プログラム を行っている。図 3-16にその出力例を示す。 50 在室管理システム 在室 不在 入退室記録 在室 不在 図 3-16 在室状況出力テキスト 測定は約 2 時間連続的に行い、何度か入退出を繰り返した。上記図より、入退室記録と在 室システムとの出力が同じであることを示している。また、前述したように設置環境にモ ーションセンサの反応が全く見られない場合に、現在の環境の初期データを更新している ためその旨が明記されている。同様にして、熱源(ヒーター)などをONにしたまま入退出を 繰り返したが、在室確認は問題なく行われた。しかしながら、設置環境の熱源よりモーシ ョンセンサの反応が検知されるため、図 3-17の様に環境初期データの更新は行われない。 図 3-17 熱源(ヒータ)を設置した場合の在室確認 51 3-7 判断不可能な事例 3.7.1 熱源の移動 作成したシステムでは、そもそもモーションセンサのみでは、 「熱源を全て人と認識し てしまうという」点を補うという意味合いで、距離センサとの相関を取ることとした。 しかしながら、このアルゴリズムであっても判断不能な条件があるためそれを記述する。 事例については図 3-18に図示し、その出力は図 3-19に示す。 暖房 暖房移動 回転 回転 入口 センサノード 入口 センサノード 無人状態 図 3-18 熱源移動 無人→熱源移動した場合 52 角度(Deg) 500 ヒーター移動 400 無人時 300 200 100 0 モーションセンサ 検知 未検知 0 30 60 図 3-19 90 距離(cm) 120 150 180 無人時→ヒータ移動後出力 出力の破線部分から参照可能な様に無人時の距離からヒータが移動した場合に検出距離に 変化が見られることが確認できる。しかしながら、加えて熱源に対してモーションセンサ が反応しているため。提案したアルゴリズムを用いるならばこの事例には対処は事実上不 可能に思える。 しかしながら、解決策として最初に設置する場所に対して制約を設けて やれば十分回避可能であると考える。例えば、このヒータ移動の事例では足元に設置して いる温風ヒータが問題となっているため、その本体よりも高い場所にセンサノードを設置 してやれば十分回避可能である。 3.7.2 検知箇所の狭窄化によるデメリット 前述したとおり検知範囲を明確とするために、フレネルレンズを用いてモーションセンサ の検知範囲の狭窄化を行った。この結果角度ごとにそのポイント毎の熱源の有無が明確と なった。しかしながら、検知範囲を限られたポイントで指定しているために、在室者が動 き回った場合や、起立中の足などは検出可能面積が狭く検知出来ない場合が存在した。こ の問題については、いつも検知出来ない訳ではないため、誤差範囲として在室判断を行う 間隔を長くすれば、問題の大きさは変って来る。 53 第4章 考察 提案した在室確認システムは、いくらかの制限要因はあるが、システムとして運用可能 な所まで検討が出来た。居室ではその所有者の座る場所などがいくらか限定されてくるた め、導入時の設置場所にある程度気をつけてやれば十分実用は可能だと考える。 加えて、ヒータを移動させるとご認識を起こすが、そもそもヒータを稼動したまま退席 を行う場合は、少なくとも部屋主本人はすぐに戻ってくるつもりがあると考える。 り、在室判断間隔を長くする事によってこの問題の大きさは変ってくると考察する。 54 つま 第5章 まとめ はじめに、複数のセンサを用いたセンシングについて検討を行い、センサ同士の相関を 得る事によって、人の検知が可能である事を示した。 また、センサの検知範囲について複数のセンサノードを設置しこれをカバーするのではな く、搭載したセンサの検知範囲を広域化するべく検討し、実装を行った。センサノードに 求められる省電力化についての検討し、一般的なサーボモータを用いる事とした。次に、 考案した在室判断アルゴリズムを用いて、現実的な幾つかのパターンについて検証を行い、 検知不可能なパターンについて解決策を提示した。 最終的に、製作したシステムは、その設置環境に制約を設ける事で実用が可能である。 55 謝辞 本研究を行うにあたって、常日頃からご指導、その多大なる知識のご教示を賜 った電子・光システム工学科 岩下克教授に深く感謝致します。 また、副査として論文を精査して頂いた、綿森道夫教授、植田和憲講師に深く感謝 致します。 回路実装時における AVR や回路実装技術教示等でお世話になった 綿森研究室 車 載仁さんに深く感謝致します。 日頃から素晴らしい研究環境を作っていただいた同研究室メンバー 島村 卓嗣さん 恒安 宏一さん 速水佑治さん 中妻宏太さん 渡部隆寛さんまた 同研究室 4 年生の皆様に感謝意を表したいと思います。 また個別に、共同研究者である村井祐さんには互いに諦めず最後まで研究を行って くださったことに対し、再度お礼を申し上げます。 56 参考文献 [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] 櫻井 他 “センサネットワークによる人の行動認識のための実験系の検討” 信学会 総合全大 A21-12 p.369(2005) [5] 滝本 他 “無線センサネットワークを用いた動線検出システムの試作” 信学会 ソサ エティ大 B-15-4 p.614(2003) [6] 多木勝彦 高知工科大学 [7] 乾梨 紗 高知工科大学 位置情報管理システム –センサネットワークの試作- 学位論文 位置情報管理システム -管理システムの設計- 学位論文 57 付録 センサノード内 PIC プログラムリスト .include "m48def.inc" ;Mega48 定義ファイルをインクルード .include "macro.inc" ;ピンアサイン // PB0 -> 未定義 // PB1 -> LED // PB2 -> 未定義 // PB3 -> 未定義(プログラム時 MOSI) // PB4 -> 未定義(プログラム時 MISO) // PB5 -> 未定義(プログラム時 UCSK?) // PB6 -> 未定義 // PB7 -> 未定義 // PC0 <- ADC0 // PC1 <- Motion センサー デジタル INPUT // PC2 <- ADC2 // PC3 -> D_550 電源制御 150cm 取得 550cm 取得 // PC4 -> D_150 電源制御 // PC5 -> Motion 電源制御 // PC6 -> 未定義 // PD0 <- 未定義(RxD) // PD1 -> 未定義(TxD) // PD2 <- 割り込み PIN // PD3 -> 未定義 // PD4 -> 未定義 // PD5 -> 未定義 // PD6 -> 未定義 // PD7 -> 未定義 .cseg /////////////////////////////////////////////////////////// //変数宣言部 .def ZERO = R0 .def S_posH = R1 .def S_posL = R2 .def Rot_dir = R3 //Servo の ROTate_DIRection .def Rot_Spd = R4 //Servo の ROTate_SPeeD .def Rot_Step= R5 //Servo の Start_POStion //Servo の ROTate_STEP .def CNT1 = R6 .def CNT2 = R7 .def CNT3 = R8 .def CNT4 = R9 .def CNT5 = R10 .def TEMP_H = R11 //ソフトタイマ用カウンタ 1~5 //HEX2CHR で使用 .def TEMP_L = R12 // .def work = R16 //ワーキングレジスタ .def TEMP1 = R17 //Comp_Hex、Tx、Rx .def TEMP2 = R18 //CMD4 .def TEMP3 CMD3 = R19 //CMD4 CMD3 .def RXDATA = R20 //USART 受信データ格納 .def TXDATA = R21 //USART 送信データ格納 //.def XL_TEMP = R22 //.def XH_TEMP = .def Wid_L = R24 //PWM パルス幅 Low 格納 .def Wid_H = R25 //PWM パルス幅 High 格納 //26-31 X Y Z // X movS2S 使用時 ADC2 結果ストア時 // Y Motion 結果ストア時 // Z ADC0 結果ストア時 Msg_out //.def //.def /////////////////////////////////////////////////////////////// .org 0x00 rjmp reset rjmp INT_INT0 ;rjmp 相対ジャンプで Reset へ //rjmp int1 reti //rjmp int2 reti //rjmp int3 reti //rjmp int4 reti //rjmp int5 reti //rjmp int6 reti //rjmp int7 reti //rjmp int8 reti //rjmp int9 reti //rjmp intA reti //rjmp intB rjmp INT_PWM //rjmp intC reti //rjmp intD reti //rjmp intE reti //rjmp intF reti //rjmp int10 reti //rjmp int11 rjmp INT_Rx //rjmp int12 reti //rjmp int13 reti //rjmp int14 rjmp INT_ADC //rjmp int15 59 reti //rjmp int16 reti //rjmp int17 reti //rjmp int18 reti //rjmp int19 /////////////////////////////////////////////////////////// //送信文字列テーブル message0: .db "Mode0_Manual_Move... ",0 message1: .db "Mode1_Soft_Reset...",0 message2: .db "Mode2_Programed_move...",0 message3: .db "Mode3_General_Mode...",0 message4: .db "Quit ",0 message5: .db "Hello_Plz_input_Num_0-6... ",0x0d,0x0a,0 message6: .db "Mode4_SRAM_Outputing...",0 message7: .db "END",0 message8: .db "Out_of_Range...",0 message9: .db "Mode5_OneOutPut_Send",0 Text1: .db "150cm = ",0 Text2: .db "500cm = ",0 Text3: .db "Motion = ",0 Text4: .db "Light = ",0 ///////////////////////////////////////////// //外部入力ピン割り込み(Motion センサ接続) INT_INT0: reti //////////////////////////////////////////// //PWM_OCR1C=TCNT1 コンペアマッチ割り込み INT_PWM: rcall Chck_Lmt //回転角リミッタ sts OCR1BH,Wid_H sts OCR1BL,Wid_L INT_PWM_OFF //OCRB1 割り込み不許可 reti //////////////////////////////////////////// //受信データ割り込み 各 jump ルーチンへ INT_Rx: movS2S //幅反映 RXDATA,UDR0 60 cpi breq RXDATA,'0' CMD_0_jump cpi breq CMD_1_jump CMD_2_jump RXDATA,'3' RXDATA,'4' //SRAM 列挙 RXDATA,'5' CMD_5_jump cpi breq //通常動作モード CMD_4_jump cpi breq //プログラム駆動モード CMD_3_jump cpi breq //リセットモード RXDATA,'2' cpi breq //手動駆動モード RXDATA,'1' cpi breq //AD1 件取得&送信 RXDATA,'6' CMD_6_jump //テストモード reti ////////////////////////////////////////////////////////////// //ADC 割り込み INT_ADC: //各所からの呼び出しにつき特別何も行わない。 reti //////////////////////////////////////////////////////////// //コマンド選択 Jamp 部分 CMD_0_jump: rcall CMD_0 rjmp END_CMD CMD_1_jump: rcall CMD_1 rjmp END_CMD CMD_2_jump: rcall CMD_2 rjmp END_CMD CMD_3_jump: rcall CMD_3 rjmp END_CMD CMD_4_jump: rcall CMD_4 rjmp END_CMD CMD_5_jump: rcall CMD_5 rjmp END_CMD CMD_6_Jump: rcall //比較キャラ 0~6 CMD_6 61 rjmp END_CMD END_CMD: CRLF Msg_out message4 CRLF CRLF Msg_out message5 reti ///////////////////////////////////////////////////////////// //モード 0 手動駆動モード CMD_0: Msg_out message0 rcall Rx macro_Ecohback cpi RXDATA,'q' breq END_CMD_0 mov work,RXDATA rcall Comp_STR mov Wid_H,Work rcall Rx //q なら抜ける // //受信データ反映 macro_Ecohback mov work,RXDATA rcall Comp_STR mov Wid_L,Work //受信データ反映 swap Wid_L //スワップし上位桁として格納 rcall Rx macro_Ecohback mov work,RXDATA rcall Comp_STR add Wid_L,work ldi TXDATA,0x0a rcall tx // //下位桁を加算 INT_PWM_ON sei //一時的に割り込み ON 62 rcall delay_10m rcall delay_10m rcall delay_10m //20m で割り込み 30m おいてみた。 cli rjmp //再度割り込み禁止 CMD_0 END_CMD_0: ret ///////////////////////////////////////////////////////////// //モード 1 ソフトウェアリセットモード CMD_1: Msg_out message1 //"Mode1_Soft_Reset..." 送信 ldi ZH,0x01 //SRAM 初期 0x100 格納 ldi ZL,0x00 ldi work,0x00 //SRAM 書込み値 0x00 格納 CMD_1__LOOP: ST cpi brne Z+,work //SRAM をクリアし Z をインクリメント ZH,0x02 //ZH コンペア 0x2XX ならZL 比較へブランチ pc+3 cpi ZL,0xFF breq CMD_1_END rjmp CMD_1__LOOP //Z が 0x2FF なら終了 CMD_1_END: rjmp reset ///////////////////////////////////////////////////////////// //モード 2 プログラム駆動モード CMD_2: Msg_out message2 //Message2「Mode2_Programed_move...」送信 CRLF in work,portB Andi work,0b11111101 out portB,work //LED_OFF INT_PWM_OFF //OCR1B 割り込み不許可 INT_UART_OFF //Tx,Rx 禁止 受信完了割り込み禁止 //使用センサ ALLOFF iout PORTC,0b11000000 //PC0(150),1(cds),2(500)をInput 3(Motion),4(550),5(150) CMD_2__LOOP: rcall delay_1000m //AD チャネル選択レジスタ設定 ists ADMUX,0b01100001 //ADC1 使用 sei 63 iout SMCR,0b00000011 //SLEEP 許可 SMCR,0b00000010 //SLEEP 禁止 SLEEP iout AD 開始 //SLEEP→ADC→ADC 完了割り込みへ cli LDS work,ADCH //ADC1 結果 8Bit のみを work へ cpi work,0x10 //0x10 以上なら復帰 brge Sleep_Back // rjmp CMD_2__LOOP //それ以外の場合はループへ Sleep_Back: //センサ ON は行わない 各所で目的に応じて ON INT_PWM_ON //PWM 割り込み ON INT_UART_ON //UART 割り込み ON iout msg_out portB,0b11111111 message4 CRLF ret //コマンドエンドへ ///////////////////////////////////////////////////////////// //モード 3 通常駆動モード CMD_3: Msg_out message3 imov Rot_dir,0 //0=正転 1=逆転 imov S_PosH,0x00 //モーター回転開始位置(0 度格納) 66 imov S_PosL,0x59 //Low バイト格納 imov Rot_Step,0x37 //移動ステップ数 imov Rot_Spd,0x01 //基本 30m+2*10m=50m //Dir データ格納 rcall Rx mov work,RXDATA rcall Comp_STR mov Rot_Dir,work //Pos データ格納 H→L rcall Rx mov work,RXDATA rcall Comp_STR mov S_PosH,work rcall Rx //受信結果格納 64 Difo=55 mov work,RXDATA rcall Comp_STR mov S_PosL,work //受信結果格納 swap S_PosL //下位、上位入れ替え rcall Rx mov work,RXDATA rcall Comp_STR mov TEMP1,S_PosL add TEMP1,work mov S_PosL,TEMP1 //Step データ格納 rcall Rx mov work,RXDATA rcall Comp_STR mov Rot_Step,work //受信結果格納 swap Rot_Step //下位、上位入れ替え rcall Rx mov work,RXDATA rcall Comp_STR mov TEMP1,Rot_Step add TEMP1,work mov Rot_Step,TEMP1 //Spd データ格納 rcall Rx mov work,RXDATA rcall Comp_STR mov Rot_Spd,work //受信結果格納 swap Rot_Spd //下位、上位入れ替え rcall Rx mov work,RXDATA rcall Comp_STR mov TEMP1,Rot_Spd add TEMP1,work mov Rot_Spd,TEMP1 rcall SubMain ret //コマンドエンドへ /////////////////////////////////////////////////////////// 65 //モード 4 SRAM レジスタ内送信モード CMD_4: Msg_out message6 CRLF mov TEMP2,ZERO //L 桁表示、開始は 0 mov work,TEMP2 //0x00-0x00 を ASCII 変換 rcall HEX2CHR SPACE SPACE SPACE CMD_4__INIT: mov TXDATA,TEMP_L rcall Tx //LOW バイトのみ送信 SPACE SPACE cpi TEMP2,0x0f breq CMD_4__LORD inc TEMP2 rjmp CMD_4__INIT //0x0f まで到達したら SRAM 送信 SEC へ CMD_4__LORD: CRLF ldi ZH,0x01 ldi ZL,0x00 ldi TEMP2,0x10 ldi TEMP3,0x00 //文字数カウンタ CMD_4__LORD__LOOP1: //先頭に High バイト+16 バイトで折り返し。 mov work,TEMP2 rcall HEX2CHR mov TXDATA,TEMP_H rcall Tx mov TXDATA,TEMP_L rcall Tx //0x10-0x2F までを ASCII 変換 //High バイト送信 //LOW バイト送信 SPACE CMD_4__LORD__LOOP2: cpi TEMP3,0x10 breq CMD_4_CRLF LD work,Z+ rcall HEX2CHR mov TXDATA,TEMP_H //17Chr 目なら改行 66 rcall Tx mov TXDATA,TEMP_L rcall Tx SPACE inc TEMP3 cpi ZH,0x02 brne pc+3 cpi ZL,0xFF breq CMD_4_END rjmp CMD_4__LORD__LOOP2 CMD_4_END: LD work,Z //最終 2FF だけ手動 rcall HEX2CHR mov TXDATA,TEMP_H rcall Tx mov TXDATA,TEMP_L rcall Tx ret CMD_4_CRLF: CRLF inc TEMP2 ldi TEMP3,0x00 rjmp CMD_4__LORD__LOOP1 /////////////////////////////////////////////////////////// //モード 5 ADC&Motion1 件取得送信モード CMD_5: msg_out message9 CRLF iout PORTC,0b11101000 //PC0(150),1(cds),2(500)を Input 3(Motion),4(550),5(150) //AD チャネル選択レジスタ設定 ists ADMUX,0b01100000 // ||||||||_(0)MUX0ADC0 使用 // |||||||_(1)MUX1 // ||||||_(2)MUX2 // |||||_(3)MUX3 // ||||_(4)none // |||_(5)ADLAR // ||_(6)REFS0 67 1 で AD 結果左揃え // |_(7)REFS1 ldi rcall AVCC、VCC と一緒 work,10 /電源投入時から 100ms Delay_user //AD チャネル選択レジスタ設定 ists ADCSRA,0b10001000 // ||||||||_(0)ADPS0 // |||||||_(1)ADPS1 // ||||||_(2)ADPS2 // |||||_(3)ADIE // ||||_(4)ADIF // |||_(5)ADATE AD クロック CK/2 AD 割り込み許可 // ||_(6)ADSC AD 開始ビット // |_(7)ADEN AD 許可 ists DIDR0,0b00000111 sei iout SMCR,0b00000011 //SLEEP 許可 SMCR,0b00000010 //SLEEP 禁止 Text1 //"150cm = " LDS work,ADCH /AD 結果 8Bit のみを work へ rcall HEX2CHR //16 進をキャラへ変換 mov TXDATA,TEMP_H rcall Tx mov TXDATA,TEMP_L rcall Tx SLEEP iout AD 開始 //SLEEP→ADC→ADC 完了割り込みへ cli //150cm 電圧送信 msg_out CRLF //500cm電圧送信 iout PORTC,0b11011000 //(150),1(cds),2(500)を Input3(Motion),4(500),5(150) //AD チャネル選択レジスタ設定 ists ADMUX,0b01100010 //ADC2 使用 ldi work,6 //電源投入時から 100ms rcall Delay_user sei iout SMCR,0b00000011 //SLEEP 許可 SLEEP iout SMCR,0b00000010 //SLEEP 禁止 Text2 //"500cm = " cli msg_out AD 開始 //SLEEP→ADC→ADC 完了割り込みへ 68 LDS work,ADCH //AD 結果 8Bit のみを work へ rcall HEX2CHR //16 進をキャラへ変換 mov TXDATA,TEMP_H rcall Tx mov TXDATA,TEMP_L rcall Tx CRLF /Cds 電圧送信 iout PORTC,0b11001000 //C0(150),1(cds),2(500)を Input 3(Motion),4(550),5(150) //AD チャネル選択レジスタ設定 ists ADMUX,0b01100001 //ADC1 使用 SMCR,0b00000011 //SLEEP 許可 sei iout SLEEP iout D 開始 //SLEEP→ADC→ADC 完了割り込みへ SMCR,0b00000010 //SLEEP 禁止 msg_out Text4 //"Light = " LDS work,ADCH cli rcall HEX2CHR mov TXDATA,TEMP_H rcall Tx mov TXDATA,TEMP_L rcall Tx //AD 結果 8Bit のみを work へ //16 進をキャラへ変換 CRLF //Motion ON/OFF 送信 msg_out Text3 in work,PIND andi work,0b00000100 LSR work LSR work rcall HEX2CHR mov TXDATA,work rcall Tx //"Motion = " //PD2 のみマスク //PD2 の状態を右に 2 つシフトし 0x00 か 0x01 で表現 ret /////////////////////////////////////////////////////////// //モード 6 テストモード CMD_6: rcall Cds ret 69 /////////////////////////////////////////////////////////// //ソフト or ハードリセット後開始位置 Reset: // iout SPL,low(RAMEND) //スタックポインタ領域設定 iout SPH,high(RAMEND) clr ZERO iout DDRB, 0b11111111 iout PORTB,0b11111111 iout DDRC, 0b11111000 //PC0,1,2 を Input iout PORTC,0b11111000 //PC5,4,3 150,500,Motion iout DDRD, 0b11111010 iout PORTD,0b01111010 //PD0 Rx PD2INT0&Motion rcall INIT_SRAM //SRAM 初期化 rcall INIT_USART //USART 機能初期化 rcall INIT_PWM //PWM 機能初期化 rcall INIT_ADC //ADC 機能初期化 rjmp main ///////////////////////////////////////////////// //USART 初期化部分 INIT_USART: ists UBRR0L,25 sts UBRR0H, ZERO //19200 baud INT_UART_ON ret ///////////////////////////////////////////////// //PWM 初期化部分 INIT_PWM: ldi wid_H,0 ldi wid_L,0xC2 ists OCR1AH,7 //Width を中央初期値セット C2 //0x9C4=2500 2500*8u=20ms //1875=753 ists OCR1AL,0x53 ists OCR1BH,0 ists OCR1BL,68 ists TCCR1A,0b00100011 //X*8u=1.496ms // ||||||||_(0)WGM1_0 // |||||||_(1)WGM1_1 70 高速 PWM 高速 PWM // ||||||_(2)none // |||||_(3)none // ||||_(4)COM1B0 // |||_(5)COM1B1 // ||_(6)COM1A0 PWM 非反転動作 // |_(7)COM1A1 PWM 非反転動作 ists TCCR1B,0b00011011 // ||||||||_(0)CS10 64 分周 // |||||||_(1)CS11 " // ||||||_(2)CS12 " // |||||_(3)WGM12 高速 PWM // ||||_(4)WGM13 // |||_(5)none // ||_(6)ICES1 PWM 非反転動作 // |_(7)ICNC1 PWM 非反転動作 高速 PWM INT_PWM_ON ret ///////////////////////////////////////////////// //ADC 初期化部分 INIT_ADC: //AD チャネル選択レジスタ設定 ists ADMUX,0b01100000 // ||||||||_(0)MUX0ADC0 使用 // |||||||_(1)MUX1 // ||||||_(2)MUX2 // |||||_(3)MUX3 // |||_(4)none // ||_(5)ADLAR // ||_(6)REFS0 // |_(7)REFS1 1 で AD 結果左揃え AVCC、VCC と一緒 //AD チャネル選択レジスタ設定 ists CSRA,0b10001000 // ||||||_(0)ADPS0 // |||||||_(1)ADPS1 // ||||||_(2)ADPS2 // |||||_(3)ADIE // ||||_(4)ADIF // |||_(5)ADATE // ||_(6)ADSC AD 開始ビット // |_(7)ADEN AD 許可 ists DIDR0,0b00000101 71 AD クロック CK/2 AD 変換完了割り込み ists ADCSRB,0b00000000 iout SMCR,0b00000011 //AD 連続変換 128 分周 //電力制御レジスタ設定 // |||||||_(0)SE SLEEP 許可は SLEEP 開始直前に行う // |||||||_(1)SM0 001 AD ノイズ低減動作 // ||||||_(2)SM1 // |||||_(3)SM2 // ||||_(4)noen // |||_(5)none // ||_(6)none // |_(7)none sei sleep cli iout SMCR,0b00000010 LDS ork,ADCH //ADC1 結果 8Bit のみを work へ ret /////////////////////////////////////////////////////////// //MAIN ルーチン MAIN: sei rjmp MAIN__LOOP ///////////////////////////////////////////////// //スタッククリア MAIN__INIT_SPL: iout SPL,low(RAMEND) //スタックポインタ領域設定 H iout SPH,high(RAMEND) msg_out message5 MAIN__LOOP: sei MAIN__LOOP1: sei rcall //受信割り込み&PWM 割り込み処理 Delay_10m cli INT_PWM_OFF rcall Cds //明るさ監視 INT_PWM_ON rjmp MAIN__LOOP1 72 /////////////////////////////////////////////////////////// //サーボ回転ルーチン SubMain: CRLF mov Wid_H,S_posH mov Wid_L,S_PosL //Wid_L 初期値格納 mov TEMP2,RoT_Step //比較用 TEMP 値格納 ldi ZL,low(D150_DATA) //D150_DATA 先頭アドレス格納 ldi ZH,High(D150_DATA) // ldi YL,low(M_DATA) //M_DATA 先頭アドレス格納 ldi YH,high(M_DATA) // INT_PWM_ON sei rcall delay_10m rcall delay_10m //15m で割り込み 20m cli ldi work,50 rcall Delay_user //0.5 秒待つ SubMain__LOOP: mov work,ROT_DIR cpi work,0x00 brne PC+2 adiw Wid_H:Wid_L, 3 cpi work,0x01 brne PC+2 sbiw Wid_L, 3 //回転方向確認 ROT_DIR=0x00 なら正転 //回転方向確認 ROT_DIR=0x01 なら逆転 INT_PWM_ON sei GIE 許可&禁止 rcall delay_10m rcall delay_10m //15m で割り込み 20m おいてみた。 INT_PWM_OFF //回転終了確認 73 //センサ取得へ //150cm 有効(500 無効) iout PORTC,0b11101000 //PC0,1,2 を Input 3(Motion ),4(550),5(150) //AD チャネル 0 選択 150cm 計測 ists DMUX,0b01100000 // ||||||||_(0)MUX0 ADC0 使用 // |||||||_(1)MUX1 // ||||||_(2)MUX2 // |||||_(3)MUX3 // ||||_(4)none // |||_(5)ADLAR // ||_(6)REFS0 // |_(7)REFS1 ldi work,12 rcall Delay_user iout 1 で AD 結果左揃え AVCC、VCC と一緒 //電源投入時から 60ms*2 SMCR,0b00000011 //SLEEP 許可 SLEEP AD 開始 //SLEEP→ADC→ADC 完了割り込みへ iout SMCR,0b00000010 //SLEEP 禁止 rcall ADC_ST //ADC 結果判断&ストアルーチン //500cm 有効(150 無効) iout PORTC,0b11011000 //PC0,1,2 を Input 3(Motion ),4(550),5(150) //AD チャネル 2 選択 550cm 計測 ists ADMUX,0b01100010 // ||||||||_(0)MUX0 ADC2 使用 // |||||||_(1)MUX1 // ||||||_(2)MUX2 // |||||_(3)MUX3 // ||||_(4)none // |||_(5)ADLAR // ||_(6)REFS0 // |_(7)REFS1 ldi work,6 rcall Delay_user 1 で AD 結果左揃え AVCC、VCC と一緒 //電源投入時から 30ms*2 74 iout SMCR,0b00000011 //SLEEP 許可 iout SMCR,0b00000010 //SLEEP 禁止 rcall ADC_ST //ADC 結果判断&ストアルーチン dec TEMP2 //TEMP-1 cpi TEMP2,0x00 //回転終了比較 breq Sub__LOOP__END //Z フラグでメインループへ mov work,Rot_Spd //回転スピード格納→Work へ rcall Delay_user //可変 UserDelay 呼び出し rjmp SubMain__LOOP SLEEP AD 開始 //SLEEP→ADC→ADC 完了割り込みへ ///////////////////////////////////////////////// //ADC 完了割り込み後判断&ストアルーチン ADC_ST: movS2S work,ADMUX //ADMUX 状態を work へ andi work,(1<< MUX3) | (1<<MUX2) | (1<< MUX1) | (1<< MUX0) cpi work,0b00000000 breq ADC_ST__ADC0 movS2S work,ADMUX andi work,(1<< MUX3) | (1<<MUX2) | (1<< MUX1) | (1<< MUX0) cpi work,0b00000010 breq ADC_ST__ADC2 //ADC0 使用 //ADMUX 状態を work へ //ADC2 使用 ADC_ST__ADC0: LDS work,ADCH //ADC0 結果 8Bit のみを work へ ST Z,work //ADC0 結果ストア→Z をインクリメントしない LDS work,ADCH //ADC0 結果 8Bit のみを work へ adiw Z,55 ST Z+,work subi ZL,55 reti ADC_ST__ADC2: in work,PIND andi work,0b00000100 LSR work LSR work ST Y+,work //ADC0 結果ストア→Z をインクリメント //PD2 のみマスク //PD2 の状態を右に 2 つシフトし 0x00 か 0x01 で表現 //PD2 状態をストア→Y をインクリメント ret 75 Sub__LOOP__END: rcall send_pack ret //CMD3 へ戻る? rjmp MAIN__INIT_SPL Str_out: lpm work,Z+ //message データを work へ Z は+1 cpi work,0 //0 確認 breq End_str //String 終了 mov TXDATA,work rcall Tx rjmp Str_out //work 内データを TXDATA へ End_str: ldi TXDATA,0x0A rcall tx //LF コード送信 ret ////////////////////////////////////////////////////////////// //取得済みデータ送信ルーチン Send_pack: mov work,Rot_dir rcall Comp_Hex mov TXDATA,work rcall tx mov work,S_PosH rcall Comp_Hex mov TXDATA,work rcall tx mov work,S_PosL mov TEMP3,work swap work andi work,0x0F rcall Comp_Hex mov TXDATA,work rcall tx andi TEMP3,0x0F mov work,TEMP3 rcall Comp_Hex mov TXDATA,work rcall tx //下位桁のみマスク 76 mov work,Rot_Step mov TEMP3,work swap work andi work,0x0F rcall Comp_Hex //下位桁のみマスク mov TXDATA,work rcall tx andi TEMP3,0x0F mov work,TEMP3 rcall Comp_Hex mov TXDATA,work rcall tx mov work,Rot_Spd mov TEMP3,work swap work andi work,0x0F rcall Comp_Hex //下位桁のみマスク mov TXDATA,work rcall tx andi TEMP3,0x0F mov work,TEMP3 rcall Comp_Hex mov TXDATA,work rcall tx comma ldi ZL,low(D150_DATA) //結果格納レジスタの初期アドレスを格納 ldi ZH,high(D150_DATA) //D550_DATA は D150_DATA に+55 で対応 ldi YL,low(M_DATA) ldi YH,high(M_DATA) ldi TEMP2,0x00 /////////////////////////////////////////////////////////// //SRAM ストアデータ送信ルーチン Send_pack__LOOP: //Motion データ送信 LD work,Y+ 77 rcall Comp_Hex mov TXDATA,work rcall tx //150cm 距離センサ送信 LD work,Z mov TEMP3,work swap work andi work,0x0F rcall Comp_Hex mov TXDATA,work rcall tx andi TEMP3,0x0F mov work,TEMP3 rcall Comp_hex mov TXDATA,work rcall tx //Z はインクリメントしない //下位桁のみマスク //550cm 距離センサ送信 add ZL,ROT_STEP LD work,Z+ sub ZL,ROT_STEP mov TEMP3,work swap work andi work,0x0F rcall Comp_Hex mov TXDATA,work rcall tx andi TEMP3,0x0F mov work,TEMP3 rcall Comp_hex mov TXDATA,work rcall tx //Z+ROT_STEP //Z に戻す //下位桁のみマスク comma mov work,ROT_STEP subi work,1 cp TEMP2,work breq End_Send_pack inc TEMP2 rjmp Send_pack__Loop //ROT_STEP-1 件送信 END_Send_pack: msg_out message7 78 ret ////////////////////////////////////////////////////////////// //回転リミッタルーチン Chck_Lmt: mov work,Wid_H subi work,0x02 brsh Out_Range cpi Wid_H,0x00 brne PC+4 mov work,Wid_L subi work,0x4D //work-46=? brlo Out_Range //負なら範囲外 cpi Wid_H,0x01 brne PC+4 mov work,Wid_L //H が 0x00or0x01 以外ならレンジ外 subi work,0x3F brsh Out_Range // //0x13F 以上ならレンジ外 ret Out_Range://0x4A-13D の範囲外の場合 MAIN へジャンプ rjmp MAIN__INIT_SPL ////////////////////////////////////////////////////////////// //USART 送受信ルーチン Rx://movS2S 使用禁止(ZH、ZL 使用のため) movS2S work,UCSR0A sbrs work,7 rjmp Rx movS2S RXDATA,UDR0 ret Tx: movS2S work,UCSR0A sbrs work,5 rjmp Tx sts //UDRE0 送信準備完了フラグチェック UDR0,TXDATA ret /////////////////////////////////////////////////////////// //16 進数データをキャラデータに変換 Work→TEMP_H TEMP_L HEX2CHR: mov TEMP_H,work //変換前データ格納 79 mov TEMP_L,work ldi work,0xF0 and TEMP_H,work ldi work,0x0F and TEMP_L,work //下位桁マスク swap TEMP_H //上位レジスタを反転 mov work,TEMP_H //上位バイト変換 rcall Comp_Hex mov TEMP_H,work mov work,TEMP_L rcall Comp_Hex mov TEMP_L,work // //上位桁マスク //下位バイト変換 ret Comp_Hex: //work→work に格納 cpi work,0x00 breq Comp_Hex__0_9 cpi work,0x01 breq Comp_Hex__0_9 cpi work,0x02 breq Comp_Hex__0_9 cpi work,0x03 breq Comp_Hex__0_9 cpi work,0x04 breq Comp_Hex__0_9 cpi work,0x05 breq Comp_Hex__0_9 cpi work,0x06 breq Comp_Hex__0_9 cpi work,0x07 breq Comp_Hex__0_9 cpi work,0x08 breq Comp_Hex__0_9 cpi work,0x09 breq Comp_Hex__0_9 cpi work,0x0A breq Comp_Hex__A_F cpi work,0x0B breq Comp_Hex__A_F //0→'0'へ //1→'1'へ //2→'2'へ //3→'3'へ //4→'4'へ //5→'5'へ //6→'6'へ //7→'7'へ //8→'8'へ //9→'9'へ //A→'A'へ //B→'B'へ 80 cpi work,0x0C breq Comp_Hex__A_F cpi work,0x0D breq Comp_Hex__A_F cpi work,0x0E breq Comp_Hex__A_F cpi work,0x0F breq Comp_Hex__A_F //C→'C'へ //D→'D'へ //E→'E'へ //F→'F'へ ret Comp_Hex__END: ret Comp_Hex__0_9: ldi TEMP1,0x30 add work,TEMP1 rjmp Comp_Hex__END Comp_Hex__A_F: ldi TEMP1,0x37 add work,TEMP1 rjmp Comp_Hex__END //かもしれない。 ///////////////////////////////////////////////////////// //文字データを数値データに変換 Comp_STR: cpi work,0x30 breq STR_0_9 cpi work,0x31 breq STR_0_9 cpi work,0x32 breq STR_0_9 cpi work,0x33 breq STR_0_9 cpi work,0x34 breq STR_0_9 cpi work,0x35 breq STR_0_9 cpi work,0x36 breq STR_0_9 cpi work,0x37 breq STR_0_9 cpi work,0x38 breq STR_0_9 //"0" //"1" //"2" //"3" //"4" //"5" //"6" //"7" //"8" 81 cpi work,0x39 breq STR_0_9 cpi work,0x41 breq STR_A_F cpi work,0x42 breq STR_A_F cpi work,0x43 breq STR_A_F cpi work,0x44 breq STR_A_F cpi work,0x45 breq STR_A_F cpi work,0x46 breq STR_A_F //"9" //"A" //"B" //"C" //"D" //"E" //"F" ret //変換完了 STR_0_9: subi //アスキー→数値データへ処理 work,0x30 ret STR_A_F: subi work,0x37 ret /////////////////////////////////////////////////////////// //Cds セルポート ADC→判断ルーチン Cds: //AD チャネル 1 選択 Cds 計測 ists DIDR0,0b00000111 ists ADMUX,0b01100001 // //ADC1 使用時 PINC1 はバッファ禁止 ||||||||_(0)MUX0 ADC1 使用 // |||||||_(1)MUX1 // ||||||_(2)MUX2 // |||||_(3)MUX3 // ||||_(4)none // |||_(5)ADLAR // ||_(6)REFS0 // |_(7)REFS1 1 で AD 結果左揃え AVCC、VCC と一緒 INT_PWM_OFF iout SMCR,0b00000011 //SLEEP 許可 AD 開始 sei SLEEP //SLEEP→ADC→ADC 完了割り込みへ cli iout SMCR,0b00000010 //SLEEP 禁止 82 LDS work,ADCH cpi work,0x01 brlo Cds__low rcall Delay_10m //ADC1 結果 8Bit のみを work へ //0x01 以下なら分岐 INT_PWM_ON ret Cds__high: ret Cds__low: rjmp Cmd_2 //コマンド 2 実行 ret /////////////////////////////////////////////////////////// //遅延時間生成サブルーチン //8MHz=>0.125us ///* Delay_user://10m* X とする mov CNT5,work Delay_user__Loop: rcall Delay_10m dec CNT5 brbc 1,Delay_user__Loop ret Delay_1u://8 サイクル 3(rcall)+4(ret)+1=8 nop ret Delay_100u://800=72*8 +1(ldi)+72*[1(dec)+1(brbc)]+1(brbc 確定)+4(Ret) imov CNT1,0x48 loop_100u: rcall Delay_1u dec CNT1 brbc 1,loop_100u ret Delay_10m: imov CNT2,0x64 83 loop_10m: rcall Delay_100u dec CNT2 brbc 1,loop_10m ret Delay_100m: imov CNT3,0x0A rcall Delay_10m dec CNT3 brbc 1,loop_100m loop_100m: ret Delay_1000m: imov CNT4,0x0A rcall Delay_100m dec CNT4 brbc 1,loop_1000m loop_1000m: ret //SRAM 容量確保 .dseg M_DATA: .byte 55 //モーションデータ用 55Byte D150_DATA: .byte 55 //150cm 距離センサ用 55Byte D550_DATA: .byte 55 //550cm 距離センサ用 55Byte Motion_ON: .byte 1 //Motion ON/OFF フラグ 84 1Byte 管理ソフトウェア プログラムリスト Dim OpenFileName As String 'ファイル名 Dim ROT_DIR_Num As String '回転方向 Dim START_DIG_Num As String '回転方向 Dim DELAY_CNT_Num As String '回転速度 Dim ROT_CNT_Num As String '回転数 Dim Send_data As String '送信文字列 Dim ReciveBox(56) As Object '受信データ格納配列 設定+55点+ENDフラグ Dim MotionOut(57) As String 'モーションセンサ出力格納配列 Dim MotionOut2(57) As String Dim Dis150(56) As String '150cm距離センサ出力格納配列 Dim Dis500(56) As String '550cm距離センサ出力格納配列 Dim AvgTmp150(56) As String '取得データ平均化用 Dim AvgTmp500(56) As String Dim AvgCnt As Integer '平均化回数 Dim ReciveString As String '受信文字列格納変数 Dim CMD_MODE_F As Integer = 10 'コマンドモード一時保存 Dim CMD_MODE_Fix As Integer = 10 'コマンドモード状態保持 Dim lngPoint As Integer '文字列検索フラグ Dim SmpNum As Integer = 55 'サンプリング総数 Dim GraphicsMotion As System.Drawing.Graphics '図形描画用 Dim PenColor1 As New System.Drawing.Pen(System.Drawing.Color.White, 2) '線色、白、太さ2 Dim Pencolor2 As New System.Drawing.Pen(System.Drawing.Color.Red, 1) '線色、赤、太さ1 Dim Pencolor3 As New System.Drawing.Pen(System.Drawing.Color.Orange, 1) '線色、赤、太さ1 Dim GraphicsDistance As System.Drawing.Graphics '距離線描画用 Dim GraphicsGrid As System.Drawing.Graphics 'グリッド線描画用 Dim Over150flagM As Boolean Dim Under500flagM As Boolean 'HTML作成関連変数 Dim InputStr As String 'User.jsファイル内文字列 Dim JsStr(50) As String 'User.jsファイル内文字列分割 Dim SystemP(5) As Integer '在室管理フラグ Dim FileLen As Integer '読み込みファイル行数 Dim HTML_Name As String '作成HTML_URL '在室確認ルーチン用変数 85 Dim DefEnv(56) As String '無人時の環境格納配列 Dim NowEnv(56) As String '現在の環境格納配列 Dim SysInitFlg As Boolean = False Dim PreAvg As Integer Dim Pre(1) As String '確認システム初期化フラグ '在室、不在確定のための確認カウンタ '前回回転時の在室状況格納0=前、1=現在 Private UserBoxS() As System.Windows.Forms.TextBox Public Property TextBoxText() As String Get Return comNum.Text() End Get Set(ByVal Value As String) comNum.Text = Value End Set End Property Public Property MScommConf_com() As Short Get Return AxMSComm2.CommPort End Get Set(ByVal Value As Short) AxMSComm2.CommPort = Value End Set End Property ' Public Property MScommConf_set() As String Get Return AxMSComm2.Settings End Get Set(ByVal Value As String) AxMSComm2.Settings = Value End Set End Property 'Window読み込み時 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim i As Integer '繰り返し用変数 Dim temp(4) As String 'Temp Dim StrLen As Integer '取得文字長 Dim UserNum As String 'User数格納変数 Dim UserName(5) As String 'User名格納変数 Dim lngPoint As Integer '文字列検索ポイント ROT_DIR.Items.Add("逆転") '回転方向BOX初期値格納 ROT_DIR.Items.Add("正転") 86 'send_data_labelの初期値 If ROT_DIR.Text = "正転" Then '正転の場合0 ROT_DIR_Num = "0" Else '反転の場合1 ROT_DIR_Num = "1" End If 'MScomm初期設定 AxMSComm2.CommPort = 4 AxMSComm2.Settings = "19200,n,8,1" AxMSComm2.Handshaking = AxMSComm2.Handshaking.comNone AxMSComm2.RTSEnable = False AxMSComm2.RThreshold = 1 AxMSComm2.SThreshold = 1 comNum.Text = AxMSComm2.CommPort.ToString '現在の設定のCom番号表示 '設定タブの設定 '通信速度選択ボックスに値を読み込み Speed.Items.Add(9600) Speed.Items.Add(19200) Speed.Items.Add(38400) temp = Split(AxMSComm2.Settings, ",") 'Mscommの通信設定を読み込み','コードでセパレートし格 Speed.Text = temp(0) '0番は速度 ComPort.Value = AxMSComm2.CommPort 'CommPort番号反映 納 '外部User.js読み込み OpenFileName = "User.js" FileOpen(1, OpenFileName, OpenMode.Input) FileLen = 0 While Not EOF(1) '読み込みファイル行数カウンタ初期化 'EOFまでループ InputStr = InputStr + LineInput(1) ' 1行取得し格納 FileLen = FileLen + 1 End While JsStr = Split(InputStr, ";") ';でスプリット For i = 0 To FileLen - 1 jstxt.Text = jstxt.Text + JsStr(i) + ";" + Chr(13) + Chr(10) Next i '取得文字列内 "を省く For i = 0 To FileLen - 1 87 JsStr(i) = Replace(JsStr(i), Chr(34), "") Next i FileClose(1) 'lngPoint = InStr(JsStr(0), "UserNum = ") UserNum_box.Value = CInt(Mid(JsStr(0), Len("UserNum = ") + 1, 1)) 'User数取得反映 i = 0 lngPoint = InStr(JsStr(i + 2), "User[" & i & "] = ") User1_box.Text = Mid(JsStr(i + 2), Len("User[" & i & "] = ") + lngPoint, 5) i = 1 lngPoint = InStr(JsStr(i + 2), "User[" & i & "] = ") User2_box.Text = Mid(JsStr(i + 2), Len("User[" & i & "] = ") + lngPoint, 5) i = 2 lngPoint = InStr(JsStr(i + 2), "User[" & i & "] = ") User3_box.Text = Mid(JsStr(i + 2), Len("User[" & i & "] = ") + lngPoint, 5) i = 3 lngPoint = InStr(JsStr(i + 2), "User[" & i & "] = ") User4_box.Text = Mid(JsStr(i + 2), Len("User[" & i & "] = ") + lngPoint, 5) i = 4 lngPoint = InStr(JsStr(i + 2), "User[" & i & "] = ") User5_box.Text = Mid(JsStr(i + 2), Len("User[" & i & "] = ") + lngPoint, 5) HTML_Name = "C:\PC-02\多木さん作業用フォルダ\在室管理システム\2007.08.20 RS232C\bin\index.html" HTML_Name_box.Text = HTML_Name End Sub '通信開始ボタン Private Sub Conect_btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Conect_btn.Click Try AxMSComm2.PortOpen = Not AxMSComm2.PortOpen If AxMSComm2.PortOpen = True Then 88 '各種ボタン設定 Conect_btn.Text = "通信停止" Rot_Send_btn.Enabled = True Button4.Enabled = True WinClear.Enabled = True AutoMove.Enabled = True ReturnPos.Enabled = True GraphClear.Enabled = True comNum.Enabled = False Speed.Enabled = False ComPort.Enabled = False OK_button.Enabled = False '環境初期データ更新チェックタイマOFF Timer2.Enabled = True Else '各種ボタン設定 Conect_btn.Text = "通信開始" Rot_Send_btn.Enabled = False Button4.Enabled = False WinClear.Enabled = False AutoMove.Enabled = False ReturnPos.Enabled = False GraphClear.Enabled = False comNum.Enabled = True Speed.Enabled = True ComPort.Enabled = True OK_button.Enabled = True '環境初期データ更新チェックタイマOFF Timer2.Enabled = False End If Catch ex As Exception 'エラー処理 If ex.Message = "HRESULT からの例外です : 0x800A1F42。" Then TextBox2.AppendText("ERROR:ComPortがオープン出来ません" + Chr(13) + Chr(10)) Else TextBox2.AppendText("* " & ex.Message + Chr(13) + Chr(10)) End If Exit Sub 89 End Try End Sub 'Mscommイベント発生時 Private Sub AxMScomm2_OnComm(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AxMSComm2.OnComm Dim Buffer As Object '受信データ格納バッファ Dim lngPointCMD As Integer 'コマンド返信文字列検索フラグ Dim j As Integer '繰り返し用変数 Dim i As Integer '繰り返し用変数 Dim x As Integer Dim Mode5_out(3) As String 'Mode5出力処理用 Select Case AxMSComm2.CommEvent 'CommEventにより各種分岐 Case CShort(MSCommLib.OnCommConstants.comEvCD) Case CShort(MSCommLib.OnCommConstants.comEvCTS) Case CShort(MSCommLib.OnCommConstants.comEvDSR) Case CShort(MSCommLib.OnCommConstants.comEvRing) Case CShort(MSCommLib.OnCommConstants.comEvReceive) If CMD_MODE_F = 10 Then '通常受信モード Buffer = AxMSComm2.Input TextBox2.AppendText(CStr(Buffer)) '受信バッファをそのつどTextBox2へ ReciveString = ReciveString & CStr(Buffer) '受信バッファをそのつどReciveString へ連結 If lngPoint <> 0 Then ReciveString = Nothing End If End If 'モードチェック 2,3,4,5,10(コマンド外)対応 lngPoint = InStr(ReciveString, "Mode") If ReciveString = Nothing <> True Then '文字列が空出なければモード選別 CMD_MODE_F = CInt(Mid(ReciveString, lngPoint + 4, 1)) CMD_MODE_Fix = CMD_MODE_F 'コマンドフラグが変化するのでCMD_MODE_Fixで保持 'ReciveString = Nothing If CMD_MODE_F <> 3 And CMD_MODE_F <> 2 And CMD_MODE_F <> 4 And CMD_MODE_F <> 5 Then CMD_MODE_F = 10 ReciveString = Nothing 90 End If End If '現在のモードより処理を選択 Select Case CMD_MODE_F 'MODE2_SLEEPの処理 Quitが来たら抜ける。 Case 2 Buffer = AxMSComm2.Input ReciveString = ReciveString & CStr(Buffer) lngPoint = InStr(ReciveString, "Quit") If lngPoint <> 0 Then MyPrint("SLEEPが解除されました。") ReciveString = Nothing CMD_MODE_F = 10 CMD_MODE_Fix = 10 End If 'Mode3_Generalの処理 ENDが来たら抜ける Case 3 Buffer = AxMSComm2.Input If CStr(Buffer) = Chr(10) Or CStr(Buffer) = Chr(13) Then 'バッファがCR又は、LFな ら抜ける Exit Sub End If lngPoint = InStr(ReciveString, "END") If lngPoint <> 0 Then Call CalArray() '取得データ処理ルーチン呼び出し CMD_MODE_F = 10 CMD_MODE_Fix = 10 Else CMD_MODE_F = 10 '受信待機へ End If 'Mode4_SRAM_Sendの処理 Quitが来たら抜ける。 Case 4 Buffer = AxMSComm2.Input ReciveString = ReciveString & CStr(Buffer) lngPoint = InStr(ReciveString, "Quit") If lngPoint <> 0 Then TextBox2.AppendText(ReciveString) 91 CMD_MODE_F = 10 CMD_MODE_Fix = 10 ReciveString = Nothing End If 'Mode5_Sensor_Output_Sendの処理 Quitが来たら抜ける Case 5 Buffer = AxMSComm2.Input ReciveString = ReciveString & CStr(Buffer) lngPoint = InStr(ReciveString, "Quit") If lngPoint <> 0 Then lngPoint = InStr(ReciveString, "150cm = ") Mode5_out(0) = Mid(ReciveString, lngPoint + 10, 2) lngPoint = InStr(ReciveString, "500cm = ") Mode5_out(1) = Mid(ReciveString, lngPoint + 10, 2) lngPoint = InStr(ReciveString, "Light = ") Mode5_out(2) = Mid(ReciveString, lngPoint + 10, 2) lngPoint = InStr(ReciveString, "Motion = ") Mode5_out(3) = Mid(ReciveString, lngPoint + 10, 1) CMD_MODE_F = 10 CalVol(Mode5_out, 0, 2) '電圧変換ルーチン MyPrint("150cm = " & Mode5_out(0) & "V") MyPrint("500cm = " & Mode5_out(1) & "V") MyPrint("Light = " & Mode5_out(2) & "V") MyPrint("Motion = " & Mode5_out(3)) 'センサ距離算出 x = CInt(Mode5_out(0)) Mode5_out(0) = CStr(19.751 * x ^ 6 - 198.46 * x ^ 5 + 799.72 * x ^ 4 - 1659.7 * x ^ 3 + 1897.7 * x ^ 2 - 1189 * x + 383.94) x = CInt(Mode5_out(1)) Mode5_out(1) = CStr(43.765 * x ^ 6 - 427.45 * x ^ 5 + 1592.5 * x ^ 4 - 2825.3 * x ^ 3 + 2488.3 * x ^ 2 - 1246.5 * x + 684.81) MyPrint("150cm= " & Mode5_out(0) & "cm") MyPrint("500cm= " & Mode5_out(1) & "cm") CMD_MODE_F = 10 CMD_MODE_Fix = 10 92 ReciveString = Nothing '受信文字列初期化 End If End Select 'コマンドモードを抜ける Case CShort(MSCommLib.OnCommConstants.comEvSend) Case CShort(MSCommLib.OnCommConstants.comEvEOF) Case CShort(MSCommLib.CommEventConstants.comEventBreak) MyPrint("中断信号") Case CShort(MSCommLib.CommEventConstants.comEventFrame) MyPrint("フレームエラー") Case CShort(MSCommLib.CommEventConstants.comEventOverrun) MyPrint("オーバーランエラー") Case CShort(MSCommLib.CommEventConstants.comEventRxOver) MyPrint("受信バッファオーバー") Case CShort(MSCommLib.CommEventConstants.comEventRxParity) MyPrint("受信パリティエラー") Case CShort(MSCommLib.CommEventConstants.comEventTxFull) MyPrint("送信バッファフル") Case CShort(MSCommLib.CommEventConstants.comEventDCB) MyPrint("DSB取得エラー") Case Else MyPrint("未定義エラー発生") End Select End Sub '受信データ格納ルーチン Sub CalArray() Dim lngPoint As Integer '文字列検索フラグ Dim BeforOutput As Integer '前受信パケット記憶変数 Dim temp(55) As String 'Temp用配列 Dim i, j As Integer '繰り返し用変数 Dim x As Double '距離計算近似式変数x Dim GraphWidth As Single = CSng(PictureBox1.Width / 180) Dim GraphHeigh As Single = CSng(PictureBox1.Height / 4 * 2) Dim NowX, NowY As Single 'X,Y座標現在地 GraphicsMotion = PictureBox1.CreateGraphics 'グラフ描画ウインド宣言 GraphicsDistance = PictureBox2.CreateGraphics MyPrint("ENDコード検知") ReciveBox = Split(ReciveString, ",") ReciveString = Nothing '受信文字列初期化 93 If AvgCnt >= 1 Then Call String2Array(ReciveBox, AvgTmp150, AvgTmp500, MotionOut, 1, SmpNum) '逆回転の場合 降順、昇順を入れ替え If ROT_DIR_Num = "1" Then Call ReSortArray(MotionOut, 1, SmpNum) Call ReSortArray(AvgTmp150, 1, SmpNum) Call ReSortArray(AvgTmp500, 1, SmpNum) End If '150cmセンサの値を電圧値へ Call CalVol(AvgTmp150, 1, SmpNum) Call CalVol(AvgTmp500, 1, SmpNum) For i = 1 To SmpNum Dis150(i) = Dis150(i) + AvgTmp150(i) Dis500(i) = Dis500(i) + AvgTmp500(i) Next i AvgCnt = AvgCnt - 1 If AvgCnt = 0 Then For i = 1 To SmpNum Dis150(i) = CStr(CDbl(AvgTmp150(i)) / AvgNum_box.Value) Dis500(i) = CStr(CDbl(AvgTmp500(i)) / AvgNum_box.Value) Next i Else CMD_MODE_F = 3 'コマンド受信モードへ CMD_MODE_Fix = 3 ' lngPoint = 1 '変数初期化 ReciveString = Nothing AxMSComm2.Output = "3" Thread.Sleep(300) AxMSComm2.Output = Send_data Return End If Else 'ReciveBoxから値を取得し3つの配列へ Call String2Array(ReciveBox, Dis150, Dis500, MotionOut, 1, SmpNum) '逆回転の場合 降順、昇順を入れ替え If ROT_DIR_Num = "1" Then 94 Call ReSortArray(MotionOut, 1, SmpNum) Call ReSortArray(Dis150, 1, SmpNum) Call ReSortArray(Dis500, 1, SmpNum) End If '150cmセンサの値を電圧値へ Call CalVol(Dis150, 1, SmpNum) '550cmセンサの値を電圧値へ Call CalVol(Dis500, 1, SmpNum) End If '取得データをテキストに出力する。(電圧Ver) 'チェックボックスの確認 If FileoutCheck1.Checked = True Then 'ファイル名は現在時刻を参照 OpenFileName = "Vol" + DateTime.Now.Hour.ToString + DateTime.Now.Minute.ToString + "-" + DateTime.Now.Second.ToString + ".txt" '保存ファイル名定義 FileOpen(1, OpenFileName, OpenMode.Append) '距離センサ出力+モーションセンサ出力をファイルに書き出し For i = 1 To SmpNum PrintLine(1, Format(15 + 2.67 * i, "0##.0") & " " & Dis150(i) & " " & Dis500(i)) Next i FileClose(1) End If '式より距離を算出 For i = 1 To SmpNum x = CDbl(Dis150(i)) Dis150(i) = CStr(19.751 * x ^ 6 - 198.46 * x ^ 5 + 799.72 * x ^ 4 - 1659.7 * x ^ 3 + 1897.7 * x ^ 2 - 1189 * x + 383.94) Next i For i = 1 To SmpNum x = CDbl(Dis500(i)) Dis500(i) = CStr(43.765 * x ^ 6 - 427.45 * x ^ 5 + 1592.5 * x ^ 4 - 2825.3 * x ^ 3 + 2488.3 * x ^ 2 - 1246.5 * x + 684.81) 'Dis500(i) = CStr(19.643 * x ^ 6 - 190.68 * x ^ 5 + 688.84 * x ^ 4 - 1121.4 * x ^ 3 + 810.13 * x ^ 2 - 405.96 * x + 505.11) Next i '距離センサーリミッター Call DisLim(Dis150, Dis500, 1, SmpNum) 95 'TexBox2に出力をリスト化 For i = 1 To SmpNum MyPrint(Format(15 + i * 2.73, "0##.0") & "Deg= " & MotionOut(i) & " " & Format(CInt(Dis150(i)), "##0") + "cm " & Format(CInt(Dis500(i)), "##0") + "cm") Next i '取得データをテキストに出力する。 'チェックボックスの確認 If FileoutCheck1.Checked = True Then 'ファイル名は現在時刻を参照 OpenFileName = DateTime.Now.Hour.ToString + DateTime.Now.Minute.ToString + "-" + DateTime.Now.Second.ToString + ".txt" '保存ファイル名定義 FileOpen(1, OpenFileName, OpenMode.Append) '距離センサ出力+モーションセンサ出力をファイルに書き出し For i = 1 To SmpNum PrintLine(1, CStr(15 + 2.67 * i) & " " & MotionOut(i) & " " & Dis150(i) & " " & Dis500(i)) Next i FileClose(1) End If BeforOutput = 0 '現在出力は0 'PicBOX1内モーションセンサ出力グラフ描画 NowX = CSng(PictureBox1.Width / 180 * 15) NowY = CSng(PictureBox1.Height / 4 * 3) For i = 1 To SmpNum If MotionOut(i) = "0" Then If BeforOutput = 0 Then GraphicsMotion.DrawLine(PenColor1, NowX, NowY, CInt(NowX + GraphWidth * 2.7), NowY) NowX = CInt(NowX + GraphWidth * 2.7) Else GraphicsMotion.DrawLine(PenColor1, NowX, NowY, NowX, NowY + GraphHeigh) NowY = NowY + GraphHeigh GraphicsMotion.DrawLine(PenColor1, NowX, NowY, CInt(NowX + GraphWidth * 2.7), NowY) NowX = CInt(NowX + GraphWidth * 2.7) End If BeforOutput = 0 '現在の点は0 96 Else If BeforOutput = 0 Then GraphicsMotion.DrawLine(PenColor1, NowX, NowY, NowX, NowY - GraphHeigh) NowY = NowY - GraphHeigh GraphicsMotion.DrawLine(PenColor1, NowX, NowY, CInt(NowX + GraphWidth * 2.7), NowY) NowX = CInt(NowX + GraphWidth * 2.7) Else GraphicsMotion.DrawLine(PenColor1, NowX, NowY, CSng(NowX + GraphWidth * 2.7), NowY) NowX = CInt(NowX + GraphWidth * 2.7) End If BeforOutput = 1 '現在の点は1 End If Next i 'PicBox2内距離センサ出力描画1 NowX = CSng(PictureBox2.Width / 180 * 15) NowY = PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(Dis150(1))) For i = 1 To SmpNum GraphicsDistance.DrawLine(Pencolor2, NowX, NowY, CInt(NowX + GraphWidth * 2.67), * 2.67), PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(Dis150(i)))) NowX = CSng(NowX + GraphWidth * 2.67) NowY = PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(Dis150(i))) Next i 'PicBox2内距離センサ出力描画2 NowX = CSng(PictureBox2.Width / 180 * 15) NowY = PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(Dis500(1))) For i = 1 To SmpNum GraphicsDistance.DrawLine(Pencolor3, NowX, NowY, CInt(NowX + GraphWidth PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(Dis500(i)))) NowX = CSng(NowX + GraphWidth * 2.67) NowY = PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(Dis500(i))) Next i Dim temp1 As String Dim temp2 As String temp1 = Dis150(1) temp2 = Dis500(1) 'PicBox2内距離センサ出力描画3 Call check(1, temp1, temp2, Over150flagM, Under500flagM) 97 NowX = CSng(PictureBox2.Width / 180 * 15) If Over150flagM = True And Under500flagM = False Then '150cmセンサでオーバー 500cmセンサで普通 temp(1) = Dis500(1) End If NowY = PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(temp1)) '初期位置は判断後格納済み インデックスは1~smpNumまで For i = 1 To SmpNum temp1 = Dis150(i) temp2 = Dis500(i) Call check(1, temp1, temp2, Over150flagM, Under500flagM) temp(i) = Dis150(i) If Over150flagM = True And Under500flagM = False Then '150cmセンサでオーバー 500cmセンサで 普通 temp(i) = Dis500(i) End If Next i j = 0 For i = 1 To SmpNum If MotionOut(i) = "1" Then j = j + 1 End If Next If j = 0 Then SysInitFlg = False 'Motionセンサ反応なし 初期データ更新 MyPrint("環境初期データ更新") OpenFileName = "presedence2.txt" FileOpen(1, "presedence2.txt", OpenMode.Append) PrintLine(1, "環境初期データ更新") FileClose(1) End If 'システム初期化フラグチェック '1件目~SmpNumまで For i = 1 To SmpNum If SysInitFlg = False Then 98 DefEnv(i) = temp(i) If i = SmpNum Then '確定した距離を標準環境としてセーブ '格納終了した場合に初期化フラグをON SysInitFlg = True End If Else NowEnv(i) = temp(i) '初期化終了後はNowEnvへ格納 End If Next i For i = 1 To SmpNum MotionOut2(i) = MotionOut(i) Next i For i = 1 To SmpNum '実距離判断後描画へ GraphicsDistance.DrawLine(PenColor1, NowX, NowY, CInt(NowX + GraphWidth * 2.67), PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(temp(i)))) NowX = CSng(NowX + GraphWidth * 2.67) NowY = PictureBox2.Height - CSng(PictureBox2.Height / 500 * CSng(temp(i))) Next i Call PresenceCheck() '取得データをテキストに出力する。 'チェックボックスの確認 If FileoutCheck1.Checked = True Then 'ファイル名は現在時刻を参照 OpenFileName = DateTime.Now.Hour.ToString + DateTime.Now.Minute.ToString DateTime.Now.Second.ToString + "距離精査後.txt" '保存ファイル名定義 FileOpen(1, OpenFileName, OpenMode.Append) '距離センサ出力+モーションセンサ出力をファイルに書き出し For i = 1 To SmpNum PrintLine(1, CStr(15 + 2.67 * i) & " " & MotionOut(i) & " " & temp(i)) Next i FileClose(1) End If FileClose() ReciveString = Nothing End Sub 99 + "-" + '回転データ送信ボタン Private Sub Rot_Send_btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Rot_Send_btn.Click '回転データ送信ボタンクリック Dim StringLen As Integer '文字列の長さ取得 'Delay_BOX値*1000msを開始ディレイとする MyPrint("回転開始Delay" & Delay_box.Value.ToString & "秒") Thread.Sleep(1000 * CInt(Delay_box.Value)) MyPrint("スタート") Call Mode3_Move() AvgCnt = CInt(AvgNum_box.Value) '平均化回数格納 End Sub 'Windowクローズ時 Private Sub Form1_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed FileClose() End Sub 'グラフ描画内容クリア Private Sub GraphClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GraphClear.Click PictureBox2.Refresh() PictureBox1.Refresh() End Sub '回転開始位置へ移動 Private Sub ReturnPos_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ReturnPos.Click Dim i As Short Dim Send_data As String '送信する文字列 Dim StringLen As Integer '文字列の長さ取得 If ROT_DIR_Num = "1" Then ROT_DIR_Num = "0" ElseIf ROT_DIR_Num = "0" Then ROT_DIR_Num = "1" START_DIG_Num = CStr(Hex((START_DIG.Value + 4 * (ROT_CNT.Value) - 1))) StringLen = Len(START_DIG_Num) If StringLen = 1 Then 100 START_DIG_Num = "00" + START_DIG_Num End If If StringLen = 2 Then START_DIG_Num = "0" + START_DIG_Num End If Send_data = ROT_DIR_Num + START_DIG_Num + ROT_CNT_Num + DELAY_CNT_Num + "," TextBox2.AppendText("送信データ=" + Send_data & Chr(10)) AxMSComm2.Output = Send_data End If End Sub 'テキストウインドウ内クリア Private Sub WinClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WinClear.Click TextBox2.Clear() End Sub 'イベント Comポート番号変化 Private Sub comNum_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles comNum.TextChanged If comNum.Text <> "" Then AxMSComm2.CommPort = CShort(comNum.Text) End If End Sub '送信Box内テキスト送信ボタン Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click AxMSComm2.Output = Send_Text.Text End Sub 'Tab2通信設定反映ボタン Private Sub OK_button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim temp(3) As String 'MScomm.setting内容格納配列 AxMSComm2.CommPort = CShort(ComPort.Value) 'Comport番号反映 comNum.Text = ComPort.Value.ToString 'Comport番号表示反映 temp = Split(AxMSComm2.Settings, ",") 'Mscommの通信設定を読み込み','コードでセパレートし格 temp(0) = Speed.Text 'SPEED反映 納 AxMSComm2.Settings = temp(0) + "," + temp(1) + "," + temp(2) + "," + temp(3) End Sub '在室チェックルーチン 101 Sub PresenceCheck() Dim Par As Double = CDbl(PrePar_box.Text) / 100 '設定タブより誤差値 Dim ParCal As Double '算出誤差 Dim i, j As Integer '繰り返しカウンタ Dim k As Integer = 1 '時間経過カウンタ(iの値をセーブ) Dim Preflg As Integer 'ルーチン内フラグ If SysInitFlg = False Then 'システム初期化が行われているか? MyPrint("無人時環境読込必要性有") '未初期化の場合、メッセージを出してを抜ける Exit Sub End If For i = 1 To SmpNum ParCal = (CDbl(NowEnv(i)) / CDbl(DefEnv(i)) - 1) '誤差算出 If i - k > 2 Then '前回誤差発生から3Step以上経過なら j = 0 'jを初期化 k = i '現在のiをkに保存 End If If ParCal < Par Then j = j + 1 '誤差が既定以上かチェック いじった 'jをインクリメント If j > 2 Then j = 0 End If End If If (j = 2 And MotionOut2(i) = "1") Or ((j = 2 And MotionOut2(i + 1) = "1")) Then 以上が連続する場合 SystemP(0) = 1 '在室フラグON MyPrint((15 + i * 2.67) & "度付近に検出" & ParCal.ToString) Preflg = Preflg + 1 OpenFileName = "Presence.txt" FileOpen(1, OpenFileName, OpenMode.Append) PrintLine(1, Date.Now & " " & (15 + i * 2.67) & "度付近に検出") FileClose(1) j = 0 'J初期化 End If Next i OpenFileName = "Presedence2.txt" '在室状況をテキスト出力(毎回) FileOpen(1, OpenFileName, OpenMode.Append) '追記OPEN If Preflg > 0 Then 102 '誤差既定 PrintLine(1, Date.Now & "在室中") FileClose(1) Pre(1) = "在室中" Call CheckPreFin() '在室状況最終判断 Else PrintLine(1, Date.Now & "不在中") FileClose(1) Pre(1) = "不在中" Call CheckPreFin() '在室状況最終判断 End If End Sub '前回の在室状況と比較し2回連続であれば確定する。 Sub CheckPreFin() If Pre(0) <> Pre(1) Then Pre(0) = Pre(1) Else OpenFileName = "FinalPre.txt" FileOpen(1, OpenFileName, OpenMode.Append) PrintLine(1, Date.Now & Pre(1)) FileClose(1) Pre(0) = Pre(1) If Pre(1) = "在室中" Then SystemP(0) = 1 ElseIf Pre(1) = "不在中" Then SystemP(0) = 0 End If '確定した在室状況を外部HTMLへ Call TxtSaveSub() If SystemP(0) = 0 Then SysSta_lbl.Text = "不在中" SysSta_lbl.ForeColor = Color.White SysSta_lbl.BackColor = Color.Red ElseIf SystemP(0) = 1 Then SysSta_lbl.Text = "在室中" SysSta_lbl.ForeColor = Color.White SysSta_lbl.BackColor = Color.Blue End If 103 End If End Sub 'Tab1 手動在室チェック発動ボタン Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click PresenceCheck() End Sub 'Tab3 jstxt内容をUser.jsへセーブ Private Sub TXTsave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TXTsave.Click Call TxtSaveSub() End Sub 'テキスト作成セーブ Sub TxtSaveSub() Dim OutStr As String Dim i As Integer Dim System(2) As String 'システム状況 System(0) = "<b>不在</b>" System(1) = "<b>在室</b>" System(2) = "<b>未実装</b>" 'システム検知情報 'SystemP(0) = 1 SystemP(1) = 0 SystemP(2) = 0 SystemP(3) = 0 SystemP(4) = 1 OpenFileName = "User.js" 'JavaScript外部ファイル指定 FileOpen(1, OpenFileName, OpenMode.Output) '外部js 出力モードOPEN JsStr = Split(InputStr, ";") ' ; でスプリット For i = 0 To FileLen - 1 ' ; を付加し格納し直し JsStr(i) = JsStr(i) + ";" Next 'ユーザー数 & ユーザーネーム格納 'コントロールを配列化 Me.UserBoxS = New System.Windows.Forms.TextBox(5) {} 104 UserBoxS(1) = User1_box UserBoxS(2) = User2_box UserBoxS(3) = User3_box UserBoxS(4) = User4_box UserBoxS(5) = User5_box JsStr(0) = "UserNum = " & UserNum_box.Value & ";" For i = 2 To 6 JsStr(i) = "User[i-2] = " & Chr(34) & UserBoxS(i - 1).ToString & Chr(34) & ";" Next '不在時(時間表記)、在室時(なし) 未実装時(なし) For i = 0 To 4 If SystemP(i) = 0 Then JsStr(12 + i) = "Away[" & i & "] = " & Chr(34) & DateTime.Now.ToString & Chr(34) & ";" Else JsStr(12 + i) = "Away[" & i & "] = " & Chr(34) & Chr(34) & ";" End If Next i '更新時間格納 JsStr(23) = "myModify = " + Chr(34) + DateTime.Now.ToString & Chr(34) & ";" For i = 0 To 4 JsStr(18 + i) = "SystemP[" & i & "] = " & CInt(SystemP(i)) & ";" Next i For i = 0 To FileLen - 1 OutStr = OutStr & JsStr(i) + Chr(13) + Chr(10) Next i Print(1, OutStr) FileClose(1) 'User.js内容再度読み込み FileOpen(1, OpenFileName, OpenMode.Input) jstxt.Clear() While Not EOF(1) ' EOFまでループ jstxt.AppendText(LineInput(1) + Chr(13) + Chr(10)) End While FileClose(1) End Sub 105 'Tab3ShowHTMLボタン Private Sub ShowHTML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ShowHTML.Click 'HTMLファイルを標準ブラウザを用いて表示 Dim Explorer As SHDocVw.InternetExplorer Explorer = New SHDocVw.InternetExplorer Explorer.Visible = True Explorer.Navigate(HTML_Name) End Sub 'テキスト追加ルーチン Public Sub MyPrint(ByVal Str As String) TextBox2.AppendText(Str + Chr(13) + Chr(10)) End Sub '自動運転用タイマ開始ボタン Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AutoMove.Click If Timer1.Enabled = False Then AutoMove.Text = "停止" Timer1.Interval = CInt(AutoMoveDelay.Value * 1000) Timer1.Enabled = True '自動運転インターバル反映 'Timer1をイネーブル Else Timer1.Enabled = False AutoMove.Text = "自動運転" SysSta_lbl.Text = "システム停止中" SysSta_lbl.ForeColor = Color.Black SysSta_lbl.BackColor = SystemColors.ActiveBorder End If End Sub 'Timer1イベント 自動運転イベント発生 Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If CMD_MODE_Fix = 2 Then SysSta_lbl.Text = "システム休止中" SysSta_lbl.ForeColor = Color.Black SysSta_lbl.BackColor = SystemColors.ActiveBorder MyPrint("システム休止") OpenFileName = "FinalPre.txt" FileOpen(1, OpenFileName, OpenMode.Append) PrintLine(1, Date.Now & "システム休止中") 106 FileClose(1) Else 'MyPrint("自動運転イベント発生") Call Mode3_Move() End If End Sub 'Mode3回転用コード Sub Mode3_Move() Dim StrLen As Integer If AxMSComm2.PortOpen = True Then 'ポート確認 AxMSComm2.Output = "3" 'Mode3選択 Thread.Sleep(300) '300ms待ち If ROT_DIR.Text = "正転" Then '正転の場合0 ROT_DIR_Num = "0" Else '反転の場合1 ROT_DIR_Num = "1" End If START_DIG_Num = Hex(START_DIG.Text) StrLen = Len(START_DIG_Num) If StrLen = 1 Then START_DIG_Num = "00" + START_DIG_Num End If If StrLen = 2 Then START_DIG_Num = "0" + START_DIG_Num End If ROT_CNT_Num = Hex(ROT_CNT.Text) StrLen = Len(ROT_CNT_Num) If StrLen = 1 Then ROT_CNT_Num = "0" + ROT_CNT_Num End If DELAY_CNT_Num = Hex(DELAY_CNT.Text) StrLen = Len(DELAY_CNT_Num) If StrLen = 1 Then DELAY_CNT_Num = "0" + DELAY_CNT_Num End If 107 Send_data = ROT_DIR_Num + START_DIG_Num + ROT_CNT_Num + DELAY_CNT_Num MyPrint("送信データ=" + Send_data) AxMSComm2.Output = Send_data CMD_MODE_F = 10 CMD_MODE_Fix = 3 End If End Sub Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick Dim i As Integer Dim TimeStr As Object 'カウンタ '時刻格納文字列 TimeStr = Date.Now.ToShortTimeString MyPrint(CStr(TimeStr)) TimeStr = Split(CStr(TimeStr), Chr(58)) If Date.Now.ToShortTimeString = InitTime_box.Text Then MyPrint("時刻イベント発生") If CMD_MODE_Fix <> 2 Then 'モード2で無い場合 TimeStr(1) = CInt(TimeStr(1)) + 5 '5分後に再度確認 If CInt(TimeStr(1)) > 60 Then '時間、分桁ともに60を越えたらインクリメント TimeStr(1) = CInt(TimeStr(1)) - 60 TimeStr(0) = CInt(TimeStr(0)) + 1 End If If TimeStr(0) > 24 Then TimeStr(0) = CInt(TimeStr(0)) - 24 End If InitTime_box.Text = (TimeStr(0) & ":" & TimeStr(1)) MyPrint("室内点灯中5分後に再度確認") End If 'SLEEP中の処理 初期環境データ更新(初期化フラグは触らない) For i = 1 To SmpNum DefEnv(i) = NowEnv(i) '現在の環境を初期環境にシフト Next i MyPrint("居室内消灯&設定時刻につき環境初期化") End If End Sub End Class 108 管理ソフトウェア プログラムリスト(モジュール) Module Module1 '出力チェックルーチン Sub check(ByVal x As Integer, ByVal A As String, ByVal B As String, ByRef Over150flag As Boolean, ByRef Under500flag As Boolean) Over150flag = False Under500flag = False If CInt(A) >= 150 Then '150cmセンサ150以上の場合 Over150flag = True End If If CInt(B) <= 100 Then '500cmセンサ100cm以下の場合 Under500flag = True End If End Sub 'Oncommイベント内で使用 距離センサの距離リミッタ Sub DisLim(ByRef DistanceA() As String, ByRef DistanceB() As String, ByVal x As Integer, ByVal Cnt As Integer) Dim i As Integer For i = x To Cnt If CInt(DistanceA(i)) > 150 Then ' DistanceA(i) = "150" ElseIf CInt(DistanceA(i)) < 20 Then DistanceA(i) = "20" End If If CInt(DistanceB(i)) > 500 Then DistanceB(i) = "500" ElseIf CInt(DistanceB(i)) < 100 Then DistanceB(i) = "100" End If Next i End Sub Sub ReSortArray(ByRef A() As String, ByVal x As Integer, ByVal Cnt As Integer) Dim i As Integer 'カウンタ Dim j As Integer = Cnt 'カウンタ Dim Temp() As String ReDim Temp(Cnt) '配列容量確保 For x = i To Cnt 109 Temp(j) = A(i) j = j - 1 Next x j = 1 For x = i To Cnt A(i) = Temp(j) j = j + 1 Next End Sub 'CalArray内 文字列よりデータを配列に取得 Sub String2Array(ByVal RevBox() As Object, ByRef DistanceA() As String, ByRef DistanceB() As String, ByRef Motion() As String, ByVal x As Integer, ByVal Cnt As Integer) '仕様 3種のセンサの文字列を配列へ x~Cnt回繰り返す。 Dim i As Integer 'カウンタ For i = x To Cnt Motion(i) = Mid(CStr(RevBox(i)), 1, 1) DistanceA(i) = Mid(CStr(RevBox(i)), 2, 2) DistanceB(i) = Mid(CStr(RevBox(i)), 4, 2) Next i End Sub 'CalArray内 対象配列を電圧に変換格納 Sub CalVol(ByRef Distance() As String, ByVal j As Integer, ByVal cnt As Integer) Dim i As Integer ' カウンタ Dim x As Double '計算対象 For i = j To cnt Distance(i) = "&H" & CStr(Distance(i)) Next i 'MsgBox(ReciveBox(i)) For i = j To cnt Distance(i) = CStr(CInt(CDec(Distance(i)))) Next i For i = j To cnt Distance(i) = CStr(3.3 / 256 * CDbl(Distance(i))) Next i End Sub End Module 110