![]()
8ピンPIC、8ピンシリアルEEPROM、8ピンリアルタイムクロックモジュール(秋月製、RTC-8564NB使用)を使った喋る時計。振動スイッチを使って、揺れると時刻を喋ってくれる。待機時にはPICはSLEEPしているので消費電力はごくわずか(0.5uW程度)。
LEDなどの光モノを一切使わない初のPIC工作となった。と思ったら、RTCモジュールにLEDが載っていた。使っていないが。
参照サイト
・http://www.zea.jp/audio/vck/vck_01.ht 音声告知クロック
・Microchipアプリケーションノート:AN982
【ハードウェア】
![]()
回路図
PIC12F615の信号ピン6ピンのうち、I2C通信に2ピン使用、音声出力のためのDA変換はPWMで行うので1ピン、時刻設定スイッチに2ピン、時刻発声のスイッチに1ピン使用して余りなし。
電源は単三電池×2本の3V。待機時にはPICをスリープさせておくので、消費電力は0.5uW程度。
拡大図(スキャナが使えなかったのでデジカメ写真)。無保証です。
![]()
ブレッドボードで試作
回路は簡単だが、ブレッドボードでいろいろ試した。
![]()
ユニバーサル基板に実装
手元にあったユニバーサル基板の切れ端に実装。全てソケットを利用して実装した。パスコンはソケットの中へ。
![]()
ソケットに実装
左から、EEPROM、RTCモジュール、PIC12F615。
![]()
振動スイッチ
基板は立ててケースに取り付けるので、振動スイッチは立てたときに水平になるように取り付けた。
【音声データ作成】
![]()
Softalkで発声
時・分などを33個のフレーズに分けて発声させ、wav形式で録音する。デフォルトの発声スピードでは、1Mbitに収まらなかったため、少し発声スピードをあげている。
後述のwavchopプログラムで分割した際、データサイズが表示されるので 0x1FFFF を超えないようにする。
![]()
8bit,8KHzに変換
1MbitEEPROMに格納できるデータ量(録音時間)の制約から、8bit,8KHz,モノラルのサンプリングに変換する。1Mbit(1,048,576) / 8bit / 8KHz = 約16秒 の音声が格納できる。
WindowsXPについているサウンドレコーダを使った(拡大図)。
![]()
wavの加工
wavのヘッダー部を除いた音声部本体を切り出し、無音部をセパレータとして切り刻み、インデックスを作成するツール wavchop.exe を作った。C言語で書いたプログラムでWindowsのDOS窓で使う(拡大図)。
EEPROMに書き込むデータは、切り刻んだ各フレーズの開始アドレスを並べたインデックス部と、それぞれの音声データ部から構成される。音声データの終端は0x00としている。
[Index部] 音声1開始アドレス(2バイト)、音声2開始アドレス(2バイト) … [音声本体部] 音声1データ0x00、音声2データ0x00、…インデックス部は、EEPROMの0x00アドレスから開始し、インデックスが終わったところから音声データ本体が開始となる。
1Mbitメモリなのでバイトアドレスは、0x00000 〜 0x1FFFF となり、アドレスを示すために17ビット必要。しかし、1つの音声データのアドレスに 17ビット使うとすると 3バイト必要になってもったいない。そこで、音声データは必ず2バイトバウンダリから開始するように配置し、アドレスを1ビット右シフトして、16bitで表すようにした。
PIC側でインデックス部を読んだ際、アドレスを1ビット左シフトして、元のアドレスを復元する。
![]()
音声データ(バイナリ)
加工した音声データをバイナリエディタでみた様子(拡大図)。
一つ目の音声データの実際のアドレスは 0x0042 だが、インデックス部は2バイトに圧縮した アドレス 0x0021 となっている。
wavchopで処理した音声データバイナリ softalk_bin.zip、無保証です。
また、今回使用したEEPROMは、512Kbit単位にBlockが分かれており、Blockを跨いだ連続リードができない。そこで音声のフレーズデータがBlockを跨がないように自動的にスペースを空けて配置している。
wavchopプログラム
- [使い方]
- wavchop.exe 音声ファイル.wav
- [出力ファイル]
- 入力した音声ファイルと同じフォルダに、音声ファイル.wav.bin という名称で作成
- [実行例]
- 実行結果
- [注意事項]
- ・8ビット,8KHz,モノラル形式しか扱えません。
- ・サウンドレコーダ、SoundEngine(フリーソフト)で出力したwav形式は読めます。他のツールで作成したwavは未確認です。
- ・音声フレーズ間の無音部分の検出は連続する 0x80 (8ビットの中央値)で行っています。Softalkで発声させたとき、テキスト改行時の無音時間を目安にしています。
- ・分割した音声フレーズの終端は、0x00 なので、元の音声データに 0x00 があると(音が割れていると可能性がある)PICでの再生時に音声が途中で切れます。
- ・大きすぎるwavを処理させると異常終了する可能性があります。
- [プログラム]
- ダウンロード:wavchop.zip 無保証です(ウィルスチェック済み)。
- 展開後、適当なフォルダにおいて、DOS窓から実行してください。
【EEPROM書き込み】
![]()
EEPROM書き込みアダプタ
シリアルEEPROMへの書き込みはPICkit 2を使用する。PICkit2とEEPROMの結線方法がわからずググったら、PICkit 2のHELPのReadmeにあることがわかった(拡大図)。
PICに書き込むときには使わないAUXピンも使う。
![]()
EEPROM書き込みアダプタ
Readmeの結線図をベースにユニバーサル基板とソケット、ヘッダーピンで書き込みアダプタを作った。
![]()
音声データEEPROM書き込み
音声データをPickit 2で書き込む。HEXファイルにしなくても、バイナリファイルのまま書き込める。
【プログラム】
![]()
処理概要
起動する(電池を入れる)と、クロックモジュールの初期化を行い、初期時刻12:00を発声してSLEEPする。
時刻設定スイッチや発声スイッチ(振動スイッチ)の状態が変化すると、SLEEPから起き出してそれぞれの処理を行う。
時刻発声は、クロックモジュールから時刻情報を取り出した後、時・分それぞれの音声データをEEPROMから読み出して発声する。音声データの「分」は10分の位と1分の位が分けてあるので、合成する。
発声は、録音時の8KHzにあわせたタイミングでEEPROMから1バイトずつデータを読み出し、PWMデューティに設定することで行う。PWM周波数はクロックの都合で20KHz弱となったので、多少音声に高い音が混ざってしまう。一応、ローパスフィルタ(コンデンサ)で除去してみた。
また、メモリの容量の都合で、録音時にデフォルトのスピードより速いスピードで発声させたので、再生時には8KHzより遅いスピードに調整(waitを入れている)している。
時刻設定方法
- MODEスイッチを押すと、時刻設定モードに入る。「時刻設定」と発声後、現在の「時」が発声され、まず「時」を設定する。
- ADJ/INCスイッチを押すと、「時」がインクリメントする。
- 「時」が所望の値になったら、MODEスイッチを押すことで「分」設定モードに移る。
- ADJ/INCスイッチで「分」をインクリメントして、「分」を設定。
- 再びMODEスイッチを押すと、時刻設定を完了し、設定した時刻を発声する。
時刻アジャスト
- 毎正分の±30秒以内の誤差は、ADJ/INCスイッチで補正できる。
- たとえば、12:30:15 のときに ADJ/INCスイッチを押すと 12:30:00 と、00秒にリセットされる。
- 12:30:40 のときには、分をインクリメントし、秒を 00にリセットし、12:31:00 となる。
- 補正の際には、補正した時刻を発声する。
I2CインタフェースのプログラムはMicrochip社のアプリケーションノート(AN982:Interfacing I2C Serial EEPROMs to PIC10 and PIC12 Drivers)を利用し、PIC12F615用に変更、また1Mbit用に拡張。
アセンブラソースです。無保証です。
【ケース加工と組み立て】
![]()
ケース加工
ケースは100均のスピーカをそのまま利用した。
裏側に時刻設定スイッチの穴と、基板取り付け用の穴を開ける。
![]()
ケースに取り付け
基板をケースに取り付けた様子。本体基板、スイッチ基板共に2mmのビスで固定。
![]()
電池ボックス固定
電池ボックス(単三電池2本)はスポンジ状の両面テープでケースの底に固定。単三電池がぴったり収まる。
![]()
ケース組み立て
スピーカ部をかぶせて、3本のビスで固定。このあと左側に写っているパンチングメタルのカバーを取り付けて完成。
![]()
スピーカ裏側
裏側には基板取り付けビスの頭と、下のほうに時刻設定スイッチが見える。
赤いスイッチがMODEスイッチ、黒いスイッチがINC/ADJスイッチ。
![]()
完成
正面から見ると100均スピーカそのまま。時計が埋め込まれているとは思うまい。
完成動画
動画(2分55秒)をアップしてみました。音声を確認できます。
以上