【Arduino】WaveShieldのプログラミングを解体!!

最近お弁当と一緒にお味噌汁を飲んでます。満足度が倍増しますねぇ
あ、こんにちは! ヨリミチ団です!

早速ですが、前回のプログラミングを私のフィーリングで紐解いてみます!


#include < FatReader.h >
#include < SdReader.h >
#include < avr/pgmspace.h >
#include “WaveUtil.h”
#include “WaveHC.h”


冒頭に書いてあるこちら
これは外部のライブラリから引用することで自分のスケッチに取り込むことができます。
今回はWaveHCがそのライブラリに該当します。
よく見ると #include の後に、<> と ” “ に分かれておりますね。

#include < .h> …. .hのライブラリを指定するするものです。
#include “ .h” …. 外部のライブラリの(今回はWave.Util.h, WaveHC.h)ヘッダファイルを使用するものです。
調べた結果意味はなんとなくわかりましたが、根本的な理由は書かれているプログラム次第となるものと思います。
フィーリング解説で申し訳ございません。私はコピペマスターなのです

私も初心者なのでざっくりサクサク進めます!(もっと勉強します!)
以下青文字は本家の文章に書いてあったユーモアあふれる言葉を意訳してみました


SdReader card; //このオブジェクトがSDカードの情報処理をします
FatVolume vol; //SDカードのパーティションを処理します。SDカードフォーマットのときにFatにしましたよね!
FatReader root; // SDカードのファイルシステムを処理します
FatReader f; //SDカードの音源を再生しているときに処理します

WaveHC wave; // 音の処理をするオブジェクトです

#define DEBOUNCE 5 // ボタンをノイズなくきれいに認識してくれるもの

// 今回はアナログINの6つの穴にボタンを用意できます
byte buttons[] = {14, 15, 16, 17, 18, 19};
//この手頃なマクロは上記の整列のサイズをチェックして決定します。(直訳しましたが理解不能..とりあえず処理してくれているのでしょう…)

#define NUMBUTTONS sizeof(buttons)
//ボタンが一度押された、離された、押し続けられている状態を以下のpressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];として認識します

volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS];

//この手頃な関数はRAMで計算して空き容量バイトを算出してくれます。デバッグにはいいですね。

int freeRam(void)
{
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) – ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) – ((int)__brkval);
}
return free_memory;
}

void sdErrorCheck(void)
{
if (!card.errorCode()) return;
putstring(“\n\rSD I/O error: “);
Serial.print(card.errorCode(), HEX);
putstring(“, “);
Serial.println(card.errorData(), HEX);
while(1);
}


ふぅ… ちょっと疲れてしまいましたが、プログラムに無駄は一つもないんだなと思い知らされます。
ちなみにArduino内の // はプログラムとして認識されないのでメモ欄としてしばしば利用されます!


void setup() {
byte i;


//シリアルポートを指定します。(大体9600です)

Serial.begin(9600);
putstring_nl(“WaveHC with “);
Serial.print(NUMBUTTONS, DEC);
putstring_nl(“buttons”);

putstring(“Free RAM: “);
// デバッグに有効です。RAM不足はよくありません、とのこと。きっとRAM開放するのでしょうね。

Serial.println(freeRam());
// もしも150バイトを下回ると文章に問題がでるかも!


// DAC(デジタルアナログコンバータ)アウトを指定します。これは先程includeしたライブラリで指定されています。

pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);


// 実は再生中はpin13LEDが光ります!!これで再生確認をLEDの点灯でも目視できますね。

pinMode(13, OUTPUT);

// Make input & enable pull-up resistors on switch pins
for (i=0; i< NUMBUTTONS; i++) {
pinMode(buttons[i], INPUT);
digitalWrite(buttons[i], HIGH);
}

// もし (!card.init(true)) { //4 MHz spi(spi:シリアル・ペリフェラル・インターフェース)で再生、もし8MHz であると再生しません。
if (!card.init()) {
//8 MHz spiで再生します (default faster!)
putstring_nl(“Card init. failed!”);
// もしもエラーがでたら”Card init. failed!”と書きます
sdErrorCheck();
while(1);
// ‘halt(停止の意)’ – 何も再生しません!
}

// 最適な読み取りを許可 – いくつかのSDカードでは読み取れない時があります。もしも問題があれば許可しないようにしてください。どういう意味だろう…
card.partialBlockRead(true);

// FATのパーティションを確認します
uint8_t part;
for (part = 0; part < 5; part++) {
//5つのスロットを確認する必要があります
if (vol.init(card, part))
break;
//1つ見つけました。開放しまししょう。
}
if (part == 5) {
// もしも1つも見つからなかったら… :( ←多分外人特有のAAの悲しい顔
putstring_nl(“No valid FAT partition!”);
sdErrorCheck();
// 何かがおかしいですね。printして何がおかしいか書き出てもらいましましょう。
while(1);
// ‘halt(停止の意)’ – 何も再生しません!
}

// ユーザー(我々のこと)に何を発見したか知らせましょう。
putstring(“Using partition “);
Serial.print(part, DEC);
putstring(“, type is FAT”);
Serial.println(vol.fatType(),DEC);
// FAT16 or FAT32?

// ルートディレクトリを開きます
if (!root.openRoot(vol)) {
putstring_nl(“Can’t open root dir!”);
// 何かがおかしい
while(1);
// ‘halt(停止の意)’ – 何も再生しません!
}

// やっと難しいところを切り抜けたね!汗
putstring_nl(“Ready!”);

TCCR2A = 0;
TCCR2B = 1<

//Timer2 Overflow Interrupt Enable割り込みを許可
TIMSK2 |= 1<<TOIE2;

}

SIGNAL(TIMER2_OVF_vect) {
check_switches();
}

void check_switches()
{
static byte previousstate[NUMBUTTONS];
static byte currentstate[NUMBUTTONS];
byte index;

for (index = 0; index < NUMBUTTONS; index++) {
currentstate[index] = digitalRead(buttons[index]);
// ボタンを読み込む

/*
Serial.print(index, DEC);
Serial.print(“: cstate=”);
Serial.print(currentstate[index], DEC);
Serial.print(“, pstate=”);
Serial.print(previousstate[index], DEC);
Serial.print(“, press=”);
*/

if (currentstate[index] == previousstate[index]) {
if ((pressed[index] == LOW) && (currentstate[index] == LOW)) {
// just pressed押されました
justpressed[index] = 1;
}
else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) {
// just released押されました
justreleased[index] = 1;
}
pressed[index] = !currentstate[index];
// 覚えておいてね、digital HIGH はボタンを”押されていない状態”のことですよ
}
//Serial.println(pressed[index], DEC);何かをプリントします(シリアルモニタで確認確認できるはず..)
previousstate[index] = currentstate[index];
// ボタンの計算を走らせ続けます
}
}


ここまではSDカードリーダーや、ボタン認識の設定のようですね。

さぁ、最後の塊もやっつけましょう!


void loop() {
byte i;

if (justpressed[0]) {
justpressed[0] = 0;
playfile(“DO.WAV”);
}
else if (justpressed[1]) {
justpressed[1] = 0;
playfile(“RE.WAV”);
}
else if (justpressed[2]) {
justpressed[2] = 0;
playfile(“MI.WAV”);
}
else if (justpressed[3]) {
justpressed[3] = 0;
playfile(“FA.WAV”);
}
else if (justpressed[4]) {
justpressed[4] = 0;
playfile(“SO.WAV”);
}
else if (justpressed[5]) {
justpressed[5] = 0;
playfile(“LA.WAV”);
}
}

// 音源の最後まで止まらずに再生します
void playcomplete(char *name) {
// この音源の名前を表示します
playfile(name);
while (wave.isplaying) {
// 再生中は何もしません
}
// 再生が完了しました
}

void playfile(char *name) {
// waveオブジェクト(音源のことと思われる)が今何かしているか確認
if (wave.isplaying) {
// 何か再生していたら、停止する
wave.stop();
// これで停止
}
//ルートディレクトリを開き確認する
if (!f.open(root, name)) {
putstring(“Couldn’t open file “); Serial.print(name); return;
}
// これでファイルを読み込んでwavオブジェクト(音源)に変換を許可します
if (!wave.create(f)) {
putstring_nl(“Not a valid WAV”); return;
}

// これで再生が可能になります!
wave.play();
}


最後はどのボタンを押したら、なんの音源を流すかの指定。
塊の最後には、音を止める処理を施してから、再びボタンを押される準備をしているようです。

ひゃぁ 疲れたぁ
でもなんだか文脈がなんとなくわかった気がしますね!

これでどこを書き換えればいいか気がついた人は鋭いです!
そう そ・れ・は…

つづく!

この記事が気に入ったら
いいね ! しよう


PAGE TOP