2012年3月16日金曜日

音楽プレーヤーをさくっと作成

AVRでSDカードの読み書きが出来るようになりました。

ポイントは

  • 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で作っています。


  1. SDから1byte読む
  2. PWMでデータを出力
  3. 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()
{
}

2012年3月12日月曜日

Japaninoのブートローダー、fuseの復旧

引き続きAVRをいじっています。
本業が忙しいのでほそぼそですが。

現在SDカードをSPIモードでアクセスを試みています。
ディレクトリを読めたのでまずはOK。この件についてはそのうち。

ブレッドボード上にArduinoもどきを作っていますが、
リファレンス機として、大人の科学付録のJapaninoもたまに使っています。
が、てきとーにfuseビットを書き換えてしまい、
sketchを書き込めなくなってしまいました。
復旧方法を調べたのですが、まとまっていなかったので、
記録しておきます。

1. 機材

JTAGICE MKIIを使ってISP書き込みを行いました。
普通にISPライターを使えば良いのですが、たまたま手元にあったので、
オーバースペックですがISPライターがわりに使いました。

接続は、
jtagiceの凸となっているコネクタを、

1 3 5 7 9
2 4 6 8 10


というピン配列とすると、
AVR側(DIPの168のピン番号)とは


1: SCK(pin19 = D13)
2: GND
3: MISO(pin18 = D12)
4: Vcc
6: RESET(pin1)
9: MOSI(pin17 = D11)
※ほかのピンは放置


と接続します。
Japaninoの場合は、黒いピンソケットのD11-13, RESET, +5V, GNDを使いました。
別にICSPソケットは付けなくてもよさそうです。
リード線で結べばOK。



jtagiceをパソコンと接続し、japaninoをパソコンのUSBポートに接続したら
準備OK。
パソコン側ではAVR studioで書き込みを行います。


2. 情報のありか


さて、問題はどのブートローダーを書き込むのか、fuseビット等はどうするのか、
という情報ですが、
ウェブを探してもどうにも見つかりませんでした。

結局、大人の科学のサポートページからダウンロードできる、
開発環境にヒントがありました。

arduino-0018/hardware/arduino/boards.txt

というファイルがありました。中には、


japanino.name=Gakken Japanino(学研 大人の科学 ジャパニーノ)

japanino.upload.protocol=stk500
japanino.upload.maximum_size=14336
japanino.upload.speed=19200

japanino.bootloader.low_fuses=0xe2
japanino.bootloader.high_fuses=0xdd
japanino.bootloader.extended_fuses=0x00
japanino.bootloader.path=lilypad
japanino.bootloader.file=LilyPadBOOT_168.hex
japanino.bootloader.unlock_bits=0x3F
japanino.bootloader.lock_bits=0x0F

japanino.build.mcu=atmega168
japanino.build.f_cpu=8000000L
japanino.build.core=arduino


てなことが書かれていました。
つまり、ブートローダーはLilypad用のを使い、
fuseビットはL:e2, H:dd, Ex:00で、ロックビットは0fにしろ、ってことですね。

ブートローダーはサブディレクトリの

bootloaders/lilypad/LilyPadBOOT_168.hex

がそれっぽいですね。
ブートローダー書き込み、fuseビット書き込み、ロックビット書き込み、
という順番で作業を行いました。
できたっぽいです。
なお、fuseビットのextendedは読み込み直すとf8になり、
ロックビットはcfに見えますが、未使用のビットが1に見えるらしいので
正常に書き込めています。

で、動作確認はsketchのサンプルから適当に選び、
シリアルで書き込みます。
jtagiceは外さないとダメっぽいです。
サンプルはfadeあたりがわかりやすいですかね。



GNDとD9をLEDと抵抗(2-300Ωくらい?)で直列に結べば、ぼあーっとLEDが点滅する。
ワニ口クリップが意外と便利。


3. 外部クロックに対応


デフォルトのfuseビットには問題があり、
内蔵クロックで動作するらしいです。
せっかくjapaninoには水晶が乗っているので
これを使用することにします。

単にfuseビットのloをe2からe6にするだけみたいです。
一応動作はしましたが、
外部発振器が使われているかどうかは見た目ではわかりませんね。