Arduinoを使用して時計を作成しましたが、時間がずれているようです。ロールオーバーの問題を認識しています。時計は1週間で約15分ドリフトするようです。
Digi-keyのこの共振器でカスタムPCBを使用しています。コードは、各ループの開始時にmillis()関数を読み取り、その値から機能します。
私の質問は、Arduinoで時間を測定するにはどうすればよいですか。
millis()
。
Arduinoを使用して時計を作成しましたが、時間がずれているようです。ロールオーバーの問題を認識しています。時計は1週間で約15分ドリフトするようです。
Digi-keyのこの共振器でカスタムPCBを使用しています。コードは、各ループの開始時にmillis()関数を読み取り、その値から機能します。
私の質問は、Arduinoで時間を測定するにはどうすればよいですか。
millis()
。
回答:
注:私の答えは受け入れられ、より高い投票スコアを持っていますが、ArduinoにRTCを使用せずに時間を維持させる方法に関するエドガーボネットの素晴らしい答えを必ず読んでください。
DS1307リアルタイムクロックの使用に非常に成功しています。データシートへのリンクはこちらです。
以下にその機能の一部を示します。
Arduinoとの通信にICインターフェースを使用しているため、適切なライブラリ(ネットで入手可能)を使用して簡単にプログラミングできます。
SCLおよびSDAピン(それぞれアナログA4およびA5)を介してArduinoに接続されているため、2つのピンのみを使用します。
実行に必要な外部コンポーネントはごくわずかです。
ITはコイン型電池に接続できるため、Arduinoがオフになっていても時間を維持できます。低電力モードでは、コイン型電池は数年間持続します。
ドリフトはほとんどありません(私の場合、週に数秒しかドリフトしません)。
それほど高価ではありません。
RTCを使用する予定がない場合は、Farnelまたは他のこのような水晶発振器モジュールにArduinoにクロックを提供するために一般的に使用される水晶を交換できます。以下の画像のように、4ピンパッケージで提供されます。彼らはあなたのarduinoのためにより正確な時計を生成します。
記載されているモジュールは両方とも50 ppmの許容誤差を持ち、5 Vで動作します。
繰り返しますが、明確にするために、これらの水晶発振器モジュールは、以下のような通常の2ピンクリスタルと混同しないでください。これらは、たとえば、MCUの外部クロックの回路の一部です。
クロックを構築するためにRTCは必要ありません。ATmegaチップには、RTC自体の機能を実行するために必要なすべてのハードウェアが備わっています。方法は次のとおりです。
32768 Hzの時計用クリスタルを購入します。購入するか、古い時計を分解します。これらの水晶は、特に時間管理のために設計されており、温度ドリフトが非常に小さくなっています。RTCチップを使用する場合は、これらのいずれかが必要です。
ATmegaのヒューズを8 MHz RCオシレーターで動作するように設定します。これにより、millis()
機能が恐ろしく不正確になり、XTAL1ピンとXTAL2ピンも解放されます。
時計のクリスタルをTOSC1およびTOSC2ピンに接続します。これらはXTAL1およびXTAL2と同じピンです(328Pでは9および10)。異なる名前は、異なる機能を意味するために使用されます。
タイマー/カウンター2を非同期操作、通常のカウントモード、プリスケーラーを128に設定し、タイマーオーバーフロー割り込みを有効にします。
これで、1秒に1回という非常に安定した速度でTIMER2_OVF割り込みが発生します。ISRで時計の表示を1秒進めるだけです。割り込みの間に、MCUを非常に深いスリープ(省電力スリープモード:タイマー/カウンター2以外は何も実行しない)にして、数個のAAセルで何年も実行できます。ディスプレイが電力を大量に消費する場合を除き、明らかに。
私はこれを24時間片手で壁掛け時計を作るために丁度やりました。このリンクは、フランス語の元のドキュメントの英語の翻訳を指すようになりました。
クォーツのキャリブレーションを行わない場合、通常は週に数秒の大きなドリフトが予想されます。ドリフト率は、水晶をMCUに接続するトレースの浮遊容量に依存します。原則として、微調整された静電容量を追加することで除去できます。RTCで同じドリフトの問題が発生することに注意してください。
この種の精度に満足しているなら、それで生きて幸せになりましょう。ただし、ドリフトを測定する場合は、ドリフトが非常に安定していることに気付くでしょう。その後、ソフトウェアで簡単に補正し、年間数秒の精度を達成できます。
ドリフトを修正するアルゴリズムは非常に簡単です。測定されたドリフトから、割り込み間の正確な遅延を計算します。これは10 9 ナノ秒に非常に近いはずです。
#define ONE_SECOND 1000000000 // in nanoseconds
#define ONE_INTERRUPT 999993482 // for example
ISR(TIMER2_OVF_vect)
{
static uint32_t unaccounted_time;
unaccounted_time += ONE_INTERRUPT;
while (unaccounted_time >= ONE_SECOND) {
advance_display_by_one_second();
unaccounted_time -= ONE_SECOND;
}
}
上記の例では、クォーツの速度がわずかに速すぎるため、ソフトウェアは数日ごとにティックを「逃す」ことで補正します。クォーツが遅すぎる場合は、代わりに同じコードが数日に1回ダブルティックします。
この種のキャリブレーションはRTCに対しても実行できますが、RTCは時間を自然に算術演算に役立たない内訳形式で報告するため、大幅に複雑になります。
指定した共振器の安定性は0.3%で、水晶または水晶発振器(Ricardoによると)は50ppmです。何倍も安定しています。共振器の温度ドリフトは恐ろしいことは言うまでもありません。日光で加熱すると変化します。したがって、長時間にわたって時間を維持するために共振器を使用しないでください。
したがって、水晶または水晶発振器のいずれかを使用すると、必要なものが得られます。ATmegaでそれを使用してヒューズをそれぞれ設定するか、RTCに接続されたヒューズを使用します。
リアルタイムクロック(DSDS1307など)のような追加のハードウェアを使用したくない場合は、未使用の割り込みをすべて無効にすることで、タイミングの精度を大幅に向上させることができます。デフォルトでは、Arduinoスケッチにはさまざまな割り込みルーチンが有効になっており、実際のスケッチには使用されないことがよくあります。あなたがそれを試して無効にするためにそれをせずに行うことができるかどうかを調べる最も簡単な方法noInterrupts();
millis()
あなたが他の問題を持っている場合にはあなたがそれらにサービスを提供し、一度に複数のミリ秒を過ごすために管理していない限り、... 4.無効割り込みnoInterrupts()
防ぐことができますmillis()
すべての時間を保つことからを!
私は、Arduinoの精神の多くが質素で、時には問題を突き抜けていることを理解しています。私は職場でArduinoを使用しています(現在はRAMが10倍、クロック速度が10倍であるため、chipKIT)。可能な限り高速で動作するために「周辺機能」が必要です。
プロジェクトの1つでsparkfunリアルタイムクロックを使用していますが、非常に満足しています。また、「Dead on」バリアントもあります。