[M5Stack]オーディオ再生時にGPIO26を使えるようにする方法
M5StackでMP3などのオーディオファイルを再生する場合、ESP8266Audioというライブラリがよく使われます。
オーディオファイルを再生すると、I2Sインターフェースにデジタルのオーディオデータが出力されますが、そのままでは音にならないので、DACを介してアナログ電圧に変換します。M5Stackに内蔵のESP32はDACを持っていますので、そのDACを使うのが手っ取り早い選択になります。
このDACを使うと、左右の音声のアナログ電圧がGPIO25及びGPIO26ピンに出力されます。M5Stackのスピーカーは1個で、GPIO25ピンからの音声が出力されるようになっています。
ステレオで再生したい場合はGPIO26ピンにアンプとスピーカを接続する必要があります。
M5Stackに他のモジュールをスタックし、色々な機能を持たせたいと思った時、GPIOのピンが不足する事があります。
オーディオを再生しながらGPIO26ピンが使えると有難いですが問題が生じます。
次の波形は、GPS受信機からのUARTのシリアルデータがGPIO26に入力されている時の波形で、左側は正常な場合、右側はオーディオ再生した場合の波形です。
右側の波形でLowの時の電圧が0Vでなく1.2V程度に上昇しています。
これはDACからの出力とGPS受信機からの出力が競合しているためです。

この問題を解決するためにはGPIO26を通じてのDACの出力を止める必要があります。
色々調べたところ、次のようにするとうまく行く事が分かりました。
修正するファイル:
C:\Users\ユーザ\Documents\Arduino\libraries\ESP8266Audio\src\AudioOutputI2S.cpp
bool AudioOutputI2S::begin(bool txDAC)
{
..
if (output_mode == INTERNAL_DAC || output_mode == INTERNAL_PDM)
{
if (this->mono) // <<<< 追加
{ //
i2s_pin_config_t pinMono; //
memset(&pinMono,0,sizeof(pinMono)); //
pinMono.data_out_num = 25; //
i2s_set_pin((i2s_port_t)portNo, &pinMono); //
i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN); //
} // <<< 追加
else
{
i2s_set_pin((i2s_port_t)portNo, NULL); // <<< 元からあったコード
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); // <<<
}
}
..
}
上記の修正を行った後、次のようなコードでオーディオ再生を行います。
void playWaveFile()
{
file_w = new AudioFileSourceSD("/sample.wav");
out_w = new AudioOutputI2S(0,1);
out_w->SetOutputModeMono(true); // <<< この設定を必ず行う
out_w->SetGain(0.3);
wav = new AudioGeneratorWAV();
wav->begin(file_w, out_w);
while(wav->isRunning()){
if (!wav->loop()) wav->stop();
}
}
これでGPIO26が自由に使えるようになりました。