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

110. 音声(お喋り)時計 2題

[ 初公開日:2020年1月12日 ]

 私の過去に製作をした作品群の中で、少しばかり変わり種のものを見つけたので、ここに紹介をすることにしました。

 これまでにいろいろと製作をしてきたデジタル時計では、時刻表示には、7セグメントLEDを代表として、ドットマトリクスLED、キャラクターまたはグラフィックの各液晶モジュール、ニキシー管など、 それらのすべてが視覚に訴えるものばかりで、補助的にアラーム(ビープ)音を併用していました。

 それらに対して、このページで紹介をするものは視覚ではなく、時刻そのものを音声による聴覚によって知らせる、というユニークなものです。

 音声(お喋り)時計(PIC16F877A 版)

 音声(お喋り)時計 II(PIC16F873A 版)



□ 音声(お喋り)時計(PIC16F877A 版) □

 このクロックは 2008 年 5 月頃に製作をしたもので、私のオリジナルではなく、サイト "電子マスカット" さんで紹介されている PIC16F877A を使用した "音声告知クロック" で、回路構成やプログラムも殆んどオリジナルのままに製作をしています。

 なお、音声データ用の EEPROM(AT24C1024)がなぜか紛失してしまいました。 私が所有するPICライタやパソコン環境が本機の作製当時とはすっかり変わってしまったため、現在では自前で音声データを EEPROM に書き込むことができなくなってしまいました。 しかし、"電子マスカット" さんのページに EEPROM の書き込みをしていただける旨が書かれていたので、お願いをして書き込んで頂きました。 ありがとうございました。

■ 回路図 ■

 上で述べているように、回路構成は殆んどオリジナルのままですが、回路図は私自身が分かり易くなるように回路定数等を図中に書き入れて、全体を私流?に書き改めてあります。 唯一異なっているのは、音声用アンプの電源が ON になったことを目で確認ができるように、LEDとその電流制限抵抗を追加した点のみでしょうか。

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

■ EEPROM と音声データ ■

 上回路図で左上に位置する AT24C1024 が1メガビットの I2C-EEPROM で、本機においてはなくてはならない ある意味最も重要なデバイスです。 ROM 内にはスピーカーで喋るための 音声データが書き込まれており、本機で時刻を告げるために必要となる各フレーズが、下表に示すように 32 種類に分割してデジタル信号として格納されています。

 PICとはそのときに必要となるフレーズが、I2C 通信を行いながらPIC内に読み出されて、デジタル−アナログ変換、電力増幅を経てスピーカーから出力されます。
      フレーズ アドレス フレーズ アドレス フレーズ アドレス フレーズ アドレス
      00 じゅうにじ 00000h 08 はちじ 06AD0h 16 ごじゅっぷん 10000h 24 さんぷん 16D20h
      01 いちじ 011D0h 09 くじ 07A60h 17 じゅう 111B0h 25 よんぷん 18190h
      02 にじ 01FF0h 10 じゅうじ 08340h 18 にじゅう 118F0h 26 ごふん 19080h
      03 さんじ 02970h 11 じゅういちじ 08F00h 19 さんじゅう 12570h 27 ろっぷん 1A050h
      04 よじ 037F0h 12 じゅっぷん 0A510h 20 よんじゅう 13490h 28 ななふん 1B350h
      05 ごじ 042D0h 13 にじゅっぷん 0B5A0h 21 ごじゅう 14420h 29 はっぷん 1C130h
      06 ろくじ 04D10h 14 さんじゅっぷん 0C940h 22 いっぷん 14F90h 30 きゅうふん 1D100h
      07 しちじ 05BA0h 15 よんじゅっぷん 0E2D0h 23 にふん 160D0h 31 です 1DF70h
      *注.上表は "電子マスカット" さんのページにある表を元に作り変え、転載をさせていただきました。
      アドレスは、各フレーズが格納されている I2C-EEPROM 上の先頭アドレスを示していて、プログラムの作成時に必要となります。
 これらの各フレーズの音声データを作成されたのは "電子マスカット" さんで、その作成をする過程は大変なご苦労であったことは想像に難くないのですが、それを利用させていただく私としては、 ただ、ただ、感謝あるのみで、本当にありがとうございます。

| ページトップ |

■ 機能と使用法 ■

  • まず初めに、本機に電池をセットすると、12 時 00 分 00 秒から時刻のカウントが始まる。 しかし、本機にはこれらの数字を表示するための7セグLEDを代表とするような視覚表示器がないため、 その時刻を目で確認することはできない。

  • 本機がカウント中の現在時刻を知る唯一の方法は、音声告知(VOICE)スイッチ を押すことで、音声でその時刻を知らせる。 電池をセットした直後にこの VOICE スイッチを押すと、 「PiPi ... 12 時です」とスピーカーが喋る。 このように、「秒」の音声表示は一切なく、また、毎時 00 分のときには「分」の音声表示も省略がされる。

  • このスピーカーで喋るための音声データの各フレーズは、PICとは別の外付けの EEPROM 内に格納されており、PICと I2C 通信を行いながらそのときに必要となるフレーズが、PIC内に読み出される。 これらのフレーズは、上表 に示すように全部で 32 種類が用意されている。

  • これらのフレーズは、初めに電池をセットするときに 音声告知(VOICE)スイッチを押しながらセットをすると、音声データのテストモードとなってすべてのフレーズを発声した後、通常動作となる。

  • 上述のように、電池をセットすると 12 時 00 分 00 秒から時刻のカウントが始まるが、当然ながらリアルな現在時刻とは異なっているため、この「時」「分」「秒」の時刻を変更することが必要となる。

  • そのために、本機では「時」設定(H ADJ)スイッチ、「分」設定(M ADJ)スイッチの2つが用意されている。

  • 「時」設定(H ADJ)スイッチ は、押すごとに「時」が +1され、1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12 → 1 → ・・・ の順に変更がされて、 スピーカーが喋りながらその変更の様子を知らせる。

  • このときに、「時」設定(H ADJ)スイッチを離すことなく連続で押していると、押している間中は「時」が +1を繰り返す。

  • 一方、「分」設定(M ADJ)スイッチ は、押すごとに「分」が +1され、1 → 2 → 3 → 4 → 5 → ・・・ → 55 → 56 → 57 → 58 → 59 →(無音)→ 1 → 2 → 3 → ・・・ の順に変更がされて、 スピーカーが喋りながらその変更の様子を知らせる。

  • このときに、「分」設定(M ADJ)スイッチを離すことなく連続で押していると、押している間中は「分」が +1を繰り返す。

  • なお、この「分」設定(M ADJ)スイッチによって「分」が変更されるときには、「分」が変更がされると同時に、本機内部の「秒」カウンタはゼロクリアされる。

  • このように、音声告知(VOICE)スイッチ を押したとき、「時」設定(H ADJ)スイッチ、「分」設定(M ADJ)スイッチの操作で時刻を変更したときには、スピーカーでその内容を喋ってユーザに知らせるが、 そのほかにも毎時と毎時 30 分になると自動でその時刻を告げる。

  • 毎時のときには「PiPi ... ○○時です」 と喋り、毎時 30 分では「Pi ... ○○時 30 分です」 と喋べってその時刻を知らせる。

| ページトップ |

■ プログラム ■

 プログラムのソースファイルについても上の回路図と同様に、私自身が分かり易くなるようにと、オリジナルから私の書き方スタイルに書き換えてありますが、 基本的にはオリジナルのものと変わりません。 私の個人的な好みもあって小文字使用への変換、各サブルーチンの順序などの構成の変更、一部のラベル名の変更、空白行の多用やコメントの追加などがしてあります。

現在の最新バージョン: Ver. 1.01

| ページトップ |

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

 基板の左上に乗っている丸いものはスピーカーで、手持ちに小さなものがあったので使用したのですが、これは失敗でした。 小さ過ぎるために音が割れてしまいます。 接着剤で固定をしたので取り外すことができないため、そのままにしてあります。

 そのスピーカーの右横にある3P のピンヘッダは外付けのスピーカーとの切り替え用で、右写真のように上2端子をショートピンで短絡するとこの小さなスピーカーに接続され、外付けスピーカーを使用するときには 下2端子に接続をします。

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

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

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

■ 使用部品表 ■

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

(データシート)
PICマイコン .................... PIC16F877A
I2C-EEPROM .................... AT24C1024
低周波電力増幅IC .................... TA7368P
トランジスタ .................... 2SA950

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

■ 参考資料・サイト ■

音声告知クロック ..... http://www.zea.jp/audio/vck/vck_01.htm

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



□ 音声(お喋り)時計 II(PIC16F873A 版) □

 オリジナルでは 40 ピンの PIC16F877A を使用していますが、上の 回路図 に示すように使用をしていない空きピンの多さが、ずいぶんと目に留まります。 そこで、この無駄となるピンの数を極力減らすために、PICを 28 ピンの PIC16F873A に変更をして、このページの公開のために新しく作り直すことにしました。

 なお、先の PIC16F877A 版ではプリント基板のままで、試作品扱いのようになってしまいましたが、この PIC16F873A 版ではケースにも収納して、実用性を高めてみました。


経過時計機能の追加 ( 2020/06/08 更新 )

 ユーザがスイッチ操作をした時点を起点として、現在の時刻には関係なく、刻々と経過をして行く時間を音声で自動的に告て行く、という経過時計の機能を追加しました。 詳細は、機能と使用法(2)項末、および プログラム(2)項末 を参照してください。

■ 回路図(2) ■

 デジタル信号からアナログ信号への変換用の R-2R ラダー抵抗を収容するためのポートとして、オリジナルの PIC16F877A 版ではポートDの8ビットすべてをまとめて使用をしていたのですが、 PIC16F873A 版では同一グループのポートで、8ビットをまとめて割り当てることができません。

 それは、ポートBはスリープ状態のときにポートBの割り込み機能を契機として、スイッチ操作をさせるために必要となります。 ポートCの RC0:T1OSO、RC1:T1OSI には 32.768KHz のクリスタルを繋ぐために必須です。 また、ポートAにはもともと RA0 〜 RA5 の6個しかありません。 したがって、8ビットをまとめて割り当てるポートがないため、次の回路図に示すように RB0 〜 RB4 と RC5 〜 RC7 に分割をして割り当てました。 プログラムがほんの少し面倒になるだけです。

 ポートBの割り込み機能については、オリジナルの PIC16F877A 版では、3つのスイッチ入力をダイオードでORをとって、"RB0/INT 外部割り込み" を起こさせています。 これに対して PIC16F873A 版では、3つのスイッチ入力を RB5 〜 RB7 に収容し、それぞれの "RB ポート変化割り込み" を起こさせます。 なお、この PIC16F873A 版では、内部プルアップ機能を ON にして 3つのスイッチの外付けのプルアップ抵抗を省き、また、割り込みタイプの変更でORをとる必要もなくなったため、ダイオードも必要がありません。


 EEPROM と PIC 間の I2C 通信には、PIC16F873A 版でもオリジナルの PIC16F877A 版のままを引き継ぎ、ソフトウエアのみでおこなっていますが、PIC の MSSP モジュールを使う方法にも変更ができるように、 とりあえず RC3:SCL、RC4:SDA のピンを空けておきました。

 また、R-2R ラダー抵抗には その後 Yahoo!オークションで入手した、専用の SIP 抵抗 があったので R 値は異なっていますがそれを使用しました。 省スペース化が期待できます。

 PIC16F877A 版では "時"(H ADJ)、"分"(M ADJ) の設定用スイッチを押す毎にその値が +1ずつ更新されますが、プラス方向のみで使用していて不便さを感じたので、この PIC16F873A 版ではプラスマイナスの両方向に変更ができるように、 UP/DOWN スイッチを新たに追加をしました。

 "時"、"分" スイッチを単独で押したときには従来通りですが、UP/DOWN スイッチを押しながら "時"、"分" スイッチを押したときには、押す毎にその値が −1ずつ更新されます。 なお、UP/DOWN スイッチはポートA(RA3)に 収容されているので、UP/DOWN スイッチだけを押したときには割り込みも何も起こりません。

<注> 上図の左下にあるLEDは、プログラムのデバッグ用に取り付けたもので、無くても一向に構いません。 現在は、4秒毎にタイマー1割り込みが起こったときなどに、瞬間点灯をするようにしてあります。 (詳細は、プログラム(2) の項を参照のこと。)

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

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

ケース正面の斜め上から見たところ ケース背面の斜め上から見たところ
ケース左側面の斜め上から見たところ ケース右側面の斜め上から見たところ


左右側面にある一対のねじ(M2.6)を外すと
上箱(右)と下箱(左)が分離する ( 拡大

スピーカーの取り付けについては下の *を参照

なお、裏面から見て右側のスイッチは、機能追
加のときに使用するためのもの で、今は未使用
下の **を参照 ( 2020/06/08 更新 )
ケース上面を真上から見たところ ケース裏面を真上から見たところ

* スピーカーの取り付け方法については、別ページ "051. テルミン" の スピーカーの取り付け で詳細に述べているので参考にしてください。 なお、自作金具の形状については、そこでは上から押しつぶした Z 型のような形で説明をしていますが、ここで作製をしたものは少し開いた L 型にしています。 加工の工程を一手間減らしてもスピーカーを固定する効果は十分で ほとんど変わりません。

** 裏面から見て右側のスイッチは、プリント基板上のコネクタを通して UP/DOWN スイッチ に接続をする(プリント基板(2)パターン図 (部品面) を参照)。 この右側の UP/DOWN スイッチ を押しながら 左側の VOICE スイッチを押すと、機能追加をした "経過時計" として動作をするようになる。

(注) 上の写真では真ん中のもの(拡大ができる写真)のみを差し替えただけで、他のものは旧写真のままで変更が反映されていないので、注意をしてください。 ( 2020/06/08 更新 )

| ページトップ |

■ 機能と使用法(2) ■

    本機(PIC16F873A 版)では、少々の機能拡張を行って上述の 機能と使用法 とは異なる部分があるため、その追加だけでなく重複部分も含めて再掲をしました。

  • まず初めに、本機に電池をセットすると、12 時 00 分 00 秒から時刻のカウントが始まる。 しかし、本機にはこれらの数字を表示するための7セグLEDを代表とするような視覚表示器がないため、 その時刻を目で確認することはできない。

  • 本機がカウント中の現在時刻を知る唯一の方法は、音声告知(VOICE)スイッチ を押すことで、音声でその時刻を知らせる。 電池をセットした直後にこの VOICE スイッチを押すと、 「PiPi ... 12 時です」とスピーカーが喋る。 このように、「秒」の音声表示は一切なく、また、毎時 00 分のときには「分」の音声表示も省略がされる。

  • このスピーカーで喋るための音声データの各フレーズは、PICとは別の外付けの EEPROM 内に格納されており、PICと I2C 通信を行いながらそのときに必要となるフレーズが、PIC内に読み出される。 これらのフレーズは、上表 に示すように全部で 32 種類が用意されている。

  • これらのフレーズは、初めに電池をセットするときに 音声告知(VOICE)スイッチを押しながらセットをすると、音声データのテストモードとなってすべてのフレーズを発声した後、通常動作となる。

  • 上述のように、電池をセットすると 12 時 00 分 00 秒から時刻のカウントが始まるが、当然ながらリアルな現在時刻とは異なっているため、この「時」「分」「秒」の時刻を変更することが必要となる。

  • そのために、本機では「時」設定(H ADJ)スイッチ、「分」設定(M ADJ)スイッチと、他に変更操作が効率よく行えるように UP/DOWN スイッチの計3つが用意されている。

  • 「時」設定(H ADJ)スイッチ は、押すごとに「時」が +1され、1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9 → 10 → 11 → 12 → 1 → ・・・ の順に変更がされて、 スピーカーが喋りながらその変更の様子を知らせる。

  • このとき、UP/DOWN スイッチ を押しながら 「時」設定(H ADJ)スイッチ を押すと、押すごとに「時」が −1され、12 → 11 → 10 → 9 → 8 → 7 → 6 → 5 → 4 → 3 → 2 → 1 → 12 ・・・ の順に変更がされて、同様にスピーカーが喋りながらその変更の様子を知らせる。

  • これらのときに、「時」設定(H ADJ)スイッチを離すことなく連続で押していると、押している間中は「時」が +1、または −1を繰り返すが、後述するような早送り機能は持たせていない。

  • 一方、「分」設定(M ADJ)スイッチ は、押すごとに「分」が +1され、1 → 2 → 3 → 4 → 5 → ・・・ → 55 → 56 → 57 → 58 → 59 →(無音)→ 1 → 2 → 3 → ・・・ の順に変更がされて、 スピーカーが喋りながらその変更の様子を知らせる。

  • このとき、 UP/DOWN スイッチ を押しながら 「分」設定(M ADJ)スイッチ を押すと、押すごとに「分」が −1され、59 → 58 → 57 → 56 → 55 → ・・・ → 5 → 4 → 3 → 2 → 1 →(無音)→ 59 → 58 → 57 → ・・・ の順に変更がされて、同様にスピーカーが喋りながらその変更の様子を知らせる。

  • これらのときに、「分」設定(M ADJ)スイッチを離すことなく連続で押していると、初めの5回までは「分」が +1、または −1を繰り返すが、なおも連続で押していると、その後は +5、または −5 を繰り返す 早送り動作 をするようになり、押している間中はそれらが続けられる。

  • なお、この「分」設定(M ADJ)スイッチによって「分」が変更されるときには、「分」が変更がされると同時に、本機内部の「秒」カウンタはゼロクリアされる。

  • このように、音声告知(VOICE)スイッチ を押したとき、「時」設定(H ADJ)スイッチ、「分」設定(M ADJ)スイッチの操作で時刻を変更したときには、スピーカーでその内容を喋ってユーザに知らせるが、 そのほかにも毎時と毎時 30 分になると自動でその時刻を告げる。

  • 毎時のときには「PiPi ... ○○時です」 と喋り、毎時 30 分では「Pi ... ○○時 30 分です」 と喋べってその時刻を知らせる。

  • 本機(PIC16F873A 版)では、元々デバッグ用に使用をしたLED(赤)を、デバッグ終了後に、4秒間隔で瞬時点灯(約 10 ミリ秒間)をさせて、時間の流れが実感できるようにした。 他にも、音声用アンプの電源が ON になったことを目で確認ができるように、その間だけLED(黄)が点灯をする。
 経過時計機能の追加 ( 2020/06/08 更新 )
  • 本機(PIC16F873A 版)では通常は上述したように、音声でその時その時の現在の時刻を告げる "音声(お喋り)時計" として機能をするが、UP/DOWN スイッチ を押しながら 音声告知(VOICE)スイッチ を押すと、その時点から 経過時計 として機能をするようになる。

  • 経過時計とは、このようにスイッチ操作をしたときを起点として、現在の時刻には関係なく、その時その時の経過をした時間を音声で自動的に告げる、というもので、その告げる内容として毎十秒ごとを最小単位として、 毎分ごと、毎時間ごとに、その時点での経過時計の「秒」、「分」、「時」だけを 「○十」、「○○分」、「○○時」 と単独で知らせる。 なお、この毎十秒ごとのときには、「○十」と告げるだけで 「秒」の発音をすることはない。( EEPROM 上表 にフレーズの登録がない)

  • このとき、毎 00 秒のときには、毎分ごとが必ず重なり、毎 00 分のときには、毎時間ごとが必ず重なるが、これらのときには毎分、もしくは毎時の大きな単位の方を優先して告知がされる。

  • また、この経過時計が動作中も、現在時刻のカウントはもちろん内部では行っているが、経過時計の方を優先して、現在時刻の毎時や毎時 30 分のときの自動告知は抑止される。 そして、この経過時計が動作中には、「時」設定(H ADJ)スイッチや「分」設定(M ADJ)スイッチも抑止されて機能をしない。 ただし、音声告知(VOICE)スイッチ だけを単独で押したときには、 従来通り現在時刻の告知をすることができる。

  • しかし、このように経過時計が動作中に、再度、UP/DOWN スイッチ を押しながら 音声告知(VOICE)スイッチ を押すと、その時点で経過時計としての機能は終了をする。

| ページトップ |

■ プログラム(2) ■

 この PIC16F873A 版では、ポート数など PIC16F877A 版とは異なるハードウェアからくる制約もあり、また、機能を少し拡張したこと、その他などもあって、上の PIC16F877A 版の プログラム に比べると、現時点では大幅に変更がしてあります。 その過程において、ここの項末の 現在の最新バージョン に掲げてある 参考: 旧 Ver. 1.10 のソースファイルの開発のときには、 その中の1つの不具合のために大変な苦戦を強いられました。 ・・・ そのときの話です。

 その不具合とは、前項の 機能と使用法(2)項末 に述べている、本機の目玉ともいうべき "毎時と毎時 30 分になると自動でその時刻を告げる" という機能がまったく働かない、というものです。 実にやっかいな致命的なバグで、これでは本機としては成り立たなくなってしまいます。

 「時」設定(H ADJ)スイッチ「分」設定(M ADJ)スイッチを押したときには、何の問題もなく「時」「分」が更新したことを告げてくれます。 音声告知(VOICE)スイッチを押したときにも、そのときの時刻の経過を 間違いなく告げてくれます。 "毎時と毎時 30 分になると自動でその時刻を告げる" ということだけがまったく機能しないのです。

 まず初めに疑うのは、やはり、毎時と毎時 30 分になったときにそれらのフラグをセットしている部分ですが、これらは割り込み処理ルーチン内のタイマー1割り込みで行っており、PIC16F877A 版のものを変更することなく そのままを引き継いでいるので、まず間違いは起こらない筈です。

 上述の3つのスイッチを押したときに起こさせる割り込みの種別は、下のリストに示すように "外部割り込み" から "ポート変化割り込み" に変更をしましたが、タイマー1割り込みの処理についてはまったく内容の変更をしていないのです。
				:
		 		:

		;;	; 外部割り込み (RB0/INT) 							;
		;;											;
		;;	bcf	INTCON,INTF	;外部割り込み(RB0/INT)を解除				;
		;;	bsf	stat_byte,swint	;外部割り込み(RB0/INT)であることを記憶			;
		;;	goto	int_out									;
													;(Ver. 1.10 変更)
			; RB ポート変化割り込み処理							;
													;
	int_rb		bcf	INTCON,RBIF	;RBポート変化割り込みフラグをクリア			;
			bcf	INTCON,RBIE	;RBポート変化割り込みを禁止				;
			bsf	stat_byte,swint	;RBポート変化割り込みであることを記憶			;
			goto	int_out									;

			; タイマー1割り込み

	int_tmr1	bcf	PIR1,TMR1IF	;タイマ1オーバフローを解除

			incf	s4_cnt,F	;4秒カウンタ + 1
			movlw	15
			subwf	s4_cnt,W
			btfss	STATUS,Z	;4秒カウンタ = 15 か?
			goto	int_out		;No

			clrf	s4_cnt		;Yes. 15回のカウントでレジスタクリア

			incf	ml_cnt,F	;分カウンタ + 1
			movlw	10
			subwf	ml_cnt,W
			btfss	STATUS,Z	;分カウンタ = 10 か?
			goto	int_out		;No

			clrf	ml_cnt		;Yes. 10回のカウントでレジスタクリア

			incf	mh_cnt,F	;十分カウンタ + 1
			movlw	3
			subwf	mh_cnt,W
			btfsc	STATUS,Z	;十分カウンタ = 3 か?
			bsf	stat_byte,auto30 ;Yes. 30分オートスピーチフラグをセット		; <<<<<

			movlw	6
			subwf	mh_cnt,W
			btfss	STATUS,Z	;十分カウンタ = 6 か?
			goto	int_out		;No

			clrf	mh_cnt		;Yes. 6回のカウントでレジスタクリア

			incf	ho_cnt,F	;時カウンタ + 1
			bsf	stat_byte,auto00 ;00分オートスピーチフラグをセット		; <<<<<
			movlw	12
			subwf	ho_cnt,W
			btfss	STATUS,Z	;時カウンタ = 12 か?
			goto	int_out		;No

			clrf	ho_cnt		;Yes. 12回のカウントでレジスタクリア

	int_out	 		:
		 		:
 上のリストにおいて、最右端に ; <<<<< の記号を付したところがそれらのフラグを立てている部分です。 くどいようですが、PIC16F877A 版のものを変更することなく そのままを引き継いでいるので、 ここでは問題は起こらない(間違いなくフラグはセットされる)筈です。

 このように、それぞれの時刻を検出すると問題なくフラグをセットしているにもかかわらず、なぜそれらの "時刻を告げる" ということをしてくれないのでしょうか。 この "時刻を告げる" ということを行っている所は、 割り込み処理ルーチンから抜け出た後にメインルーチンに戻ってその中で行っています。

 本機では、メインルーチンの1周期が終了する直前部分にある SLEEP 命令 のために、必ずスリープ状態になります。 そして、そのスリープ中に 3つのスイッチの内のどれかが押されたときと、 4秒間隔でタイマー1割り込みが起こったときに、一旦、割り込み処理ルーチン内を経た後、再びメインルーチンに戻り(SLEEP 命令の次の命令)、スリープ状態から目覚め(ウェイクアップ)ます。

 そして、メインルーチンの1周期の最終命令( goto main )で、再びメインルーチンのトップに戻って次の周期が始まりますが、その様子を見ていただくためにその部分のリスト(メインルーチン)を次に示します。 リスト中の最右端に(Ver. 1.10 変更)とある部分が PIC16F877A 版から変更をした部分です。

 これらのプログラム変更は、ハードウェアの構成(3つのスイッチ、R-2R ラダー抵抗、音声用アンプの電源制御などの収容ポートのすべて)を変更したために必要になったもので、 他に、既に 上述 しているように、3つのスイッチのどれかを押したときに起こさせる割り込みの種別も、PIC16F877A 版では "RB0/INT 外部割り込み" であったものを、PIC16F873A 版では "RB ポート変化割り込み" に変更をしました。(RB0 ポートを他目的で使用するため)

 メインルーチンのトップに戻ると、初めに、ウェイクアップしたのは スイッチの押下によるものか、または タイマー1割り込みによるものかを区別をし、後者の場合には ラベル main01 にジャンプします。 そして、そこでは 毎時( auto00 )/毎時 30 分( auto30 ) のどちらのフラグがセットされているかを判断をしていますが、どちらでもない(どちらもセットされていない)場合には ラベル main09 にジャンプして、 やがて、再びスリープ状態になります。

 一方、どちらかのフラグがセットされていた場合には、それぞれのフラグによって ラベル main06、または main07 にジャンプをして、そこでそれぞれの時刻を告げるているのです。 これは正常の場合のことであって、時刻を告げることができない ― ということは、何らかの不具合があってこの ラベル main06、または main07 にジャンプをすることができないでいるわけです。
		 		:
		 		:

	;==========================================================================
	;		メイン・ルーチン
	;==========================================================================

	main
		;;	btfss	stat_byte,swint	;外部割り込み(RB0/INT)か?				;(Ver. 1.10 変更)
			btfss	stat_byte,swint	;RB ポート変化割り込みか?				;
			goto	main01		;No

			btfss	PORTB,voice_sw	;音声告知スイッチが押されているか?
			goto	main02		;Yes

			btfss	PORTB,h_adj_sw	;時刻調整「時」スイッチが押されているか?
			goto	main03		;Yes

			btfss	PORTB,m_adj_sw	;時刻調整「分」スイッチが押されているか?
			goto	main04		;Yes

	main01		btfsc	stat_byte,auto00 ;毎時スピーチか?
			goto	main06		;Yes	

			btfsc	stat_byte,auto30 ;毎30分スピーチか?
			goto	main07		;Yes
			goto	main09		;No

	main02	 		:
		 		:

		 	( この間は問題がないので省略 )

		 		:
		 		:

			; 毎時スピーチ
	main06		call	audio_set	;オーディオ回路の設定
			call	beep		;ビープ音2回
			call	tim_100ms
			call	beep
			goto	main08

			; 毎30分スピーチ / 音声告知スイッチが押された
	main07		call	audio_set	;オーディオ回路の設定
			call	beep		;ビープ音1回

	main08		call	tim_200ms
			call	tim_200ms
			call	tim_200ms
			bcf	INTCON,GIE	;全割込み禁止
			call	sp_hour		;スピーチ順序ルーチン「時」
			call	sp_minute	;スピーチ順序ルーチン「分」
			call	sp_des		;フレーズ「です」読み出し
			bsf	INTCON,GIE	;全割込み許可

			; オーディオ電源 OFF
	main09	;;	bsf	PORTB,amp_cntl	;電力増幅IC 電源OFF					;(Ver. 1.10 変更)
			bsf	PORTA,amp_cntl	;電力増幅IC 電源OFF					;
			clrf	stat_byte	;状態バイトのクリア			; (A)
			movf	cl_da_cnt,F
			btfsc	STATUS,Z	;割り込み回数カウンタ = 0 か?
			goto	main10		;Yes

			decf	cl_da_cnt,F	;割り込み回数カウンタ - 1
		;;	btfsc	STATUS,Z	;割り込み回数カウンタ = 0 か?				;
		;;	clrf	PORTD		;Yes. ラダー抵抗ポートをクリア				;
			btfss	STATUS,Z	;割り込み回数カウンタ = 0 か?				;
			goto	main10		;No							;(Ver. 1.10 変更)
													;
			clrf	PORTB		;ラダー抵抗ポート下5ビットをクリア			;
			clrf	PORTC		;ラダー抵抗ポート上3ビットをクリア			;

	main10	;;	sleep			;普段はここ						;
		;;	nop										;
		;;	goto	main									;
													;
			bsf	INTCON,RBIE	;RBポート変化割り込みを許可				;
			sleep			;普段はここ						;
			;										;
			;										;
			btfss	stat_byte,swint	;RB ポート変化割り込みか?		; (B)		;
			goto	main11		;No							;
													;(Ver. 1.10 変更)
			movf	PORTB,W									;
			andlw	h'e0'		;スイッチ入力を						;
			xorlw	h'e0'		;反転							;
			btfss	STATUS,Z	;スイッチ操作 = あり か?				;
			goto	main11		;Yes 							;
						;間違いのため						;
			bcf	stat_byte,swint	;RBポート変化割り込みの記憶をクリア 	; (C)		;
			goto	main10		;再度 sleep						;
													;
	main11		goto	main									;

		 		:
		 		:
 上に示したメインルーチンのリストは、不具合を修正した後のものなので当然ながら解決策が含まれているわけで、下から3行目の命令 (C) に注目をしてください。 結論から先にいうと この命令 (C) が無かった(考慮するのを忘れていた)ために不具合が起こっていました。 このことに気づくまでに何と、5、6日も費やしてしまい、その間、ああでもない、こうでもないと毎日悩んでいました。 気づいてしまえば何でもないことなのですが ・・・

 上のリストで ラベル main10 以降の動作の説明をすると、まず、INTCON レジスタのビット RBIE = 1 にセットをして、"RB ポート変化割り込み" を許可して準備を整えた上で、スリープ状態に移行をしています。 上述したように本機では、3つのスイッチの内のどれかが押されたとき(すなわち、RB ポート変化割り込みが起こったとき)と、4秒間隔でタイマー1割り込みが起こったときに割り込み処理ルーチンに移行をし、 その結果、スリープ状態からウェイクアップ(SLEEP 命令の次の命令 (B) に移行)をします。

 SLEEP 命令の次の命令 (B) では、ウェイクアップをした原因がどちらの割り込みによるものなのかを調べています。 後者のタイマー1の場合には、ラベル main11 経由でメインのトップにジャンプしますが、 前者の RB ポート変化の場合には、次に、本当に3つのスイッチの内のどれかが押されたのかどうかを確認して、YES であればタイマー1の場合と同様に ラベル main11 経由でメインのトップにジャンプしています。 NO のときには問題となった命令 (C) を実行後、再度 ラベル main10 に戻って再びスリープ状態にしています。

 ここで、NO のときとはどんなときなのでしょうか? 言い方を変えると、RB ポート変化割り込みが起こったにも拘らずスイッチが押されていない、そんなことがあり得るのか? ・・・ 実はあるのです。

 3つのスイッチが接続されている各入力ポートには、内部プルアップ機能によって常時 "H" が入力されていますが、どれかのスイッチが ON されるとそのポートに "L" が入力されて、この状態が "H" → "L" に変化したことにより "RB ポート変化割り込み" が起こり、その動作は上述した通りです。

 ところが、ON されたスイッチは次にはまた必ず OFF に戻って、すなわち、そのポートは "L" → "H" に再び状態が変化をして、もう一度 "RB ポート変化割り込み" が起こります。 この二度目の割り込みについては、ユーザが意図していない動作ですから無視をするようなプログラムにしなければなりません。 そのために再度スリープ状態に戻しているわけです。 このように、一度のスイッチ操作ごとに必ず二度の割り込みが起こる のです。

 "RB ポート変化割り込み" が起こったときに、その割り込みルーチン内ではどのようなことをしているかは、既に 上のリスト に示したように、一旦、"RB ポート変化割り込み" を禁止するとともに、 swint フラグをセットして "RB ポート変化割り込み" が起こったことを記憶しています。 このフラグをセットすることは、上述した二度目の割り込みのときにも区別なく同様に行なわれます。

 そして、一度目のときには ラベル main11 経由でメインのトップにジャンプした後、3つのスイッチの内のどれかの音声告知処理を済ませた後に、命令 (A) で 役目が済んだ swint フラグをクリア し、 スリープ状態に戻ります。

 これに対して、二度目のときには メインのトップにジャンプすることはなく、再びスリープ状態に戻しているのですが、不具合が起こっていたときには命令 (C) を記述することを忘れていたために、 swint フラグがセットされたままとなり、やがて、4秒間隔で タイマー1割り込みが起こったときにも、命令 (B) では常に "RB ポート変化割り込み" と誤認識 をされてしまいます。

 誤認識をされた後は、このプログラムでは3つのスイッチの内のどれかが押されたかどうかを検出しているだけですから、タイマー1割り込みでは当然 NO のため再びスリープ状態に戻されます。 したがって、例え 毎時( auto00 )/毎時 30 分( auto30 ) のどちらかのフラグがセットされていても、それらは無視をされてメインのトップにジャンプされることはなく、ましてや、 ラベル main06、または main07 にジャンプされることもないため、自動でその時刻を告げる という機能も実行されることはなかったのです。

 時刻のカウントアップそのものは、タイマー1割り込みが起これば 上のリスト に示したように、その割り込みルーチン内で正しく行われているので、音声告知(VOICE)スイッチを押したときには、 そのときの時刻の経過を間違いなく告げていたわけで、自動告知の機能だけががまったく働かない、という症状だったのです。


< 予告 > 本機の機能については、今回は UP/DOWN スイッチを追加して「時」「分」の設定用スイッチを押したときの機能改善をしただけにとどまっていますが、他にももう少し機能追加をしてみたい という構想もありますので、その時期はお約束できませんが、今後もときどきはこのページをご覧になってみてください。


経過時計機能の追加 ( 2020/06/08 更新 )

 上で <予告> をしたように、この度少しばかり機能の追加をしてみました。 以前に他のページで紹介をしている "157. アラーム音通知型経過時計" がありますが、 刻々と経過をして行くその時その時の "時"、"分"、"秒" の時間を伝えるために、ビープ音の音色の違いや数種類のビープ音の組み合わせの違いで "時"、"分"、"秒" の違いを表現していたのですが、自ずから限度があって そのために7セグLEDで表示をして視覚の力も借りることにした、どちらかというと中途半端な作品になってしまいました。

 そのときにつくづく思いました。 ビープ音の音色や組み合わせの違いだけでは、その時その時の時間を伝えることには所詮無理がある、と。 そして、その無理を乗り越えるためにはビープ音ではなく、 やはり言葉による音声の力が必要である、と。 そのときに本機(PIC16F873A 版はまだ存在しなかった)の前身である (PIC16F877A 版)が頭をよぎりました。

 そのような経緯があって、経過時計の機能を本機(PIC16F873A 版)に盛り込むことにしたのです。

 本機では時刻を刻むために、オリジナル(PIC16F877A 版)と同様に、4秒周期でタイマー1割り込みを起こさせています。 この4秒周期とした一番の理由としては省電力化のためで、常時はスリープモードにしておいて 割り込みが起こった一瞬だけ目覚めさせて時刻を刻ませ、その後はまたスリープモードにしています。

 しかし、4秒周期では本機の経過時計機能で必要とする最小単位の 10 秒を作り出すことができません。 そこで、経過時計が動作中の間だけ2秒周期に切り替えるようにしました。

 また、平常時の自動告知としては、毎時の「PiPi ... ○○時です」 と、毎時 30 分の「Pi ... ○○時 30 分です」の2種類で 30 分に1度の頻度ですが、経過時計の動作中には 10 秒に1度 「○十」、「○○分」、「○○時」 の どれかを告知するようになります。 「○十」というのは "秒" の省略形として用い、元々本機では "秒" の告知は考えていないため、上表 に示すように EEPROM 内に格納がされていないためです。 そして、経過時計が動作中には平常時の自動告知と区別をするために、「PiPi ... 」や「Pi ... 」のビープ音と「です」を省きました。

 このように経過時計が動作中には、割り込みや自動告知の頻度が増加するためにその分消費電流も多くなりますが、そのためにも経過時計の自動告知には短い形をとりました。

現在の最新バージョン: Ver. 1.21  ( 2020/06/09 更新 )
参考: 前のバージョン: Ver. 1.14
参考: 旧 Ver. 1.10  ... PIC16F873A 版に変更した直後のソースファイル

| ページトップ |

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

 上の 回路図(2) の項で述べたように、PICを 40 ピンから 28 ピンに変更をしたこと、3つのスイッチの各外付けのプルアップ抵抗とダイオードを省いたこと、 R-2R ラダー抵抗に SIP 抵抗を使用したこと、などの省スペース化を図ったことからプリント基板のサイズを、前作の PIC16F877A 版に比べて 1 / 2 に縮小することができました。

 使用したプリント基板は、"秋月電子" の "片面ガラス・ユニバーサル基板 Cタイプ(72×47.5mm)めっき仕上げ(通販コード P-00517)" ですが、下の ケース加工図 に示すケース内に収めるためには横幅のサイズがほんの少しですがギリギリで大きいため、プリント基板に部品を取り付ける前にやすりで少々削っておいた方が楽にケース内に収まります。

(修正前) (修正後) (修正後写真)

 また、左側のパターン図と右側の写真とは、基板の右端部分が少しばかり異なっています。 写真のように実際の基板にはΦ2のLED(赤)と抵抗1本が追加されていますが、 これは前項の プログラム(2) で述べたように、当初、バグの原因がなかなか分からなかったために業を煮やして、回路図(2) に示すようにトラップを仕掛けた名残りです。

 初めは仮付けの空中配線でデバッグをしていたのですが、バグ解決後に、さんざん悩ませてくれた記念(?)として正式に基板内に組み込んでおきました。 現在では、4秒毎にタイマー1割り込みが起こったときと、 3つのスイッチの内のどれかを押してポート変化割り込みが起こったときに、瞬間(約 10 ミリ秒間)点灯をするようにしてありますが、そのような訳なので無くても一向に構いません。

プリント基板の修正 ( 2020/06/08 )

 機能と使用法(2) の項末プログラム(2) の項末 で述べたように、経過時計の機能を追加するためには、ケース上面にある未配線だった左側スイッチにも、UP/DOWN スイッチ としての 配線が必要となります。 そのためにはプリント基板にも簡単な修正が必要で、上のパターン図 (部品面) や下のパターン図 (ハンダ面) に示したように、4P のコネクタ(ピンヘッダ)の配線替えを行います。

 そして、メス側の 4P のコネクタ(ピンソケット)を介して、各コネクタピンから延びているケーブルも、所定のスイッチ(UP/DOWN/VOICE)やスピーカーに、正しく配線をするようにします。

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

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

(修正後) (修正前) (修正後写真)

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

■ ケース加工図 ■

 使用したケースは、100均(セリア)で購入した "クリアケース ミニ (L-8033) サナダ精工" という、ポリスチレンケースです。

 図中の下箱上面図で、プリント基板を取り付けるための4つの小さな丸穴は、通常は M3 ビス用の穴を開けるのですが、今回はプリント基板の横幅がいっぱいで M3 のビスが使用できないため、M2.6 用の穴を開けました。 このケースの下箱はテーパー状になっていて入り口に比べて、底の方が少し狭くなっています。

 そのために、ケース内側とプリント基板の間に挟むスペーサー(M3 用を使用 *)の穴に、M3 のビスでは入らなくて M2.6 であれば何とか入れることができるため、今回は M2.6 ビスを使用します。 ( * M2.6 用のスペーサーは入手が難しい。)

 また、上箱上面図の2つのΦ6.5 の丸穴は押しボタンスイッチ用で、右側が音声告知(VOICE)スイッチ用です。 左側のものは今回(Ver. 1.14)では使用しませんが、プログラム(2)の項末の 予告 で述べた機能追加のときに使用するためのスイッチ用です。 先行して取り付けておきました。

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

■ 使用部品表(2) ■

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

(データシート)
PICマイコン .................... PIC16F873A
I2C-EEPROM .................... AT24C1024
低周波電力増幅IC .................... TA7368P
トランジスタ .................... 2SA950

使用した R-2R ラダー用 SIP 抵抗について
 この抵抗については、回路図(2) の項でも少し触れたように、7、8年ほど以前に Yahoo!オークションで入手したもので、"多摩電気の MRG-C08B(メーカー、型番)で 抵抗値 R = 4.7 KΩ" という右写真のようなものです。
【 お知らせ 】 ( 2020/06/08 )

 この R-2R ラダー用 SIP 抵抗は決して高価なものではありませんが、どちらかというと少しばかり特殊な部類になるため、住んでいる地域によってはその入手が難しいかもしれません。 (私も地元では簡単に購入できるようなお店は知りません。)

 私は上述のように、以前に Yahoo!オークションで入手したものですが、現在、私個人では使用し切れない数量(90 個以上)を所有しています。 そこで、これらの資源を大切にする意味からも希望される方々には、 無償(送料のみ)で差し上げたいと考えています。

 なるべく、入手が難しい多くの方々にお分けをしたいため、先着順でお一人様、1、2個程度にはなりますが、私までメールでお問い合わせください。 メールアドレスは、 当サイトの トップページ(ホーム) の 【 ご挨拶とお願い 】 をクリックしていただけると、開いたページに表示がされています。

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

| ホーム |


Copyright (C) 2008-2023 やまもとみのる
初版:2008年5月8日、初公開:2020年1月12日、最終更新:2023年10月30日