2014/01/26
Arduino UNO/Mega 2560 .WAVファイルの再生
Arduino UNO/Mega 2560で動作する.WAVファイル再生スケッチを作成しました。
.WAVファイルは、フォーマット変換アプリで「8000Hz/8bit/Mono」または「16000Hz/8bit/Mono」形式にして、SDカードにコピーします(サンプルスケッチでは「test0001.wav」です)。
UNOではD3pin、MegaではD9pinから出力されますので簡単なローパスフィルターを通してアンプに接続します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include <SPI.h> #include <SD.h> #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) const int debugPort = 8; // debug port const int soundPort = 9; // sound out const int chipSelect = 53; // SD CS #define BUFF_SIZE 512 // buffer size #else const int debugPort = 8; // debug port const int soundPort = 3; // sound out const int chipSelect = 10; // SD CS #define BUFF_SIZE 256 // buffer size #endif unsigned char buffs[BUFF_SIZE * 2]; volatile unsigned short bufGP; // buffer pointer for GET volatile unsigned short bufPP; // buffer pointer for PUT ISR(TIMER2_OVF_vect) // Timer2 overflow ISR { static unsigned char intCnt = 0; if (++intCnt >= 4) { // 8:8kHz, 4:16kHz intCnt = 0; if (bufGP != bufPP) { OCR2B = buffs[bufGP]; // analogWrite(soundPort, buffs[bufGP]); if (++bufGP >= sizeof(buffs)) bufGP = 0; } } } void dispErr(int rc) { while (1) { for (int i = 0; i < rc; i++) { digitalWrite(debugPort, HIGH); delay(500); digitalWrite(debugPort, LOW); delay(500); } delay(2000); } } int playWav(char *waveFile) { File dataFile; if (!(dataFile = SD.open(waveFile))) return(2); // can't open File. bufPP = dataFile.read((void *)&buffs[0], BUFF_SIZE); if (bufPP < 44) return(3); // bad format. bufGP = 44; TIMSK2 |= _BV(TOIE2); // Timer2 overflow interrupt enable while (dataFile.available()) { if (((bufPP < bufGP) && ((bufPP + BUFF_SIZE) < bufGP)) || ((bufPP > bufGP) && ((bufPP - BUFF_SIZE) < bufGP))) { digitalWrite(debugPort, HIGH); bufPP += dataFile.read((void *)&buffs[bufPP], BUFF_SIZE); if (bufPP >= sizeof(buffs)) bufPP = 0; digitalWrite(debugPort, LOW); } } while (bufGP != bufPP) ; TIMSK2 &= ~_BV(TOIE2); // Timer2 overflow interrupt disable dataFile.close(); return(10); } void setup() { pinMode(debugPort, OUTPUT); pinMode(soundPort, OUTPUT); if (!SD.begin(chipSelect)) dispErr(1); // can't open SD. // Timer2 Setup TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // Mode = 3(First PWM) TCCR2B = _BV(CS20); // Prescale factor = 1:1 } void loop() { dispErr(playWav("test0001.wav")); } |
コメント:0