今回は、家の固定電話を使って、Arduinoで電話をかけてみます。
お宅の電話の契約は、どちらになっていますか?……今時、ダイヤル回線って、契約できるのかどうか知りませんが……。もし、ダイヤル回線であれば、今回の実験はできませんので、あきらめてください。
ダイヤル回線と言うのは、電話番号の数値をパルスの数で送信する回線です。例えば、"9"と言う番号を送信する時には、ある間隔で「プツッ」というパルス信号を9回送信します。"2"と言う数字なら、2回です。パルスとパルスの間は、ある程度空けないと、交換機側が認識してくれないので、"99-8800"みたいな、大きな数字が多い電話番号への発信は、非常に時間がかかります。ちなみに、"0"では、10回パルスを送ります。
逆に、"11-2233"みたいな電話番号であれば、短い時間で発信できます。緊急通報の"110"や"119"が小さい数字"1"を使っているのは、緊急度の高い通報に時間をかけないため。最後の"0"や"9"は、ダイヤルした後、先方と通話する前に、一呼吸おいて冷静になってもらうため、と、聞いたことがあります。
さて、最近の電話回線は、プッシュ回線と言って、パルスの代わりにDTMF(Dual-Tone Multi-Frequency)というトーンを送ることで、電話番号を交換機に伝える仕組みです。DTMFでは、8種類の周波数の組み合わせで、番号を通知します(下表)。
高群[Hz] | |||||
1,209 | 1,336 | 1,477 | 1,633 | ||
低群 [Hz] |
697 | 1 | 2 | 3 | A |
770 | 4 | 5 | 6 | B | |
852 | 7 | 8 | 9 | C | |
941 | * | 0 | # | D |
電話機のボタン配置をご覧になると、上の様になっていませんか?PCのキーボードや電卓のキー配置と異なり、上側に1や2等小さな数字、下側に8や9等大きな数字が配置されています。このボタン配置の行と列に対して、上表に記載した周波数(697〜1,633[Hz])が割り当てられています。
例えば、"6"という番号を発信したい時には、行の770Hzと、列の1,477Hzの音を同時に鳴らすのです。これらの周波数は可聴域(20〜20k[Hz])なので、そのまま音として交換機に到達します。交換機では、音の周波数を解析して、770Hzと1,477Hzのピークを検出、よって、"6"だと知ります。
これが、プッシュ回線で電話機から交換機に先方の電話番号を通知する通信手段です。
※電話機では、一番右端の列、「ABCD」は使われていないみたいですね?このボタンが付いている電話機を見たことが無いので……。
DTMFを発信する時間には規定があり:
お気づきでしょうか?電話機から、交換機に対して、先方の電話番号を通知するプロトコルはこれだけ、なのです。
電話機:「今から番号を送信するよ」
交換機:「OK、どうぞ」
電話機:「11-2233ですよ」
交換機:「OK、先方を呼び出します」
みたいなハンドシェイクも何も「無い!」のです。平たく言うと、受話器を上げ、通話口に向けて決まった周波数の音を鳴らすだけで、電話はかかります。電話機のボタンを押さなくてもかかるのです。
と、言うことで、「Arduinoで電話をかける」と言うテーマは、「ArduinoでDTMFを鳴らす」に帰着しました。尚、「受話器を上げる」とか、その辺の物理的動作は今回のテーマに含みませんので、あしからず。そこは、皆様の「手」をお借りします。
※筆者宅は、IP電話になっており、所謂、NTTとの回線契約は無いのですが、この先の実験でDTMFを鳴らして、電話をかけることができましたので、IP電話でも実験は可能だと思われます。
「#5-8 MMLで音楽を奏でる」では、Arduinoで音階を奏でました。今回は、「ドレミファ…」と言った音階とは少しずれた周波数の音を鳴らす必要があるのですが、原理は同じ事です。最大の違いは、DTMFでは「2音を同時に鳴らす必要がある」ことです。
「#5-8 MMLで音楽を奏でる」では、タイマを制御して、音階に相当する周波数のPWMを出力し、音階を奏でました。1音だけだったので、タイマも1本を占有使用しました。今回は2音ですので、タイマも2本使います。
タイマはTC1(16ビット)とTC2(8ビット)を使用します。以下、各タイマの設定です。
TC1 | |||
レジスタ | アドレス | 設定値 | 備考 |
TCCR1A | 0x0080 | 0x43 | fast pwm mode (OCR1A),OC1A=toggle |
TCCR1B | 0x0081 | 0x1b | fast pwm mode (OCR1A),fcpu/64 |
OCR1A | 0x0088 | 0x0000 | 周波数に従って設定 |
TC2 | |||
レジスタ | アドレス | 設定値 | 備考 |
TCCR2A | 0x00b0 | 0x43 | fast pwm mode (OCR2A),OC2A=toggle |
TCCR2B | 0x00b1 | 0x0c | fast pwm mode (OCR2A),fcpu/64 |
OCR2A | 0x00b3 | 0x00 | 周波数に従って設定 |
TC1も8ビットタイマ相当で使用して、TC2との設定の共通化を図りました。
TC1、TC2共、カウントクロックをfcpu/64に設定しました。また、モードも「fast pwm mode (OCRxA),OCxA=toggle」にそろえたので、両タイマとも、(OCRxA+1)×2を周期とするデューティ50%のPWM波形を出力します。
鳴らしたい周波数をfDTMFとすると、その周期(1/fDTMF)がタイマの周期となる様に、OCRxA値を設定すれば良いことになります。
1/fDTMF=(OCRxA+1)×2×(1/(fcpu/64)) より、
OCRxA=1/fDTMF/2×fcpu/64−1
この式で計算した、各周波数に対応するOCRxAレジスタの設定値は、以下の対応となります。
周波数[Hz] | OCRxA設定値 | 備考 | |
低群 | 697 | 179−1 |
周期/2を計算して、そこから −1すると、OCRxAの 設定値となる。 |
770 | 162−1 | ||
851 | 147−1 | ||
941 | 133−1 | ||
高群 | 1,209 | 103−1 | |
1,336 | 94−1 | ||
1,477 | 85−1 | ||
1,633 | 77−1 | ||
無音 | 125,000 | 0 |
OCRxAに0x00を書き込むと、 125kHzのPWMが出力される。 可聴域外&LPFで遮断される ので、音は鳴らない。 |
TC1、TC2で、ほぼ同じ動作になるようなモードに設定してあるので、どの周波数をどちらのタイマで鳴らしてもOKです。完成版プログラム(play_dtmf.ino)では、低群をTC1、高群をTC2に割り当ててあります。
1つのDTMFを送出する手順は、以下の通りとなります。
信号送出時間(dtmf_msec_SIGO)=100ms、ミニマムポーズ(dtmf_msec_PAUS)=50msと、してあります。プログラム先頭付近の定数で調整可能です。
回路図は以下の通りです。
「#5-8 MMLで音楽を奏でる」と同様に、VP-P=5VのデジタルPWM波形をLPFで鈍らせることによって、イヤホン等に送るVP-P=0.5〜1.0[V]程度になるように、調整します。ここの原理については、「#5-8 MMLで音楽を奏でる」を参照してください。
鳴らす周波数(低群Vloと高群Vhi)によって、時定数CRの値を調整し、同程度の音量(VP-P)になるように調整してあります。
今回は2音を同時に鳴らす必要があったため、PWM出力が2本、従って、LPFが2個あります。2つの音声信号(Vlo,Vhi)ができるので、これをオペアンプの加算回路を使って加算しようかとも思ったのですが、ただのアナログ音声信号だったので、直結(ショート)してしまいました(1^^;)。音声信号としては、何ら問題ないはずです。
では、完成版プログラムをリンクしておきます。
完成版プログラム:play_dtmf.ino
コンパイルしてUNOに書き込んだら、シリアルモニタを開いてください。以下のコマンドを受け付けるようになっています。
実験サンプル:【 】内はシリアルモニタからの送信データ
【DTMF,123456789*0#ABCD】
OK: dtmf 123456789*0#ABCD
とりあえず、全部鳴らしてみました。スマホのボイスレコーダで録音したデータは以下の通りです。
:ar84_rec.wav
録音したデータを、WindowsのSoundEngine Freeというソフトウェアで解析してみた結果がこちら(↓)です。
横軸は時間の流れになっていて、左から右へ向けて時間が進んでいます。縦軸は録音した音に含まれる周波数であり、色で強度を示しています。
低群と高群に分かれて、しっかりと2音づつ鳴っています。スケールが粗くてわかり難いですが、まあ、所望の周波数が出ている様です。
※PWM → LPFで作った波形は、正弦波には程遠く、三角波に近いので、2kHzを超えた辺りには、うっすらと高調波成分(低群の高調波と思われる)が見えています……。
ここからは、実際に固定電話を使って、電話をかけてみます。
もう一度言っておきますが、本当に、電話がかかってしまいますので、十分注意して実験してください。
ご自身の携帯電話をお持ちなら、固定電話から自身の携帯電話にかけ、携帯電話の着信を確認したら、通話せずに切ると、通話料が発生しません。
さすがにイヤホン出力だと、音量が小さくて発信できませんので、出力をアンプ内蔵スピーカに繋いで、十分大きな音が鳴るようにボリュームを調整してください。
受話器を取って、相手の番号を入力できる状態になったら、電話機のボタンは押さずに、シリアルモニタから【dtmf,xxx-yyyy】などと、かけたい電話番号(xxx-yyyy)を入力して、送信してください。
この時、通話口(受話器のマイク部分)をスピーカに接近させて、DTMFの音を拾えるようにしてください。
どうでしょう?かかりましたか?
DTMFって、電話くらいにしか使われていないみたいなので、どう応用するか?ですね。そもそも、固定電話自体が衰退していますし、わざわざArduinoに発信させなくても、今時の電話機には「電話帳」機能が付いていますから……。
「#8-7 I/Oエクスパンダを使う」にて、4×4キーパッドを使って、DTMFを鳴らせるように、プログラム(play_dtmf.ino)を改定しました元のプログラムを差し替えてあるので、どこからダウンロードしても、最新版(改定版)になっています。
4×4キーパッドを繋がなくても、本ページの記事の通りの実験はできるようになっていますので、ご安心を。
「#8-7 I/Oエクスパンダを使う」で改定したプログラム(play_dtmf.ino)では、2音を同時に演奏可能な回路の利点を活かして、電子オルガンの機能が追加されていますので、併せて記事をご覧ください。