ポイントは
- 5Vで動作させると面倒なので、2.7-3.6Vで駆動(信号線のレベルをSDに合わせる必要があるため)
- 配線はサンプルスケッチの説明どおり
- ATmega168Pでは容量不足か?ATmega328Pだと動いた
調子に乗って音声データをSDカードに入れて、それをPWMで
音にしてみました。
しょぼしょぼですが音楽プレーヤーの完成です。
動作の様子はこちら。
http://www.youtube.com/watch?v=UsRMV_p-O_8
思っていたより音が綺麗で笑えます。
PWMの出力はほぼそのままスピーカーに入れています。
一応手元の抵抗とコンデンサをつないでRCフィルター的な接続をしてみましたが、
意味はあるかわかりません。
電源は3VのACアダプタです。電圧が微妙なのは3.3Vが売り切れていたからだったりします。
スケッチを書き込むときは3V駆動ではだめなようで、
5V(USBから給電が簡単)にします。
動かすときはまた3Vに切り替えます。
まちがえて5Vを入れてしまったこともありますが、SDカードは壊れなかったようです。
まずはスペック。
音声データはモノラル8bit PCMで、サンプリングレート8000Hzとしました。
曲はビートルズのLove me do。ちなみに、オリジナルアルバムではなく、アンソロジーのテイクだったりします。
MP3データをaudacityでフォーマット変換しwavにしておきます。
ファイル名は決めうちで、wavファイルをSDカードのルートにおきます。
SDカードを取り付けた状態で電源を投入すると曲が再生されます。
終わったら停止します。つまり、1曲しか再生できずリピートもしません。
PWMはDigital9(pin15)を利用しています。
変な信号で機材を壊しては困るので、壊れても惜しくないスピーカーをつなぎます。
アクティブスピーカーじゃないと音が小さすぎるかも。
PWM周波数がデフォルトで500Hz弱と音声再生には使えない値なので、周波数は変更の必要があります。
方法はhttp://www.arduino.cc/playground/Main/TimerPWMCheatsheetを参考にしました。
これらを踏まえて、スケッチを作成しました。
ベースにしたのはサンプルのSD->DumpFileです。
読みとったデータをシリアル出力するところを書き換えて、PWMに出すようにしました。
サンプリング周波数はタイマーを使わず、delayで作っています。
- SDから1byte読む
- PWMでデータを出力
- delay(!!ダサい)
といった感じですね。なのでサンプリング周波数はてきとーです。
delay値は耳で聞いて決めました。めちゃくちゃですね。
そのうちちゃんとするとして、ひとまず音が出て楽しかったので勇み足で
ブログを書いたのでした。
スケッチは以下のようになりました。
簡単に出来てしまいました。
/*
SD card file dump
This example shows how to read a file from the SD card using the
SD library and send it over the serial port.
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
created 22 December 2010
This example code is in the public domain.
*/
#include
// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;
int sndPin = 9;
void setup()
{
Serial.begin(9600);
Serial.print("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
// pwm frequency is set to 31khz
TCCR1B = TCCR1B & 0b11111000 | 0x01;
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
//File dataFile = SD.open("datalog.txt");
File dataFile = SD.open("test.wav");
//File outFile = SD.open("out.txt", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
while (dataFile.available()) {
//Serial.write(dataFile.read());
//outFile.write(dataFile.read());
analogWrite(sndPin, dataFile.read());
//delay(1);
delayMicroseconds(80);
}
dataFile.close();
//outFile.close();
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
void loop()
{
}