Accuracy of timer
自作GPSロガーを作っていますが、☆board Orange スタック基板に取り付けたGPSモジュール(GM-316)は、1PPS信号が出ているので、それと mbed の Timer の精度を比べてみることにしました。


GPSモジュール(GM-316)のURLとドキュメントです。Time accuracy は 1μs or less とあります。
http://www.aitendo.co.jp/product/1321
1PPS信号は、mbed p15ピンに接続しました。
PPS(pulse per second)とは?
「(ほぼ)正確な秒周期」を表します。1PPSは、(ほぼ)正確な1秒周期のパルスを出力するもので、GPSモジュールにはこの出力信号がついているものがあります(ついていないものもあります)。
GPS時刻はナノ秒レベルで正確ですが、GPS時刻をNTPサーバとして使うには、時刻情報(何時何分何秒)と、それを同期するための信号(PPS)の二つが必要です。
GM-316 の資料を信じれば、GM-316は1マイクロ未満の1秒周期パルスを出しているはずです。
Timer の精度を測ってみる
二通りの方法で試してみました。
- InterruptIn を使い、p15 の立ち上がりで割り込みをかけて、Timer の差分を計算する。
- main() で while() でポーリングして、p15 の立ち上がりを見つけて Timer の差分を計算する。
考え方は、両方とも、1秒((1,000,000マイクロ秒)パルスの立ち上がりを掴まえて、Timer を読んだ時の値を調べると言う考え方です。
結果
- InterruptIn を使う方法→約3マイクロ~4マイクロの誤差がありました。
- main() で while() でポーリングする方法→これも約3マイクロ~4マイクロの誤差がありました。
テストコード
#include "mbed.h"
Serial debug(USBTX,USBRX);
#if 1
InterruptIn PPS(p15);
Timer tim;
int tim_val[5];
int tim_r = 0;
int tim_w = 0;
int tim_pre = 0;
void pps_rise()
{
int tim_now = tim.read_us();
tim_val[tim_r] = tim_now - tim_pre;
tim_r = (tim_r + 1) & 0x03;
tim_pre = tim_now;
}
int main(void) {
debug.format(8,Serial::None,1);
debug.baud(115200);
printf("*** GPS 1PPS Test (Interrupt) ***\n");
tim.start();
PPS.rise(pps_rise);
while(1){
if(tim_r != tim_w){
debug.printf("%d\n",tim_val[tim_w]);
tim_w = (tim_w + 1) & 0x03;
}
}
}
#else
DigitalIn PPS(p15);
Timer tim;
int main(void) {
int pre = 0;
int tim_pre = 0;
int tim_now = 0;
debug.format(8,Serial::None,1);
debug.baud(115200);
printf("*** GPS 1PPS Test (polling) ***\n");
tim.start();
while(1){
int now = PPS.read();
if((pre == 0) && (now != 0)){
tim_now = tim.read_us();
debug.printf("%d\n",tim_now - tim_pre);
tim_pre = tim_now;
}
pre = now;
}
}
#endif
テストプログラムの出力結果(抜粋)
*** GPS 1PPS Test (Interrupt) *** 250647 1000003 1000004 1000004 1000004 1000004 1000004 1000004 1000003 1000004 1000004 ...
*** GPS 1PPS Test (polling) *** 5057 1000004 1000004 1000004 1000004 1000004 1000004 1000004 1000004 1000003 1000004 1000004 1000004 ...
細かく平均は取っていませんが、1秒(1,000,000マイクロ秒)の周期に対し、3マイクロ~4マイクロの差が出ています。
考察
気になるのは、InterruptIn の方法でも、ポーリングの方法でも、結果に殆ど差が見受けられないと言う事です。
InterruptIn を使うと、割り込みハンドラとしての処理があるので、ポーリングの方が若干でも誤差が縮まるかと思いましたが、あまり差は感じられません。
Timer クラスの read_us() 自身が、もしかすると遅いのかもしれません。もちろん、GPS モジュール側の誤差も考えられます。
また時間を見つけて、調べてみたいと考えています。
一番良いのは、校正済みのオシロを使って測定することかと思います(汗。もし、測定された方がいましたら、教えて頂けたら嬉しいです。
追記
mbed が使用しているクロックオシレータは,下記の URL にある回路図を見ると,
ASE-12-D-C-T と言うクロックオシレータを使っています.
http://mbed.org/media/uploads/chris/mbed-005.1.pdf
ASE-12-D-C-T は,下記から仕様が分かります.
http://www.abracon.com/Oscillators/ASEseries.pdf
- 12MHz
- -10度~+60度
- +/- 50ppm
12MHz のクロックで 50ppm の精度です.これは,クロック数(12MHz)に関係なく,1秒に対して 50ppm の精度であると言う事から,50マイクロ秒(0.000050秒)の誤差を含む場合があると言う事です.
実際の測定では,概ね3マイクロ~4マイクロなので,今回の測定(2010年10月6日)では,良い成績だったと言えます.
温度が変われば,誤差はもっと変わるかもしれません.
なお,正確な時間が必要なために高精度なクロックオシレータを入れない限り,通常のクロックオシレータは,調べると大体 25ppm ~ 100ppm の精度です.
したがって,mbed のクロックオシレータが低い訳ではありません.通常利用の範囲内と考えています.
1 comment
You need to log in to post a comment
