ArduinoでNTPを使用する
ArduinoのNTP libraryを見つけたので動かしてみました。DateTime libraryを使って時刻の管理を行いたい場合に、Arduino起動時に時計を合わせるのが面倒だったのですが、NTPがあれば便利です。DateTime libraryの時計精度は日差数秒程度で、秋月電子さんで売っているRTC(リアルタイムクロックモジュール)と大差ないレベルの精度が得られるのですが、バッテリーバックアップが効かないため、電源ON/リセット時の時計合わせが煩雑でした(PCからシリアル通信で時間情報をもらうなどの操作が必要)。
ライブラリのインストール
IDEは最新の0016を使用しました。Ethernet libraryのバグ修正が行われているため、Ethernet Shieldをお持ちの方は0016への更新がおすすめです。
NTPライブラリは、cynshard / arduino-ntpを使用しました。リンクページのdownloadボタンを押すとzipファイルがダウンロードできます。ダウンロードしたファイルを、\IDEフォルダ\hardware\libraries\ntpにコピーします。
NTPライブラリのダウンロードページにも記載がありますが、NTPを使用するためにUDPライブラリの追加が必要です。Ethernet library配下のutilityフォルダにある、socket.cにはsendto()いうUDPデーターグラム送信関数が用意されているのですが、Ethernet libraryは現状TCPしかサポートしていません。
cynshard arduino-ntpは、bjoern / arduino_oscというライブラリの一部として公開されているUDPライブラリを使用します。ダウンロードページにある、arduino_osc-tip.zipというファイルをダウンロードし、その中にあるEthernetフォルダのファイルを、\IDEフォルダ\hardware\libraries\Ethernetにコピーします。
最後に、「UdpBytewise.h」の送受信バッファサイズを以下の値に変更します。(オリジナルは32です)
#define UDP_TX_PACKET_MAX_SIZE 64
#define UDP_RX_PACKET_MAX_SIZE 64
この変更を行わないとNTPが正しく動作しませんでした。
上記の作業が終わったら、ntp\examples\datetime-syncをビルドして動作確認ができます。
メールチェッカーへの応用
メールチェッカーに、DateTime libraryを使って現在時刻を表示できるようにしました。表示内容を以下に示します。
メールチェック・ログ(DEBUG_PRINT)のタイムスタンプが、以前はmillis()関数で取得した起動からの経過時だったのですが、こちらも日時を表示するようにしました。また、24hに1回NTPサーバーにアクセスして時刻同期を行います。
Ethernet libraryをIDE-0016に変更したため、TCPパケット送信用メンバー関数を、バグがあったclient.println()からclient.write()に変更しました。何回かこのブログにコメントをいただいた、hamayanさんのUnder Power 研究所でwrite()関数のことを知りました。ライブラリのドキュメントが更新されていないため、上記ブログを見ないとメンバー関数の追加に気がつかなかったかもしれません。情報ありがとうございました。
最新版のソースを以下に示します。
Arduinoスケッチのスタックサイズ
メールチェッカーに時刻表示の機能を追加した際に、「MM/DD hh:mm:ss」の形式に文字列の編集が必要となり、関数を追加したところ動作が不安定になってしまいました。
関数内で長さ4文字のStringオブジェクトを一つ定義し、このオブジェクトへの参照を別の関数に渡すようにしたのですが、この変更でスタックが溢れた可能性があります。上記のStringオブジェクトをグローバル変数にして関数間での受け渡しもやめたところ安定しました。
使用しているいるMCUはATmega328ですので、SRAMは2KBあります。ダイナミックデーターは1KBも使っていないと思うのですが、スタックにどれだけの領域が割り当てられているのが気になります。ローカル変数を一つなくすことで挙動が変わるため、ぎりぎりで動いている感じがします。
2009/6/8 追記
以下のコードを入れてheapの変化を追いかけると、どうもメモリーリークがあるようです。そのため、長時間動作させるとハング・リセットが発生します。
Ardunino Playground Available Memoryより
uint8_t * heapptr, * stackptr;
void check_mem() {
stackptr = (uint8_t *)malloc(4); // use stackptr temporarily
heapptr = stackptr; // save value of heap pointer
free(stackptr); // free up the memory again (sets stackptr to 0)
stackptr = (uint8_t *)(SP); // save value of stack pointer
}
6/6日版のコードはメールチェックあたり15byteのリークですが、6/7日版のコードはリークの量が不定でかつ増えてしまいました。時刻表示のために、Stringクラスを使用した文字列操作を多用しているのですが、このあたりが怪しそうです。
2009/6/9 追記:
メモリーリークの対策版を以下の記事で公開しました。
Arduino TexitStringライブラリのメモリーリーク
Arduinoメールチェッカー(その3)
| 固定リンク
「Arduino」カテゴリの記事
- ArduinoでXMLを解析する(2009.08.25)
- Arduino RSSリーダー(2009.09.06)
- Arduino 0017(2009.08.14)
- SPIデバイスの混在とSS信号の初期状態(2009.08.31)
- Arduino Nano 3.0 Get(2009.08.12)


コメント