Audio FX Sound Boardは、3.3Vでも制御できる偉い子なので、
ESP8266で音制御するのに使えないかなと思って、試してみました。
1. Example、うごかへん...。
Adafruit_Soundboardのexamplesにある、menucommands.inoを実行したが動かなかった。
原因: 無限ループ
サンプルのsetup関数は、下記のようになってます。
// we'll be using software serial
SoftwareSerial ss = SoftwareSerial(SFX_TX, SFX_RX);
// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&ss, NULL, SFX_RST);
// can also try hardware serial with
// Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);
void setup() {
Serial.begin(115200);
Serial.println("Adafruit Sound Board!");
// softwareserial at 9600 baud
ss.begin(9600);
// can also do Serial1.begin(9600)
if (!sfx.reset()) { // ← こいつがわるさしてる
Serial.println("Not found");
while (1);
}
Serial.println("SFX board found");
}
- sfx.reset()のところで、常にfalseが帰ってきてしまい、while(1)が走り続けます。
- ESP8266のWDTが1000msで、1000ms以内に関数内の処理をおえないとリセットがかかります。
- 1に戻ります。
解消方法: reset()関数のreturnを無視 + SoftwareSerialからの卒業
というわけで、sfx.reset()がtrueを返すかとかを無視することにしました。
ついでに、SoftwareSerialが不安定なので、ESP8266ではIO2をSerial1のTXピンとして使えるので、下記のように処理を変更しました。
// pass the software serial to Adafruit_soundboard, the second
// argument is the debug port (not used really) and the third
// arg is the reset pin
Adafruit_Soundboard sfx = Adafruit_Soundboard(&Serial1, NULL, SFX_RST);
void setup() {
Serial.begin(115200);
Serial.println("Adafruit Sound Board!");
// softwareserial at 9600 baud
Serial1.begin(9600);
// just reset!
sfx.reset();
}
これだけで良かったんや!!
2. 割込再生をやりたいんや(やりたいんや)
Audio FX Sound Boardさんは、MP3 Triggerさんみたいに割込で楽曲の切替ができません。
でも、やりたいんやで。
パターン1: 1曲目が勝手にとまって2曲目を再生できたら嬉しいけどできないパターン
たとえば、下記のようなコードを書いても、1曲目が勝手に止まって2番目が再生…とはいきません。
※ ただ、1曲目が2.5 秒以内の場合は2曲目は問題なく再生されます
// 1曲目を再生するます
sfx.playTrack(1);
// 2.5秒待ってから、、、
delay(2500);
// 1曲目を止めて、2曲目を再生したい、、、がしかし再生されず
sfx.playTrack(2);
パターン2: 1曲目を手動でとめて2曲目再生するが、ラグがかなりあるパターン
たとえば、下記のようにstop関数を入れてからやるという方法があるのですが、以下の理由からあまり使えません。
- 何も再生してない時にstop関数を走らせるとバグる
- stop関数からの次の再生までのラグが異様にある
// 1曲目を再生するます
sfx.playTrack(1);
// 2.5秒待ってから、、、
delay(2500);
// 手動でストップ(割と時間かかる)
sfx.stop();
// 2曲目を再生
sfx.playTrack(2);
何も再生していない時にstop()関数を走らせないようにするには、ACKピン(再生中はLOW、ストップ中はHIGHを出力)を見ながらやるという方法もあるのですが、いずれにせよstop()関数を挟んでから別の楽曲再生となると、ちと遅くなってしまいます。
パターン3: たとえばstop()ではなく、reset()
強制的に楽曲を止めるといえば、reset()関数つかえばいいのかな?と思ってやってみたのですが、
Adafruit_Soundboardの元ソースでは、リセット後1000ms待つ処理が入ってました。
そりゃ遅いわ。
// 1曲目を再生するます
sfx.playTrack(1);
// 2.5秒待ってから、、、
delay(2500);
// 強制的に止めるために、リセット(しかしこれがおそい)
sfx.reset();
// 2曲目を再生
sfx.playTrack(2);
ちなみに、ライブラリの該当箇所のソース。
boolean Adafruit_Soundboard::reset(void) {
digitalWrite(reset_pin, LOW);
pinMode(reset_pin, OUTPUT);
delay(10);
pinMode(reset_pin, INPUT);
delay(1000); // give a bit of time to 'boot up'
パターン4: 手動リセット(最終型)
というわけで、リセット後の起き上がり時間を直接操作できるように、
下記のようにしたところ、割と現実的な待ち時間になりました(1/4!)。
// 1曲目を再生するます
sfx.playTrack(1);
// 2.5秒待ってから、、、
delay(2500);
// 手動リセット(250msですむ)
digitalWrite(SFX_RST, LOW);
pinMode(SFX_RST, OUTPUT);
delay(10);
pinMode(SFX_RST, INPUT);
delay(250); // ここがミソ
// 2曲目を再生
sfx.playTrack(2);
ちなみに、200msとかにすると楽曲再生できなかったです。
以上。