PIC18F4550で時計を作ってみる
2017/03/19


16x2行の表示器での表示が出来たのと、その前に作ったタイマーを使って、時計を作ってみる。
せっかく3.3Vで動くのだから、しばらく動作させてみて、どのくらいの誤差というか精度で動くのか実験しようと思うのである。



まずは仕様で、いったいどんな時計が良いのだろうか?

1、表示

表示としては、普通は年月日時分秒とあり、年月日だけで10文字は使うし、時分秒でも10文字使う。
すると、今回の表示器は一行が16文字なので、一行で全ての表示は出来ない。

となると、どちらにしても二行使ってしまい、次のような表示になる。

YY/MM/DD
HH:MM:SS

それとも、年を省略して「MM/DD HH:MM:SS」とすると半角14文字となり、一行に全て収まる。
年を省略してしまえば、うるう年の計算をする必要も無くなるしな〜・・・・という感じである。
どちらにしようか・・・・どちらにしてもそう厄介な話ではないのである。

今回は年を省略し(2月は常に28日)MM/DD HH:MM:SS という14桁として、一行で表示することにした。


2、時刻合わせ。

これはけっこう真剣に考えないと、意外に厄介なのである。

通常の状態から、時刻合わせの状態へはどうやって遷移するか?
たとえばスイッチで切り替えるのが比較的容易だし確実である。

あと、数字を合わせるには、カウントアップするボタンと、ダウンするボタン、これでOKというボタンが必要である。

test_pgm008
ということで、前回のLCDを動かしたときの回路に、16進のスイッチ(300円くらい)が一つと、普通のタクトスイッチ(10円くらい)を三つを追加した回路になった。

図には入っていないが、全てのスイッチの回路は5Kの抵抗でプルアップしてある。

全てをRBのポートで済ませたかったのだが、RB0とRB1はSDAとSCLで使用しており、RB6とRB7はPICKit-3との接続で使用している。

また、RCポートは、RC0とRC1が時計用水晶振動子のために確保されており、もし、今回の実験の精度が悪い場合は時計用水晶振動子もテストしたいので空けておく。

また、RC4とRC5は、次の実験でUSBを繋ぎたいので、これまた使用出来ない。

ということで、RB2〜RB5を16進のスイッチで、RD0〜RD2の3個をタクトスイッチで使用する。



さて、どんなシステム設計にするのが良いのだろうか?

時計の次にもいくつかの機能を追加していきたいので、状態遷移を中心にしたイベントドリブン型のシステムを作っていく。

オペレーションとしては、以下のような想定である。

1、16進のスイッチをF以外の状態からFにすると、時計合わせになる。
※時計は表示とは別にカウントを続行している。
2、月日時分の順番で設定する。
※秒は必ず0とする。
3、設定はアップとダウンのスイッチで行う。
4、設定が終了するとOKのスイッチを押し、次の設定に移行する。
5、全ての設定を行って16進のスイッチをF以外にしたときに設定した時間を反映する。
※途中でFから外れると何も変更されない。
※単純にスイッチを回してFにしても、分の設定でOKのスイッチを押さなければ何も起こらない。

上記のような機能とすると、具体的な状態遷移は以下のようになりそうである。

状態1、16進スイッチがF以外のとき:通常の動作。
状態2、16進スイッチがFになったとき:時計合わせ状態:月の表示が点滅。
※アップ又はダウンのスイッチが押されて、月の情報が変化。
状態3、OKのスイッチが押されて月が確定し、日の表示が点滅。
※アップ又はダウンのスイッチが押されて、日の情報が変化。
状態4、OKのスイッチが押されて日が確定し、時の表示が点滅。
※アップ又はダウンのスイッチが押されて、時の情報が変化。
状態5、OKのスイッチが押されて時が確定し、分の表示が点滅。
※アップ又はダウンのスイッチが押されて、分の情報が変化。
状態6、OKのスイッチが押されて分が確定。

※どの状態の場合でも16進スイッチがFから外れる場合があり、状態6以外の場合は全てキャンセルとして変更なし。

※こういうマン・マシン・インターフェイス(人間が操作する部分)のプログラムは、どんなシステムでも一番プログラムがメンドクサイ部分なのである。
実際の操作は上記程度のものでも、電源を入れてすぐにダウンのボタンを押されたら、月ならば12になるべきだし、時なら23時になるべきだし、分なら59になるべきだし、日は1月なら31日に、2月なら28日の方が良いとか・・・・・もうたいへんメンドクサイのである。

まぁ、売り物ではないので、適当なところで手を打つのである。



ここまで考えて、LCDの実験をやったプログラムにタイマーを動作させたプログラムを追加して動かしてみる。

するとナント!!、タイマーが動かないのである。
これはいったいどうしたものであろうか?

動かないというのは、具体的にはタイマーの割り込みが発生しなくなってしまうのである。

調べると、どうやらI2Cの初期設定をすると、タイマーが停止するようである。
そこで、タイマーの設定のパラメータでアヤシイものを探すと、Interrupt Priority Enable bitというものがある。
これはプライオリティ(優先的に後先を使う)とういうようなものらしい。

試しにそれを「使用しない」とすると、あら不思議、割り込みが動くのである。


良かった、良かったと思っていたが、それでも割り込みのプログラムで時間計測を入れ、表示のプログラムを作って動かしてみると、なんだか表示の動きが変なのである。
そして、どうも原因がよく解らない。

よくは解らないのだが、なんとなくというか、ウスウス私は気になっていることがあったのである。
それは、割り込みを使うと必ず発生する、処理のバッティングなのである。

たとえば、I2Cでデータを送信している最中に割り込みが発生した場合にどうなるのか?ということなのである。

通常の場合では、「割り込みが起こり、通常の処理を一時中断して割り込みの処理を行い、その処理が終了したら、通常の処理を続行する」ということになり、通常の処理が若干遅くなったということになるのである。
しかし、通常の処理が通信のようにタイミングが重要な場合には重大な問題になる場合があるのである。

さて、実際はどれくらいI2Cの通信と割り込みの処理が重なるものなのだろうか?

I2C通信がどのくらいの頻度でどのくらいの時間を消費しているのか調べると、400mm秒毎に6mm秒使用している。
時間の割合としては1.5%である。

この400mm秒というのは、私が勝手に設定した「表示をこの間隔で最新のものに変更する」というもので、目のちらつきとか、表示の遅れが気にならない程度に設定したものである。
6mm秒というのは計測したものでI2C通信で時分秒のデータを送信している時間である。

タイマーは20mm秒毎に割り込みをかけており、それとの関係はどうなるのだろうか?

タイマーの時間間隔がもし6mm秒より少ないと、ずっとI2C通信中にタイマー割り込みが入るということになる。
もし、タイマー割り込みが12mm秒なら、二回に一回は当たるということになる。
ということで、20mm秒の割り込みは3.33回に一回もの割合でI2C通信に当たるということになる。 時間にすれば3.33*400->1.33秒に一回ということである。
※本当にこんな計算になるのだろうか?

ということで、どうやら思ったより多くI2Cの通信中にタイマー割り込みが発生するようなので、割り込みのルーチンに入るとすぐに I2C_Master_Wait();という、I2Cの通信が実行中ならwaitしろという関数を追加した。
すると、どうやら図星だったようで、なんとかうまく動いたのである。


test_pgm009
これが動作中の時計で、左下にあるのがPIC18F4550と16進のスイッチと3個のタクトスイッチ。

電波時計に時間を合わせて、誤差の測定中である。



さて、実際はどのくらいの精度があるものなのだろうか?

まず、水晶振動子の精度は通常のもので10の-4〜-5乗のオーダーらしい。
つまり1/10000〜1/100000ということで、一日は86400秒なので、一日に8.6秒〜0.86秒の狂いが生じるということになる。

そして、PICのプログラムを作っていると、そもそも原理的に遅れる方向に誤差が出ると思うのである。

まず、タイマーが正確に20mm秒だったとしても、時間が来ると以下の処理を行うのである。

1、割り込みベクトルへのジャンプ。
2、タイマー1での割り込みか判断する。
3、タイマー1での割り込みフラグをクリアー
4、タイマーカウンターの上位バイトへ値をセット
5、タイマーカウンターの下位バイトへ値をセット

これから次の時間計測が始まるので、これら5つの作業が20mm秒毎に発生しているわけである。
一つ一つはごく短時間なのだろうが、20mm秒ということは、i秒に5回発生しており、1日には43万回も発生するのである。

実際に測ってみると、だいたい6時間で3秒弱の遅れが出るようである。
一日に換算すると12秒弱ということで、これを多いと見るか少ないと見るかは議論のあるところだろう。

6時間で3秒ほど遅れるということは、3/21600ずれるということで、20mm秒のカウンター30000をその割合で計算すると約4となる。
カウンターを4増やせば誤差が相当修正されるはずなのである。

結果、6時間くらいなら目で見てずれていることがすぐに分かるような誤差は無くなったようなのである。
あとは数日間動かしてずれを見ることになる。


HOME