いろいろと手をひろげる癖があるもんで、プラモデル、Nゲージのコントローラ・・なかなか完成品ができない・・・
PICマイコンでメモリ上のWavファイルのデータを再生
Nゲージ用のコントローラやレイアウトなどを音が出るものにしようとして、MP3プレーヤボードを買って、PICマイコンで制御するように製作中。
だが、単純な効果音の再生用としてはPIC24FJ64BA002(16ビットマイコン)を使って、Wavファイルを再生してみようかなと。
ひとまずはメモリ上に置いたWavファイルのデータを出力する部分の試作。
PICマイコンでMP3プレーヤ相当のものを作るのに、VS1011eというデコーダICを使っている例がみられる。
アタイも検討してみたが、制御するPICマイコンやVS1011e、MP3ファイルを格納するSDかメモリチップなどを購入すると千数百円はかかりそう。
一方、マイコンキットドットコムからMK144というMP3プレーヤボードが1980円で販売されている。
制御するタクトスイッチや制御用の基板を購入すると、もう数百円は単価は上がりそうだが。
費用的には自作のほうがちょっぴりお得か?等々、考えてみたが、最終的にはMK144を複数買って、それを自作のコントローラで制御しようかなぁ、とゴソゴソと作業を始めた。
しかし・・まだ、完成したわけではないが途中でフッ..と思った。
駅に停車中のディーゼルカーの「ゴロッ、ゴロッ、ゴロッ」というエンジンのアイドリング音や、蒸気機関車のドンキーポンプの音などは単調な音が繰り返されているだけ。
0.5秒程度の「ゴロッ」という音の繰り返しや、数秒程度の繰り返し音などは別にMP3プレーヤを使って再生させなくてもいいんじゃないかなぁと。
MP3ボードを制御するのにPICマイコンを使用したとしても、PICマイコンは再生開始や停止を指示するコマンドを送信するだけが仕事で、MP3ボードが音を再生している間は基本的には・・暇。
ならば、単調な繰り返し音はちょっと性能の良いPICマイコンを買って、それでやってしまおう。
現在作っているNゲージの踏切の警報音などもPICマイコンで出力しているが、音のデータを格納できるサイズは本当に限られていて、長い音の格納はできない。
また、1つの音源ごとにPICマイコンを使っていてはPICマイコンだらけになってしまう。
やっぱ音源はSDカード類から読込んで、スイッチによって複数の音源を切り替えて再生できる仕組みが必要だろう。
本格的に作ってみる前に・・
Wavファイルのデータを出力する部分の試作
ひとまずはメモリ上に置いたWavファイルのデータを出力する部分の試作を開始。
PIC24FJ64BA002(16ビットマイコン)を使って、メモリ内に書き込んでおいた数秒程度のWavファイルを再生してみることにした。
手元にはマイコンキットドットコムで購入したMP3 プレーヤボード用コントローラキットMK148がある。
この部分は代替品を自作することにしたのでお役御免の予定だった。
しかし、基板上にはアンプ(LM386)が2つ載っているし、usart 通信でMP3 プレーヤーボードを制御するための配線も簡単に作れそうなので再度登板。
(右のオレンジ色の基板)とMK148(左の緑色の基盤)を裏側でアクリル板を使ってくっつけてみた。
PIC24FJ64GA002を載せたユニバーサル基板電源はMK148からPIC24FJ64GA002のボード側に供給。
PICマイコンからの音声の出力はMK148上のアンプ(LM386)で本来のMP3ボードの音声とミキシングして出力するように変更。
メモリ内に書き込んだWavファイルを再生するのであるが、この次のステップとしてSDカードからWavファイルを読み込ませようとしている。
そのため、ユニバーサル基板上にはSDカードスロットも載っけて配線もすませておいた。
(写真のオレンジ色の基盤の右上の部分)
この基板の空き地には、ファイルセレクタ用のスイッチやら、開始、停止用のスイッチなどが入る予定。
仕様とプログラム
・Wavファイルは「8kHz 16bit モノラル」のみを対象
・今回のサンプルプログラムはRB0(4ピン)、RB1(5ピン)に同じデータを出力
・Wavファイルはメモリに格納できるだけのサイズのものを使用してフラッシュメモリに格納
main.c
/********************************************** * * PIC24FJ64GA002 * * 8kHz sampling , 16bit モノラル Wav再生テスト * コンパイラ XC16 ***********************************************/ #include // CONFIG2 #pragma config POSCMOD = HS #pragma config I2C1SEL = PRI #pragma config IOL1WAY = OFF #pragma config OSCIOFNC = OFF #pragma config FCKSM = CSDCMD #pragma config FNOSC = PRIPLL #pragma config SOSCSEL = SOSC #pragma config WUTSEL = LEG #pragma config IESO = OFF // CONFIG1 #pragma config WDTPS = PS32768 #pragma config FWPSA = PR128 #pragma config WINDIS = ON #pragma config FWDTEN = OFF #pragma config ICS = PGx1 #pragma config GWRP = OFF #pragma config GCP = OFF #pragma config JTAGEN = OFF #include "chime.h" unsigned int chimeidx; int playFlag; /*********************** * タイマ4割り込み処理関数 ***********************/ void __attribute__((interrupt, no_auto_psv)) _T4Interrupt(void) { int d = 128; if(playFlag){ // chimeデータの配列は偶数バイトで作成しておくこと d = chime[chimeidx] | (chime[chimeidx+1]<<8); d = d + 32768; d = d >>8; d = d & 0xff; chimeidx += 2; if(chimeidx>(sizeof chime)){ playFlag = chimeidx = 0; } } OC1RS = (PR2+1)*d/256; // RP0出力 OC2RS = (PR2+1)*d/256; // RP1出力 IFS1bits.T4IF = 0; // 割り込みフラグクリア } /************************** * メイン関数 ***************************/ int main(void) { playFlag = chimeidx = 0; CLKDIV = 0; AD1PCFG = 0xFFFF; // I/Oをすべてデジタルに TRISB = 0xfffc; // RB0(4ピン)、RB1(5ピン)を音声出力に CMCON = 0; // コンパレータオフ // タイマ2設定 T2CON = 0b1000000000000000; // タイマ2モード設定 PR2 = 159; //100kHz // OC1 RPOR0bits.RP0R = 18; // OC1をRP0(4ピン)に割付け OC1CON = 0x0006; // タイマ2使用,PWM mode,OCFx disabled OC1RS = (PR2+1)/2; // 50% // OC2 RPOR0bits.RP1R = 19; // OC2をRP1(5ピン)に割付け OC2CON = 0x0006; // タイマ2使用,PWM mode,OCFx disabled OC2RS = (PR2+1)/2; //50% // タイマ4モード設定 T4CON = 0b1000000000010000; PR4 = 249; // 125usec 8kHz IPC6bits.T4IP = 5; // 割り込みレベル = 5 IFS1bits.T4IF = 0; IEC1bits.T4IE = 1; // 割り込み許可 while(1){ playFlag = 1; } }
音声データ
音声のデータとなるWavファイルは「8kHz 16bit モノラル」で2~3秒のチャイム音を16進で記述してヘッダファイルとして作成し、プログラム内に格納した。
作成方法は、次のとおり
(1)Wavファイルをバイナリエディタで開く
(2)dataチャンクがあらわれるまで(‘data’の文字列があるのでわかります)を削除
(3)dataチャンクのID(‘data’の文字)とレングスを示す4バイト分を削除
(4)その後以降が波形データであるが、末尾の作成したソフトな名前などが入っている場合があるので、その部分があれば削除
(5)1バイト毎に0xと,をつけたりしてプログラムのヘッダファイルとして使用できるように編集。
編集は・・
秀丸等のエディタにデータを貼り付けて、置換コマンドで各バイトの先頭に0xをつけたり、,をつけたり。
1行を80文字くらいで改行したければ、同じく置換コマンドで「^.{80}\f\0\n」を「\0\n」に置換したりして編集。
以上のファイルをヘッダファイルにして、main関数でインクルードする。
ちなみに、今回はチャイム音を使ってみた。
chime.h
/******************************************************************** チャイム音 Wav 8kHz モノラル 16bit ********************************************************************/ const unsigned char chime[] = { // dataチャンクID'data'とサイズの後から、末尾の拡張部分の前までを登録 0xBD , 0xFF , 0x25 , 0x00 , 0xC5 , 0xFF , 0x97 , 0xFF , 0xB9 , 0x00 , 0x46 , 0x00 , 0xD2 , 0xFF , 0x62 , 0x00 , 0x85 , 0x01 , 0xD6 , 0xFF , 0xA6 , 0xFB , 0xFF , 0xF8 , 0xBA , 0xFD , 0xEF , 0x08 , 0x9A , 0x0B , 0xFF , 0x03 , 0x6A , 0x00 , 0x6F , 0xF3 , 0x5A , 0xEE , 0xAC , 0xFC , 0xDE , 0x14 , 0x4F , 0x09 , 0x54 , 0xFB , 0xE0 , 0x05 , 0x27 , 0x04 , 0xDA , 0xEC , 0x06 , 0xED , 0x42 , 0x02 , ~ 省略 ~ };
本番のプログラム(SDカードからファイルを読んで再生するプログラム)を作成するとき、動作中にエラーがあった場合にエラーを表示する機能が欲しい。
そのエラー表示にLEDを点滅させようとすると、PICマイコンのポートを占有してしまう。
そこで、今回作ったチャイム音データは本番プログラムでもプログラム内に格納しておいて、エラーがあった場合にはこのチャイム音を鳴らすことにした。
こうすることで、
・エラー音をSDファイルに格納しておくと、SDファイルが読めない時にエラー音が出せないが、プログラム内に格納しておくとその心配はない。
・一度エラー音が出ることを確認しておけば、サンプリングなどに問題があって再生できないファイルなのか、再生モジュール自体に問題があって音が出力ができないのか、プログラムにデグレードがあるのかなどの切り分けができる。
というメリットがありそう。
試作した結果
回路図エディタ持ってないので図面は省略(^^;
プログラム中のコメントにPICマイコンのどのピンに出力しているのか書いときましたんで、それをアンプにつなげて・・
その他は、PICマイコンへの電源供給とPIC24FJ64BA002の場合はコンデンサなどの接続等々が必要。
それらはPICマイコンのメーカーが出している説明書に書かれているポートに配線して・・
という感じでご自身で・・(^^;
ひとまず、アタイの試作品は、メモリ内に格納したWavファイルの音声は無事出力できた。
次のステップとしては、
PIC24FJ64BA002を使ったWavファイルプレーヤーの次のステップでは、
・SDファイルから音声データを読込んで、それを出力する。
・ついでにusart 通信で市販のMP3プレーヤーボードを制御する。
ということになる。
このプログラムで、2つのポートから同じ音声を出力しているのは、2ファイルを読みながら音声を出力できるだけの能力がでるようにプロクラムが組めるか検証するため。
PICマイコンにその性能があれば、2種類の音が同時にだせるのではないかともくろんでいるからなのだが。
スイッチをつけてSDファイルから読むデータを切り替えられるようになったら、プラモデルやNゲージのシーナリーなどを置く台の下などに格納できるようにするつもり。
予定では、mp3のBGMが流れると同時にWavの繰り返し音が流れるのであった。
・雪なんかとディーゼルカーがあるNゲージのレイアウトのセクションでは気動車のエンジンのアイドリング音と「鉄道員(ぽっぽや)」のBGM
・三陸鉄道の36系があるNゲージのセクションでは気動車のエンジンのアイドリング音と「あまちゃん」のBGM
・ハーレーのバイクがあるプラモデルの飾り台では3拍子のアイドリング音とBGMは「Born to Be Wild」….
まぁ、そんなことを考えながら、次のステップに進もう。
寄り道が多くて、なかなかNゲージのコントローラなどは完成しないのであるが..
追記
SDカードから読み込んで再生するものを作ってみた。
2ファイルを読みながら、2つのモノラルの音声を出力することができる。
鉄道模型レイアウト・プラモデル展示台用の音(PICでWAV再生)