パソコンを利用してミリ秒単位の時間を測定するものです。レースのラップタイムなど低頻度(毎秒数回以下)だが間隔が長いスイッチOn/Offの測定に向いています。以下に他の方法との比較を載せます。
方法 | 長所 | 短所 |
---|---|---|
市販のオシロスコープ | 非常に高精度 | 非常に高価 |
サウンドカード | 安価かつ高精度 | On/Offの頻度が低いと信頼性確保が困難 (*1) |
OSが提供する時間関数 | 追加費用無し・扱い易い | 低精度 (*2) |
本方法 | 最長5日弱に渡る測定が可能 | 回路とプログラムを作らないといけない・激しい繰り返しには追従できない |
右側ユニバーサル基板部分に載っている白いIC(フォトカプラ)やヒートシンク(電圧レギュレータ)、及びそれより右のコネクタ類はこの時使用したセンサとの接続用で、用途に応じて変更が必要です。
AVRでは割り込み処理により10KHz・毎秒1万回内部カウンタを増加させています。 この時PB0-PB7の状態が前回と変化している場合その時のカウンタの値を記録、USBを通してPC側にカウンタ値とポートの番号を連絡します。 PC側はこのカウンタ値を前回のものと差を取ることで時間を測定できます。
プルアップされたPB0とGND間にスイッチが接続されているとします。スイッチOffの時はPB0=Highとなり、OnでLowとなります。 BGCNT(後述)コマンドで内部カウンタをスタートした後スイッチを押すと、PCは以下のデータを受け取ります。
PRTRG 00 0 25460
00はポート番号、0はPB0=Low、25460がその時の内部カウンタとなります。 この時点では内部カウンタの値はあまり意味を持ちません。BGCNTコマンドが処理されてから2.546秒経過したというだけです。 後述注意点でも述べますが、PCがBGCNTコマンドを送ってから実際AVRが処理するまでの時間は不安定ですので、2.546秒=PCがBGCNTコマンドを発行してから経った時間とはなりません。
次にスイッチをOffにするとPCは以下のデータを受け取ります。
PRTRG 00 1 31621
00がポート番号、PB0=High、カウンタ値31621。PC側ではこの二つのカウンタ値の差6161=0.6161秒がPB0に繋がれたスイッチがOnであった時間と知ることができます。 この時間はPC-USB間の通信の依存しないため、ミリ秒単位で信頼できるものとなります。
AVR側は単純な機能しか提供してませんので、どう使うかはPC側のプログラム次第ということになります。
ミリ秒という時間測定に対しては、PC-AVR間通信にかかる時間は不安定であると考えたほうがいいです。これは主に以下の処理にかかる時間がミリ秒単位では不安定なためです。
よって以下の注意点が発生します。
特に特殊なことはしてません。ストロベリーリナックス社のAVR-USBマイコンボード AT90USB162を使用すると作業がかなり楽になると思います。
AVRのソースをコンパイルする知識があることを前提にしています。AVR StudioやWinAVRに関してはここでは説明しません。
#ifdef __GNUC__ #define Clear_prescaler() (clock_prescale_set(0)) ↓ #define Clear_prescaler() clock_prescale_set(0)
Windows(98SE以降?)ではドライバはOS標準で提供されていますが、INFファイルが必要です。
Linux/Macその他のOSでも、USBで規格化されているCDC(Communication Driver Class)をサポートするドライバを使えばなんとかなるはずです。後日機会があれば更新します。
目的によりアプリケーションの形態が大きく異なりますので、汎用的なものはここでは提供しません。 以下に示すコマンド表を参考に目的にあったものを作成してください。
Windowsの場合、通信はCOMポートと扱われます。 何番ポートに割り当てられるかは環境によりますが、上記のINFファイルを用いた場合COMポートには「AT90USBxxx CDC USB to UART MGM」の名前がつきます。 TeratermなどCOMポートを扱えるターミナルソフトを使えば手動でコマンドを実行することも可能です(基本的には専用アプリケーションと通信するように設計されています)。
チャタリング制御として、ある一定回数連続しないと状態が変わったとみなさない機能を備えてます。 例えばチャタリング制御値が5でPB0がHigh→Lowになる場合、Lowが5カウント連続(0.5ミリ秒)続かないとLowになったとしません。 チャタリング制御値はSTCHTコマンドで設定、PRCHTコマンドで確認できます。値の範囲は0-65535(6.5535秒)です。 設定した値はAVRのEEPROMに書き込まれ、次回以降も有効です。
構造上、測定時間の精度はAVRの駆動クロックのそれに直結しているため、水晶発振器などなるべく高精度なクロックの使用を勧めますが、それでも微妙な誤差が出ます。 より厳密な測定を求めるなら、校正を行ったほうがいいでしょう。
方法の一例としては、NTP(W32TimeサービスではなくNTPDなど)などで時計を調整したPCにAVRを接続、 ある時間をおいてPRCNTコマンドを実行し、理論値毎秒1万カウントからどれくらいずれているかを見ます。 何度か述べているとおりPRCNTコマンドはPC-AVR間通信による不正確さを含みますので、その影響を打ち消すためPRCNTコマンド発行間隔を長くしたり、何回か行って平均をとるといいでしょう。 ちなみにこの方法でストロベリーリナックスのボードを使い、24時間かけて測定してみた所毎秒9999.67カウントでした。
校正値を管理するコマンドとしてSTCLB/PRCLBを用意してますが、
送信 | 受信 | 内容 | BGCNT | BGCNT | 内部カウンタを開始します(USBに接続した直後は停止してます)。PD0にLEDを接続している場合は、点滅を開始します。 |
---|---|---|
ENCNT | ENCNT | 内部カウンタを停止します |
PRCNT | PRCNT カウンタ値 | 現在のカウント値を表示します。PCがコマンドを発行してからAVR側で処理するまでの時間が誤差として含まれます。 |
STCHT 値 | STCHT 採用された値 | チャタリング制御値を変更します。最大値は65535です。 |
PRCHT | PRCHT 現在の値 | 現在のチャタリング制御値を返します。 |
STCLB | STCLB 採用された値 | 校正値を変更します。最大値は4294967295です。 |
PRCLB | PRCLB 現在の値 | 現在の校正値を返します。 |
PRREV | PRREV | AVRプログラムのリビジョンを返します。 |
PRCLK | PRCLK クロック プリスケーラ コンパレータ | AVRプログラムで設定されているクロック、プリスケーラ、コンパレータの値を返します。この組み合わせで10kHzになるはずです。詳しいことはAVRプロセッサの仕様書Timerに関する記述を参考にしてください。 |
(不正なコマンド) | INVALID COMMAND | 間違ったコマンドを入力したときに返します。 |
(なし) | PRTRG ポート番号 新状態 カウンタ | PB0-7の入力が変化したことを通知します。新状態は1=High/0=Lowです。 |