2014-08-11

2013-08-29 新作「無線LAN対応NTP時計」はこちら

更新履歴

NTP時計

概要

AVRマイコンATMEGA328PとATTINY2313、イーサネットコントローラENC28J60を使用した、大型デジタル床置き時計です。

ヤフオクで購入した、大型青色LEDを搭載した電波時計が、あまりにも不甲斐ないのです。

そこで、7セグメントLEDだけ再利用して、ネットワーク(NTPサーバ)から時刻を取得する、正確な時計を作ってみました。

制作

分解

中国製です。

ふたを開けたところ。

LED表示基板

7セグメントLEDを外して、基板に配置しました。

年月日時分秒を表示するための基板を5つに分けます。

制御用マイコンはATTINY2313を使用します。

回路図(PDF)

基板図(PDF)

時計制御基板

マイコンはATMEGA328P、イーサネットコントローラはENC28J60を使用します。

回路図(PDF)

基板図(PDF)

組み立て

木製(MDF板)の土台に配置します。

時計制御基板を土台の背面に取り付けます。

LED表示基板と配線します。

ATMEGA328Pのから各表示基板へ

ATTINY2313(表示基板)のSPI入力部分

前面の様子。

アクリル板のフロントパネルを取り付けて完成です。

ファームウェア

ntpclock-20140630.zip

時計制御基板(ATMEGA328P)用と、LED表示制御基板(ATTINY2313)用に分かれています。さらに、LED表示制御基板は、年、月日、時、分、秒の5種類あります。

ntpclock.hex 時計制御基板(ATMEGA328P)用 インターネット接続し、時刻を取得する。 また、各表示基板に表示すべき数字情報を送信する。
clock_led_year.hex LED表示制御基板(ATTINY2313)用その1 「年」を表示する。
clock_led_day.hex LED表示制御基板(ATTINY2313)用その2 「月日」を表示する。
clock_led_hour.hex LED表示制御基板(ATTINY2313)用その3 「時」を表示する。
clock_led_min.hex LED表示制御基板(ATTINY2313)用その4 「分」を表示する。
clock_led_sec.hex LED表示制御基板(ATTINY2313)用その5 「秒」を表示する。

ATMEGA328P

ファームウェアntpclock.hexを書き込みます。ヒューズビットは、Low=0xe6、High=0xd9、Ext=0xffを設定します。

クロック周波数は19.6608MHzです。外付けの水晶発振子を使用します。

ATTINY2313

ファームウェアは、各エレメント毎に、clock_led_*.hexを書き込みます。ヒューズビットは、Low=0xe4を設定します。

クロック周波数は8MHzです。チップ内蔵のオシレータを利用します。

動作の仕組み

ブロック図

blockdiagram

ATMEGA328PとENC28J60とは、マイコン搭載のSPI機能で通信します。ATMEGA328Pと各ATTINY2313とは、ソフトウェア制御によるSPIで通信します。

時計制御回路の動作

  1. 電源ON
  2. タイマの初期化
  3. I/Oポートの初期化
  4. イーサネットコントローラの初期化
  5. DHCPでIPアドレスを取得
  6. DNSでNTPサーバ(ntp.nict.jp)のアドレスを取得
  7. NTPサーバにクエリパケットを送信
  8. 表示を更新

1時間に2回(毎時29分30秒と59分30秒)時刻の更新をします。

ATMEGA328Pは、プログラムメモリが32kB、データ用SRAMが2kBしかありませんので、TCP/IPの全機能を実装するには小さすぎます。以下のプロトコルに限定して実装しました。データ通信はUDPのみで、TCPには対応していません。また、パケットサイズは、イーサネットの規定では最大1518バイトですが、本機では、最大384バイトに制限しています。

MACアドレスは、本来、世界にただ一つになるように設定する必要がありますが、同一LAN内で重複しなければいいと考えて、とりあえずFE:FF:FF:00:00:01を設定しています。この装置を同一LAN内に複数設置する場合は、MACアドレスを個別に設定する必要があります。本機はEEPROM等を搭載しておらず、ATMEGA328Pのファームウェアに定数で書き込んでありますので、変更するには再コンパイルが必要です。

個人使用のためのMACアドレスの割り当て方

通信内容

パケットキャプチャ(Wireshark)で通信内容を表示させてみました。

カレンダー計算

NTPサーバから送られてくるデータは、1900年1月1日(UTC)からの積算秒数で表されます。これをユリウス通日に変換し、タイムゾーン値を加算した後、グレゴリオ暦に変換します。

※ 参考:「プログラマのためのSQL 第4版」 第38章:ユリウス日付


void convert_cjd_to_ymd(unsigned long j, int *year, int *month, int *day)
{
int y, m, d;
y = (j * 4 + 128179) / 146097;
d = (j * 4 - y * 146097 + 128179) / 4 * 4 + 3;
j = d / 1461;
d = (d - j * 1461) / 4 * 5 + 2;
m = d / 153;
d = (d - m * 153) / 5 + 1;
y = (y - 48) * 100 + j;
if (m < 10) {
m += 3;
} else {
m -= 9;
y++;
}
*year = y;
*month = m;
*day = d;
}

表示データ送信プロトコル

ATMEGA328PからATTINY2313へ送信するデータのプロトコルを説明します。

ATMEGA328PのPORT.D.0がクロック、PORT.D.1がデータです。

表示する数字の桁位置と文字を1バイトのデータで送信します。

spi

クロックの推奨周波数は100kHzです。速すぎると、ATTINY2313側で受信できません。遅すぎると、タイムアウトして、これも受信できません。タイムアウトさせないための最低周波数は1kHzです。

ビット 7 6 5 4 3 2 1 0
内容 桁位置 数字

桁位置は0~13、数字は0~9です。

桁位置

0 秒の1の位
1 秒の10の位
2 分の1の位
3 分の10の位
4 時の1の位
5 時の10の位
6 日の1の位
7 日の10の位
8 月の1の位
9 月の10の位
10 年の1の位
11 年の10の位
12 年の100の位
13 年の1000の位

各ATTINY2313は、自分が表示すべき桁位置のデータが送られてきたら数字を更新して、それ以外のデータは無視します。

設計情報

電圧

安定化された5VのスイッチングACアダプタを使用します。

LED表示回路は5Vで動作します。

ATMEGA328PとENC28J60は3.3Vですが、手持ち部品の中に、適当な3.3Vのレギュレータが無かったので、ダイオード2本を直列につないで3.4V程度まで降下させています。

電流

電源投入直後の数秒間は770mA程度流れます。NTPサーバから時刻の取得が成功し、平常動作になると670mAくらいで安定します。ACアダプタは1A以上のものを使用します。

電解コンデンサ

ENC28J60のデータシートにはVCAP端子に低ESRなコンデンサを使うよう書かれていましたので、三洋OS-CONを使用しました。実験時には、安価な汎用品を使用しましたが、それでも正常に動いていたようですので、あまり気にしなくてもいいのかもしれません。