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
さんが
2021/02/21
に
編集
をしました。
(メッセージ: 初版)
-
eepoo
さんが
2021/03/13
に
編集
をしました。
ログインしてコメントを投稿する