回路設計
アナログ フィルター部
音声の入出力で不要な高周波成分を除くため、オペアンプによるアクティブ ローパス フィルターを使用します。今回はデジタル フィルターを併用しているため、アナログ フィルターの次数は 4 次としています。
アナログ フィルターの設計には、マイクロチップの FilterLab を利用しました。フィルターのパラメーターは以下の通りとしました。
パラメーター | 値 |
---|---|
フィルターの種類 | ローパス |
パスバンド周波数 | 3,500 Hz |
パスバンド減衰率 | -3.01 dB |
ストップバンド周波数 | 16,000 Hz |
ストップバンド減衰率 | -50 dB |
フィルター特性 | バタワース |
次数 | 4 |
FilterLab で設計したフィルターの回路図および、周波数特性のシミュレーション結果を以下の図に示します。なお、実際に使用するオペアンプは、2 回路入りの MCP6002 (マイクロチップ) を選定しました。このオペアンプは低電圧単電源動作が可能で、レール to レール入出力対応です。


マルチプレクサ部
ブロック図のセクションで述べたとおり、音声の録音と再生は同時に行わないため、アナログ フィルターは 1 回路のみ用意し、アナログ マルチプレクサを使用して回路を切り替えます。
アナログ マルチプレクサには、標準ロジック IC である、74HC4053 を使用します。下図では省略されていますが、0Y、1Y については、切り替わっていない側の入力 (パワー アンプまたは A/D IN) がオープンになってしまうため、100 kΩでプルダウンします。

マイク入力部、スピーカー出力部
これらについては、簡素化のため、秋月電子の高感度マイク アンプ キットおよび LM386G 使用モノラル パワー アンプ キットを利用しています。

マイクの電源は、Raspberry Pi Pico 2 の 3.3 V 出力から取っています (無音時の出力電圧がちょうど中間電位になるため、A/D コンバーターに直接入力できます)。一方、パワー アンプの電源は、VBUS から取っています (パワー アンプの動作電源電圧が 4 V 以上であるため)。
回路図
作成した回路図を以下に示します (マイク、パワー アンプ部は省略)。TP1 (AUDIO IN) に、マイク アンプの出力、TP2 (AUDIO OUT) に、パワー アンプの入力が接続されます。

パーツ リスト
今回使用したパーツは以下の通りです (これらのほかに、ブレッドボード、ジャンプ ワイヤーなどを別途使用しています)。
パーツ名 | 型番・数値 | 数量 |
---|---|---|
Raspberry Pi Pico 2 | SC1631 | 1 |
細ピンヘッダー 1×20 | PHA-1x20SG | 2 |
タクト スイッチ | DTS-63-N-V-BLK(TS-0606-F-N-BLK | 3 |
オペアンプ | MCP6002 | 1 |
アナログ マルチプレクサ | 74HC4053 | 1 |
抵抗 | 3.3 kΩ | 1 |
抵抗 | 8.2 kΩ | 1 |
抵抗 | 9.1 kΩ | 1 |
抵抗 | 20 kΩ | 1 |
抵抗 | 100 kΩ | 2 |
コンデンサ | 1200 pF | 1 |
コンデンサ | 6800 pF | 1 |
コンデンサ | 0.01 μF | 2 |
高感度マイク アンプ キット | AE-MICAMP | 1 |
LM386G 使用モノラル パワー アンプ キット | AE-KIT45-386AMP | 1 |
スピーカー ユニット 4cm 4Ω3W | DXYD40-22P-4A | 1 |
入出力波形の観測
音声入力に 3 kHz の正弦波を入力したときの入出力波形を以下の図に示します。


出力波形には、PWM と思われるノイズがかなり重畳していますが、元の波形は再現できています。
動作デモ
ブレッドボードで組み立てたものを、以下の写真に示します。

動作させている模様を以下の動画でご覧ください。ここでは、音声サンプルとして、音街ウナが話す音声を録音・再生しています。
感想
今回、ソフトウェアでオーバー サンプリングなどを初めて実装しましたが、実際にプログラムを組んでみると、案外少ない行数で実装できるものだなというのを実感しました。Raspberry Pi Pico で音声入出力ができることが分かったので、デジタル信号処理と組み合わせて、いろいろ面白いものが作れそうな気がしました。
コーディングが終わって初めて動作させた際、なぜかプログラムがハングアップしてしまい、いろいろな箇所に printf を入れたり、デバッガーをつないだりしましたが原因がわからず、ドツボにハマってしまいました。
改めてソース コードを確認すると、VoiceMessage クラスのコンストラクタから Initialize メソッドを呼び出し忘れていて、周辺回路が初期化されていなかったというポカミスでした (どうりで LED が点灯しなかったわけだ)。デバッグでハマったときは思い込みを捨て、疑ってかかることが大事だなと改めて思いました。