eepooのアイコン画像
eepoo 2021年02月21日作成 (2021年03月13日更新)
製作品 製作品 閲覧数 2101
eepoo 2021年02月21日作成 (2021年03月13日更新) 製作品 製作品 閲覧数 2101

GPSのPPSを利用したRTCの精度測定器

GPSのPPSを利用したRTCの精度測定器

DS3231を使ったRTCが安く出回っている。データシートによると2ppmを詠っているので一日0.2秒弱の誤差のはずだが結構当たりはずれがある。最初は選別するために電波時計と目視比較でチェックしていたが、0.2秒程度の解像度(笑)しか期待できない上に、電波時計も校正直後以外は案外ずれていることが分かった。
 なんたって精度ならGPSでしょう。ということで手持ちのGPSが流してくれるシリアルデータを解析。特定のタグを毎秒流すのでそれを利用した。ところが短期間は安定しているものの、数時間でごそっとシフトすることが分かった。理由はわからないが、、
 次に117の音声信号をマイクで拾ってLow Pass Filterをかけて信号の立ち上がりを比較するようにした。悪くないんだけど、117が案外お金がかかる。
 ネット上のJJY的な信号を流しているところや原子時計アプリも使ってみたが、ちゃんとモニターしてみると信号が安定していない。
 本家JJYを受信しようとキットも買ったが家の中では電波が弱くて、、

聞けばGPSは一秒ごとのパルスを出してくれるはずというではないか。
いや、私のGPSにはそんな端子がないんですけど、、ん、でもLEDにPPSって書いてあるぞ。
だめもとで高度な半田テクニック(笑)を用いて信号線を引き出した。(画像黄色のリード線)
キャプションを入力できます
モニターしてみるときれいなパルスが出ている、、が電圧が低いのでトランジスタでしゃっきりさせてarduino nanoの割込みポートへ。一方のRTCからもSQWという端子からPPSが出ているのでそちらも割込みへ。双方の割込み時の micros() を比較し、差を7セグ表示機(TM1637)に表示。一度に2つチェックできるようにnanoを二つ並べGPS信号は共用した。
キャプションを入力できます
キャプションを入力できます
これで適当な時間にチェックして表示の差を時間で割れば、一日当たりの精度を求めることができる。

#include <DS3231.h> #include <Wire.h> #include <TM1637Display.h> #define CLK 6 #define DIO 5 TM1637Display display(CLK, DIO); volatile unsigned long cpuClock = 0; //GPSトリガー毎のcpuClock数をバッファする volatile unsigned long lastGPS = 0; //GPSトリガー毎のcpuClock数を算出するため volatile bool sqrInt = false; volatile bool d3Int = false; volatile unsigned long lastDS = 0; volatile unsigned long lastDelta = 0; DS3231 Clock; //DS3231からの一秒ごとの割込み void sqrSecIntHandler() { lastDS = micros(); } //GPSからのPPS D3に繋いだ void d3Out() { d3Int = true; unsigned long curr = micros(); cpuClock = curr - lastGPS; lastGPS = curr; lastDelta = micros() - lastDS; } void setup() { Serial.begin(115200); Wire.begin(); display.setBrightness(0x0f); display.showNumberDec(0, false); pinMode(2, INPUT);//DS3231からのオシレート Clock.enableOscillator(true, true, 0); attachInterrupt(0, sqrSecIntHandler, FALLING); pinMode(3, INPUT_PULLUP); attachInterrupt(1, d3Out, FALLING); } void loop() { //GPSのオシレート if (d3Int) { d3Int = false; //cpuの温度ドリフトによるクロック数変化をキャンセルする float delta = (float)lastDelta * 1000000.0 / (float)cpuClock; lastDelta = delta; display.showNumberDec(lastDelta / 100, false); } }
eepooのアイコン画像
プログラミング大好きな本業メカ屋 arduinoからマイコンに手を出し、BluePillやESP32などでいろいろ作っています。 HUB75のLED Matrix Panelのライブラリを作ったりもしています。
ログインしてコメントを投稿する