| ホーム |     私の電子工作作品集

202. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー III

[ 初公開日:2025年5月14日 ]

 本機は、前作 "201. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー II" の後継機で、前作に、電源バッテリー(18650 リチウムイオン電池)の電圧監視機能や、 タイマーによる時間監視とアラーム音での通知機能などを追加した、より高機能な万年カレンダーとなっています。

 当初は、前作のホームページ上でこれらの追加した機能などを紹介するつもりでいましたが、ハードウエアも新たに製作をし直したこともあって、本機のためのこのホームページを新たに作ることにしました。 したがって、本ページは前作のページと重複するような部分が多くありますが、本ページは本ページとしてご覧になってください。


 また、本機(万年カレンダー III)としては、ハードウエア、ソフトウエア共に、3月中にはそのほとんどが完成をしていたのですが、その後の気の緩みと公的な忙しさも少々あって、本ページの作成が大幅に遅れ、結果、ページの公開も遅くなってしまいました。

■ 回路図 ■

*注.  入力ポート RA0, RA1, RA4, RA5, RC4, RC5 は、内部プルアップ機能を ON にして使用。 また、SLEEP 中には それらのポート に状態変化割り込み機能を使用。
**注. リアルタイムクロックモジュールに "DS3231 For PI" を使用する場合には、SQW にプルアップ抵抗が必要。

 前作 "201. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー II" の回路図では、SSD1306 の VCC をコントロールする目的で挿入した、PIC のポート RC2 に接続されていた抵抗 3.3 KΩとトランジスタ 2SA1015Y が、 実は不要と分かったために本機では撤去をしました。

 そして空いたポート RC2 を、電源に使用しているリチウムイオン電池の、電圧チェック用の電圧計として使用できるように、本機ではアナログポートとして新たな機能を追加することにしました。 また、もともと空いていたポート RC4 には TIMER / TMSET スイッチを新設して、これもまた新たな機能を追加しました。

 また、上の回路図には I2C インタフェースのための SCL、SDA の両線に、それぞれプルアップ抵抗が挿入されていますが、実はこれらの抵抗も不要です。 後述のリアルタイムクロック( DS3231 )モジュールの 回路図 をご覧になれば分かるように、既にモジュール内に内蔵されていました。

 そのリアルタイムクロックモジュールとして、前作では "DS3231 For PI" を改造して使用していましたが、手持ちの残りがなくなったことと、"190. I2C IF モジュール + LCD(1602A) 表示時計" などで使用した、 従来型?の DS3231(RTC)モジュールを、最近、再び入手したのでそちらを使用しました。

| 回路図 (PerpetualCalendarIII.CE3) | ページトップ |

■ 本機で使用した各モジュール ■

 上回路図を見ていただくと分かるように、本機では3つのモジュール(黄色に塗りつぶしたもの)を使用しています。 これらのモジュールについて、私が感じた問題点やその他の注意点などを交えて、次に順に挙げていきます。
● 有機 EL ディスプレイ(OLED)( SSD1306 )モジュール

 初回に製作した "174. グラフィック液晶表示 万年カレンダー" では、作品名のように、横 128 x 縦 64 ドットのグラフィック液晶(SG12864A)モジュールを使用しましたが、本機では前作(万年カレンダー II)と同様に、 I2C 制御の有機 EL (OLED) モジュールの 128 x 64 グラフィックディスプレイを使用しました。 この有機 EL (OLED) モジュールには SSD1306 という制御チップが使われていて、前者の液晶(SG12864A)モジュールとは制御方法がまったく異なっています。

 このモジュールについては、私がアマゾンの中華モールなるものの存在を知ってから初期の 2020 年 8 月ごろに、複数種類の異なった OLED モジュールとともに購入したものの中の一つで、現在まで4年半以上眠らせたままになっていましたが、 前作(万年カレンダー II)に続いて2度目の使用になります。

 カタログ写真を見ていると、発光色としては、白色、青色、上2列黄色で下6列青色、の3種類のモジュールが存在するようですが、私は白色のモジュールを選択購入しました。


 外観は上写真のようなものですが、実際のサイズはかなり小さなもので 0.96 インチと商品説明には書かれており、写真左側の中央に位置する横長の長方形スクリーン部分のサイズは、実測で約 24.5 x 13.5 mm 程のものです。 実際に表示をさせてみても小さ過ぎる感が強く、実用的にはもっと大きな表示器を選択した方が良いと思います(しかし、価格もそれなりに高価になりますが ・・・)。 今回はこの OLED( SSD1306 )モジュールを使用することも、私にとっては目的の一つなのでこのまま製作を進めます。

 価格的には、安価に販売をしているアマゾン内のショップ等では、私が購入をした当時とあまり変わっていないようで、現在でも 500 円少々程度で購入が可能なようです。 ちなみに、"秋月電子" でも大きな差はなく 580 円(2024 年 11 月現在)となっています。 本機のようなお遊びとしての製作物では、お手頃価格?かと思います。

 また、このモジュールについても、Arduino や Raspberry Pi 用には各種のライブラリが存在しているようですが、本機のように PIC(特にアセンブラ言語)を使用した場合には、既成のライブラリの存在はまったく期待することはできません。 したがって、プログラム面においてはすべてを自分自身で作成(万年カレンダー II で自作のライブラリを作成済み)することになります。

● リアルタイムクロック( DS3231 )モジュール

 前作 "有機 EL ディスプレイ(OLED) 表示 万年カレンダー II" のクロック源には、左下の写真に示すような RTC モジュール "DS3231 For PI" を使用しましたが、上述もしたように、本機 "万年カレンダー III" では、右下の写真に示すような RTC モジュールを使用しました。

 これは私の手持ちにある RTC モジュールの都合なので、DS3231 であればどちらを使用しても良いのですが、本機ではプログラム内で SQW 信号を使用するために、左下写真の "DS3231 For PI" を使用する場合には、その信号線を外部に引き出すための改造と プルアップ抵抗が必要になります。 その場合の改造方法等を "200. 6桁ニキシー管時計 III(IN-17)" の、リアルタイムクロックモジュール( DS3231 For PI ) で詳述しているので、そちらを参考にしてください。

 一方、右下写真のモジュールを使用する場合には、下回路図に示すように、SQW 信号端子とそのプルアップ抵抗も内蔵されているので、その点での改造の必要はありませんが、他に、以降に述べるような改造を私は行いました。

RTC モジュール "DS3231 For PI" AT24C32 が搭載された DS3231 モジュール

 本項では、右側の RTC モジュールを本機で使用する上での改造方法、および注意点を述べますが、もちろんこれは絶対的なものではなく、本機ではこのようにした方が良い ― と私が勝手に判断したものなので、 他に良い方法があれば自己責任でもってそのようにすればよいと思います。

 改造点は4つあります。 まず1つ目はモジュールのバックアップ用のコイン型バッテリーについてですが、下回路図に示すように、充電池(二次電池) LIR2032 を使用することを想定した充電回路(ダイオード 1N4148 と抵抗 200Ω)が付属されているため、 そのままでは一次電池の CR2032 を使用することはできません。

 したがって CR2032 を使用する場合には、ダイオード 1N4148 か抵抗 200Ωのどちらかを取り除いて、充電電流が流れないようにする必要があります。 充電池の LIR2032 は高価なので、私は右下写真のように、抵抗 200Ωを取り外し て一次電池の CR2032 を使用することにしました。

 2つ目はモジュールの POWER インジケータ用 LED についてですが、本機を携帯機として使用するためには、極力余計な電流消費を抑えるようにしなければなりません。 また、本機ではこのようなインジケータは不要なため取り除くことにしました。 具体的には下回路図の左上に位置する LED と直列に接続の 抵抗 1KΩを取り外し ました。




黄色 1KΩ → と 200Ω↓の位置

ストレート型に取り替え


 本モジュールを購入すると、先の写真に示したように6ピンのL型ピンヘッダが取り付けられていますが、このモジュールを本機で使用するに当たっては、ストレート型のピンヘッダに取り替え る必要があります。 これが3つ目の改造です。 L型ピンヘッダのままだとプリント基板に取り付けたときに、プリント基板の平面に対してモジュール基板が垂直となって空間的に邪魔になるため、本機ではストレート型への交換は必須です。

 4つ目は、3つ目で交換した6ピンのストレート型ピンヘッダとは反対側の4ピン端子にも、4ピンのストレート型ピンヘッダを取り付けました。 このピンヘッダの取り付けは任意で必須ではありませんが、横長のモジュール基板を取り付けたときに、 片側だけでは不安定さを感じるため 反対側にもピンヘッダを取り付け、また、プリント基板側にもピンソケットが必要になりますが、それの配線は不要です。

 なお、上述の有機 EL (OLED) モジュールの取り付けにも同様のことが言えますが、前作(万年カレンダー II)と同様に、今回も取り敢えず片側だけで取り付けています。

● TP4056 リチウムイオン電池充電モジュール

 本機を使用するための電源として、商用AC電源からスイッチングACアダプタ等を介した方法を採るか、それ以外の電池等の電源とするかを決めるにあたって、本機を据え置き型として使用する場合には当然前者の方が良いのですが、 本機では携帯性を持たすために後者としました。 そして本機では、18650 リチウムイオン電池を採用することにしました。

 18650 リチウムイオン電池を使用する場合に、私は生セルタイプを使用することが多くなるため、電池を充電することはもちろんのこと、使用時に過放電(2.4V)、過電流から保護するように、安全面からも "TP4056 リチウムイオン電池充電モジュール" なるものが必須となります。

 "TP4056 リチウムイオン電池充電モジュール" として、私は以前には、Micro USB タイプ のモジュールを使用していましたが、最近になって、タイプ C の USB コネクタを使用したモジュールを入手する機会を得たので、 本機では後者のモジュールを使用しました。 前者で使用している USB コネクタは使用時の外力には弱く、容易にモジュール基板から剥がれてしまうことも予測されますが、後者のモジュールでは、USB コネクタがスルーホールでがっちりと取り付けられているため、 使用時に破損させてしまう心配がありません。

Micro USB タイプ充電モジュール タイプ C 充電モジュール

 タイプ C の USB コネクタを使用したモジュールは、アマゾン等を覗いてみると、Micro USB タイプのモジュールに比べて、かなり高価で販売されているショップを多く見かけますが、私は Temu で安価なショップを見つけたので購入をしてみました。 ちなみに、2024 年 6 月現在において 15 個セットで 445 円でした。 1個当たり 30 円弱ですが、アマゾン等で販売している他のショップでは、これほどの安価な充電モジュールを見かけたことはありません。 願わくは、不良品が混在していないように!と祈るばかりです。

 なお、"TP4056 リチウムイオン電池充電モジュール" の機能等については、"197. 18650 リチウムイオン電池充電器" の TP4056 リチウムイオン電池充電モジュール で詳述しているので、そちらを参照してください。 また、上写真のように両者を見比べてみると、購入ショップが異なるためかメーカーも恐らく異なっているらしく、両者では微妙に使用部品の配置や回路構成なども、若干ですが異なっている様子が窺えます。

| ページトップ |

■ ケース外観と内部の様子 ■

右側面側から見た様子 左側面側から見た様子
前側面側から見た様子 後側面側から見た様子

以下は外観6面写真です。

後側面
左側面 正面(上面) 右側面
前側面
背面(下面) 天地を逆にした写真

上蓋を開いてケース内部を見た様子 撮る角度を少し変えてもう1枚
カレンダー表示をしている様子 本機の電源の 18650 リチウムイオン電池を充電中の様子

| ページトップ |

■ 機能概要と使用法 ■

  • 本機では携帯使用をするために、電源には 18650 リチウムイオン電池を採用している。 そして、リアルタイムクロック(RTC)モジュールを搭載(バックアップ用のバッテリーも搭載)してあるため、リチウムイオン電池の消耗などで電源が切れたときはもちろん、 本機の不使用時の長時間の電源断にも、安定した時刻の継続が期待できる。

  • また、本機には 18650 リチウムイオン電池のための充電機能も内蔵しているので、USB コネクタから + 5 V 電源を供給すれば電池を充電することも可能である。 ただし、本機では充電中には本機の電源スイッチを切っておく必要があり、 充電しながらの連続使用はできない。

◎ 本機の起動時の動作
  • さて、本機の電源スイッチを ON にすると、"ピポッ" と開始ブザー音を出力後、プログラムのタイトル、およびバージョン番号などの表示とともに、有機 EL ディスプレイ(OLED) のデモ表示が数 10 秒間行われる。 (前作をご覧になった方にはお馴染みの、縁枠のドット移動表示デモを今回作にも取り入れた。)
    			 Perpetual Calendar
    			   (OLED Edition)
    			    Version x.xx
    			    by m.yamamoto
    

  • ただし、このデモ表示だけで約 20 秒ほどを要するため、DOWN スイッチと UP スイッチを同時に押しながら電源を投入 すると、デモ表示だけを省略 することができる。

  • ディスプレイ(OLED) のデモ表示が終了すると、PIC のフラッシュメモリ (High-Endurance) に記憶されている、各種の引き継ぎ情報を RAM バッファ、および各種変数へ読み出す。

  • その後、リアルタイムクロック(RTC)モジュールの状態がチェックされ、初めて電源を入れたときや、バックアップ用バッテリーが異常なとき等に、次のエラーメッセージがディスプレイ(OLED) 画面に表示されるとともに、"ブッブー" ブザー音が出力される。
    			 DS3231 Error !
    			         Init ? _
    

  • なお、このときディスプレイ(OLED) 画面では "Init ? " の後 "_" の部分がブリンク表示されているが、これはリアルタイムクロック(RTC)モジュールの初期設定をするかどうかを、ユーザに応答を求めていることを表している。 ユーザはバックアップ用バッテリーの状態等を確認してその対処を行った後、この場合には 6個のスイッチの内のどれかを押して応答 をする。

  • すると、リアルタイムクロック(RTC)モジュールの初期設定を行った後、再度リアルタイムクロック(RTC)モジュールの状態がチェックされ、なおも NG であれば同様にエラーメッセージの表示が繰り返されるが、OK であれば時計機能が開始され、 ディスプレイ(OLED) 画面は、時間表示とともにカレンダー表示に切り替わる。 このとき表示される画面を NORMAL モード という。

        NORMAL モードで時計機能が開始

| 機能概要のトップに戻る |


◎ 基本機能とスイッチ操作
    			 SIGNAL    TIMER    ZERO     DOWN      UP      MODE
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │●│   │●│   │●│   │●│   │●│   │●│
    			 └─┘   └─┘   └─┘   └─┘   └─┘   └─┘
    			/CANCEL   /TMSET   /BACK   /MAINTE   /TMODE    /SET
    
    		MODE スイッチ        ..... NORMAL モード / LARGE モードの切り替え
    
    		MODE スイッチ 長押し ..... SET モードに移行(3秒以上の長押し)
    		(SET スイッチ)
    
    		  UP スイッチ        ..... カレンダーめくり機能(1か月前に進める)
    					 ( LARGE モード中は無視)
    
    		  UP スイッチ 長押し ..... 24時間表示 / 12時間表示の切り替え(3秒以上の長押し)
    	      (TMODE スイッチ)
    
    		DOWN スイッチ        ..... カレンダーめくり機能(1か月後に進める)
    					 ( LARGE モード中は無視)
    
    		DOWN スイッチ 長押し ..... メンテナンス機能に移行(3秒以上の長押し)
    	     (MAINTE スイッチ)		 (カレンダーめくり機能中はカレンダーめくり機能)
    
    		ZERO スイッチ        ..... 毎正時プラス・マイナス5分以内を 00分00秒に設定
    					 (5分以外では無視)
    
    	       TIMER スイッチ        ..... タイマーメモリの読み出しと消去
    
    	       TIMER スイッチ 長押し ..... タイマーメモリの設定(3秒以上の長押し)
    	      (TMSET スイッチ)
    
    	      SIGNAL スイッチ        ..... 毎時の時報音とタイマー一致音出力の ON / OFF 制御機能
    
    
  • 初めて本機に電源を投入すると、カレンダーおよび時間は "2025/01/01"、"00:00:00" と、本機をプログラミングしたときの設定値から始まって表示をするため、後述の「SET モード機能とスイッチ操作」手順で現在の年月日、 時分秒に設定をし直す必要がある。

  • なお、本機には上図のように操作をするための押しボタンスイッチが6個ありその機能概略を示すが、以降にその使用法の詳細を順に説明して行く。

    [ NORMAL / LARGE モードの切り替え機能 ]

  • その設定手順の説明をする前に、LARGE モードについてを先に触れると、上述のように、デモ表示の後 NORMAL モードに移行して、ディスプレイ(OLED) 画面は通常の7曜カレンダー表示をしているが、この状態のときに MODE / SET スイッチ を押すと、 画面には大きな文字が表示されるようになり、この状態を LARGE モード という。 当然ながら文字が大きくなったため、7曜カレンダー表示はできない。

        LARGE モードに切り替わった

  • NORMAL モードと LARGE モードは、MODE スイッチ を押すごとに交互にそのモードを切り替えることができる。 このように MODE スイッチをチョンと押して、NORMAL モードと LARGE モードを切り替えるのではなく、長押し をすることにより、 後述 のように年月日、時分秒を希望値に設定変更することができる SET モード となる。

    [ カレンダーめくり機能 ]

  • NORMAL モードにおいての UP スイッチ または DOWN スイッチ の振る舞いは、後述の SET モードのように項目の設定値を変更するのではなく、現在、ディスプレイ画面に表示されている 年月表示とカレンダー表示を、月ごとに前進、または後退 させて、紙のカレンダーをめくるように変更表示をする。 なお、このときの時分秒の時刻については、カレンダーめくりの機能とは関係なく現在時刻をきざみ続ける。

  • そして、ディスプレイ画面のメッセージエリアには、"←Down Up→" が表示され、かつ、"←Down" または "Up→" のどちらかが反転表示されて、本日の年月日(現在位置)からどちらの方向に偏っているかを表している。 本日の年月日にもどると、これらのメッセージは消えて7曜カレンダー内の該当日(本日)が反点表示される。

        1か月前を表示(後退) 本日の年月日(現在位置) 1か月後を表示(前進)

  • なお、この "←Down Up→" が表示されている [ カレンダーめくり機能 ] のときには、MODE / SET スイッチの操作をしても無視されて、LARGE モードへの切り替え、および SET モードへの移行はできない。 また 後述 するように、TIMER / TMSET スイッチによる、[タイマー機能] への移行も無視されてできない。

  • LARGE モードにおいては7曜カレンダー表示されることがないため、 UP スイッチまたは DOWN スイッチを押しても、画面表示の変化はなく無視される。

    [ 24時間表示 / 12時間表示の切り替え機能 ]

  • NORMAL モード、または LARGE モードのときに、UP / TMODE スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、24時間表示 / 12時間表示の切り替えが行われ、この操作を行うごとに表示形式が交互に切り替わる。

      • (12H 表示例) AM 01 : 23 : 45 (12H 表示例) PM 01 : 23 : 45 (24H 表示例) 01 : 23 : 45

             ( LARGE 画面での表示画面例 )

  • そして、24時間表示 から 12時間表示になったときには、直ちに "am" または "pm" が、そのときの時 "xx" の設定値によって変更表示される。 逆に、12時間表示 から 24時間表示になったときには、"am"、"pm" 表示は消える。

    [ ZERO スイッチ機能 ]

  • ZERO / BACK スイッチ は、後述するように SET モードでは BACK スイッチとして機能するが、それ以外の NORMAL モード、および LARGE モードでは、毎正時プラス・マイナス5分以内に押されると 、00分 00秒に設定するための ZERO スイッチとして機能 し、ZERO スイッチを放した直後に、リアルタイムクロック(RTC)モジュールと PIC のフラッシュメモリ (High-Endurance) を更新後、"ピピッ" ブザー音を伴って更新したことを知らせる。

  • なお、毎正時プラス・マイナス5分以外に同スイッチが押されたときには、時間を更新することなく無視される。

    [ 毎時の時報音とタイマー一致音出力の ON / OFF 制御機能 ]

  • SIGNAL / CANCEL スイッチ は、押すごとにディスプレイ画面右下のメッセージエリアに、"Signal On" と "Signal Off" を交互に3秒間反転表示し、毎時の時報音のブザー音出力を、有効/無効に交互に設定をする。

        時報音が無効に設定 時報音が有効に設定

  • このとき、"Signal On" の有効のときには "ピピピッ" ブザー音を、"Signal Off" の無効のときには "ブー" ブザー音を伴って知らせる。 なお、電源を投入直後は "Signal On" の有効に設定がされている。

  • また、LARGE モードにおいては SET モードに切り替わったときと同様、メッセージエリアの確保のために2行目と3行目が上部位置に移動して、同メッセージが反転表示されるが、3秒間の経過後はメッセージエリアの消滅とともに、 通常の LARGE モードの表示位置に戻る。

        LARGE モード時の時報音 OFF の状態 LARGE モード時の時報音 ON の状態

  • なお、ここで設定するブザー音出力の有効/無効は、あくまでも毎時の時報音、およびタイマー一致音のアラーム出力だけに関わる設定であって、その他のスイッチ操作等に伴なって出力される効果音には、当てはまらないので注意が必要である。

    [ スリープモード ]

  • NORMAL モード( [ カレンダーめくり機能 ] 時も含めて)、または LARGE モードのときに、どのスイッチも操作しない状態が 10 分(デフォルト)以上続く と、省エネのため自動的にディスプレイ (OLED) をスリープさせるとともに、本機自体も スリープモード に移行する。( SET モード機能、 メンテナンス機能を実行中はスリープモードに移行しないので要注意。)

  • 本機がスリープモードに移行するときには、10 分(デフォルト)を経過する3秒前から、秒ごとに "ブッ" ブザー音を3回、また、10 分を経過直後に "ブッブー" ブザー音とともにスリープモードに移行する。

  • なお、この移行までの時間は後述の 「メンテナンス機能とスイッチ操作」 で、0 〜 60 分の範囲(ただし、0 設定時はスリープしない)で変更することができる。

  • また、本機自体およびディスプレイ (OLED) がスリープモードになっているときに、6個の全スイッチの内のどれかが操作 されると本機は ウエイクアップ して、 "ピピッ" ブザー音とともに、再びディスプレイ (OLED) 画面の表示がされるようになる。

  • そして、このウエイクアップしたのを契機として、その度ごとの直後に、ディスプレイ画面右下のメッセージエリアに "[Batt=x.xxV]" と、本機に使用している電源 18650 リチウムイオン電池の現在電圧値が、約 10 秒間だけ反転表示される。

        電源リチウムイオン電池の電圧値表示 LARGE モードでウエイクアップしたとき

  • このときに、LARGE モードでウエイクアップしたときには、前項の [ 毎時の時報音とタイマー一致音出力の ON / OFF 制御機能 ] と同様に、メッセージエリアの確保のために2行目と3行目が上部位置に移動して表示されるが、 10 秒間の経過後はメッセージエリアの消滅とともに、通常の LARGE モードの表示位置に戻る。

| 機能概要のトップに戻る |


◎ SET モード機能とスイッチ操作
    			 SIGNAL    TIMER    ZERO     DOWN      UP      MODE
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │●│   │○│   │●│   │●│   │●│   │●│
    			 └─┘   └─┘   └─┘   └─┘   └─┘   └─┘
    			/CANCEL   /TMSET   /BACK   /MAINTE   /TMODE    /SET
    
    		 SET スイッチ        ..... ブリンク位置のポインタを + 1
    
    		BACK スイッチ        ..... ブリンク位置のポインタを - 1
    
    		  UP スイッチ        ..... ブリンク位置の値を + 1
    		  UP スイッチ 長押し ..... ブリンク位置の値を + 1 早送り
    
    		DOWN スイッチ        ..... ブリンク位置の値を - 1
    		DOWN スイッチ 長押し ..... ブリンク位置の値を - 1 早送り
    
        (秒選択時に) SET スイッチ        ..... SET モードを終了し、NORMAL / LARGE モードに戻る
    
    	      CANCEL スイッチ        ..... SET モードを中断し、NORMAL / LARGE モードに戻る
    
    
  • さて、ここで話を戻して、年月日、時分秒の設定を変更する手順は、まず MODE / SET スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、ディスプレイ画面右下のメッセージエリアに "SET MODE" と反転表示されて、NORMAL モード、 または LARGE モードから SET モード に切り替わったことを示し、年月日および時分秒の表示は更新が停止する。

  • なお、このとき LARGE モードから SET モードに切り替わった場合には、メッセージエリアの確保のため、2行目(曜日、am/pm)の表示と3行目(時分秒)の表示が、以降 SET モードの間中は上部位置に移動して表示される。

        SET モードに切り替わった LARGE モードから SET モードに

  • そこで MODE / SET スイッチを放すと、メッセージは "Year Hi ?" に変わり、左上の年月 "xxxx/xx" 表示エリアの先頭2桁がブリンク表示されて、年の上位2桁の変更が可能となる。 (下の写真では反転表示になっているだけであるが、実際にはブリンク表示がされる。 以下、同様。)

        年の上位2桁の変更が可能 LARGE 画面で年の上位2桁の変更時

  • もし変更が必要であれば、UP スイッチ を押すごとに現在値より1ずつ増加し、また DOWN スイッチ を押すごとに1ずつ減少するので、適宜希望する値に変更する。

  • 年の上位2桁の変更が済んだら、再び MODE / SET スイッチ を押すとメッセージは "Year Lo ?" に変わり、左上の年月 "xxxx/xx" 表示エリアの 年の下位2桁がブリンク表示され、年の下位2桁の変更が可能となる。

        年の下位2桁の変更が可能 LARGE 画面で年の下位2桁の変更時

  • 同様に変更が必要であれば、UP スイッチまたは DOWN スイッチを押すことによって、適宜希望する値に変更する。 なお、これらの値の増減幅を大きくしたい場合には、UP スイッチまたは DOWN スイッチを押したままにしていると、 1秒当たり 4 〜 5 の増減幅で更新をするようになる。

  • 以降、同様に SET スイッチ を押すごとに、月 → 日 → 24H/12H → 時 → 分 → 秒 と設定項目を変更することができるので、変更が必要であればその該当項目の選択時に、UP スイッチまたは DOWN スイッチを押すことによって、 適宜希望する値に変更する。

  • また、このときのメッセージエリアには、それぞれ "Month ?"、"Today ?"、"24H/12H ?"、"Hour ?"、"Minute ?"、"Second ?" と反転表示され、NORMAL 画面では1行目の該当項目の月、24H/12H、時、分、秒の、それぞれがブリンク表示されて選択項目を表す。 LARGE 画面においても位置は異なっているが、該当する項目が同様にブリンク表示される。

             ( 設定例 )
        年 "xxxx"、月 "xx" は変更なし 日 を "16" に設定 デフォルトは "24H" になっている
        "12H" に変更後、時を "pm 8" に設定 分 を "35" に設定 秒 を "30" に設定

             ( LARGE 画面での設定画面例 )

  • 選択項目の日 "xx" については、NORMAL 画面では7曜カレンダー内で該当日(本日)がブリンク表示されるので、同様に UP スイッチまたは DOWN スイッチによって、その位置を移動変更することにより選択をする。 また、LARGE 画面においては1行目の右端2桁がブリンク表示され、他の項目と同様に UP スイッチまたは DOWN スイッチを押すことによって、適宜希望する値に変更する。

  • この SET スイッチによって項目を選択中に、誤って希望する項目を通り過ぎてしまったような場合には、BACK スイッチ を押すごとにひとつずつ前の項目に戻ることができる。

  • 最後の秒の項目選択時に更に SET スイッチを押すと、今まで変更されてきた各項目の設定値が、新たな情報として リアルタイムクロック(RTC)モジュール と PIC の フラッシュメモリ (High-Endurance) に書き込み更新 され、 その後、SET モードからNORMAL モード、または LARGE モードの、SET モードに移行する前のディスプレイ(OLED) 画面に再び戻って、その設定値から年月日、時分秒の表示が再開される。

      • 設定再開後、"47 秒" が経過した SET モードから再び LARGE モードに

  • SET モードでの選択項目の推移をまとめると次図のようになる。
    	                               BACK            BACK  BACK  BACK       BACK  BACK  BACK
    	             MODE               ←              ←    ←    ←         ←    ←    ←
    	             /SET              SET             SET   SET   SET        SET   SET   SET   SET
    	 NORMALモード ─→ 年(上位2桁) → 年(下位2桁) → 月 → 日 → 24H/12H → 時 → 分 → 秒 ─→ NORMALモード
    	 (LARGEモード)          │                                                            ↑     (LARGEモード)
    	                    BACK└──────────────────────────────┘
    
    
  • ここで項目 24H/12H について補足をしておくと、これは時表示を 24時間表示にするか 12時間表示にするか、どちらかを選択することで、UP スイッチまたは DOWN スイッチのどちらかを押すことによって、交互に切り替えることができる。

        デフォルトは "24H" になっている "12H" に切り替えた

  • 24H を選択した場合は、次の項目に移った時に "24H/12H" 表示エリアには何も表示されないが、12H を選択した場合は、次の項目に移った時に "am" または "pm" が、そのときの時 "xx" の設定値によって変更表示される。

        次項目に移ると "pm" が表示される

  • 次に、12時間表示と 24時間表示の対応を示す。 なお、12時間表示の場合だけ 時 "xx" の先頭の1桁目は、ゼロサプレスを行なって表示をする。
    		(24H)  00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
    		(12H)  12  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11
    		       am am am am am am am am am am am am pm pm pm pm pm pm pm pm pm pm pm pm
    
    
  • 上述のように、最後の秒の項目選択時に更に SET スイッチ を押した場合には、リアルタイムクロック(RTC)モジュール等を更新 後、"ピピッ" ブザー音を伴って正常に終了したことを知らせる。

  • また、各項目の変更中に何らかの理由があって途中で変更作業を中断したい場合には、SIGNAL / CANCEL スイッチ を押すことによって、直ちに SET モードから NORMAL モード、または LARGE モードの、SET モードに移行する前に戻ることができる。 この場合には、リアルタイムクロック(RTC)モジュール等を更新することはなく、"ブー" ブザー音を伴って中断終了したことを知らせる。

| 機能概要のトップに戻る |


◎ メンテナンス機能とスイッチ操作
    			 SIGNAL    TIMER    ZERO     DOWN      UP      MODE
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │●│   │○│   │●│   │●│   │●│   │●│
    			 └─┘   └─┘   └─┘   └─┘   └─┘   └─┘
    			/CANCEL   /TMSET   /BACK   /MAINTE   /TMODE    /SET
    
    		 SET スイッチ        ..... OLED コントラスト / スリープまでの移行時間 の選択
    
    		  UP スイッチ        ..... ブリンク位置の値を + 1
    		  UP スイッチ 長押し ..... ブリンク位置の値を + 1 早送り
    
    		  UP スイッチ +
    		DOWN スイッチ        ..... ブリンク位置の値をデフォルト値に設定
    
    		DOWN スイッチ        ..... ブリンク位置の値を - 1
    		DOWN スイッチ 長押し ..... ブリンク位置の値を - 1 早送り
    
    		DOWN スイッチ +
    		  UP スイッチ        ..... ブリンク位置の値をデフォルト値に設定
    
    		BACK スイッチ        ..... メンテナンス機能を終了し、NORMAL / LARGE モードに戻る
    
    	      CANCEL スイッチ        ..... メンテナンス機能を中断し、NORMAL / LARGE モードに戻る
    
    
  • NORMAL モードのときに、DOWN / MAINTE スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、ディスプレイ画面右下のメッセージエリアに "Maintenance" と反転表示されて、メンテナンス機能への移行準備が行われるので、 DOWN / MAINTE スイッチを放すと、ディスプレイ画面が [メンテナンス機能] 画面に切り替わる。


  • また、LARGE モードのときに、DOWN / MAINTE スイッチ を3秒間以上押し続けると、SET モードに切り替わったときと同様、メッセージエリアの確保のために2行目と3行目が上部位置に移動して表示され、以降は NORMAL モードのときと同様である。
    			=== Maintenance ===
    			  [ Batt = x.xxV ]
    			 > OLED Contrast
    			  (001-255) ? _ xxx
    			 > Sleep Time
    			  (00-60) ? _ xx
    

  • 表示された [メンテナンス機能] 画面の2行目には、本機に使用している電源 18650 リチウムイオン電池の現在電圧値を、リアルタイム(5秒ごとに更新)で表示しているので、電池の充電時期の判断に使用することができる。

  • 画面の3行目以降の表示は、本機におけるメンテナンス機能を表し、OLED コントラストの設定変更スリープまでの移行時間(分)の設定変更、の2つの設定変更機能があり、本 [メンテナンス機能] 画面に切り替わった直後は、 前者の設定変更が選択されて "(001-255) ? _ xxx" メッセージ の "xxx" 部分がブリンク表示される。

  • そこで、前者設定値を変更したい場合には、UP スイッチ を押すごとに現在値より1ずつ増加し、また DOWN スイッチ を押すごとに1ずつ減少するので、適宜希望する値に変更する。

  • また、後者の設定変更を選択したい場合には、MODE / SET スイッチ を押すことによって "(00-60) ? _ xx" メッセージ の "xx" 部分がブリンク表示されるので、同様に UP スイッチまたは DOWN スイッチを押すことによって、 希望する値に変更する。


  • このときの MODE / SET スイッチは、押すごとに両者の設定変更の選択を交互に切り替えることができ、それぞれで変更できる 設定範囲は 、前者では 001 〜 255 まで、後者では 00 〜 60 までとなっている。 ただし、後者で 00 を設定した場合には、スリープモードには移行しなくなるので注意が必要である。

    (余談) 前者の設定値として、SSD1306 では 000 の設定も可能ではあるが、その場合には画面が完全に消えてしまうので、本機では設定値から外すことにした。

  • また、UP スイッチまたは DOWN スイッチによる増減幅を大きくしたい場合には、UP スイッチまたは DOWN スイッチを押したまま にしていると、増減値が早送りされる ようになる。

  • なお、OLED コントラストを設定変更、スリープまでの移行時間(分)を設定変更、の2つの設定値のデフォルト値は、それぞれ 127 と 10 に規定されており、それぞれの設定変更が選択されているときに、UP スイッチと DOWN スイッチを同時に押す ことによって、それぞれの デフォルト値に簡単に設定する ことができる。

  • 両者の設定変更が済んで、元の NORMAL モードまたは LARGE モードに戻りたい場合は、ZERO / BACK スイッチ を押すことによって行われ、変更された設定値で PIC の フラッシュメモリ (High-Endurance) を更新 後、 "ピピッ" ブザー音を伴って正常に終了したことを知らせる。

  • また、何らかの理由があって途中で設定変更を中断したい場合には、SIGNAL / CANCEL スイッチ を押すことによって、メンテナンス機能に移行する前の NORMAL モードまたは LARGE モードに戻ることができる。 この場合には、それまでに 変更された設定値は破棄 され、"ブー" ブザー音を伴って中断終了したことを知らせる。

| 機能概要のトップに戻る |


◎ タイマー機能とスイッチ操作
  • 本機におけるタイマー機能には、[メモリの設定]、[メモリの読み出しと消去]、[タイマーメモリの監視] の3機能があり、まず初めにタイマー情報をメモリに設定しておくと、[タイマーメモリの監視] 機能によって、 設定時刻が現在時刻に一致するとアラーム音によって通知をする。

  • これらのメモリに設定したタイマー情報は、[メモリの読み出し] 機能によっていつでもその内容を確認することができ、不要になった場合には消去する機能も備えている。

  • [メモリの設定] 機能には、年タイマー、週間タイマーの2種類があり、年タイマー では "年、月、日、時、分" を設定するが、監視機能によるアラーム音の通知後はそのタイマー情報は不要になるため、 タイマーメモリから自動的に消去される。

  • また、週間タイマー では "曜日、時、分" を設定し、これらのタイマー情報は自動的に消去されることがないため、上述の消去機能によって消去をしない限り、毎週同時刻になるとアラーム音の通知を行う。 なお、曜日には関係なく毎日の指定をすることもできる。

  • これらの年タイマー、週間タイマーの設定数は、両者を合わせて合計 10 個まで設定をすることができる。

    [ タイマーメモリの設定 ]

  • NORMAL モードのときに、TIMER / TMSET スイッチ を3秒間以上押し続けると、"ピッ" とブザー音とともに、ディスプレイ画面右下のメッセージエリアに " TIMER SET " と反転表示されて、[タイマーメモリの設定] 機能への移行準備が行われるので、 TIMER / TMSET スイッチを放すと、ディスプレイ画面が [タイマーメモリの設定] 機能の [タイマー種類の選択] 画面に切り替わる。


  • また、LARGE モードのときに、TIMER / TMSET スイッチ を3秒間以上押し続けると、SET モードに切り替わったときと同様、メッセージエリアの確保のために2行目と3行目が上部位置に移動して表示され、以降は NORMAL モードのときと同様である。

    タイマー種類の選択時
    			 SIGNAL    TIMER    ZERO     DOWN      UP      MODE
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │●│   │○│   │○│   │●│   │●│   │●│
    			 └─┘   └─┘   └─┘   └─┘   └─┘   └─┘
    			/CANCEL   /TMSET   /BACK   /MAINTE   /TMODE    /SET
    
    			    UP スイッチ ..... ブリンク位置のポインタを + 1
    			  DOWN スイッチ ..... ブリンク位置のポインタを - 1
    
    			   SET スイッチ ..... タイマー種類選択を終了し、次項目の設定に移行する
    
    			CANCEL スイッチ ..... タイマー種類選択を中断し、NORMAL / LARGE モードに戻る
    
    
  • このように TIMER / TMSET スイッチを放すと、初めに次のような [タイマー種類の選択] 画面が表示されるので、年タイマー (Date)、週間タイマー (Weekly) の2種類の内、どちらかを UP または DOWN スイッチ によって選択をする。 このときデフォルトでは "Date" が選択されブリンク表示をする。
    			= Timer Memory Set =
    			
    			 Type = Date Weekly
    			
    			
    			 UP/DOWN SET/CANCEL 
    

  • このときの [タイマー種類の選択] 画面の最下行には、"UP/DOWN SET/CANCEL" の文字列が反転表示され、この画面のときに使用ができるスイッチ種類を、簡易的な操作ガイドとして表示がされる。(この画面では UP, DOWN, SET, CANCEL スイッチの4種類だけが 使用できることを案内している。)

  • UP または DOWN スイッチによってどちらかを選択(ブリンクする表示位置を変更)後、SET スイッチ を押すことによってその選択が決定され、次に、年タイマー (Date)、週間タイマー (Weekly) の、それぞれに決められた [タイマー情報の設定] 画面が新たに表示される。

  • また、この [タイマー種類の選択] 時には、上記の選択画面を表示する前に、タイマー用メモリに登録をするための空きがあるかどうかを事前にチェックをし、空きがある場合のみ選択画面が表示される。

  • タイマー用メモリに空きがない場合には、"ブッブー" ブザー音とともに次のメッセージが表示されるので、全スイッチの内のどれかを押すと [タイマーメモリの設定] 機能が終了し、NORMAL モード、または LARGE モードの表示画面に戻る。
    			  Memory full !
    			   Any switch ? _
    

  • なお、この [タイマー種類の選択] 画面のときに、何らかの理由があって 選択を中止したい場合 には、CANCEL スイッチ を押すことによって [タイマーメモリの設定] 機能が中止され、"ブー" ブザー音を出力後、通常の NORMAL モード、または LARGE モードの表示画面に戻る。

    タイマー情報の設定時
    			 SIGNAL    TIMER    ZERO     DOWN      UP      MODE
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │●│   │●│   │●│   │●│   │●│   │●│
    			 └─┘   └─┘   └─┘   └─┘   └─┘   └─┘
    			/CANCEL   /TMSET   /BACK   /MAINTE   /TMODE    /SET
    
    			   SET スイッチ ..... ブリンク位置のポインタを + 1
    			  BACK スイッチ ..... ブリンク位置のポインタを - 1
    
    			    UP スイッチ ..... ブリンク位置の値を + 1
    			  DOWN スイッチ ..... ブリンク位置の値を - 1
    
    	    (分選択時に) TIMER スイッチ ..... 1件分のタイマー設定を終了し、次の設定に備える
    
    			CANCEL スイッチ ..... タイマー設定を中断し、NORMAL / LARGE モードに戻る
    
    
  • まず、年タイマー (Date) が選択決定された場合 には、"ピッ" ブザー音を出力後、次のように SET モード機能のとき と同様な設定画面に切り替わり、以降、ブリンク表示されている位置と画面右下のメッセージエリアの案内 に従って、それぞれの項目を順に入力して行く。


  • この [年タイマー (Date) の設定] 画面と SET モード機能の設定画面は、そのほとんどが同様に表示されるが、両者での大きな相違点は、前者では画面右上に "秒( :xx )" の項目が表示されないことで、見分けることができる。

  • SET モード機能のときと同様のスイッチ操作によって、各項目を選択、入力して行くが、下図のように "分" がブリンク表示して選択 されているときに、TIMER スイッチ を押すことによって、入力された年タイマー (Date) の情報が、 既存のタイマー情報と比較(重複データチェック)され、重複エラーがない場合に限って、タイマー用メモリへの書き込みが行われ、"ポッポッ" ブザー音が出力される。
                                   BACK            BACK  BACK  BACK       BACK  BACK
                                    ←              ←    ←    ←         ←    ←
                 SET               SET             SET   SET   SET        SET   SET    TIMER
     種類の選択 ──→ 年(上位2桁) → 年(下位2桁) → 月 → 日 → 24H/12H → 時 → 分 ──→ 種類の選択
         (Date)            │↑                                                    │↑
                           ││                                                 SET││
                       BACK│└──────────────────────────┘│
                           └────────────────────────────┘
    
  • 重複エラーがなくタイマー用メモリへの書き込みが行われた後は、再び [タイマー種類の選択] 画面が表示されるので、次のタイマー情報がある場合には引き続き設定をする。 (次のタイマー情報がない場合には、CANCEL スイッチ を押して [タイマーメモリの設定] 機能を終了させる。)

  • 上図には記入がされていないが [タイマー種類の選択] のときと同様に、各項目を選択中に何らかの理由があって 設定を中止したい場合 には、CANCEL スイッチ を押すことによって [タイマーメモリの設定] 機能が中止され、"ブー" ブザー音を出力後、 通常の NORMAL モード、または LARGE モードの表示画面に戻ることもできる。

  • 一方、[タイマー種類の選択] 画面のときに、週間タイマー (Weekly) が選択決定された場合 には、"ピッ" ブザー音を出力後、次の設定画面が表示されて曜日選択から始めるように、デフォルトでは "Eday"(毎日)が選択されブリンク表示する。
    			= Timer Memory Set =
    
    			Eday
    			Su Mo Tu We Th Fr Sa
    
    			    xx:xx		..... 時:分
    
    			SET/BAK UP/DW TIM/CAN
    

  • このときにも設定画面の最下行には、"SET/BAK UP/DW TIM/CAN" の文字列が反転表示され、この画面のときに使用ができるスイッチ種類を、簡易的な操作ガイドとして表示がされる。(この画面では SET, BAK, UP, DOWN, TIMER, CANCEL の全スイッチが使用できることを 案内している。)

  • 初めの曜日選択では UP、または DOWN スイッチ によって、希望する曜日の選択をする。 そして SET、または BACK スイッチ によって、下図のように各項目間を移動することができ、"分" がブリンク表示して選択 されているときに、 TIMER スイッチ を押すことによって、以降は、上述の [年タイマー (Date) の設定] のときと同様である。
    	                       BACK       BACK  BACK
    	                        ←         ←    ←
    	             SET       SET        SET   SET    TIMER
    	 種類の選択 ──→ 曜日 → 24H/12H → 時 → 分 ──→ 種類の選択
    	   (Weekly)        │↑                    │↑
    	                   ││                 SET││
    	               BACK│└──────────┘│
    	                   └────────────┘
    
  • 年タイマー (Date)、週間タイマー (Weekly) のタイマー情報が、上述のようにタイマー用メモリへの書き込みが行われた場合には、[タイマーメモリの設定] の終了時に、High-Endurance フラッシュメモリにもそのバックアップが書き込まれ、本機の電源スイッチ OFF などの停電時に備える。

    [ タイマーメモリの読み出しと消去 ]
    			 SIGNAL    TIMER    ZERO     DOWN      UP      MODE
    			 ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐   ┌─┐
    			 │○│   │●│   │●│   │●│   │●│   │○│
    			 └─┘   └─┘   └─┘   └─┘   └─┘   └─┘
    			/CANCEL   /TMSET   /BACK   /MAINTE   /TMODE    /SET
    
    		    UP スイッチ ..... ブリンクする表示番号を - 1
    		  DOWN スイッチ ..... ブリンクする表示番号を + 1
    
    		  ZERO スイッチ ..... ブリンクする表示番号の登録データを消去する
    
    		 TIMER スイッチ ..... タイマーメモリの読み出しを終了し、NORMAL / LARGE モードに戻る
    
    
  • NORMAL モード、または LARGE モードのときに、TIMER / TMSET スイッチ を押すと、タイマー用メモリのデータ表示に先立って、登録データがあるかどうかを事前にチェックをし、登録データがある場合のみ次のような画面が表示される。

  • (1)、(2) の形式は年タイマー (Date) が登録 されており、かつ、(1) は 24H、(2) は 12H の時間表示で登録がされている例を示す。 また、(3)、(4) の形式は週間タイマー (Weekly) が登録 されており、かつ、(3) は 24H、(4) は 12H の時間表示で登録がされている例を示す。
    			= Timer Memory Read =
    
    			xx xxxx/xx/xx   xx:xx     ... (1)
    			xx xxxx/xx/xx xx x:xx     ... (2)
    			xx       xxxx   xx:xx     ... (3)
    			xx       xxxx xx x:xx     ... (4)
    
    			↓:DOWN ↑:UP del:ZERO
    

  • この表示画面の最下行にも、"↓:DOWN ↑:UP del:ZERO" の文字列が反転表示され、この画面のときに使用ができるスイッチ種類を、簡易的な操作ガイドとして表示がされる。(この画面では DOWN, UP, ZERO の3種類のスイッチが使用できることを案内しているが、 他にも、表示はされていないが TIMER スイッチを押すと、データ表示機能を終了する。)

  • 上図のように、各データ行の左端2桁には登録順に番号が付けられ、01 から始まってデフォルトでは 01 番が選択されブリンク表示をする。 本機では、ディスプレイ(OLED) 画面の中央4行だけにしか登録データの表示ができないため、それ以上の登録データがある場合には、 ↓: DOWN スイッチ、または ↑: UP スイッチ を押すことによって、ブリンク表示する選択番号を変更させ、デフォルトの4行以外の登録データを選択表示させることができる。

  • このように、複数の登録データがあっても選択番号を変更させることによって、対象とする登録データを変更させ、もしもその登録データが不要になった場合には、ZERO スイッチ を押すことによって、 その登録データだけをタイマー用メモリから消去する。

  • そして、この登録データを消去した場合には、[タイマーメモリの読み出しと消去] の終了時に、High-Endurance フラッシュメモリにもそのバックアップが書き込まれ、本機の電源スイッチ OFF などの停電時に備える。

  • 上述した登録データの事前チェックで、登録データがなかった場合には、"ブッブー" ブザー音とともに次のメッセージが表示されるので、全スイッチの内のどれかを押すと [タイマーメモリの読み出しと消去] 機能が終了し、NORMAL モード、または LARGE モードの表示画面に戻る。
    			  No registration !
    			       Any switch ? _
    

  • また、登録データの表示中に TIMER スイッチ を押すことによって、同様に、[タイマーメモリの読み出しと消去] 機能が終了し、NORMAL モード、または LARGE モードの表示画面に戻る。

    [ タイマーメモリの監視 ]

  • 本機がスリープモード中を含む NORMAL モード、または LARGE モードのときに、アラーム音出力が許可されている と、本機の時計機能が 毎分 "00" 秒 になると、監視プログラムによってタイマー用メモリ中に登録がされている タイマー情報が検索され、時刻が一致した情報が存在した場合には、"ピポッピポッ" アラーム音を 10 回出力して知らせる。

  • このように時刻が一致したタイマー情報は、年タイマー (Date) の場合には以降は不要となるために、自動的にタイマー用メモリ中から消去される。 週間タイマー (Weekly) の場合には、[タイマーメモリの読み出しと消去] 機能で消去を行わない限り、 いつまでもタイマー用メモリ中に存在をし続けるため、毎週同時刻になるとアラーム音を出力する。

  • なお、上述した 年タイマー (Date) の場合の [タイマー情報の設定] で、現在時刻よりも過去の情報を入力した場合には、一旦はタイマー用メモリに登録されるが、この監視プログラムが実行された時点で自動的に消去される。

| 機能概要のトップに戻る | ページトップ |

■ プログラム ■

 本機(万年カレンダー III)のプログラムは、もちろん、前作(万年カレンダー II)の延長線上に位置するものであって、前作のプログラムに新しい機能を追加したものなので、使用した PIC も同じ PIC16F1705 を採用してプログラム開発を行っています。

 このプログラムの機能追加については、当初の自分自身の心づもりではもっと短期間で行えると思っていたのですが、実際には2か月近くの長丁場となってしまいました。  本機でも使用した、リアルタイムクロックモジュールのプログラミングについては、既に、"190. I2C IF モジュール + LCD(1602A) 表示時計" で詳述をしているので、そちらへのリンクが張ってあります。 また、有機 EL ディスプレイ(OLED)( SSD1306 )モジュールのプログラミングについては、"前作(万年カレンダー II)" で詳述をしているので、これについてもそちらへのリンクが張ってあります。

● 本機で使用した PIC16F1705 のメモリの使用状況

 最近の私作の規模が大きいプログラムでは恒例となった、次に挙げるように、データメモリやプログラムメモリの使用状況についてを、ここに示しておきます。

 本機のプログラム全体を理解する上で、データメモリの内の特殊機能レジスタ (SFR) や汎用レジスタ(GPR) には、プログラムでどのレジスタにアクセスをしているかとか、4ページあるプログラムメモリの使用状況がどのようになっているか、 などの情報が事前に分かっていると、他の人はもちろんのこと、作者の自分自身でも数か月以上が経ってしまったときには、非常に役に立つものです。

◎ 本機におけるデータメモリの使用状況

 次の TABLE 3-2、TABLE 3-3 は、Microchip Technology Inc. 社の PIC16F1705 データシートから、データメモリの内の一部分を抜粋したもので、私がプログラムで一度でもアクセスをしたレジスタについて、それらがよく分かるように彩色を施しました。

 黄色や青色、ピンク色に塗ったレジスタが 特殊機能レジスタ (SFR) で、これらの内で青色のものは、High-Endurance フラッシュメモリにアクセスをするときに必要になるレジスタ群、ピンク色のものは、ADC モジュールのプログラミングに必要となるレジスタ群です。 また、薄緑色や水色のレジスタ群は特殊機能レジスタ (SFR) ではなく、一般の変数など、ユーザが自由に使用できる 汎用レジスタ(GPR) を表しています。 その内の水色のレジスタ群は、リニア データメモリとして使用しています。

| プログラムのトップに戻る |

◎ 本機におけるプログラムメモリの使用状況

 次表は、本機(プログラムバージョン: Ver. 2.08 現在)における PIC のプログラムメモリの使用状況を、各処理別に分けたメモリ分布(割り付け)をページごとに表したもので、ご覧のように、全ページに亘ってほとんど空きがなくなってしまったので、 今後については大きなプログラム追加などを行うことはまず無理で、バグが発生したときの対処など、小さなプログラム修正しかできない状況になっています。

        ページ 使用メモリ範囲 サイズ プログラム処理
        0 h'0000' 〜 h'004D' 78 words   割り込み処理 
        h'004E' 〜 h'01F2' 421 words   外部サブルーチン include エリア *1 
        h'01F3' 〜 h'02DA' 232 words   初期化処理等、他 
        h'02DB' 〜 h'0342' 104 words   メインプログラムの処理
        h'0343' 〜 h'0374' 50 words   UP スイッチの処理
        h'0375' 〜 h'03B3' 63 words   DOWN スイッチの処理
        h'03B4' 〜 h'045B' 168 words   UP、DOWN スイッチ、その他の共通処理
        h'045C' 〜 h'0490' 53 words   ZERO スイッチの処理
        h'0491 〜 h'04EB' 91 words   SIGNAL スイッチの処理
        h'04EC' 〜 h'0576' 139 words   MODE / SET スイッチの処理
        h'0577' 〜 h'05E8' 114 words   SET モード内での各種スイッチの処理
        h'05E9' 〜 h'0641' 89 words   メンテナンス機能の処理
        h'0642' 〜 h'0685' 68 words   メンテナンス機能内での各種スイッチの処理
        h'0686' 〜 h'06BA' 53 words   時間の監視とスリープモード処理
        h'06BB' 〜 h'075C' 162 words   アラーム関連、ウェイトルーチン
        h'075D' 〜 h'07A2' 70 words   ページ変換サブルーチン (Page 0 用)
        h'07A3' 〜 h'07FF' 93 words   空き
        1 h'0800' 〜 h'097C' 381 words   各_BCD カウンタのインクリメント / デクリメント計算
        h'097D' 〜 h'09AB' 47 words   ページ変換サブルーチン (Page 1 用)
        h'09AC' 〜 h'0BFB' 592 words   NORMAL / LARGE モード時の各種スクリーン表示
        h'0BFC' 〜 h'0D1D' 290 words   SETモード時のブリンク表示
        h'0D1E' 〜 h'0F02' 485 words   タイトルの表示と縁枠のドット移動デモ表示
        h'0F03' 〜 h'0FBC' 186 words   メンテナンスメッセージの表示
        h'0FBD' 〜 h'0FFF' 67 words   空き
        2 h'1000' 〜 h'103E' 63 words   ページ変換サブルーチン (Page 2 用)
        h'103F' 〜 h'1130' 242 words   バッテリー(18650 リチウムイオン電池)の電圧測定
        h'1131' 〜 h'11BA' 138 words   TIMER スイッチの処理
        h'11BB' 〜 h'13D8' 542 words   タイマーメモリの設定
        h'13D9' 〜 h'15CC' 500 words   タイマーメモリの読み出しと消去
        h'15CD' 〜 h'161D' 81 words   タイマー用メモリの監視(一致検査)
        h'161E' 〜 h'17FF' 482 words   空き
        3 h'1800' 〜 h'1BBF' 960 words   文字フォント (5 x 7) データ 外部テーブル include エリア *2 
        h'1BC0' 〜 h'1E55' 662 words   文字フォント (10 x 14) データテーブル
        h'1E56' 〜 h'1F02' 173 words   High-Endurance フラッシュメモリ関連アクセス *3、他
        h'1F03' 〜 h'1F7F' 125 words   空き
        h'1F80' 〜 h'1FC9' 74 words   (High-Endurance フラッシュメモリ) バックアップデータ
        h'1FCA' 〜 h'1FFF' 54 words   (High-Endurance フラッシュメモリ) 空き
        *1: I2C (SCLクロック周波数 = 100/400 KHz) サブルーチン(ソフトウエア I2C 版)(I2C_XS.sub)
        I2C RTC(DS3231/1307)モジュール 制御サブルーチン (I2C_RTCII.sub)
        OLED モジュール ( SSD1306 ) 制御サブルーチン (OLED_SSD1306.sub)
        *2: 文字フォント(5 x 7)データテーブル (Font5x7.tbl)
        *3: 本機では、ページ 0 の空きエリアを増やすために、High-Endurance フラッシュメモリ関連アクセス サブルーチンを、ページ 0 からページ 3 に移動した。

| プログラムのトップに戻る |

● A / D コンバータ モジュールのプログラミング

 本機では、電源に使用している 18650 リチウムイオン電池の、電圧チェックがいつでも行えるように、PIC 内蔵の A / D コンバータ モジュールを使用して、[メンテナンス機能] 画面を表示したときと、本機がスリープモードからウエイクアップした直後に、 そのときの電池の電圧値をディスプレイ (OLED) 画面上に表示をさせています。

 この A / D コンバータ モジュールのプログラミングについては、"194. FMステレオラジオ III" の A / D コンバータ モジュールのプログラミング においても述べたところで、重複する部分も出てきますが、ここでは本機におけるプログラミング例を示しておきます。

 まず初めに、次に示すリストは、本機のプログラムで必要となる変数のレジスタ(GPR)割付けと、SFR レジスタ群の初期設定をしている部分で、特に、ADC モジュールを使用するために必要な、固定参照電圧制御レジスタ ( FVRCON )、ADC 制御レジスタ 0 ( ADCON0 )、 ADC 制御レジスタ 1 ( ADCON1 ) について( TABLE 3-3 を参照)の使用法が重要です。

 次リスト中の初期化処理以前は変数のレジスタ(GPR)割付けのほんの一部分で、変数 ad_res_hi, ad_res_lo は、バンク切り替えを気にしなくても済むように共通 RAM 領域に定義しています。 また、その下に定義しているレジスタ群は、主に割り算サブルーチンやデータ形式の変換サブルーチン等で使用する変数で、通常であればバンク 0 に割付けるのですが、現在、バンク 0 内はほとんど満タン状態なので、仕方なくバンク 1 内に割付けました。
      			:
      			:
      
      		cblock	h'70'			;バンク 0(共通 RAM 領域)
      
      			:
      ad_res_hi					;
      ad_res_lo					;
      			:
      
      		endc
      
      		cblock	h'a0'			;バンク 1
      a16_hi						;16ビット演算引き数A(上位) 
      a16_lo						;16ビット演算引き数A(下位) 
      b16_hi						;16ビット演算引き数B(上位)
      b16_lo						;16ビット演算引き数B(下位)
      lcnt1						;ループカウンタ / ワーク
      lcnt2						;ループカウンタ
      x16_hi						;div_16 答えの上位
      x16_lo						;div_16 答えの下位
      y16_hi						;div_16 余りの上位
      y16_lo						;div_16 余りの下位
      buff0						;変換文字列の格納エリア	;┐
      buff1						;			;│
      buff2						;			;│順序を変更しないこと!
      buff3						;			;│
      buff4						;			;┘
      		endc
      			:
      			:
      
      ;==========================================================================
      ;		初期化処理
      ;==========================================================================
      
      initialize
      		clrf	STATUS			;STATUS クリア
      	 	clrf	INTCON			;INTCON クリア
      
      		; 内部クロックを 8 MHz に設定
      
      		movlb	1			;バンク 1
      		movlw	b'01110000'		;CLOCK=8MHz
      		movwf	OSCCON
      
      		; PORTA,PORTC ポートの各機能設定
      
      		movlb	0			;バンク 0
      		clrf	PORTA			;
      		clrf	PORTC			;
      
      		movlb	2			;バンク 2
      		clrf	LATA			;
      		clrf	LATC			;
      
      		movlb	3			;バンク 3
      		clrf	ANSELA			;すべて デジタル I/O ポート
      		movlw	b'00000100'		;
      		movwf	ANSELC			;RC2 のみアナログ入力ポート
      
      		movlb	1			;バンク 1
      		movlw	b'00111111'		;RA5-RA0:入力
      		movwf	TRISA			;ポートA の I/0 設定
      		movlw	b'00110100'		;RC5-RC4,RC2:入力, RC3,RC1-RC0:出力
      		movwf	TRISC			;ポートC の I/0 設定
      
      		movlb	4			;バンク 4
      		movlw	b'00110011'		;RA5-RA4,RA1-RA0
      		movwf	WPUA			;プルアップ有効
      		movlw	b'00110000'		;RC5-RC4
      		movwf	WPUC			;プルアップ有効
      
      		movlb	7			;バンク 7
      		movlw	b'00110011'		;RA5-RA4,RA1-RA0
      		movwf	IOCAN			;ポートA の立ち下がりエッジ状態変化割り込み
      		movlw	b'00110000'		;RC5-RC4
      		movwf	IOCCN			;ポートC の立ち下がりエッジ状態変化割り込み
      
      		; 固定参照電圧の設定
      
      		movlb	2			;バンク 2
      		movlw	b'10000010'
      ;			  ||||||||
      ;		bit1-0	  ||||||++----- ADFVR<1:0>: ADC FVRバッファゲイン選択ビット
      ;			  ||||||          11 = ADC FVRバッファゲインは4倍、出力VADFVR = 4x VFVR ... 固定参照電圧出力は
      ;			  ||||||      >   10 = ADC FVRバッファゲインは2倍、出力VADFVR = 2x VFVR ... VDDを超える事はできない
      ;			  ||||||          01 = ADC FVRバッファゲインは1倍、出力VADFVR = 1x VFVR
      ;			  ||||||          00 = ADC FVRバッファはOFF
      ;			  ||||||
      ;		bit3-2	  ||||++------- CDAFVR<1:0>: コンパレータFVRバッファゲイン選択ビット
      ;			  ||||            11 = コンパレータFVRバッファゲインは4倍、出力VCDAFVR = 4x VFVR
      ;			  ||||            10 = コンパレータFVRバッファゲインは2倍、出力VCDAFVR = 2x VFVR
      ;			  ||||            01 = コンパレータFVRバッファゲインは1倍、出力VCDAFVR = 1x VFVR
      ;			  ||||        >   00 = コンパレータFVRバッファはOFF
      ;			  ||||
      ;		bit4	  |||+--------- TSRNG: 温度インジケータ レンジ選択ビット
      ;			  |||             1 = VOUT = VDD - 4VT (Highレンジ)
      ;			  |||         >   0 = VOUT = VDD - 2VT (Lowレンジ)
      ;			  |||
      ;		bit5	  ||+---------- TSEN: 温度インジケータ イネーブルビット
      ;			  ||              1 = 温度インジケータを有効
      ;			  ||          >   0 = 温度インジケータを無効
      ;			  ||
      ;		bit6	  |+----------- FVRRDY: 固定参照電圧レディ フラグビット
      ;			  |               1 = 固定参照電圧出力は使える状態
      ;			  |               0 = 固定参照電圧出力の準備が整っていない(または無効)
      ;			  |
      ;		bit7	  +------------ FVREN: 固定参照電圧イネーブルビット
      ;			              >   1 = 固定参照電圧を有効
      ;			                  0 = 固定参照電圧を無効
      
      		movwf	FVRCON			;FVRCON: 固定参照電圧制御レジスタ
      
      		; ADC モジュールの設定
      
      		movlb	1			;バンク 1
      		movlw	b'00011000'
      ;			  ||||||||
      ;		bit0	  |||||||+----- ADON: ADCイネーブルビット
      ;			  |||||||         1 = ADCを有効
      ;			  |||||||     >   0 = ADCを無効、消費電流をゼロ
      ;			  |||||||          ____
      ;		bit1	  ||||||+------ GO/DONE: A/D変換ステータスビット
      ;			  ||||||          1 = A/D変換サイクルを実行中、このビットをセットするとA/D変換サイクルが開始
      ;			  ||||||              このビットは、A/D変換が完了するとハードウェアによって自動的にクリア
      ;			  ||||||      >   0 = A/D変換サイクルが完了(進行中でない)
      ;			  ||||||
      ;		bit6-2	  |+++++------- CHS<4:0>: アナログ チャンネル選択ビット
      ;			  |                 :
      ;			  |                 :
      ;			  |               00111 = AN7
      ;			  |           >   00110 = AN6
      ;			  |                 :
      ;			  |               00001 = AN1
      ;			  |               00000 = AN0
      ;			  |
      ;		bit7	  +------------ 未実装
      
      		movwf	ADCON0			;ADCON0: ADC制御レジスタ0
      
      		movlw	b'10010011'
      ;			  ||||||||
      ;		bit1-0	  ||||||++----- ADPREF<1:0>: ADC正側参照電圧コンフィグレーション ビット
      ;			  ||||||      >   11 = VREF+を内部の固定参照電圧(FVR)モジュールに接続
      ;			  ||||||          10 = VREF+を外部VREF+ピンに接続
      ;			  ||||||          01 = 予約済み
      ;			  ||||||          00 = VREF+をVDDに接続
      ;			  ||||||
      ;		bit2	  |||||+------- ADNREF: ADC負側参照電圧コンフィグレーション ビット
      ;			  |||||           1 = VREF-を外部VREF-ピンに接続
      ;			  |||||       >   0 = VREF-をVSSに接続
      ;			  |||||
      ;		bit3	  ||||+-------- 未実装
      ;			  ||||
      ;		bit6-4	  |+++--------- ADCS<2:0>: ADC変換クロック選択ビット
      ;			  |               111 = FRC(内部のRCオシレータから供給されるクロック)
      ;			  |               110 = FOSC/64
      ;			  |               101 = FOSC/16
      ;			  |               100 = FOSC/4
      ;			  |               011 = FRC(内部のRCオシレータから供給されるクロック)
      ;			  |               010 = FOSC/32
      ;			  |           >   001 = FOSC/8
      ;			  |               000 = FOSC/2
      ;			  |
      ;		bit7	  +------------ ADFM: A/D変換結果フォーマット選択ビット
      ;			              >   1 = 右詰め、変換結果を書き込むとADRESHの上位6ビットが「0」に設定
      ;			                  0 = 左詰め、変換結果を書き込むとADRESLの下位6ビットが「0」に設定
      
      		movwf	ADCON1			;ADCON1: ADC制御レジスタ1
      
      		; OPTION_REG の設定
      
      		movlb	1			;バンク 1
      		movlw	b'00000011'		;プルアップ有効、プリスケーラのスケール値 1:16
      		movwf	OPTION_REG
      
      		; 割り込みの設定
      
      		bcf	PIE1,TMR1IE		;TMR1IE: タイマー1割り込みを許可 = 0
      
      		movlb	0			;バンク 0
      		movlw	b'00000001'		;TMR1CS<1:0>: bit7-6=00: Timer1クロック源=命令クロック(FOSC/4)を選択
      						;T1CKPS<1:0>: bit5-4=00: プリスケーラ値を1:1
      						;TMR1ON:      bit0=1:    Timer1を有効
      		movwf	T1CON			;Timer1制御レジスタ
      
      		movlw	b'11000000'		;GIE:    bit7=1: グローバル割り込みを許可 = 1
      						;PEIE:   bit6=1: ペリフェラル割り込みを許可 = 1
      						;TMR0IE: bit5=0: TMR0 オーバーフロー割り込み許可 = 0
      						;INTE:   bit4=0: INT 外部割り込み許可 = 0
      						;IOCIE:  bit3=0: 状態変化割り込み許可 = 0
      		movwf	INTCON			;各割り込み要因の設定
      
      			:
      			:
      
 次に、実際にリチウムイオン電池の電圧を測定している部分を示します。 下リスト中の冒頭部分に示す図(実際の 回路図 も参照)のように、PIC のアナログ入力端子 RC2(AN6) には、固定参照電圧 2.048 V を使用するために、測定電圧を抵抗で 2 : 1 に分圧した 1 / 3 の電圧を加えています。 そのことを念頭に置いて次のリストをご覧になってください。
      ;==========================================================================
      ;		バッテリー(18650 リチウムイオン電池)の電圧測定
      ;==========================================================================
      
      ;			    ┌───┐  ┌───┐
      ;			┌─┤3.3KΩ├─┤3.3KΩ├── 電源電圧
      ;			│  └───┘  └───┘
      ;	   RC2(AN6) ──┤
      ;			│  ┌───┐
      ;			└─┤3.3KΩ├──────── GND
      ;			    └───┘
      
      battery_voltage
      
      ;	     >> BATTERY 電源電圧を測定する
      
      		movlb	1			;バンク 1
      		bsf	ADCON0,ADON		;ADC 有効 = 電源 ON
      		movlb	0			;バンク 0
      		movlp	high wait_20us
      		call	wait_20us		;アクイジション時間 (5μS以上)
      		movlp	high $
      		movlb	1			;バンク 1
      		bsf	ADCON0,ADGO		;A/D 変換開始
      		btfsc	ADCON0,ADGO		;変換完了(ハードでクリア) か?
      		goto	$ - 1			;No
      
      		bcf	ADCON0,ADON		;ADC 無効 = 電源 OFF
      		movlb	0			;バンク 0
      
      ;	     >> 結果 = ADRESH:ADRESL (右詰め) に測定電圧値
      ;
      ;		抵抗で分圧した分(2/3)を補正 ... x 3 倍する
      
      		clrf	ad_res_hi
      		clrf	ad_res_lo
      		movlw	3
      		movwf	lpcnt			;ループカウンタ
      
      battv01		movlb	1			;バンク 1
      		movf	ADRESL,W		;
      		addwf	ad_res_lo,F
      		movf	ADRESH,W		;
      		addwfc	ad_res_hi,F
      		movlb	0			;バンク 0
      		decfsz	lpcnt,F			;ループカウンタ - 1 = 0 か?
      		goto	battv01			;No
      
      ;	     >> 結果 = ad_res_hi:ad_res_lo ... x 3 倍に補正したバイナリデータ
      ;
      ;	  2.048 (V) : X (V) = 1024 : ad_res_hi:ad_res_lo
      ;
      ;	              X (V) = 2.048 * ad_res_hi:ad_res_lo / 1024
      ;	                    = 0.002 * ad_res_hi:ad_res_lo
      ;        	            = ad_res_hi:ad_res_lo / 500
      ;
      ;	        X (V) * 500 = ad_res_hi:ad_res_lo
      ;
      ;	     >> 0.01 V 単位にするため x 100 倍にする ... 5 で割る
      ;
      ;	        X (V) * 100 = ad_res_hi:ad_res_lo / 5
      
      		movlb	1			;バンク 1
      		movf	ad_res_hi,W		;割られる数
      		movwf	a16_hi
      		movf	ad_res_lo,W
      		movwf	a16_lo
      		clrf	b16_hi			;割る数
      		movlw	5
      		movwf	b16_lo
      		call	div_16			;16 ビットの割り算
      		movlb	0			;バンク 0
      
      ;	(a16_hi,a16_lo) ÷ (b16_hi,b16_lo) = (x16_hi,x16_lo) ... (y16_hi,y16_lo) 
      ;
      ;	     >> 結果 = 商 (x16_hi,x16_lo) ... 余り (y16_hi,y16_lo) は無視
      
      		return
      
      ;--------------------------------------------------------------------------
      ;		16 ÷ 16 = 16 ビットの割り算
      ;--------------------------------------------------------------------------
      
      ;	(a16_hi,a16_lo) ÷ (b16_hi,b16_lo) = (x16_hi,x16_lo) ... (y16_hi,y16_lo) 
      
      ; 使用変数:	a16_hi, a16_lo: 割られる数の上,下位	(終了時は0になる)
      ;		b16_hi, b16_lo: 割る数の    上,下位	(終了時に変化しない)
      ;		x16_hi, x16_lo: 答えの      上,下位	(答えが返る)
      ;		y16_hi, y16_lo: 余りの      上,下位	(余りが返る、ワークにも使用)
      ;		lcnt1,  lcnt2:  ループカウンタ
      ;		C フラグ:	エラーフラグ		(割る数が0であった場合 C=1)
      
      div_16
      		movlw	16
      		movwf	lcnt1			;ループカウンタ1
      		movf	b16_lo,W		;割る数下位をワークにコピー
      		movwf	y16_lo
      		movf	b16_hi,W		;割る数上位をワークにコピー
      		movwf	y16_hi
      
      d16_01		rlf	y16_lo,F		;左シフトする
      		rlf	y16_hi,F
      		btfsc	STATUS,C		;キャリフラグを見る
      		goto	d16_02			;割る数の上位ビット位置検索
      
      		decfsz	lcnt1,F
      		goto	d16_01
      
      		bsf	STATUS,C		;割る数が0である。エラー終了
      		goto	d16_09
      
      d16_02		clrf	x16_lo			;答え用変数のクリア
      		clrf	x16_hi
      		clrf	y16_lo			;ワーク変数のクリア
      		clrf	y16_hi
      
      		movlw	16
      		movwf	lcnt2			;ループカウンタ2
      		movf	lcnt1,W
      		subwf	lcnt2,F			;残り、実ループの回数
      
      d16_03		lslf	a16_lo,F
      		rlf	a16_hi,F
      		rlf	y16_lo,F
      		rlf	y16_hi,F
      		decfsz	lcnt1,F			;割られる数を初期位置までシフト
      		goto	d16_03
      
      d16_04		movf	b16_hi,W		;現位置での減算が可能かチェック
      		subwf	y16_hi,W
      		btfss	STATUS,C
      		goto	d16_06
      
      		movf	y16_hi,W
      		subwf	b16_hi,W
      		btfss	STATUS,C
      		goto	d16_05
      
      		movf	b16_lo,W
      		subwf	y16_lo,W
      		btfss	STATUS,C
      		goto	d16_06
      
      d16_05		movf	b16_lo,W
      		subwf	y16_lo,F		;ワークから下位を引く
      		btfss	STATUS,C		;キャリフラグが 1(正)なら次をスキップ
      		decf	y16_hi,F		;上位 -1
      
      		movf	b16_hi,W
      		subwf	y16_hi,F		;ワークから上位を引く
      		bsf	STATUS,C		;キャリフラグをセット
      		goto	d16_07
      
      d16_06		bcf	STATUS,C		;キャリフラグをクリア
      
      d16_07		rlf	x16_lo,F		;キャリフラグの内容を答えにシフト
      		rlf	x16_hi,F
      		movf	lcnt2,F
      		btfsc	STATUS,Z		;lcnt2 = 0 か?
      		goto	d16_08			;Yes, 終了
      
      		decf	lcnt2,F			;ビット位置を1つ下げる(右へ)
      		lslf	a16_lo,F		;ワークへ1ビット左シフト
      		rlf	a16_hi,F
      		rlf	y16_lo,F
      		rlf	y16_hi,F
      		goto	d16_04
      
      d16_08		bcf	STATUS,C		;正常終了
      
      d16_09		return
      
 上リストの battery_voltage サブルーチンによってバッテリー(18650 リチウムイオン電池)の電圧測定の結果、変数 x16_hi, x16_lo には実電圧を 100 倍したバイナリデータが得られますが、このバイナリ形式のデータでは見ても直感では分からないため、 これを次のリストのように 10進数の文字列に変換をしてから、実際の電圧値としてディスプレイ (OLED) 画面上に表示をさせています。

 この項の 冒頭 でも述べたように、本機では2つの場面で電池の電圧値がディスプレイ (OLED) 画面上に表示されますが、次のリストは [メンテナンス機能] 画面を表示したときに表示される場合の例を示しています。
      ;==========================================================================
      ;		バッテリー(18650 リチウムイオン電池)の電圧表示
      ;==========================================================================
      
      battery_volt__display
      
      		yOLED_FontPos_M	4+6*2,1		;
      		bsf	echr_flg,6		;1 bit 左(下)ずらし指示 = 1
      		yOLED_DispStr_M	batt_msg,1	;2 行目の表示
      
      		call	battery_voltage		;バッテリーの電圧測定
      
      		movlb	1			;バンク 1
      		movf	x16_hi,W
      		movwf	a16_hi
      		movf	x16_lo,W
      		movwf	a16_lo
      		call	bindec16cz_cnv		;16 ビット数値を 10進数 5桁の文字列に変換
      		movlb	0			;バンク 0
      
      		movlw	high (buff0+2)		;
      		movwf	FSR0H			;
      		movlw	low (buff0+2)		;
      		movwf	FSR0L			;間接アドレスの設定
      
      		yOLED_FontPos_M	4+6*11,1	;
      		moviw	FSR0++
      		call	ySSD1306_DispChr	;OLED へ1文字出力
      		movlw	'.'
      		call	ySSD1306_DispChr	;OLED へ1文字出力
      		moviw	FSR0++
      		call	ySSD1306_DispChr	;OLED へ1文字出力
      		moviw	FSR0++
      		call	ySSD1306_DispChr	;OLED へ1文字出力
      		return
      
      	;	dt	"=== Maintenance ===",0	;1 行目
      batt_msg	dt	  "[ Batt =  .  V ]",0	;2 行目
      
      			:
      			:
      
      ;--------------------------------------------------------------------------
      ;		16 ビット数値を 10進数 5桁の文字列に変換(ゼロサプレス)
      ;--------------------------------------------------------------------------
      
      ; 使用変数:	a16_hi, a16_lo: 変換する 16 ビット数値
      ;		 	 lcnt1: ワーク
      ;		         lcnt2: ループカウンタ
      ;		  buff0 + 0〜4: 結果
      
      bindec16cz_cnv
      		movlw	high (buff0+4+1)	;変換文字列の格納エリア
      		movwf	FSR0H
      		movlw	low (buff0+4+1)
      		movwf	FSR0L			;間接アドレスの設定
      
      		call	bd16c			;(04) 最下位変換
      		call	bd16c			;(03)
      		call	bd16c			;(02)
      		call	bd16c			;(01)
      		call	bd16c			;(00) 最上位変換
      
      		movlw	4			;
      		movwf	lcnt2			;ループカウンタに設定
      
      bd16cv01	moviw	0[FSR0]
      		sublw	h'30'
      		btfss	STATUS,Z		;(INDF) = h'30' か?
      		goto	bd16cv02		;No
      
      		movlw	' '
      		movwi	FSR0++
      		decfsz	lcnt2,F			;ループカウンタ - 1 = 0 か?
      		goto	bd16cv01		;No
      
      bd16cv02	return
      
      		; ÷10(10で除算)
      bd16c
      		movlw	16			;16ビット繰り返し
      		movwf	lcnt2			;ループカウンタに設定
      		clrf	lcnt1			;ワーク
      
      bd16c01		lslf	a16_lo,F
      		rlf	a16_hi,F
      		rlf	lcnt1,F
      		movlw	-10			;-10 = h'f6'
      		addwf	lcnt1,W
      		btfsc	STATUS,C		;C = 0 か?
      		movwf	lcnt1			;No
      		btfsc	STATUS,C		;C = 0 か?
      		incf	a16_lo,F		;No
      		decfsz	lcnt2,F			;ループカウンタ - 1 = 0 か?
      		goto	bd16c01			;No
      
      		movf	lcnt1,W			;余り
      		addlw	h'30'			;文字コードに変換
      		movwi	--FSR0
      		return
      
 なお、本機では精密な電圧測定器を作製するのが目的ではなく、電圧測定の結果を、18650 リチウムイオン電池の充電時期の判断に使用するのが目的なため、上述した 分圧抵抗器 には精密な金属皮膜抵抗等は使用しておらず、 一般的な ± 5 % のカーボン抵抗で済ませています。

| プログラムのトップに戻る |

● 高書き込み耐性フラッシュメモリのプログラミング

 まず初めに、従来、多くの PIC でデータの保存に使用されていた不揮発性メモリの EEPROM が、PIC16F1705 には存在していません。 同じ PIC16F1 ファミリーでも、例えば PIC16F1827 のように、種類によっては従来通り存在するものもありますが、 PIC16F1705 では EEPROM に代わるものとして、高書き込み耐性プログラム フラッシュメモリ (PFM) が、実装されている全プログラムメモリの内、最終ページ 3 の アドレス 1F80h 〜 1FFFh に 128 バイト 分が備えられています。

 高書き込み耐性フラッシュメモリのプログラミングとして、データの読み出しに関してはそれほど難しくなく、反してその書き込みではやや難しく(面倒に)なるので、この項では書き込みに関してを取り上げ、本機における具体例を重点的に述べてみます。

 この高書き込み耐性フラッシュメモリの内、次のリスト例のように、本機では先頭番地 save_data から 74 バイトを使用しています。 本機の前身(万年カレンダー II)ではタイマー機能がなく、したがって、そのタイマー用メモリのバックアップ用メモリも不要なため、 次リストの内の save_data から 3 バイトだけを使用していました。
      ;==========================================================================
      ;		High-Endurance フラッシュメモリ
      ;==========================================================================
      
      		org	h'1f80'
      
      		; 以下はデフォルト値
      
      save_data	dt	h'20'			;年(上位)_BCD カウンタ
      
      		dt	10			;スリープまでの移行時間(分)
      
      		dt	h'7f'			;OLED コントラスト
      
      		dt	h'a5'			;タイマー用メモリの初期設定制御バイト
      
      timer_memory_bup
      
      ;	      (これ以降 70 バイトをタイマー用メモリのバックアップ用として使用)
      
      ;==========================================================================
      
      		end				;プログラムの終了
      
 高書き込み耐性フラッシュメモリにデータを書き込む上での注意を、既に "194. FMステレオラジオ III" の 高書き込み耐性フラッシュメモリのプログラミング でも述べていますが、このことは EEPROM を扱う場合と異なって、より重要な点なので再度本項でも述べておきます。

 プログラムの命令(1ワード = 14 ビット)を格納するための、プログラムメモリ全体がフラッシュメモリで構成されているのですが、その内の高書き込み耐性フラッシュメモリ(アドレス 1F80h 〜 1FFFh の 128 バイト分)に関しては、 下位バイトしか存在しなくて(上位バイトがない)、すなわち、1ワード = 8 ビット = 1 バイトとなっています。

 EEPROM の場合には、単純に(といっても、それなりの手順はありますが)必要なバイトだけを、読み書きを行えば良かったのですが、フラッシュメモリに(書き換えるために)書き込む場合には、その前に予め書き込むメモリに対して消去処理をしておかなければならない、 というのが EEPROM の場合と比べて最も異なっている点です。

 高書き込み耐性フラッシュメモリの旧データを、新データに書き換える場合の事前の消去処理は、たとえ1バイトの書き換えであっても、その対象となる1バイトのメモリだけを消去することができず、そのメモリが所属する行全体を消去しなければなりません。 フラッシュメモリは行単位で構成されていて、1行は一定数のメモリワードで構成されているため、この1行がユーザプログラムで消去できる最小サイズとなっています。 この最小サイズは PIC の種類によって異なっていて、 本機の PIC16F1705 では 32 ワードとなっています。

 上述したように、前作(万年カレンダー II)では、高書き込み耐性フラッシュメモリの先頭番地から 3 バイトだけが、データのバックアップ対象として使用されるため、次の黒色リストのように、1行(32 ワード)消去後に 3 バイトだけを書き込んでいました。

 そのときの書き込み方法は、まず 1 バイト目と 2 バイト目を 書き込みラッチに書き込む ように指示(PMCON1 レジスタの LWLO ビットをセット) をし、最後の 3 バイト目のときに フラッシュメモリに書き込む ように指示(PMCON1 レジスタの LWLO ビットをクリア) をして、それぞれの書き込みデータを送るようにします。 このように2段階の手順を踏んだ結果、書き込みラッチ上のデータも含めてすべての 3 バイトが、フラッシュメモリに書き込まれます。
      			:
      			:
      
      		call	flash_mem_erase		;High-Endurance フラッシュメモリを1行(32 ワード)消去
      		call	flash_mem_write	       ;;RAM バッファから High-Endurance フラッシュメモリへ データ書き込み
      
      			:
      			:
      
      ;--------------------------------------------------------------------------
      ;	    High-Endurance フラッシュメモリを1行(32 ワード)消去
      ;--------------------------------------------------------------------------
      
      flash_mem_erase
      		bcf	INTCON,GIE		;割り込みを禁止
      		movlb	3			;バンク 3
      		movlw	low save_data
      		movwf	PMADRL
      		movlw	high save_data
      		movwf	PMADRH
      
      		bcf	PMCON1,CFGS		;フラッシュメモリにアクセス
      		bsf	PMCON1,FREE		;消去操作を指定、ハードウェアでクリア
      		bsf	PMCON1,WREN		;書き込みを許可
      
      		movlw	h'55'
      		movwf	PMCON2			;h'55' を PMCON2 に書き込む
      		movlw	h'aa'
      		movwf	PMCON2			;h'aa' を PMCON2 に書き込む
      		bsf	PMCON1,WR		;書き込み制御 = ON、ハードウェアでクリア
      		nop
      		nop
      		bcf	PMCON1,WREN		;書き込みを禁止
      		movlb	0			;バンク 0
      		bsf	INTCON,GIE		;割り込みを許可
      		return
      
      ;--------------------------------------------------------------------------
      ;    RAM バッファから High-Endurance フラッシュメモリへ データ書き込み
      ;--------------------------------------------------------------------------
      
      flash_mem_write
      		call	ram_buff_write		;個々の変数から RAM バッファへコピー
      
      		bcf	INTCON,GIE		;割り込みを禁止
      		movlb	3			;バンク 3
      		movlw	high save_data_ram	;フラッシュメモリの先頭アドレス
      		movwf	FSR1H			;
      		movlw	low save_data_ram	;
      		movwf	FSR1L			;間接アドレスに設定
      		movlw	save_data_end - save_data
      		movwf	f_lpcnt			;ループカウンタ
      
      		movlw	low save_data
      		movwf	PMADRL			;
      		movlw	high save_data
      		movwf	PMADRH			;
      
      		bcf	PMCON1,CFGS		;フラッシュメモリにアクセス
      		bsf	PMCON1,WREN		;書き込みを許可
      		bsf	PMCON1,LWLO		;書き込みラッチへ書き込み指示
      
      fmemwr01	moviw	FSR1++			;最初のデータバイトを下位にロード
      		movwf	PMDATL			;
      	;	moviw	FSR1++			;2番目のデータバイトを上位にロード
      	;	movwf	PMDATH			;
      		decfsz	f_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	fmemwr02		;No
      		goto	fmemwr03		;Yes
      
      fmemwr02	movlw	h'55'
      		movwf	PMCON2			;h'55' を PMCON2 に書き込む
      		movlw	h'aa'
      		movwf	PMCON2			;h'aa' を PMCON2 に書き込む
      		bsf	PMCON1,WR		;書き込み制御 = ON、ハードウェアでクリア
      		nop
      		nop
      		incf	PMADRL,F		;記録アドレスの更新
      		goto	fmemwr01
      
      fmemwr03	bcf	PMCON1,LWLO		;フラッシュメモリへ書き込み指示
      		movlw	h'55'
      		movwf	PMCON2			;h'55' を PMCON2 に書き込む
      		movlw	h'aa'
      		movwf	PMCON2			;h'aa' を PMCON2 に書き込む
      		bsf	PMCON1,WR		;書き込み制御 = ON、ハードウェアでクリア
      		nop
      		nop
      		bcf	PMCON1,WREN		;書き込みを禁止
      		movlb	0			;バンク 0
      		bsf	INTCON,GIE		;割り込みを許可
      		return
      
      ;--------------------------------------------------------------------------
      
      		; 個々の変数から RAM バッファへコピー
      ram_buff_write
      		movlw	high save_data_ram	;引継ぎ情報(データメモリ)の先頭アドレス
      		movwf	FSR1H			;
      		movlw	low save_data_ram	;
      		movwf	FSR1L			;間接アドレスに設定
      
      		movf	bcd_yh,W		;年(上位2桁)_BCD カウンタ
      		movwi	FSR1++			;
      
      		movf	sleep_time,W		;スリープまでの移行時間(分)
      		movwi	FSR1++			;
      
      		movf	contrast,W		;OLED コントラスト
      		movwi	FSR1++			;
      		return
      
      			:
      			:
      
      ;==========================================================================
      ;		High-Endurance フラッシュメモリ
      ;==========================================================================
      
      		org	h'1f80'
      
      		; 以下はデフォルト値
      
      save_data	dt	h'20'			;年(上位)_BCD カウンタ
      
      		dt	10			;スリープまでの移行時間(分)
      
      		dt	h'7f'			;OLED コントラスト
      save_data_end
      
      
      ;==========================================================================
      
      		end				;プログラムの終了
      
 これに対して本機(万年カレンダー III)では、高書き込み耐性フラッシュメモリの、先頭番地から 74 バイトがバックアップ対象として使用されるため、次の緑色リストのように書き込み方法はもう少し複雑になって、3行(32 x 3 = 96 ワード)消去後に全 74 バイトの更新データを書き込みます。

 このときの書き込み方法は、RAM バッファにある書き込みデータ 74 バイトを、先頭から初めの 32 バイト、次の 32 バイト、残りの 10 バイトの3つのグループに分け、それぞれのグループごとに書き込みを行っています。(flash_mem_write サブルーチン)

 具体的には、3つのグループそれぞれが処理できるようなループ(3回)を作り、第1ループが実行されるときには、初めのグループの 1 〜 31 バイト目までは 書き込みラッチに書き込む ように指示(PMCON1 レジスタの LWLO ビットをセット) をし、32 バイト目のときに フラッシュメモリに書き込む ように指示(PMCON1 レジスタの LWLO ビットをクリア) をして、それぞれの書き込みデータを送ると、その結果、書き込みラッチ上のデータも含めて、初めのグループのすべて 32(先頭から 1 〜 32)バイトが、フラッシュメモリに書き込まれます。

 同様に、次の第2ループが実行されるときには、次のグループの 1 〜 31(先頭から 33 〜 63)バイト目までは 書き込みラッチに書き込む ように指示(PMCON1 レジスタの LWLO ビットをセット) をし、32(先頭から 64)バイト目のときに フラッシュメモリに書き込む ように指示(PMCON1 レジスタの LWLO ビットをクリア) をして、それぞれの書き込みデータを送ると、その結果、書き込みラッチ上のデータも含めて、次のグループのすべて 32(先頭から 33 〜 64)バイトが、 フラッシュメモリに書き込まれます。

 続いて、最後の第3ループが実行されるときには、残りのグループの 1 〜 9(先頭から 65 〜 73)バイト目までは 書き込みラッチに書き込む ように指示(PMCON1 レジスタの LWLO ビットをセット) をし、10(先頭から 74)バイト目のときに フラッシュメモリに書き込む ように指示(PMCON1 レジスタの LWLO ビットをクリア) をして、それぞれの書き込みデータを送ると、その結果、書き込みラッチ上のデータも含めて、残りのグループのすべて 10(先頭から 65 〜 74)バイトが、 フラッシュメモリに書き込まれます。
      			:
      			:
      
      		call	flash_mem_erase		;High-Endurance フラッシュメモリを3行(32 x 3 ワード)消去
      		call	flash_mem_write	       ;;RAM バッファから High-Endurance フラッシュメモリへ データ書き込み
      
      			:
      			:
      
      ;--------------------------------------------------------------------------
      ;	 High-Endurance フラッシュメモリを3行(32 x 3 ワード)消去
      ;--------------------------------------------------------------------------
      
      flash_mem_erase
      		bcf	INTCON,GIE		;割り込みを禁止
      		movlb	3			;バンク 3
      		movlw	low save_data		;フラッシュメモリの先頭アドレス
      		movwf	PMADRL
      		movlw	high save_data
      		movwf	PMADRH
      
      		movlw	3
      		movwf	f_lpcnt			;ループカウンタ(共通 RAM)
      
      fmemer01	bcf	PMCON1,CFGS		;フラッシュメモリにアクセス
      		bsf	PMCON1,FREE		;消去操作を指定、ハードウェアでクリア
      		bsf	PMCON1,WREN		;書き込みを許可
      
      		movlw	h'55'
      		movwf	PMCON2			;h'55' を PMCON2 に書き込む
      		movlw	h'aa'
      		movwf	PMCON2			;h'aa' を PMCON2 に書き込む
      		bsf	PMCON1,WR		;書き込み制御 = ON、ハードウェアでクリア
      		nop
      		nop
      		bcf	PMCON1,WREN		;書き込みを禁止
      
      		movlw	32
      		addwf	PMADRL,F
      		decfsz	f_lpcnt,F		;ループカウンタ - 1 = 0 か?
      		goto	fmemer01		;No
      
      		movlb	0			;バンク 0
      		bsf	INTCON,GIE		;割り込みを許可
      		return
      
      ;--------------------------------------------------------------------------
      ;    RAM バッファから High-Endurance フラッシュメモリへ データ書き込み
      ;--------------------------------------------------------------------------
      
      flash_mem_write
      		call	ram_buff_write		;個々の変数から RAM バッファへコピー
      
      		bcf	INTCON,GIE		;割り込みを禁止
      		movlw	high save_data_ram	;引継ぎ情報(リニアデータメモリ)の先頭アドレス
      		movwf	FSR1H			;
      		movlw	low save_data_ram	;
      		movwf	FSR1L			;間接アドレスに設定
      		movlw	timer_mem_addr - save_data_ram
      		movwf	f_lpcnt			;ループカウンタ(共通 RAM)... 総書き込みバイト数
      
      		movlb	3			;バンク 3
      		movlw	low save_data		;フラッシュメモリの先頭アドレス
      		movwf	PMADRL			;
      		movlw	high save_data
      		movwf	PMADRH			;
      
      fmemwr01	movlw	32			;1 行 = 32 ラッチ数
      		movwf	f_lpcnt2		;ループカウンタ2(共通 RAM)
      
      		bcf	PMCON1,CFGS		;フラッシュメモリにアクセス
      		bsf	PMCON1,WREN		;書き込みを許可
      		bsf	PMCON1,LWLO		;書き込みラッチへ書き込み指示
      
      fmemwr02	moviw	FSR1++			;最初のデータバイトを下位にロード
      		movwf	PMDATL			;
      	;	moviw	FSR1++			;2番目のデータバイトを上位にロード
      	;	movwf	PMDATH			;
      		decf	f_lpcnt,F		;
      		btfsc	STATUS,Z		;ループカウンタ  - 1 = 0 か?
      		goto	fmemwr03		;Yes
      
      		decf	f_lpcnt2,F		;
      		btfsc	STATUS,Z		;ループカウンタ2 - 1 = 0 か?
      		goto	fmemwr03		;Yes
      
      		movlw	h'55'
      		movwf	PMCON2			;h'55' を PMCON2 に書き込む
      		movlw	h'aa'
      		movwf	PMCON2			;h'aa' を PMCON2 に書き込む
      		bsf	PMCON1,WR		;書き込み制御 = ON、ハードウェアでクリア
      		nop
      		nop
      		incf	PMADRL,F		;記録アドレスの更新
      		goto	fmemwr02
      
      fmemwr03	bcf	PMCON1,LWLO		;フラッシュメモリへ書き込み指示
      		movlw	h'55'
      		movwf	PMCON2			;h'55' を PMCON2 に書き込む
      		movlw	h'aa'
      		movwf	PMCON2			;h'aa' を PMCON2 に書き込む
      		bsf	PMCON1,WR		;書き込み制御 = ON、ハードウェアでクリア
      		nop
      		nop
      		incf	PMADRL,F		;記録アドレスの更新
      		bcf	PMCON1,WREN		;書き込みを禁止
      
      		movf	f_lpcnt,F		;
      		btfss	STATUS,Z		;ループカウンタ = 0 か?
      		goto	fmemwr01		;No
      
      		movlb	0			;バンク 0
      		bsf	INTCON,GIE		;割り込みを許可
      		return
      
      ;--------------------------------------------------------------------------
      
      		; 個々の変数から RAM バッファへコピー
      
      ram_buff_write
      		movlw	high save_data_ram	;引継ぎ情報(リニアデータメモリ)の先頭アドレス
      		movwf	FSR1H			;
      		movlw	low save_data_ram	;
      		movwf	FSR1L			;間接アドレスに設定
      
      		movf	bcd_yh,W		;年(上位2桁)_BCD カウンタ
      		movwi	FSR1++			;
      
      		movf	sleep_time,W		;スリープまでの移行時間(分)
      		movwi	FSR1++			;
      
      		movf	contrast,W		;OLED コントラスト
      		movwi	FSR1++			;
      
      		clrw				;初期設定制御バイト
      		movwi	FSR1++			;
      		return
      
 このように、本機(万年カレンダー III)の flash_mem_write サブルーチンでは、前作(万年カレンダー II)のサブルーチンに比べて、若干ですが複雑になっています。

| プログラムのトップに戻る |

● タイマー機能とそのプログラミング

 「機能概要と使用法」の タイマー機能とスイッチ操作 の項で述べたように、本機におけるタイマー機能には、[メモリの設定]、[メモリの読み出しと消去]、[タイマーメモリの監視] の3機能があり、予めタイマー情報をメモリに設定しておくと、 [タイマーメモリの監視] 機能によって、設定時刻が現在時刻に一致するとアラーム音によって通知をします。

 このタイマー情報は、[メモリの読み出し] 機能によっていつでもその内容を確認することができ、不要になった場合には手動で消去することもできますが、タイマー種類が年タイマーでは、アラーム音の通知後はそのタイマー情報は不要になるため、 タイマーメモリから自動的に消去されます。

 これらのタイマー機能は、前作 "201. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー II" に、新たな機能として追加をしたもので、PIC16F1705 のプログラムメモリ中のページ2に集中させています。 なお、この機能の核ともいえるタイマー用メモリは次に述べるように、リニア データメモリ内の一部分として存在をしています。 また、停電時のバックアップとして、High-Endurance フラッシュメモリにも同一データが書き込まれます。

 次に示す図は、本機プログラムのソースファイル (PerpetualCalendarIII.asm) からコメントの一部を抜き出したもので、「本機におけるリニアデータメモリの使用構成図」を表しています。
      ;		本機におけるリニアデータメモリの使用構成図
      
      ;linear_memory	equ	h'2000' + 80 * 2	;リニアデータメモリの先頭アドレス
      ;save_data_ram	equ	linear_memory		;引継ぎ情報の先頭アドレス
      ;timer_memory	equ	save_data_ram  + 4	;タイマー用メモリの先頭アドレス
      ;timer_capacity	equ	10			;タイマー用メモリの記憶容量の最大値
      ;timer_mem_addr	equ	timer_memory   + 7 * timer_capacity ;タイマー用メモリの先頭アドレス
      ;work_memory	equ	timer_mem_addr + 2 * timer_capacity ;ワークメモリの先頭アドレス
      ;next_memory	equ	work_memory    + 7 * timer_capacity ;次に使用できるメモリの先頭アドレス
      
      ;		  linear_memory	|				|
      ;		  save_data_ram	+-------------------------------+ 20A0 (h'2000' + 80 * 2) ―――――――
      ;				|	    (4 bytes)		|			    ↑	    ↑
      ;		   timer_memory	+-------------------------------+ 20A4			    |	    |
      ;				|				|			    |	    |
      ;				|				|			  BACKUP    |
      ;				|	   (70 bytes)		|			(74 bytes)  |
      ;				|				|			    |	    |
      ;				|				|			    ↓	    |
      ;		 timer_mem_addr	+-------------------------------+ 20EA			  ―――   USE
      ;				|	   (20 bytes)		|			       (164 bytes)
      ;				|				|				    |
      ;		    work_memory	+-------------------------------+ 20FE				    |
      ;				|				|				    |
      ;				|				|				    |
      ;				|	   (70 bytes)		|				    |
      ;				|				|				    |
      ;				|				|				    ↓
      ;		    next_memory	+-------------------------------+ 2144			  ―――――――
      ;				|				|
      ;				|				|
      
 このように、前述した TABLE 3-3 に示した水色に塗った、リニアデータメモリの先頭から 164 バイトを使用していますが、この内の先頭から 74 バイトを High-Endurance フラッシュメモリへのバックアップ対象としています。 (先頭の 4 バイトは、タイマー用メモリとは別物)

◎ タイマー用メモリの構成

 本機では、本機におけるデータメモリの使用状況 の TABLE 3-3 に示したように、データメモリの BANK2 以降の 汎用レジスタ(GPR) を、リニア データメモリ(水色に塗ったレジスタ群)として扱い、 その一部分(70 バイト)をタイマー用メモリとして使用しています。

 そのタイマー用メモリの内訳は、下図に示すように1件分のタイマー情報を 7 バイトで構成し、最大 10 件分のタイマー情報が扱えるようにプログラミングをしています。 余談ですが、70 バイトのタイマー用メモリ以外の水色に塗ったリニア データメモリ部分は、 主に、タイマー用メモリを扱う上でのワークエリアとして使用しています。


 1件分 7 バイトの内、先頭バイトは タイマー制御バイト と呼び、まず、先頭の f ビット(メモリ有効フラグ) = 1 の場合には、その1メモリ単位(7バイト)に書かれているデータ内容すべてが 有効(使用中)であることを示しています。 逆に、f ビット(メモリ有効フラグ) = 0 の場合には、例え他のビットやバイトにデータ内容が残っていても、その1メモリ単位(7バイト)は無効(空き)であることを示し、 他のデータ内容で上書をしても構わないことを意味しています。

 本機のタイマー機能の指定には2種類の形態があり、t ビット(タイマー種類フラグ) = 0 の場合には 年タイマー を表し、"年、月、日、時、分" を指定します。 この年タイマーでは監視機能によるアラーム音の通知後はそのタイマー情報は不要になるため、 タイマーメモリから自動的に消去されます。

 一方、t ビット(タイマー種類フラグ) = 1 の場合には 週間タイマー を表し、"曜日、時、分" を指定します。 この場合にはタイマーメモリから自動的に消去されることがないため、後述の消去機能によってユーザが手動で消去をしない限り、 いつまでもタイマーメモリ内に残り続け、毎週同時刻になるとアラーム音の通知を行います。 なお、曜日に '00' を指定した場合には、曜日には関係なく毎日指定をしたことになり、毎日同時刻になるとアラーム音の通知を行います。

 また、本機においては時間指定のときに、24H / 12H のどちらの時間表示の形式で指定しても構いません。 その別を aa ビット(24H/12H フラグ)で表しています。

 タイマー制御バイトの次以降の各バイトは、実際にユーザによって入力された、タイマー情報を格納しておくための各カウンタバイトで、"年4桁"、"月2桁"、"日2桁"、"時2桁"、"分2桁" の各 BCD データ形式で扱われます。 なお、週間タイマーの場合には "年4桁"、"月2桁"、"日2桁" は不要のために使用されず、"日2桁" の位置の下位4ビットが "曜日カウンタ" として使用されます。

 そのために、週間タイマーの場合には無駄なメモリが消費されますが、週間タイマーも年タイマーと同一サイズとして扱うことにより、プログラムの簡略化を図っています。 使用した PIC16F1705 には 1K バイトのデータメモリ(汎用レジスタ(GPR))が存在するので、 ふんだんに使用しました。(といっても 70 バイトのみですが ・・・)

| プログラムのトップに戻る |

◎ [タイマーメモリの監視] 機能のプログラミング

 タイマー機能と一口に言っても、この項の 冒頭 でも述べたように大きく分けて、[メモリの設定]、[メモリの読み出しと消去]、[タイマーメモリの監視] の3機能があり、全体としてはかなり大きなプログラム群となっているので、 それらのすべてについてを解説することは簡単にはできません。 したがって、この項ではその内の [タイマーメモリの監視] 機能についてのみを解説します。

 次に示すリスト中の timer_memory_monitor サブルーチン で、タイマー用メモリの監視(一致検査)を行っていますが、このサブルーチンが CALL される契機となるのは、次のリストの冒頭にあるように、毎秒ごとの RTC DS3231 から年月日、時分秒を読み出した直後に、まず初めに time_alarm_control サブルーチン が CALL され、そのサブルーチン内で毎分 00 秒を検出したのを契機として、timer_memory_monitor サブルーチンが CALL されます。

 その他、time_alarm_control サブルーチン内では、時報音(予報音と正報音)についても、それらを出力するタイミングを検出しています。 そして、実際にアラーム音を出力するのは alarm_sound サブルーチン ですが、下リストの例ではメインルーチン内での、 これらのサブルーチン同士の関係を表しています。 他に、本機がスリープ中においても同様に、時報音やタイマー用メモリの監視を行っていて、SIGNAL スイッチによって "Signal On" の有効に設定されているときには、アラーム音が出力されます。
      main
      
      			:
      			:
      
      		call	clock_rtc_read		;RTC DS3231 から年月日,時分秒を読み出し
      		call	time_alarm_control	;時報音、タイマー一致音フラグコントロール
      
      			:
      			:
      
      		call	alarm_sound		;時報音、タイマー一致音のアラーム出力
      
      			:
      			:
      
      ;==========================================================================
      ;		時報音、タイマー一致音フラグコントロール
      ;==========================================================================
      
      ;	alm_flg: アラーム音出力フラグ
      
      ;	  bit7: アラーム音出力許可フラグ
      ;	  bit3: 時報正報音フラグ           ... "ポッ〜〜ン"   音  1 回 ... bcd_ss  = h'00' & bcd_mm = h'00'
      ;	  bit2: 時報予報音フラグ           ... "プッ"         音  3 回 ... bcd_ss >= h'57' & bcd_mm = h'59'
      ;	  bit1: タイマー一致音フラグ       ... "ピポッピポッ" 音 10 回 ... bcd_ss  = h'00' & タイマー条件
      ;	  bit0: タイマー一致音継続中フラグ				   bcd_ss  < h'10' & alm_flg.0 = 1
      
      time_alarm_control
      
      		btfss	alm_flg,7		;アラーム音出力許可フラグ = 1 か?
      		goto	tacon04			;No
      
      		movf	bcd_ss,W
      		btfss	STATUS,Z		;bcd_ss = h'00' か?
      		goto	tacon02			;No
      
      		movf	bcd_mm,W
      		btfss	STATUS,Z		;bcd_mm = h'00' か?
      		goto	tacon01			;No
      
      		; bcd_ss = h'00' & bcd_mm = h'00'
      		bsf	alm_flg,3		;時報正報音フラグ = 1
      
      		; bcd_ss = h'00'
      tacon01		movlp	high timer_memory_monitor
      		call	timer_memory_monitor	;タイマー用メモリの監視(一致検査)
      		movlp	high $
      		btfss	STATUS,Z		;一致 か?
      		goto	tacon04			;No
      
      		bsf	alm_flg,1		;タイマー一致音フラグ = 1
      		bsf	alm_flg,0		;タイマー一致音継続中フラグ = 1
      		goto	tacon04
      
      tacon02		movlw	h'59'
      		subwf	bcd_mm,W		;分_BCD カウンタ
      		btfss	STATUS,Z		;bcd_mm = h'59' か?
      		goto	tacon03			;No
      
      		movlw	h'57'
      		subwf	bcd_ss,W		;秒_BCD カウンタ
      		btfss	STATUS,C		;bcd_ss >= h'57' か?
      		goto	tacon03			;No
      
      		; bcd_ss >= h'57' & bcd_mm = h'59'
      		bsf	alm_flg,2		;時報予報音フラグ = 1
      		goto	tacon04
      
      tacon03		btfss	alm_flg,0		;タイマー一致音継続中フラグ = 1 か?
      		goto	tacon04			;No
      
      		; alm_flg.0 = 1
      		movlw	h'10'
      		subwf	bcd_ss,W		;秒_BCD カウンタ
      		btfss	STATUS,C		;bcd_ss <  h'10' か?
      		bsf	alm_flg,1		;Yes. タイマー一致音フラグ = 1
      		btfsc	STATUS,C		;bcd_ss >= h'10' か?
      		bcf	alm_flg,0		;Yes. タイマー一致音継続中フラグ = 0
      
      tacon04		return
      
      ;==========================================================================
      ;		時報音、タイマー一致音のアラーム出力
      ;==========================================================================
      
      ;	出力の優先順位:  タイマー一致音 > 時報予報音 > 時報正報音
      
      ;	同時に複数のフラグ = 1 の場合は、優先順位の低いものは無視される
      
      alarm_sound
      
      ;		btfss	alm_flg,7		;アラーム音出力許可フラグ = 1 か?
      ;		goto	alarm04			;(このフラグ = 0 のときは、
      						;3つのフラグ = 1 になることはない)
      		movlw	h'0e'
      		andwf	alm_flg,W
      		btfsc	STATUS,Z		;どれかアラームフラグ = 1 か?
      		goto	alarm04			;No
      
      		btfss	alm_flg,1		;タイマー一致音フラグ = 1 か?
      		goto	alarm01			;No
      
      		call	buzzer_pipo2		;"ピポッピポッ" アラーム音出力 (520 mS)
      		goto	alarm03
      
      alarm01		btfss	alm_flg,2		;時報予報音フラグ = ON か?
      		goto	alarm02			;No
      
      		call	buzzer_pu		;"プッ" アラーム音出力 (100 mS)
      		goto	alarm03
      
      alarm02	;	btfss	alm_flg,3		;時報正報音フラグ = ON か?
      	;	goto	alarm03			;No
      
      		call	buzzer_poon		;"ポッ〜〜ン" アラーム音出力 (1000 mS)
      		bcf	PORTC,_BZ		;ブザー出力ビットを "L" にしておく
      
      alarm03		movlw	h'81'
      		andwf	alm_flg,F		;アラーム音フラグをクリア
      
      alarm04		return
      
      			:
      			:
      			:
      
      ;==========================================================================
      ;		タイマー用メモリの監視(一致検査)
      ;==========================================================================
      
      timer_memory_monitor
      
      		movlw	high timer_memory	;タイマー用メモリの先頭アドレス
      		movwf	FSR1H			;
      		movlw	low timer_memory	;
      		movwf	FSR1L			;
      
      		movlw	timer_capacity		;タイマー用メモリの記憶容量の最大値
      		movwf	lpcnt			;ループカウンタ1
      
      tmmon01		btfss	INDF1,7			;タイマー用メモリの f bit = 1 (有効) か?
      		goto	tmmon08			;No
      
      		btfsc	INDF1,0			;タイマー種類 = 1:週間タイマー か?
      		goto	tmmon03			;Yes
      
      		; 2 バイト目 〜 5 バイト目の一致チェック
      
      tmmon02		moviw	1[FSR1]			;2 バイト目
      		subwf	bcd_yh,W		;年(上位2桁)_BCD カウンタ
      		btfsc	STATUS,Z		;bcd_yh = 1[FSR1] か?
      		goto	$ + 4			;Yes
      		btfss	STATUS,C		;bcd_yh > 1[FSR1] か?
      		goto	tmmon08			;No
      		goto	tmmon05			;Yes
      
      		moviw	2[FSR1]			;3 バイト目
      		subwf	bcd_yl,W		;年(下位2桁)_BCD カウンタ
      		btfsc	STATUS,Z		;bcd_yl = 2[FSR1] か?
      		goto	$ + 4			;Yes
      		btfss	STATUS,C		;bcd_yl > 2[FSR1] か?
      		goto	tmmon08			;No
      		goto	tmmon05			;Yes
      
      		moviw	3[FSR1]			;4 バイト目
      		subwf	bcd_nn,W		;月_BCD カウンタ
      		btfsc	STATUS,Z		;bcd_nn = 3[FSR1] か?
      		goto	$ + 4			;Yes
      		btfss	STATUS,C		;bcd_nn > 3[FSR1] か?
      		goto	tmmon08			;No
      		goto	tmmon05			;Yes
      
      		moviw	4[FSR1]			;5 バイト目
      		subwf	bcd_dd,W		;日_BCD カウンタ
      		btfsc	STATUS,Z		;bcd_dd = 4[FSR1] か?
      		goto	tmmon04			;Yes
      		btfss	STATUS,C		;bcd_dd > 4[FSR1] か?
      		goto	tmmon08			;No
      		goto	tmmon05			;Yes
      
      tmmon03		moviw	4[FSR1]			;5 バイト目
      		btfsc	STATUS,Z		;4[FSR1] = h'00':"Eday" か?
      		goto	tmmon04			;Yes
      
      		subwf	bcd_ww,W		;曜日_BCD カウンタ
      		btfss	STATUS,Z		;bcd_ww = 4[FSR1] か?
      		goto	tmmon08			;No
      
      		; 6 バイト目、7 バイト目の一致チェック
      
      tmmon04		moviw	5[FSR1]			;6 バイト目
      		subwf	bcd_hh,W		;時_BCD カウンタ
      		btfsc	STATUS,Z		;bcd_hh = 5[FSR1] か?
      		goto	$ + 4			;Yes
      		btfss	STATUS,C		;bcd_hh > 5[FSR1] か?
      		goto	tmmon08			;No
      		goto	tmmon05			;Yes
      
      		moviw	6[FSR1]			;7 バイト目
      		subwf	bcd_mm,W		;分_BCD カウンタ
      		btfsc	STATUS,Z		;bcd_mm = 6[FSR1] か?
      		goto	tmmon06			;Yes
      		btfss	STATUS,C		;bcd_mm > 6[FSR1] か?
      		goto	tmmon08			;No
      
      		; (過去のもの)
      
      tmmon05		btfsc	INDF1,0			;タイマー種類 = 1:週間タイマー か?
      		goto	tmmon08			;Yes
      
      		clrf	INDF1			;タイマー用メモリの自動消去
      
      		movf	FSR1H,W			;退避
      		movwf	addr_high		;
      		movf	FSR1L,W			;
      		movwf	addr_low		;
      		call	yflash_mem_erase_write	;フラッシュメモリの消去とデータ書き込み
      		movf	addr_high,W		;
      		movwf	FSR1H			;
      		movf	addr_low,W		;
      		movwf	FSR1L			;復帰
      		goto	tmmon08
      
      		; 一致あり
      
      tmmon06		btfsc	INDF1,0			;タイマー種類 = 1:週間タイマー か?
      		goto	tmmon07			;Yes
      
      		clrf	INDF1			;タイマー用メモリの自動消去
      		call	yflash_mem_erase_write	;フラッシュメモリの消去とデータ書き込み
      
      tmmon07		bsf	STATUS,Z		;Z フラグ = 1、一致あり
      		goto	tmmon09
      
      		; 一致なし
      
      tmmon08		addfsr	FSR1,7			;間接アドレス + 7 更新
      		decfsz	lpcnt,F			;ループカウンタ1 - 1 = 0 か?
      		goto	tmmon01			;No
      
      		bcf	STATUS,Z		;Z フラグ = 0、一致なし
      
      tmmon09		return
      
 タイマー用メモリの監視(一致検査)を行う timer_memory_monitor サブルーチン では、タイマー用メモリの構成図 にしたがって、1メモリ単位データごとに 10 件分のすべてが順に調べられます。 そして、まず初めに調べられるのは、各メモリ単位データごとの先頭バイト(タイマー制御バイト)内の、先頭の f ビット(メモリ有効フラグ)で、f ビット = 0 の場合には、そのメモリ単位データは無効(空き)データなので、次のメモリ単位データの検査に移ります。

 一方、f ビット = 1 の場合には、そのメモリ単位データは有効(使用中)なので、第2バイト以降に格納されている各タイマー情報と現在の情報とが比較検査されますが、本機のタイマー種類には、年タイマーと週間タイマーの2種類があって、 先頭バイト(タイマー制御バイト)内の、t ビット(タイマー種類フラグ)によってどちらかに振り分けられ、それぞれのタイマー種類で比較対象となるバイト位置が異なります。

 年タイマーの場合には、まず、第2バイトから第5バイトまでに位置する、"年4桁、月2桁、日2桁" の各 BCD データ4バイトが比較対象となりますが、週間タイマーの場合には、第2バイトから第4バイトまではダミーバイトで使用されず、 第5バイトの下位4ビットが "曜日カウンタ" として比較対象となります。

 そして、それぞれの種類で比較一致した場合には、次に、第6バイトと第7バイトに位置する、"時2桁、分2桁" の各 BCD データ2バイトが比較されます。 このように、順にタイマー用メモリ上の各 BCD データが比較されて、すべての BCD データが一致した場合にのみ、 Z フラグ = 1 にセットして当サブルーチンを終了します。 それ以外では不一致なので次のメモリ単位データに移って、f ビット(メモリ有効フラグ)の検査から繰り返しますが、すべてのメモリ単位データで不一致の場合には、Z フラグ = 0 にセットして終了します。

 ここで、第6バイト目の "時2桁" について補足をしておくと、本機の [メモリの設定] 機能では "時" の入力設定時に、24H / 12H のどちらの時間表示形式でも入力が可能で、その情報を先頭バイト(タイマー制御バイト)内の、aa ビット(24H/12H フラグ)で 管理をしています。 しかし、これは [メモリの読み出しと消去] 機能で表示確認をさせたときに、入力設定時の表示形式と互換を取るための表示用に使用されますが、第6バイト目の "時2桁" そのものは、常に 24H 形式で登録がされます。

 なお、年タイマーで登録されているメモリ単位データは、比較一致を検出した以降ではそのタイマー情報は不要になるため、タイマー用メモリからプログラムで消去をしています。 また、[メモリの設定] 機能で、年タイマーで現在時刻よりも過去の情報を入力した場合には、 一旦はタイマー用メモリに登録されますが、この [タイマーメモリの監視] 機能が実行された時点で、同様にプログラムが消去をしています。 このように、タイマー用メモリの内容に変更が加わった場合には、バックアップ用のフラッシュメモリも更新がされます。

( 2025/5/17 追記 )

 上述したように、timer_memory_monitor サブルーチンが実行されるのは、SIGNAL スイッチによって "Signal On" の状態に設定されているときに、time_alarm_control サブルーチン内で毎分 00 秒を検出したのを契機とするため、 "Signal Off" の状態に設定されているときには、timer_memory_monitor サブルーチンは実行されません。

 したがって、この "Signal Off" 状態のときには上で述べた、年タイマーで現在時刻よりも過去の情報を入力した場合の自動消去も行われません。

 上に示した緑色リストは既に修正版に差し替えてありますが、この自動消去をさせる機能に少しばかりの不具合がありました。 消去をする過去の対象データが1件だけのときは良いのですが、複数件あった場合には、1件目だけは消去されますが2件目以降が消去されない ― という事象です。

 上の timer_memory_monitor リスト中、(過去のもの)のコメント以下の部分を修正しました。
    
    < (1) 修正前 >
    
      		; (過去のもの)
      
      tmmon05		btfsc	INDF1,0			;タイマー種類 = 1:週間タイマー か?
      		goto	tmmon08			;Yes
      
      		clrf	INDF1			;タイマー用メモリの自動消去
      		call	yflash_mem_erase_write	;フラッシュメモリの消去とデータ書き込み
      		goto	tmmon08
      
    
    < (2) 修正後 >
    
      		; (過去のもの)
      
      tmmon05		btfsc	INDF1,0			;タイマー種類 = 1:週間タイマー か?
      		goto	tmmon08			;Yes
      
      		clrf	INDF1			;タイマー用メモリの自動消去
      
      		movf	FSR1H,W			;退避
      		movwf	addr_high		;
      		movf	FSR1L,W			;
      		movwf	addr_low		;
      		call	yflash_mem_erase_write	;フラッシュメモリの消去とデータ書き込み
      		movf	addr_high,W		;
      		movwf	FSR1H			;
      		movf	addr_low,W		;
      		movwf	FSR1L			;復帰
      		goto	tmmon08
      
 timer_memory_monitor サブルーチンが実行されて、このように自動消去でタイマー用メモリの内容に変更が起こったような場合には、そのデータのバックアップである High-Endurance フラッシュメモリの内容も、yflash_mem_erase_write サブルーチンが新データに書き換えています。

 < (1) 修正前 > の timer_memory_monitor サブルーチン内では FSR1 レジスタを使用していますが、そのサブルーチン内から CALL される、yflash_mem_erase_write サブルーチン(実際には flash_mem_write サブルーチン)内でも、同じ FSR1 レジスタが別目的で使用されていたため、flash_mem_write サブルーチンから RETURN したときにはその内容が壊されてしまい、過去の対象データが複数件あった場合には、正しい FSR1 レジスタのデータを引き継ぐことができなかったための事象でした。

 そこで < (2) 修正後 > のように、yflash_mem_erase_write サブルーチンを CALL する前後で、FSR1 レジスタの退避、復帰を行うように改めました。

| プログラムのトップに戻る |

現在の最新プログラムバージョン: Ver. 2.08  ( 2025/5/17 更新 )

ソースファイル (PerpetualCalendarIII.asm)
 I2C (SCLクロック周波数 = 100/400 KHz) サブルーチン(ソフトウエア I2C 版)(I2C_XS.sub) Ver. 1.04
 I2C RTC(DS3231/1307)モジュール 制御サブルーチン (I2C_RTCII.sub) Ver. 1.04
 OLED モジュール ( SSD1306 ) 制御サブルーチン (OLED_SSD1306.sub) Ver. 1.04
 文字フォント(5 x 7)データテーブル (Font5x7a.tbl)
HEX ファイル (PerpetualCalendarIII.hex)

| ページトップ |

■ プリント基板の加工と部品配置 ■

 使用したプリント基板は、前作( 万年カレンダー II )で使用したものと同様で、メインとなる下図 左側のプリント基板 は、"秋月電子" の "片面ガラスコンポジット・ユニバーサル基板 Bタイプ めっき仕上げ(95 x 72 mm)日本製 型番: AE-B2-CEM3(販売コード 103230)" ですが、後述の ケース加工図 で示したケース内に収めるためには、 プリント基板の切断等の加工が必要です。 左図に示すように、まず基板下部の ----- X 線の位置で切断をします。

 そして、この切断によって失われた基板下部の取り付け用穴の代理となる、新たなΦ3.2 の穴を図のように2か所開けます。 次に、基板右端に位置するスイッチ用基板の取り付けのために用いる、 ジュラコンスペーサ用のΦ3.2 の穴を2か所開けます。


 次に 右側のプリント基板 は、"秋月電子" の "片面ガラス・ユニバーサル基板 Cタイプ(72 x 47.5 mm)めっき仕上げ(販売コード 100517)" で、左側メイン基板の右端に取り付けるスイッチ用基板になるもので、 他にコネクタ用の小基板2枚も切り出します。 私は前作( 万年カレンダー II )で使用した残りの基板を使用しました。

| プリント基板部品配置図 (PerpetualCalendarIIIPC0.CE3) | (PerpetualCalendarIII2PC0.CE3) | ページトップ |

■ プリント基板(1)パターン図 (部品面) ■

 メイン基板に多くのパーツを搭載するにあたっては、それぞれに対して以降に述べるような注意事項があるので、基板を組み立てる上での参考にしてください。 なお、図の中で、細長い長方形の中に ○で表したものはピンヘッダ(オス)を、同様に◎で表したものはピンソケット(メス)を使用することを表しているので、注意をしてください。


上図から黒文字を除去して表示

・DS3231 RTC モジュール
 プリント基板の左上角に位置する縦長の四角状のものが DS3231 RTC モジュールで、本機では リアルタイムクロック( DS3231 )モジュール の項で説明をした改造が必要になります。 具体的な改造方法はそちらの項で詳述しているので参考にしてください。

・TP4056 充電モジュール
 プリント基板の左下に位置する "TP4056 充電モジュール" の取り付けについては、まず、縦横4か所の各青色線で示す位置の、メイン基板のハンダ面側から 0.4 〜 0.5 mm の錫メッキ線等を通し、モジュール基板上面側で各青色線の対となるもう片方の穴へグルっとUターンをして、 再び、メイン基板のハンダ面側に通した後はんだ付けをします。 このとき、モジュール基板側は 2.54 mm ピッチではないため注意が必要ですが、メイン基板側の穴位置は、前項 プリント基板の加工と部品配置 で示した縦横4か所の各青色線で示したランド穴位置を選択すれば問題はないでしょう。

 次に、モジュール基板左側の斜2か所の青色線で示すモジュール基板側の穴に対応するメイン基板側の位置には、ランド穴が開いていないのでこの位置にΦ1 程度の穴を開ける必要があり * ます。 穴を開けた後、前の縦横4か所のときと同要領で斜2か所についても、錫メッキ線等でモジュール基板の固定をします。 ただし、前の縦横4か所についてはその後、メイン基板のハンダ面側で回路の配線が必要になりますが、この斜2か所については回路の配線はありません。
      * モジュール基板のメーカーや、TP4056 リチウムイオン電池充電モジュール で述べた、Micro USB /タイプ C の USB コネクタの種類によっては、モジュール基板の穴位置が多少異なるため、 穴開けが不要な場合もあります。 私の場合にはメイン基板の左端を超えたため、穴を開けなくても錫メッキ線を通すことができました。
 また、この充電モジュールでバッテリに充電中には、充電制御 IC TP4056 がかなり発熱をするので、手持ちにあったヒートシンクを熱伝導シール(両面粘着)で貼り付けました。

・OLED モジュール
 プリント基板の上部中央には、本機の目玉である OLED モジュールが位置します。 メイン基板側にはあらかじめ 4P のピンソケットを取り付けておき、OLED モジュール側のピンヘッダと嵌合させます。 このとき、ピンソケットには分割ピンソケットを使用するとその加工が楽になります。

・トグルスイッチ
 プリント基板下部中央に位置する POWER スイッチには、3P(1回路)のトグルスイッチで良いのですが、3P でレバーが短いタイプが私の持ち合わせになく、6P(2回路)のものがあったので私は代わりにそれを使用しました。 したがって、3P でレバーが短いタイプを入手した場合には、基板パターン図を 3P(1回路)用に変更をしてください。

 本機では ケース加工図 で示したケース(内寸高さ 24 mm)を使用したため、レバーが通常のタイプは不可で、短いタイプでないとケース内に収めることができません。

 通常、本機のように時計関連の製作物には POWER スイッチ等は設けない場合が多いのですが、本機の場合には、18650 リチウムイオン電池を充電する場合には、TP4056 充電モジュールの負荷接続端子を開放しておく必要があるために、その目的でスイッチを設置しました。

・タクトスイッチ用基板との接続コネクタ
 プリント基板の右端縦長の位置に、タクトスイッチ用基板を取り付けますが、この基板の取り付けには、後述の ケースへのプリント基板の取り付け で説明しているように、私の場合には手持ちの関係で、 13 mm 長のオネジ+メネジの六角ジュラコンスペーサ(廣杉計器 BS-313W)を使用しました。

 そして、電気的な接続には、下の プリント基板(2)パターン図 (部品面) (ハンダ面) の項で示した、タクトスイッチ用基板のケーブルコネクタ( 7P ピンソケット(メス))と、メイン基板上に設けた 7P L型ピンヘッダとを、常時接続をさせておきます。 なお、メイン基板側のピンヘッダは、パターン図や写真のように L型でないと接続ができません。

・その他
 プリント基板左下の 3P のピンヘッダ B+ と B- 端子には、本機の電源である 18650 リチウムイオン電池を、電池ホルダからの配線( 3P ピンソケット(メス))を介して接続させます。 電気的には 2P で良いのですが、 2P 状態よりも 3P の方が、しっかりとコネクタ接続ができるために 3P としました。 そのため、真ん中のピンには配線はしていません。

| プリント基板(1)パターン図 (部品面) (PerpetualCalendarIIIPC.CE3) | 左図から黒色文字を除いた図 (PerpetualCalendarIIIPC2.CE3) | ページトップ |

■ プリント基板(1)パターン図 (ハンダ面) ■

 前項 プリント基板(1)パターン図 (部品面) でも述べたように、下パターン図や写真は、トグルスイッチに 3P(1回路)ではなく 6P(2回路)を使用したものなので、3P(1回路)トグルスイッチを使用した場合には、 スイッチ周りのパターンを適宜変更をしてください。


| プリント基板(1)パターン図 (ハンダ面) (PerpetualCalendarIIIPC1.CE3) | ページトップ |

■ プリント基板(2)パターン図 (部品面) ■

 本機では、タクトスイッチをプリント基板(2) に取り付けるときには、スイッチの底面を基板にぴったり押し付けて取り付けることが必要です。 (詳細は、後述の ケースへのプリント基板の取り付け の項を参照してください。)

| プリント基板(2)パターン図 (部品面) (PerpetualCalendarIII2PC.CE3) | ページトップ |

■ プリント基板(2)パターン図 (ハンダ面) ■

| プリント基板(2)パターン図 (ハンダ面) (PerpetualCalendarIII2PC1.CE3) | ページトップ |

■ ケース加工図 ■

 本機のケースも、前作( 万年カレンダー II )で使用したものとまったく同じもので、"秋月電子" の "ABS樹脂ケース(蝶番式・中)112−TS ニシムラ (販売コード: 100277)" を使用しました。 外側(内側)寸法が 117 (112) x 84 (80) x 28 (24) mm で、可動式のフタが付いています。


 上図の(上面図)及び(左側面図)において、各丸穴の位置寸法を記入* はしてありますが、参考程度に見ておいてください。 実際に穴開けを行う場合には、プリント基板を仮に取り付けた後、ケースが透明で中が透けて見えているので、 現物合わせで丸穴の中心位置を千枚通し等で印を付けて位置決めを行った方が、穴開けがうまくいくと思います。 ただし、(下面図)におけるプリント基板の取り付け用の穴位置は、極力、正確な位置に穴開けを行うように心掛けてください。
      * ユニバーサルプリント基板は 1/10 inch = 2.54 mm というサイズ単位で穴開けがされているため、6個のタクトスイッチのキートップ用の各穴間隔は 10 mm ではなく、実際には 10.16 mm となる。
・メイン基板の取り付け
 上図の(下面図)はケースの裏面側から見た図で、上部の大きな点線の四角部分(72 x 89 mm)がメイン基板の取り付け位置です。 私がプリント基板をケース等に取り付ける場合、通常、両者の間には 5 mm 長のスペーサを挟んで 取り付けることが多いのですが、本機のメイン基板には 5 mm 長のスペーサを使用することができません。

 上の プリント基板(1)パターン図 (部品面) の項で、使用した トグルスイッチ について述べたように、本機ではレバーが短いタイプを使用していますが、メイン基板を上図のケース内に納めるためには 5 mm 長のスペーサでは長過ぎて、 上蓋が閉まらなくなってしまいます。 そこで本機では M3 のナットをスペーサ代わり、としました。 ウィルコ で購入したナットで、 "鉄(ニッケルめっき) 六角ナット・1種 FNT-03N" の厚さ 2.4 mm のものです。

 ケースの裏面側(外側)の4か所から、それぞれ M3 x 10 サイズのビス(+なべ小ねじ)を通し、ケース内側でスペーサ代わりの M3 ナット → メイン基板 → ポリカーボネート平ワッシャー → M3 ナット、の順に取り付けます。 ポリカーボネート平ワッシャーは、プリント基板表面の傷つき防止とねじ緩み防止を兼ねて挿入をしてあります。(ねじ類の型番等については、使用部品表 を参照のこと)

・電池ホルダーの取り付け
 同様に上図の(下面図)で、下部の横に細長い点線の四角部分に、18650 リチウムイオン電池用の電池ホルダーを取り付けます。 私が使用した電池ホルダー、およびその取り付けるときの注意点、方法などについては、 別ページ "198. MP3プレーヤー I" の 電池ホルダーをケースに取り付け を参考にしてください。

| ケース加工図 (PerpetualCalendarIIICS.CE3) | ページトップ |

■ ケースへのプリント基板の取り付け ■

 下図は本機ケースの右側面側から上部半分ほどを見た図で、2枚のプリント基板やタクトスイッチの取り付けの様子がよく分かるように、右側面を切り取った断面図で表しています。

 ケースへのメイン基板の取り付けに当たって、最も重要なのはその上下(高さ)位置で、重複しますが上述した メイン基板の取り付け のように、本機ではトグルスイッチ搭載のために M3 のナットをスペーサ代わりとして使用しています。 そして、前項で述べたケースを使用する限り、この状態が最もベストな上下(高さ)位置で変更することはできません。

 また、同図に示すように本機では、スイッチ用プリント基板に取り付けたタクトスイッチのトップが、ケース上面から適度な長さ(X)を飛び出すようにしなければなりません。 そのために、タクトスイッチには手持ちにあった通常のものより少々長い、 スイッチ底面からトップまでの長さが 9.5mm のものを使用し、スイッチ用基板をメイン基板に取り付けるのに、これも手持ちの関係で右写真のような、M3 x 13 mm 長のオネジ+メネジの六角ジュラコンスペーサ(廣杉計器 BS-313W)を使用しました。

 余談ですが、タクトスイッチをプリント基板に取り付ける場合に、私は通常、スイッチを基板穴に軽く押し込んだときに、足ピンがくの字に曲がったあたりで進入が止まった位置、すなわち、スイッチ底面が少し基板上面から浮いた位置でハンダ付けをすることが多いのですが、 今回は上図のように、スイッチ底面が基板上面に付くまでスイッチを押し込んで使用しました。 これは使用したタクトスイッチとスペーサの各長さによって X 値を調節するためで、ちなみに図の組み合わせでは X ≒ 2 mm ほどになりました。

| 基板の取り付け図 (pcb_attach.CE3) | ページトップ |

■ 使用部品表 ■

(主要部品: IC, トランジスタ等)

(データシート)
PICマイコン .................... PIC16F1705
三端子レギュレータ .................... S-812C33AY-B-G
有機 EL ディスプレイ(OLED) .................... SSD1306
圧電ブザー .................... PKM17EPP-4001

| 部品表 | Excel ファイル (PerpetualCalendarIII_parts.xls) | ページトップ |

■ 参考資料・参考サイト ■

PIC16F1705 データシート .......... https://ww1.microchip.com/downloads/en/DeviceDoc/40001729C.pdf
SSD1306 データシート .......... https://akizukidenshi.com/goodsaffix/ssd1306.pdf
174. グラフィック液晶表示 万年カレンダー .......... https://xyama.sakura.ne.jp/hp/PerpetualCalendar.html
201. 有機 EL ディスプレイ(OLED) 表示 万年カレンダー II .......... https://xyama.sakura.ne.jp/hp/PerpetualCalendarII.html
有機EL (OLED)をPICマイコンで制御 .......... https://jr3tgs-homebrew.net/contents/oled_test/oled_test.html

| ページトップ | ホーム |


Copyright (C) 2024-2025 やまもとみのる
初版:2024年12月10日、初公開:2025年5月14日、最終更新:2025年5月19日