昴くんからストップウォッチが欲しいとの依頼を受け、PIC12LF1822 というマイクロコントローラを使って高精度ストップウォッチを作りました。その製作でつまづいた点、工夫した点など備忘録にメモを残します。
まずは仕様決めです。
できるだけ小さいストップウォッチがよいと注文されているので、バッテリーはコイン電池CR2032(3V)としました。
1.6V~3.6Vの低電圧で駆動できる12LF1822を選択。4MHz駆動時消費電流は0.5mA。
表示器は3Vで駆動できる液晶にします。AQM0802の消費電流1mA。
コイン電池ではLED(20mA)を長時間表示できないので8セグメントLEDは却下。
ちなみにコイン電池の容量は220mAh。定格動作は0.2mAだそうで少し無理させます。
液晶8桁なので、59:59.00=59分59秒99まで、100分の1秒まで測定表示。
スイッチのチャタリング対策でCR回路を組んでいるので(C=1μF、R=10kΩ)、押すときも離すときも1ミリ秒の遅れあり。
PIC12LF1822 は 8 pin で、うち 2 pin は電源とグランドなので実質使えるのは 6 pin。
表示に使う液晶とはI2Cで接続、SCL線、SDA線の2本。
32768Hzの水晶発振器を付けるために2本。
残り2本のうち1本はストップウォッチのスタート/ストップ用。
もう1本はリセット用としました。ストップウォッチとしては最低限の機能です。
水晶発振器を部品箱から漁りますが、32768Hzのものがなかなか見つかりません。最終的には2つだけ見つかりました。
PICの駆動クロックも32768Hzにすればかなり低消費電力にできるので最初検討しましたが、I2C通信が最低100kHz必要です。I2C用のボージェネレータにクロックを供給するには4MHzで本体を駆動する必要があります。
本体を4MHzの内部オシレータで駆動し、16bitタイマーであるタイマー1モジュールを外部オシレータである水晶で32768Hz駆動することにしました。
タイマー1はゲート機能が付いていてストップウォッチを作るにはうってつけです。ゲート機能というのは、タイマーを動かしたり止めたりする制御をいろいろな外部イベントをトリガにできる機能です。例えば、ボタンを押している間だけクロック数を数える(ストップウォッチ)、GPSから拾った正確な1秒間にパルスを数える(周波数測定)、などに使えます。
今回使ったのはタイマー1ゲート機能のうちシングルパルスモードというもので、入力がOff→On→OffとなったときOnの間だけタイマー1を1回だけ(=シングルパルス)動作させることができます。ボタンを押して、離したときに、押されていた時間を水晶発振器からのパルスを何回受け取ったかカウントすることによって測ります。タイマー1は32768Hzでクロックカウントしていきますので、ちょうど2秒で0に戻ります(16bit最大値=65535なので65536をカウントした瞬間0になる、時計用水晶は65536/2=32768Hzで使いやすくなっている)。2秒を16回半分にした単位で時間が測れる分解能があるとも言えます(約10万分の3秒)。
気になるのは液晶との通信にかかる時間、液晶の表示時間、あたりです。
が、通信のほうは、100kHzの通信で1回に多くてもせいぜい20バイトのデータ量。
液晶側で1文字処理するのに数十マイクロ秒で、8文字表示するのに1ミリ秒あれば十分。2つ合わせても2ミリ秒は越えないと見積りました。
割り込みは全部で3つあり、16bitタイマーの繰り上がり(正確に2秒に1回)、ボタンOff=計測終了時、リセットボタン押下、です。ボタンONの計測開始では割り込みが発生しないのはゲート機能のおかげです。
躓いた点。
タイマー1ゲート用の pin を RA3ポート(元来のMCLR)に割り当て、MCLR をコンフィグレーションワード1で無効にしました。これで MCLR だった RA3 ポートはデジタルI/Oとしてスタート/ストップボタンになるはずでした。ところが何度やってみても想定通りの動きになりません。ゲート機能の使い方が間違っているのかとプログラムを何度も書き直しました。最後にわかったのは、コンフィグレーションワード2にあるLVPを0にすることでした。このLVP(Low Voltage Programming)はデフォルトで1になっており、低電圧用PICにはあれど普段使う電圧のPICでは無いもので、マニュアルよく読めばわかるのに、気が付くまで丸2日悩まされました。
ま、このマニュアルのページ自体を見落としてるわけで。
プログラム。前半。
割り込み関数
37行目:TMR1IFがタイマー1の繰り上がりフラグ。2秒に1回ここにくるので変数 sec を2加算。3600秒(=1時間)になったら0に戻す。
43行目:TMR1GIFがタイマー1ゲート計測完了フラグ。
49行目:IOCAF0がRA0ポートのフォーリングエッジ、インタラプト・オン・チェンジのフラグ。リセットスイッチが押されるとここにきて sec の0初期化。
プログラム。後半。
重要なのは80行目T1CONでタイマー1の設定をしているところと、89行目T1GCONでゲート設定をしているところ。
ゲートが有効になって計測を行っている最中は98行目T1GVALが1になるのでその間LCD(液晶)にリアルタイムの時間表示を行います。表示を行った後は、100m秒の休憩が入っているので液晶の表示更新は1秒に約10回です。計測前、計測終了時、リセットボタン後、は last 変数が1になっているので表示は1度だけ行われて低消費電力です。
PCBEで回路設計。
基板をケガキして回路を作成。
部品をはんだ付け。老眼で小さい部品は難しい。
スタート/ストップボタン取付前に初期表示の動作確認
FreeCADでケースをデザイン。久々のFreeCADで操作思い出しに少し手間取り。
3Dプリンタで格納ケースを印刷。2回ほど出力失敗。冬で気温が低いので細いサポート部分でレジンが固まらない。1層当たりの紫外線照射時間を1.5倍の15秒に設定しなおしてなんとか成功。
電源入れた直後。
測定中。
電源オンオフにトグルスイッチ、リセットにプッシュスイッチ(モーメンタリスイッチ)、スタート/ストップにオルタネイトスイッチ、と3種類のスイッチが使われているのも面白いです。










