m5stack」タグアーカイブ

自宅用通知マシン作成(5)

前回の続き

スタックチャンがしゃべれるようになったので、次は外部からしゃべる指令を出す端末のバージョンアップ。呼び出しは予約確認のための自宅用通知マシンと兼用。

エッジ検出処理&疑似的な並列処理はこちらに大体まとめた感じ。

メインのループ(Arduinoのloop関数)は並行処理するループ(yoyakuCheckLoop,yobidashiCheckLoop)をそれぞれ呼び出しyobidashiCheckLoopの中でボタンが押されている判定をして押されていたらネットワーク越しにスタックチャンがしゃべるURLをたたいてしゃべらせる。

最初はPOSTで叩こうとしたけどPOSTの引数違うぞみたいなエラーメッセージが出たのでとりいそぎGETメソッド(5秒も調べていない)

メインのループの中でyobidashiCheckLoopを呼び出し。下に張った中のyobidashiCheckLoopでやっていることはこちらに大体まとめた感じ。で、execYobidashi(開発環境ならexecDevYobidashi)で、httpsのリクエストを投げているだけ。セキュリティ的なものはつけていないのでそのまま叩ける。

一応全体

続けてネットワーク回り

自宅用通知マシン作成(4)

音声関連クラス化

見通しが悪くなりそうなので音声周りは別クラスに。多分まだ予想してない改造をしそなのでパラメーター渡すとか考えずに単純な別ファイル化だけ。(StackSpeaker.h)

呼び出しは

しておいて使いたいところで

通信

次に外部から呼び出せるようにserver機能を持たせる。店の外から呼び出す計画のでまずはhttpでそのまま外からつなげられるようする。そのうちリバースプロキシの後ろに隠すかもしれないけどとりあえずルーターにNAPTでさばかせておく。

wifi周り

スマートコンフィグ使おうかと考えたけど、ip指定で起動するときにデフォゲとサブネット与えないといけなかった。そいつらをしっかりと渡すとなると外から与えてスマートコンフィグの意味なくなるか、一回目の接続で取れた値を使用と面倒になりそう。というわけでおとなしく明示的に指定することにした。

と、サンプルにありそうなやつそのまま

server周り

これもよくありそうなやつ。

WebServer.hつかって、呼び出し処理があったら音声を流す処理を行う。

handleYobidashiの中で、speaker#stopVoice/speaker#startVoiceを直接呼んでいるので同期処理になっている。音声が流れ終わってから呼び出し側にはレスポンス返る。使うケース次第では非同期呼び出しにするためにさらにスレッドを呼ぶ形にする方が良い場合は多そう。

続き 呼び出し側の自宅端末バージョンアップ

M5Unified_StackChanを参考にした際のメモ

MP3_with_ESP8266Audio.inoを参考に音声出力をしていたが音がとんだり画面にノイズ?が入ったりとしていた。ツイッターで呟いたらタカヲさん(@mongonta555)から参考情報を教えてもらった。

こちらで音が出るようになった。リンク先レポジトリのメモ書きを残す。なお、M5Unified_StackChanにはあるが試していないものもある。

対象音声フォーマット

readmeにはwavとなっているけどmp3用

バッファ処理

MP3_with_ESP8266Audioにはなかったbuffer処理が入っている。下のあたり

音声ファイルのサンプリングレート

readmeには”wavファイルのサンプリング周波数は16khzか24khzにしてください。”とある。ffmpegで16khzか24khzに変換したかったが、26khzが生成されて直し方がわからなかったので26khzを受け入れて試験。サンプリングレートじゃなくてビットレートが26kbpsだった。

スピーカーのコンフィグ指定

下のようにいくつか指定が入っている。

sample_rate は出来上がったファイルに合わせてみた。

task_priorityは同じコアでの処理優先順位。数時大きい数が優先順位高くたしか23が最大値。m5avaterの中で2が使われているはずなので使っているライブラリの範囲では3にしとけば最優先のはず。

dma_buf_count /dma_buf_len はよくわかっていない。

task_pinned_core は処理をさせるCPUコアの指定(PRO_APP_NUMデフォルトで、もう一個がPRO_APP_NUM)。M5Unified_StackChanではPRO_CPU_NUMを使っていたがデフォルトでも音質違いが分からなかったのでデフォルトに戻してある。

  auto spk_cfg = M5.Speaker.config();
  spk_cfg.sample_rate = 26000;
  spk_cfg.task_priority = 23;
  spk_cfg.dma_buf_count = 20;
  spk_cfg.dma_buf_len = 128;
  //spk_cfg.task_pinned_core = PRO_CPU_NUM;
  M5.Speaker.config(spk_cfg);

ファイルクローズ処理

mp3.stop()の中でもoutやfileのクローズが呼ばれているのでソフトウェア的にはfileやoutのクローズ処理はいらないはず。ただし、どこかのサイト(メモってなかったら出典探せなくなった)で下みたいな書き方の方がスピーカーの最初の音が小さくなるみたいなことが書かれていたのでそちらに合わせた。ちなみに、スピーカーの最初の音とはスピーカーに電源が入る時のボッみたいな音。その違いが分からなかったが、こだわるところでもないので合わせておく。

補足

比較をしていないけどもともと使っていたのが160kbpsの3分というファイルだったのでそいつの影響が大きい気がしなくもない。

自宅用通知マシン作成(3)

スタックチャン風呼び出しマシン作製の続き。(これから書く)

音声の出し方はこちらでしらべて手を付けられそうになった。

まずは出し方で調べた音声用のAudioOutputM5Speakerを別ファイルに切り出し。サンプルソースほぼそのまんま。ただ、他の人とクラス名かぶりそうなのでネームスペースだけ切っておいた。

ファイル名指定したらファイル流す、止める関数追加

void stopVoice() {
  if (mp3.isRunning()) mp3.stop();
}

void startVoice(const char *filename) {
  file.open(filename);
  mp3.begin(&file, &out);
}

セットアップの中でavater.initしてループの中でボタン押されたらストップ&スタートでとりあえず音楽は流れる。が、途切れがち。CPUコア1にだいぶ頑張らせているからかな?

avater.initの中から呼ばれる描画タスクはどちらもcore1で動いている。音声もcore1。今のところ使ってないけどcore0はwifiで結構使うみたいなので開けておきたい。

CPU負荷が原因ならmp3からcpuに優しいwavにしたらいいじゃないと試してみたけど状況は悪化。ファイル形式変更の道もつらそうなのでやはりmp3で頑張ってみる。

試しにスピーカーで使うCPUをcore0に変えても状況は変わらず。もしかしてCPUのせいじゃない??

タカヲさんからサンプルを教えてもらったので一旦こちらを試す。

このあとは調べ中。タカヲさんの調べながら(おわったら?)書き足す->試したときのメモこちら

続きはこちら

EpeaAudioOutputM5Speaker.h)

MP3_with_ESP8266Audio.inoのメモ

M5UnifiedのExampleに音声再生があったのでそれで試す。

File->Example->M5Unified->Advanced->Speaker_SD_wav_fileを選択。

自宅用通知マシン作成(2)

と、行こうとしたけど色々初めてなのでメモ残しながら確認していく。描画関係はおいておいて音声出力周りのみ予定。

試しながら書いているので丸っと書き換わるかも

M5Unified

最近のM5Stackは機種間をまたいでソースをある程度共有できるM5Unifiedを使う。M5Unifidには

みたいに各階層(カテゴリ?)毎にそれぞれコンフィグがあって細かい設定を仕込めるみたい。

ダウンロードしたソースのM5Unified\src\utility\M5Unified.hppやM5Unified\src\utilityあたりに中身がいる。ドキュメントは探していないここにあった。ぱっとみ、cppのコメントパッと見た中だと日本語もある。

/// Increasing the sample_rate will improve the sound quality instead of increasing the CPU load.
    spk_cfg.sample_rate = 96000;

音質とCPU負荷は引き換えと。手持ちのM5Stack Basicのスピーカーの音質だとどうせ頑張るところじゃないと思うので下げてよいかも。

SDカード

M5Unifiedへの移植ポイントにSD.begin()の追加ってのがあるけど前はなかったのかな?よくわからん。

bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000, const char * mountpoint=”/sd”, uint8_t max_files=5, bool format_if_empty=false);

+    while (false == SD.begin(GPIO_NUM_4, SPI, 25000000))
+    {
+      delay(500);
+    }

とりあえず上のイメージでよいらしい。最後のクロックレートはSDカードの一番遅い規格だと思うのでものによってはもっとあげられるのかな。GPIO_NUM_4はESP32のPIN指定からきていると思うけど追っていない。

音声

AudioOutput(本体)、AudioFileSourceHOGE(読み込み元)、AudioGeneratorHUGA(音声化)の3点セットが基本みたい。

AudioFileSourceID3は音声ファイルのプロパティ的な奴を扱える。

AudioOutputM5Speakerはトリプルバッファリングをよろしくやってくれながら(よくわかっていない)、M5Unifidのスピーカーに音声を渡してくれている。ChatGPT API搭載AIスタックチャンのレポジトリでは別ファイルに切り出されていた。(おおよそ一緒ぐらいのふんわりした確認)何か困ったらこっちにも情報あるかも。

AudioOutputM5Speakerが依存しているのはAudioOutput.hとM5Unified.hとみたい。

で開き

で継続

で終了。

おおよそ最小ぐらいの動作ソース

イタリックになっているところは別ファイルに切り出してすっきりさせたらよさそう。

こいつをベースにサンプル等をみたら何とかなりそう。

isRunningの周辺ここに大体まとまっていた。

ボリューム

ボリューム設定は以下。特定のバーチャルチャンネルに個別設定もできる(バーチャルチャンネルはわかっていない。文字から察するになにか仮想的な音声チャンネルを使う機能があるのだろう)

    M5.Speaker.setVolume(volume);
    M5.Speaker.setChannelVolume(m5spk_virtual_channel, volume);

コア指定?

ChatGPT API搭載AIスタックチャンのレポジトリでスピーカー再生タスクを割り当てるCPUコアを以下のように割り当てている。

こちらを見ると無線関係を使っているときにはCore0(PRO_CPU_NUM)を無線関連でかなり使うので、比較的空いているCore1(APP_CPU_NUM)を指定しているのかな?

AudioGeneratorMP3#close

cppの内部でoutputとfile閉じて、running(起動確認フラグ)をfalseにしている。こちら一つでまとめてクローズする思想な気がする。

この実装を信じるとisRunningとcloseで処理できる。

自宅用通知マシン作成(2)

自宅用通知マシン作成(1)で自宅用の予約通知端末がとりあえずできたので、次は家から店に呼び出しできる機能を作る。

今は携帯で呼び出しているけど、ゆるふわろぼっとに呼び出された方が雰囲気的にも店を一時抜け出しやすそうなのでスタックチャンぽいやつで作ることにする。

書いている途中でみつけた。こちらのイメージなやつ

ハードは息子がしばらく使っていないM5Stack Basicがあったのでそいつを使用。同じ時期に買ったやつの紙にCore1.0と書いてあるので1.0なのかな。いずれにせよだいぶ古いバージョン。

開発環境構築

Arduino IDE2.3.2を使用しているけどかど開発環境出来ていなかったのでインストール。

File->Prefarence->Additional boards manager urlsに公式のURLを追記

https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json

tools->boods:hogeを選びboards managerからm5stack by m5stack officialをインストール

tools->boods:hogeからM5stack->m5coreを選択

file->examples->m5stack->Basics->FactoryTestを選びUploadを実行。なんとなく動いて要るっぽいことを確認する。

とりあえず顔をだす(M5avatar準備)

顔がないと始まらないので準備。こちらを参考にライブラリインストール。(と思ったら古いのがすでにいたので新しいものに上書き)

最近は、M5Stack.hみたいに機種ごとのライブラリをインクルードするのではなく、大体の機種をカバーしているM5Unified.hをインクルードして作るらしい。今のM5Avatarもそれを使っているということだろう。

M5Unifiedはライブラリマネージャーから入れられるとのことなのでインストール。#include <M5Stack.h>#include <M5Unified.h>に変更しコンパイル&アップロードで動いた。

ずいぶんコンパイルが重い。と思ったら、二度目から軽くなった。IDE1系の時と違い設定しなくてもコンパイル結果キャッシュするようになったのかな?普段重いものコンパイルしないから気づかなかった。

とりあえず声を出す

M5UnifiedのExampleに音声再生があったのでそれで試す。

File->Example->M5Unified->Advanced->Speaker_SD_wav_fileを選択。

MP3_with_ESP8266Audio.inoというのが開いた。中身もmp3用っぽいけど細かいことは気にしない。

/// need ESP8266Audio library. ( URL : https://github.com/earlephilhower/ESP8266Audio/ )

サンプルソースに上のコメントがある。昔入れたと思われるのが入っていたのでそれを使う。はいっていたのは下のlibrary.propertiesで今日時点で最新ぽい。ただコミットに合わせてバージョン上げてはいなそう。

name=ESP8266Audio
version=1.9.7
/// set your mp3 filename
static constexpr const char* filename[] =
{
  "/mp3/file01.mp3",
  "/mp3/file02.mp3",
  "/mp3/file03.mp3",
  "/mp3/file04.mp3",
};

mp3ファイル4つ(手元にたまたまあったやつ)をサンプルソースに書いてある上記のファイル名にリネームしてをSDカードに放り込み実行。

とりあえず音は割れまくりだが動いたっぽい。試しに他のM5Stackに入れたら音は(比較すると)ほぼ割れなかった。その後、音が変なM5Stackのアンプに直接、代わりのスピーカーを繋げたらそっちはきちんと聞こえた。スピーカー自体がお亡くなりっぽい。

サンプルソースの中身を理解する作業メモはこちらに置いておいた。

この先はこちら