コメントがあればこちらから
sorry. japanese only.
AVR(ATtiny2313)とRTC(DS3234)を使ったLCD時計
秋月でMAXIMのTCXO RTC(DS3234S SPIインターフェイス)が扱われていたので,液晶表示の
シンプルで高精度な時計(温度計つき)ユニットを作ってみた。
ついでに巨大な16セグメントLEDが捨て値で売られていたので,置き時計用にLED表示器も
作って,時計ユニットに接続できるようにしてみた。
時計ユニット本体はキャラクタLCDよりひと回り大きい程度
巨大16セグメントLED表示器で据置き用時計にもなる
全体のブロック図
●主な機能や特長について
(1) 高精度が謳い文句のTCXO RTC(DS3234)を使用しているが,やはり個体ごと環境ごとで
微調整は必要なので,RTCのAgingOffset機能を利用して進遅微調整できるようにした。
(2) 特別な機器がなくとも時報などで,微調整が行えるように正分アジャストで2秒以上
の進み遅れ調整がなされた場合に,AgingOffsetを微調整して徐々に精度が高まるよう
な時計とした。
(3) 16x2キャラクタLCD表示器(SC1602Bなど)より,1回り程度の大きい程度コンパクトな
サイズにした(基板寸法100mmx32mm コネクタ突起部含まず)。
(4) コイン電池によるバックアップで,間抜けな電力会社の自分勝手な都合による停電が
あっても安心。節電ということで使わないとき以外は,バックアップのままでもいいか
もしれないw
(5) 空いているI/Oを用いて,時刻情報を出力し外部の表示器に時刻を表示することも可能。
(6) RTCの温度センサを読み取って表示するが,その際にオフセットを指定して実際の気温
近い温度値を表示させることもできるようになっている。
(7) LCD,RTC,シリアルI/OといくばくかのI/Oを持っているので,シンプルでコンパクトな
開発プラットフォームにもなる。
(8) 都合で使用した手持ちの部品とネジ以外は,秋月で調達ができると思う。
RTCを使ったAVR時計の回路図
回路上の特徴としては、
(1) LDOレギュレータにより時計精度に影響のある電源電圧を安定化すると
ともにバックアップ時にも計時誤差が小さくなるであろうことを期待して,
RTCのバックアップ電源電圧に近い電源電圧である3.3V電源をVccとしている。
(2) キャラクタLCDに5V電圧の汎用品が使えることを期待して,コントラスト
調整電圧Vlcdには,RS-232Cインターフェイス用のICのチャージポンプ負電圧
源を利用して広範囲の調整を可能なようにしている。(秋月SC1602などが使用
できる。ほかの同様のLCDでも使えるかもしれない。手持ちのものはすべて
使えたが,使えたらラッキー位な寛容な気持ちでいて欲しい)
(3) MCUには安価なATtiny2313を使用して,キャラクタLCD,最大4個のLED出力,
最大4個のボタン入力にも可能なように時分割で4ビットバスをマルチプレク
シングして使用する。(LEDはVfが1.8V〜2.5Vのもの限定,白や青などでVfが
3V以上の高いものがあるが,それらは殆ど光らないと思う)
(4) 外部I/OとしてUARTを使用したRS-232Cの他に,10pinコネクタ(CN106)で,
電源のほか,TCXO調整のためのPPS入力,汎用IO(PA0,1),RTCの32768Hz出力
を出すようにした。
(5) RS-232Cインターフェイスに手持ちのMAX3243を使用しているが,負電圧チャー
ジポンプとRXとTXのみのレベル変換にしか使用していないので,3.3V対応の
ものであれば,接続は回路図のものとは変わるが,ADM3202などで代用は可能
であると思う。
(6) キャラクタLCD表示器で1番ピン2番ピンの電源極性のみが正反対のものがある
ため,ジャンパピンを入れ替えれば対応できるようにした。
(7) 今回掲示した記事以外にも,RTCとAVRを使った応用回路を構成できるように
SW入力4接点,LED出力4接点,外部接続3接点+RS-232C入出力の構成まで対応
できるようにしてある。
(8) ISP用のコネクタを手持ちの機材の都合でByteblasterMV準拠のものにしている。
(9) プログラムを変更すれば,MAXIMの同じTCXO RTCであるDS3231,DS3232を搭載
することも可能となっている(ソフトSPIを行っている部分をI2Cに変更する
必要あり。制御レジスタなどはほぼコンパチなのでいけるはず)
●製作物
1号機の外観(写真のLCDは20x4行構成のもの)
こんな感じで組み上げた。1号機は手作り自家製エッチング基板,2号機は基板をP板業者に
発注してかっこよく作ってみた。
当初はRS-232C入力でGPSの時刻を入力して,時刻の設定をしようかと考えていたが,あまり
一般的でないし面倒だ。また,きちんとTCXOの微調整設定をしてやれば,高精度RTCの名に
恥じないくらいの精度で,時刻設定の必要性も殆どない上に,MCUのメモリもきついので割愛した。
お陰で現在は,RS-232Cは未使用であるものの,使おうとした痕跡がソースに残っているw
その代わりに,正確なPPSを用意できればそれを使用してTCXOの設定を追い込める機能を
入れてある(後述)。また特別な機器はなくとも,簡易的な時刻設定機能である正分アジャスト
を使用して調整するたびに精度を追い込めるようにもなっている。
2号機の外観&外部表示器にマウント
基板レイアウトをちょっと工夫して,秋月で扱ってる定番キャラクタLCD(SC1602Bシリーズ)
を若干のスペーサーとピンヘッダコネクタで直接基板上にマウントできるようにした。
割りとコンパクトにできたのではないかと自画自賛している(笑)
時計をケースに組み込んで稼動した様子
時計用の基板を作る際にあわせて,巨大16セグメントLEDを使った表示器用の基板も作成
したので,あわせて上図のような巨大LED表示式時計にすることも可能である。
表示器としては,高さが60mm幅35mmの数字で1桁を表示するので,かなり視認性が高い。
表示の制御方式は125Hzのフレームレートでのダイナミック駆動式である。
簡単ながらソフトPWM制御により15段階の明るさ調整ができるようになっている。
上の写真では最低の輝度で撮影。
●操作について
ケチって2ボタンのみ実装したため,少々癖のある操作感となっている。
(ボタンは後2つ簡単に追加できるので,やる気のある方はプログラムを改善して
自分にあった操作感を実現してみて欲しい)
以下では写真の左側の上の白いボタンスイッチをBボタン,下の黒いボタン
スイッチをAボタンと呼ぶことにする。
まずは電源投入時に表示される通常表示から。
初期時は通常表示モード(Mode=0)
○B |hh:mm:ss CCYY wk| hh:mm:ssは24時間制のRTC時刻,CCYYは西暦年,wkは曜日を表示する
○A |---9.9゚C MM-DD | ---9.9゚CはRTC温度(オフセット表示:後述),MM-DD月日を表示する
通常表示時にBを押下でAging表示モード(Mode=1)
◎B |hh:mm:ss ---9 | hh:mm:ssは24時間制のRTC時刻,---9はAgingOffset値を表示する
○A |---9.9゚C XXXX | XXXXはPPSとSQWの位相差カウンタを16進数で表示する。
→ そのままBを解放すると通常表示モードに戻る
●B |hh:mm:ss ---9 | Bを押したままAをクリックすると正分アジャスト
◎A |---9.9゚C XXXX | 0-29秒なら秒を0に戻し,30-59秒なら分を1進めて秒を0にする。
正分アジャスト時に秒が2秒以上進んでいたらAgingOffset値を+1(遅れ方向に調整)
逆に秒が2秒以上遅れていたらAgingを-1(進み方向に調整)
簡単に言うと正分アジャストで2秒以上の進み遅れを調整すると,そのたびに微調整値も
徐々に修正されるので,精度が段々よくなるということになる。
通常表示時にA長押(2秒以上)で日付時刻設定モード(Mode=2)に遷移
v v v v v v Vまたは^の示す位置はカーソル移動項目
○B |hh:mm:ss CCYY wk| カーソルが表示される
◎A |---9.9゚C MM-DD >| Aクリックのたびにss→mm→hh→DD→MM
^ ^ ^ →YY→CC→wk→'>'にカーソル移動
→ Aをクリック毎にカーソル移動,Bクリックで該当項目のインクリメント
'>'にカーソル時にBクリックで微調整モードに遷移
Aを押したままBクリックで通常表示時に戻る
日付時刻設定の'>'カーソル時にBクリックで微調整モード(Mode=3)に遷移
vv
○B |hh:mm:ss ---9 +-| 1行目の+-でAgingOffset値の変更
◎A |+--9.9゚C XXXX <| 2行目の+-で表示温度オフセット温度値の変更
^^ ^ Aをクリックするたびに1行目'+'→'-'→2行目'+'→'-'→'<'
→ Aをクリック毎にカーソル移動,Bクリックで該当項目の増減
'<'にカーソル時にBクリックで日付時刻設定モードに遷移
Aを押したままBクリックで通常表示時に戻る
AgingOffset値と表示温度オフセット温度値について
AgingOffsetは-128〜127の範囲である。正の方向に変更するとクロック
が低くなり遅れ方向調整となる。逆に負の方向に変更するとクロックが
高くなる。
表示温度オフセット温度は,RTCの内蔵温度センサの温度と実際の雰囲気
温度との差異を調整する値で,RTCの内蔵温度センサの読取り値にこの
オフセットを加えた値を表示している。
表示温度オフセット温度は-8.0〜7.5℃の範囲で0.5℃単位で調整が可能。
デフォルト値は-1.0℃である。
RTCのSQWとリファレンスPPSの位相差カウンタ値(表示は16進数)について
この回路では,INT0にRTCからの1Hz矩形波を入力するようになっており,
時刻計時は,この立ち上がり入力を契機として行われている。
また予備入力としてINT1に基準となる1Hz(たとえばGPSのPPS出力※)の
信号入力を期待している。
(※5V系のPPS信号であれば,1kΩ程度の入力保護抵抗を介して接続すること)
INT1に正確な1Hzの立ち上がり入力が行われると, 前述のINT0割り込み
処理受付時の内部カウンタ(カウント周波数500kHz=2usの16ビットカウンタ)
値と,INT1割り込み処理受付時の内部カウンタ値の差を表示するように
なっており,これによりタイムインターバルによる偏差測定が可能と
なっている。
留意すべき点としては,本回路では,波形立ち上がりによる割込み駆動での
計測を行っているため,タイミングによっては大きく揺らぎ生じる場合がある。
そのため,ある程度以上の長い時間(目安としては1時間以上)で,観測を行い
平準化するなどして揺らぎをキャンセルした上で変化の値をとる必要がある。
その上でどの程度の偏差であるかを算出するには,内部カウンタが500kHz(2us)
の分解能であるので,以下の式で求めればよい。
偏差=2(us) x 位相差の変化 / 誤差の遷移時間(s) ppm で算出できる。
具体例としては,あるタイミングで表示された位相差が0x3200前後だったと
して(ここでは大雑把な数値としてとらえ揺らぎを無視することとする),その
10時間後に表示された位相差が0x3700前後に変化したとすると,その時の
TCXOの発振周波数偏差は,
→ 2 x (0x3700-0x3200) / 10x3600 = +0.071ppmとなる。
(この算出例では,1ヶ月あたり0.2秒進む程度の偏差となる)
まあ,ぶっちゃけて言えば,ある程度以上の長い時間では温度変化や電源変動なども
あるわけで,釈迦利器になって最大瞬間風速的に精度を求めても,それを維持する
ことができなければ意味がない。
実用的には正分アジャスト機能にあわせた微調整だけでも十分だったと思う。
所詮はSTM8S でやってたことをAVRでもやってみたかっただけの自己満足機能なわけw
●時計表示プログラムのソース
・ソースはアセンブり言語でフルスクラッチで作成した。
・アセンブラはWinAVRのGNUアセンブラを使用している。
・Fuseは,ATtiny2313の4MHz内蔵OSCのスロースタートで,2.7VBOD有効としている。
・表示器への表示のために,RTCから時刻を取得するタイミングで,PA0に時分情報を
BCD(RTCのレジスタ値をそのまま)形式で出力して,出力終了後にPA1に負パルスを
出力している。なおPA0は,38400bpsの8n1のソフト調歩同期シリアル出力である。
HEXファイルも同梱したプロジェクトファイル一式 を置いておきます。
(cygwin+WinAVR-20071221の環境下でmakeします)
-- core usage --
0 .text 0000079e 00000000 00000000 00000074 2**1
1 .bss 00000027 00800060 0000079e 00000812 2**0
2 .eeprom 00000037 00810000 00810000 00000812 2**0
●使用部品の一覧やコストについて
構成部品を並べてみた
注:ISP用と外部出力用の2x5ピンヘッダL型は除外して撮影した。
手持ち部材
基板単価 \890
MAX3243 \230
M2.6x8スペーサ&ねじ \72 (Dsubコネクタを固定するとともにCLCDを固定するねじ)
秋月で調達可能な部材
RTC(DS3234) \550
SC1602BS-B(14ピンヘッダ,レセプタ) \500
MCU(ATtiny2313) \100
コイン電池(CR2032) \50 (\200/1組4個)
コイン電池ホルダ \50
電圧レギュレータ(PQ033EZ) \25 (\100/1組4個)
DCジャック \25 (\100/1組4個)
タクトスイッチ \10 x 2
ICソケット(20pDIP) \10 (\100/1組10個)
半固定抵抗20K \20
チップトランジスタ
2SA1313(2SA1162) \5 (\200/1組40個)
チップ抵抗 (1608サイズ)
10k 大体\3(笑) (\500/リール2500個) 12
1k \1 (\500/リール2500個) 5
チップキャパシタ (1608サイズ)
1uF \20 (\200/1組100個) 10
Dsupコネクタ(9Pオス) \60
ジャンパ \4 x 2 (\100/1組25個)
2x2ジャンパピン \10 (2x10ピンヘッダ/\50)
オプション部品
2x5ピンヘッダL型 \25 (2x40/\100をカット)
SMD部品の一覧
全部で\2700を超える位か,基板とRTCだけで半分以上のコストを占める(笑)
●巨大16セグメントLED表示器について
こんな表示器で時刻を表示してみる
一応蛇足ながら,16セグメントLEDはAitendoで\49で売っていたものである。
多分秋月の\300の奴でも接続は全く同じなはずなので動くと思う。
巨大16セグメントLED表示器(2桁分)の回路図
表示器の概要
この巨大LED表示基板であるが,EagleCAD評価版の制限で100mmx80mmの基板までしか設計
できなかったので,2桁分を1枚の基板に実装して基板同士をコロン表示用LEDを搭載した
リンク用基板で接続して何桁でも拡張できるようにしてある。
桁を増やす場合にはモジュール式に繋いでいくわけである。各モジュールは,tiny2313の
UARTのTXとRXを数珠繋ぎに連接するようになっている。所謂ディージチェーンという方式。
多分実現することはないとは思うが,多桁表示時の伝播遅延をキャンセルするため,平行
して割り込み駆動ラインを走らせている(INT#)。これを使用して全桁分の表示データが行き
渡ったタイミングで一斉に表示を変えることにも対応している。
ついでに一応設計上は,PD3,PD4を使用して,同一基板でもLED表示器とコモンドライバを
増設することで,4桁までは容易に増設可能なようにしてある。
表示器の構成部品を並べてみた(2桁分)
表示器の使用部品の一覧やコストについて
2桁分1ユニットで大体\2600。2セットいるので\5200弱であった。こっちは約2/3が基板代...
何せLEDモジュールがジャンクだからコストの大きな部品が基板以外にないw
まあ,このサイズの基板だとサンハヤトの片面の感光基板で作ったとしても,複数作ら
なきゃいけないので,穴あけの手間を考えたらコスト的には十分折り合う。
蛇足ながら,発注した後で秋月の16セグLED用のドデカクロック用オプション基板がある
ことに気づいたけど,大量発注の秋月でさえ基板一枚が\500もする。その上7セグ動作のみ
であることを考えたらそれほど理不尽ではないということか。
手持ち部材
基板単価 約\1700(リンク用小基板2枚含む)
16セグLED(KA2311) \49 x 2
220x4抵抗アレー 約\10 x 14
秋月で調達可能な部材
MCU(ATtiny2313) \100
シフトレジスタ(NJU3711D) \80 x 2
ICソケット(20pDIP) \10 (\100/1組10個)
PNPトランジスタ(2SA950Y) \20 (\200/1組20個) 2個分
青LED(5mm) \80 (\400/1組10本) 2本分
カーボン抵抗(220オーム) 大体\2(\100/1組100本) 2本分
チップ抵抗 (1608サイズ)
10k 大体\1 (\500/リール2500個) 5個分
1k \1 (\500/リール2500個) 2個分
チップキャパシタ (1608サイズ)
1uF \2 (\200/1組100個) 3個分
2x5ピンヘッダ \50 (2x40/\100をカット) 4個分
2x5ピンソケット \40 x 4
オプション部品
1x10ピンソケット \40 x 4 (LEDモジュールを直付けするなら不要)
2x5ピンヘッダ \13 (2x40/\100をカット) 1個分 (ISP用のヘッダ)
M2.6x8スペーサ&ねじ 適宜
2x10のピンソケットでLEDモジュールを脱着可能としてある
ピンソケットでLED表示モジュールをマウントすることについて
今回は初物で,デバッグのために基板裏面をLEDモジュールが覆いつくすと手間が掛かる
ため,LEDモジュールはあえて直付けとはせずに,安易ではあるがピンソケットを使用して
脱着可能なようにした。
これは装着状態によっては,接触不良による点灯不良があるのでお勧めできない
コロン表示用LEDを搭載したリンク基板
接続したところ
LED表示モジュールについて
大型の異型多セグメントLEDモジュールではよくあることだが,各表示セグメントのサイズ
に合わせて,構成素子数が異なっている。そのため,電流制限抵抗はセグメントごとに適し
た値にする必要がある。
この表示器のLEDモジュールの個々のLED素子は,Ifが20mAであるが,各セグメントごとにLED
が単品だったり,直列だったり,それの並列だったりと一筋縄ではいかないため注意が必要
である。
また,16セグメントLEDの殆どの表示素子構成がダイオード2直列で構成されており,見かけの
Vfが3.5V以上となるため,Vccは5Vとした。
この回路では,個々の電流制限抵抗を抵抗アレーを使った合成抵抗により,素子ごとで均等に
なるようにしてあり,制限されたIfは10mA弱である。多少実装面積は食うが一律の抵抗アレー
で済むのが大きなメリット。
ちなみにこのLEDはIf=10mAで,1/4デューティのダイナミック駆動でも眩しい位なので,設置
場所によっては調光機能は必須となる。
万が一の制御不良で全桁全点灯となった場合に200mA程度の電流が流れることが想定できるので,
Icがそれ以上の定格の2SA950(Ic=800mA)をコモンドライバに使用した。
セグメントドライバには,シフトレジスタ兼用のNJU3711を2個使い16セグメント分を駆動する。
表示のうちDP(小数点)だけは,AVRのI/Oポートでドライブする。
コロン表示用にモジュールとは別のLEDをPA0,1を使ってドライブするようにした。
時計基板を装着するスペーサーを取り付けたところ
時計基板を取り付けたところ
とりあえず動作を確認してみる
LED側での時刻表示はこんな感じである
表示器を収める割り箸ケース(\100ショップで入手)
表示器をケースにねじ止めしたところ
フタを閉めて後ろから見たところ(バックライトつきLCDだと外から見えるw)
真っ暗闇での時刻表示状態
こんな感じ(コロンはぼんやりと点滅している)
↓やっつけではあるが動画にしてみた( http://www.youtube.com/watch?v=Ww6ppRZZF7w )
VIDEO
ニコ動にもほぼ同じ内容で字幕つきの紹介動画を掲載した。
気になる精度であるが,とりあえず72時間程度のエージングで初期調整した手元の時計は,
Aging offset値(+7)を設定して30日程経過したが,現在のところGPSのPPS基準で約+25ppb
(年で0.8秒程度の進み)の偏差を持っているようである。
蛇足ながら,同じシリーズのRTCであるDS3231をSTM8S-discoveryというマイコンボードに
乗せたバラックの時計を1年ほど前に作ったもの は,夏の暑い盛りにGPSから約1秒
遅れをピークに,徐々に遅れを取り戻してきつつあって,このままでいけば年間通しで
1秒以内の誤差で収まるような精度になりそうである(暑くなると僅かに遅れ気味,寒く
なると僅かに進み気味で,年間を通すとちょうどいい感じのアバウトさがあるw)。
以前,秋月で扱っていた高精度が謳い文句の12.8MHzのTCXOを使用して時計を作ったが,
回路の未熟もあってか,どう調整しても1日で数ppm振れまくって,安定した精度を維持
するのが難しかった。
結局ダイオードをセンサにしてセメント抵抗を発熱体に使ったインチキ恒温槽をTCXOの周
りにでっち上げて50-55℃に保って,やっと1ppmのブレに収めることはできたが...
手作りOCXOでもあるまいし,期待できない安定感を期待したバカらしさがそこにあったw
それに比べて,なんと手軽で高精度なのかと,改めて感心する次第である。
少々の調整の手間で,年に秒程度の誤差に収まるような時計が簡単に入手できるようになっ
た事は,時計製作マニアにとっては大変喜ばしい状況である。
コメントで初期状態無調整での精度はどれくらいか尋ねられたが,この記事で作った時計
のDS3234Sは確か+1ppmをかなり下回っていたように記憶しています。カタログスペック以上
に精度を求めるなら,自己責任で調整すればよいと思います。
このシリーズのRTCで謳っている,カタログスペック±2ppmは0〜40℃で2〜5.5Vの範囲内で
最悪±2ppmなので,その精度で十分ならば,無調整のままでもよいかとも思います。
ただ温度の急変にはかなり敏感で,この辺りは内部の温度補正が利いて安定するまでは,
ふらふら動きまくるので,短期精度はあまり期待してはいけません。
[ご注意]
・このページの記載事項については,一切無保証です。