前回作ったJJY時計(+ESP32)は、JJYの生のパルス検出信号をクロック信号とする方式だったが、やはり雑音などの影響でパルス検出が 途切れるたびに時計が狂うことになる。そこでマイコンで作る1秒周期タイマーの周期をJJYパルスと同期させて、これをクロック信号とする方式に改善した。

前回はマイコンにESP32を使ったが、Arduino相当のマイコン(ATmega328P)に変更した。消費電力はESP32に比べてだいぶん抑えられる。時刻表示に小さいLCDモジュールを使っていたが、手元にあった7セグメントLED表示器を使って時刻表示に変更した。年月日の表示はできなくなるが時計の機能としては十分だろう。

■ソフトウェア変更点
・1秒周期タイマーとしてTimer1を使う。JJYパルス入力によるGPIO割り込み処理にてTimer1をスタートさせることでJJYパルスに同期した1秒周期パルスができる。同期後はJJYパルスの入力が無くなっても1秒周期のクロックが得られることになる。ただし1秒周期の時間精度はマイコンのクロック発振子(今回はセラロックを使用)による。タイマーのスタート後もGPIO割り込み処理は続いており、割り込み発生の度にTimer1のカウンタをリセットするため、常にJJYパルスとの同期が繰り返される動作となる。なお、Timer1のカウンタレジスタ(TCNT1)にゼロを代入してカウンタをリセットしているので、その時点で改めて1秒のカウントを開始する動作となる。CTCモードを使っているので、カウンタリセット時にはタイマー割り込みは発生しないことに注意。

7セグメントLED表示器の制御もマイコンでやってみた。Arduino用のライブラリであるsevsegを使うと簡単にできた。4桁の表示を行うためのダイナミック表示にはTimer2による周期リフレッシュ処理が必要だった。2つのタイマが同時に割り込み処理動作をしていることになるが一応動いている。しかし、下の写真のように7セグメントLED表示器のためにたくさんのI/Oを接続する必要があり、ハードウェア構成としてスマートではない。そこで7セグメントLED表示器の制御はPICで行い、PICへはI2C通信で表示データを送ることにした。
DSC_0053

■ PICによる7セグメントLED表示器(I2Cスレーブ)の追加
PICはPIC16F1508を使う。20ピンパッケージで、使えるI/Oポート数が18ピンある。7セグメントLED表示器は手持ちのスペック不明品。各セグメントLEDのアノード(+極)側がコモン接続されている(アノードコモン)。セグメント当たりの消費電流は3mAくらいだった。PICのI/Oポートで流せる最大電流はデータシートによると20mAである。ダイナミック表示なので7セグメントを直接駆動できると判断した。
・回路図
7segLED_I2CDSC_0079_2



・PICのプログラム
4桁の数値を表示するために、タイマー(Timer1)割り込みを使って周期的に表示する桁を切り替える。切り替え周期の設定は、表示がちらつかない程度に決めた。一方、I2Cスレーブ受信処理にも割り込みを使う。(SSP割り込み)PIC16シリーズは複数の割り込みルーチンをハンドルできないとのことなので、割り込みルーチン(ISR)は一つとし、その中で割り込みフラグが立っていることを確認してその割り込みタスクを実行する。
表示データは1桁ずつArduino側から送信することにした。バイト値を4回送信する。時/分のデータなので60秒に一回の頻度で表示数値を更新する。もう一つ、5個目の送信データは時と分の区切り記号(コロン)の点灯用にした。1秒周期パルスに合わせてコロン表示を点滅するようにした。
I2Cスレーブ受信処理については参考にしたサイトのプログラムをコピーしてきたのでソースコードは別ファイルとなっているが、MPLAB Xのプロジェクトフォルダ内に置いておけば(ヘッダーファイルは同プロジェクトフォルダ下のIncludeフォルダに置く)、特にMakefileを書かなくてもボタン一発でコンパイル+リンクしてくれるので楽だ。

https://github.com/TakeshiKamimoto/7segLED_16F1508.X


■動作確認
JJYパルスの受信を始めてから正しくデコードが続けば大体3分ほどで時刻表示される。JJY受信モジュールの電源を切っても時刻表示は継続する。一晩置くと朝には10秒くらい遅れている。室温の変化にも影響を受けるだろう。マイコンの発振子に水晶を使えばもう少し狂わないかも。
JJY受信モジュールの電源を再び入れると自動的にデコードが始まってしばらくすれば正しい時刻に戻る。JJY受信モジュールの消費電力はかなり小さいようなので動作させっぱなしでも電池は長く持つと思われる。

FullSizeRender


https://github.com/TakeshiKamimoto/ArduinoJJY_7segLED_I2C.git

■仕上げ
時計専用にマイコンボードを作り直した。水晶発振子を使った。電源は5Vが要るが、単三電池3個で済ませたい。
クロック16MHzでは電池の電圧が減ると安定動作範囲から外れるので8MHzにした。消費電流も減るだろう。
8MHzクロックの設定が入っているブートローダーをATmega328に書き込んだ。クロック周波数が半分になるので、Timer1のカウント設定値も半分に変更して1秒周期動作させる。
FullSizeRender

FullSizeRender
シンプルな壁掛け時計ができた。




■参考にした情報