teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

追記

2019/08/08 13:33

投稿

thkana
thkana

スコア7735

answer CHANGED
@@ -44,4 +44,9 @@
44
44
  ```
45
45
  冷房は入れていない夜の室内なので28℃ぐらいの環境と思います。
46
46
  1000000msは16分40秒。0.11%ぐらいのずれ、というところでしょうか。USBで繋いでいるしWindowsなのでタイムスタンプの10ms以下はあまり意味がないと思いますが、millis()に対して100000/99882を乗じればそこそこは合うかな、というところ。もっと長くデータを取れば桁数は増えるでしょうし、温度が変わるとまた影響があるでしょう。必要なら温度センサもつけて補正係数を求める、なんてことも考えられます。
47
- 素直に正確なタイムベースを設けろ、の説もあり。質問者さんの必要な精度に合わせて手を打って下さい。
47
+ 素直に正確なタイムベースを設けろ、の説もあり。質問者さんの必要な精度に合わせて手を打って下さい。
48
+
49
+ ---
50
+ バタバタやってみたけど、読み返してみると要求は日差1秒以下、でしたっけ。腕時計なんかでも(実は腕時計って着けたり外したりで温度差が出るから条件は厳しいのだけれど)日差±15秒ぐらいじゃなかったかしら。つまり、水晶にしたとしてもその目標は困難かと。
51
+
52
+ ネットワークに繋いでNTPとか、GPSモジュール付けて時刻を拾うとかいうのが実現しやすい解決になると思います。

3

データ添付

2019/08/08 13:33

投稿

thkana
thkana

スコア7735

answer CHANGED
@@ -10,4 +10,38 @@
10
10
 
11
11
  もちろん、精度はあまり期待出来ませんから、外部の正確な時計で1時間とか一日分のmilllis()の値を計ってみていくつだったのか、というデータを取らないと時計と呼べるレベルにはなかなかならないかも知れません。長時間のデータを取れば取るほど精確な計時が期待できるようになるでしょう。1時間は単純にmsで言えば3600000msですが、millis()が精確でないが故に3601800(millis)が1時間なのかも知れないので、それで「校正」するのです。逆に言うと、millis()が1000毎に1秒、何ていう処理をしているとまともな精度が得られないかもしれません。
12
12
 
13
- もう一つ、millis()の元はマイコンが動けばいい、というクロックですから、温度や基板の実装状態によっては湿度の変化に対しても無視できない周波数変動を起こかもしれません。昔の時計みたいに、夏と冬とでずれ方が変わるとか。
13
+ もう一つ、millis()の元はマイコンが動けばいい、というクロックですから、温度や基板の実装状態によっては湿度の変化に対しても無視できない周波数変動を起こかもしれません。昔の時計みたいに、夏と冬とでずれ方が変わるとか。
14
+
15
+ ---
16
+ とりあえずデータを取ってみました。
17
+ 純正(というのかな?)のArduinoです。
18
+ ```Arduino
19
+ void setup() {
20
+ Serial.begin(115200);
21
+ }
22
+
23
+ void loop() {
24
+ unsigned long ms=millis();
25
+ if(ms%10==0){//通信量を抑えるため
26
+ Serial.println(ms);
27
+ delay(5);
28
+ }
29
+ }
30
+ ```
31
+ で、出てくるデータをteratermのタイムスタンプ付きのログで記録してみたところ、抜粋ですが
32
+ ```Text
33
+ [2019-08-08 20:34:42.702] 0
34
+ [2019-08-08 20:51:22.705] 998820
35
+ [2019-08-08 20:51:23.884] 1000000
36
+ [2019-08-08 21:08:02.705] 1997640
37
+ [2019-08-08 21:08:05.069] 2000000
38
+ [2019-08-08 21:24:42.706] 2996460
39
+ [2019-08-08 21:24:46.254] 3000000
40
+ [2019-08-08 21:34:42.696] 3595740
41
+ [2019-08-08 21:34:46.965] 3600000
42
+ [2019-08-08 21:41:22.700] 3995270
43
+ [2019-08-08 21:41:27.439] 4000000
44
+ ```
45
+ 冷房は入れていない夜の室内なので28℃ぐらいの環境と思います。
46
+ 1000000msは16分40秒。0.11%ぐらいのずれ、というところでしょうか。USBで繋いでいるしWindowsなのでタイムスタンプの10ms以下はあまり意味がないと思いますが、millis()に対して100000/99882を乗じればそこそこは合うかな、というところ。もっと長くデータを取れば桁数は増えるでしょうし、温度が変わるとまた影響があるでしょう。必要なら温度センサもつけて補正係数を求める、なんてことも考えられます。
47
+ 素直に正確なタイムベースを設けろ、の説もあり。質問者さんの必要な精度に合わせて手を打って下さい。

2

訂正

2019/08/08 12:51

投稿

thkana
thkana

スコア7735

answer CHANGED
@@ -6,7 +6,7 @@
6
6
  30cmのものさしがあったとして、ものさしの端を使わないで長さを計るとき、あなたはどうしますか? 例えば3.2cmのところから20.7cmのところまであるモノの長さはいくつでしょう。
7
7
  millis()だって基本的には同じです。ある時、millis()が返す値が1234だった。次にmillis()を呼んだら、5999だった。この間にどれだけの時間が経ったのでしょう。これが基本になります。
8
8
 
9
- それと、注意しなければいけないのはmillis()はunsigned longで値を返すこと。つまり、49日程で値が0に戻ります。単純に引き算だけで時間を求めているとこの罠にハマります。
9
+ ~~それと、注意しなければいけないのはmillis()はunsigned longで値を返すこと。つまり、49日程で値が0に戻ります。単純に引き算だけで時間を求めているとこの罠にハマります。~~(誤りなので削除)
10
10
 
11
11
  もちろん、精度はあまり期待出来ませんから、外部の正確な時計で1時間とか一日分のmilllis()の値を計ってみていくつだったのか、というデータを取らないと時計と呼べるレベルにはなかなかならないかも知れません。長時間のデータを取れば取るほど精確な計時が期待できるようになるでしょう。1時間は単純にmsで言えば3600000msですが、millis()が精確でないが故に3601800(millis)が1時間なのかも知れないので、それで「校正」するのです。逆に言うと、millis()が1000毎に1秒、何ていう処理をしているとまともな精度が得られないかもしれません。
12
12
 

1

加筆

2019/08/07 13:22

投稿

thkana
thkana

スコア7735

answer CHANGED
@@ -8,6 +8,6 @@
8
8
 
9
9
  それと、注意しなければいけないのはmillis()はunsigned longで値を返すこと。つまり、49日程で値が0に戻ります。単純に引き算だけで時間を求めているとこの罠にハマります。
10
10
 
11
- もちろん、精度はあまり期待出来ませんから、外部の正確な時計で1時間とか一日分のmilllis()の値を計ってみていくつだったのか、というデータを取らないと時計と呼べるレベルにはなかなかならないかも知れません。長時間のデータを取れば取るほど精確な計時が期待できるようになるでしょう。逆に言うと、1000を数えたら1秒、何ていう処理をしているとまともな精度が得られないかもしれません。
11
+ もちろん、精度はあまり期待出来ませんから、外部の正確な時計で1時間とか一日分のmilllis()の値を計ってみていくつだったのか、というデータを取らないと時計と呼べるレベルにはなかなかならないかも知れません。長時間のデータを取れば取るほど精確な計時が期待できるようになるでしょう。1時間は単純にmsで言えば3600000msですが、millis()が精確でないが故に3601800(millis)が1時間なのかも知れないので、それで「校正」するのです。逆に言うと、millis()が1000毎に1秒、何ていう処理をしているとまともな精度が得られないかもしれません。
12
12
 
13
13
  もう一つ、millis()の元はマイコンが動けばいい、というクロックですから、温度や基板の実装状態によっては湿度の変化に対しても無視できない周波数変動を起こかもしれません。昔の時計みたいに、夏と冬とでずれ方が変わるとか。