概要
ATOM Echoで少しスピーカーを触っていましたが、M5Stack Core2のスピーカーも調べてみました。基本は同じような構成なので同じような感じで使うことができました。
ATOM Echoとの差分
ATOM Echo | M5Stack Core2 | |
I2Sパワーアンプ | NS4168 | NS4168 |
スピーカー | 0.5W | 1W-0928 |
マイクロフォン | SPM1423 | SPM1423 |
内蔵フラッシュ | 4MB | 16MB |
PSRAM | 無し | 有り |
SDカードスロット | 無し | 有り |
ハードウエア的には、ほぼ同じで接続されているスピーカーだけM5Stack Core2の方が大きいものになります。I2Sパワーアンプ(NS4168)の出力が結構大きいので、ATOM Echoの0.5Wを超えてしまい、スピーカーが破損する問題がでていました。
ATOM Echoはアンプへの電圧を下げることで出力を弱めていますが、M5Stack Core2はより大きなスピーカーが搭載されているようです。
また、M5Stack Core2はフラッシュサイズが大きいので、より多くのデータを内蔵できますし、SDカードを利用してファイルを再生することも可能です。
ATOM Echo | M5Stack Core2 | |
BCLK | 19 | 12 |
LRCK | 33 | 0 |
DataOut | 22 | 2 |
DataIn | 23 | 34 |
SPK_EN | – | AXP_IO2 |
上記がGPIOです。ATOM EchoとM5Stack Core2では利用しているGPIOが違います。また、ATOM Echoは常にスピーカーが有効になっていますが、M5Stack Core2ではAXP192のIO2で有効と無効を選択できます。
ノイズなどでスピーカーから音がでるのを防ぐためや、スピーカーに接続しているGPIOを他の用途で利用する場合などに、スピーカーを無効化しておく必要があるからです。
公式スケッチ例
speakというスケッチ例があります。
ATOM Echoとの差ですが、まず使っているGPIOが違いますが、変更するだけです。また、ボタンが無くタッチパネルなのでそのへんも違います。
とはいえ、一番重要なのはスピーカーの有効化です。
M5.Axp.SetSpkEnable(true);
上記のようにAXP192経由でスピーカーを有効化してから再生します。あとはほとんど同じ処理で再生させることが可能です。
音声ファイルを埋め込んで見る
ATOM Echoのときにためしたように、mp3などを変換してスケッチの中に内蔵して、画面をタッチしたら再生するスケッチを作ってみました。データ変換の手順は上記のブログを参照してください。
#include <driver/i2s.h> #include <M5Core2.h> #include "wav1.h" #include "wav2.h" #include "wav3.h" #include "wav4.h" #include "wav5.h" const unsigned char *wavList[] = {wav1, wav2, wav3, wav4, wav5}; const size_t wavSize[] = {sizeof(wav1), sizeof(wav2), sizeof(wav3), sizeof(wav4), sizeof(wav5)}; #define CONFIG_I2S_BCK_PIN 12 #define CONFIG_I2S_LRCK_PIN 0 #define CONFIG_I2S_DATA_PIN 2 #define CONFIG_I2S_DATA_IN_PIN 34 #define SPEAKER_I2S_NUMBER I2S_NUM_0 #define MODE_MIC 0 #define MODE_SPK 1 void InitI2SSpeakerOrMic(int mode) { esp_err_t err = ESP_OK; i2s_driver_uninstall(SPEAKER_I2S_NUMBER); i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER), .sample_rate = 16000, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ALL_RIGHT, .communication_format = I2S_COMM_FORMAT_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 6, .dma_buf_len = 60, .use_apll = false, .tx_desc_auto_clear = true, .fixed_mclk = 0 }; if (mode == MODE_MIC) { i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM); } else { i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX); } err += i2s_driver_install(SPEAKER_I2S_NUMBER, &i2s_config, 0, NULL); i2s_pin_config_t tx_pin_config = { .bck_io_num = CONFIG_I2S_BCK_PIN, .ws_io_num = CONFIG_I2S_LRCK_PIN, .data_out_num = CONFIG_I2S_DATA_PIN, .data_in_num = CONFIG_I2S_DATA_IN_PIN, }; err += i2s_set_pin(SPEAKER_I2S_NUMBER, &tx_pin_config); if (mode != MODE_MIC) { err += i2s_set_clk(SPEAKER_I2S_NUMBER, 16000, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO); } i2s_zero_dma_buffer(SPEAKER_I2S_NUMBER); } void setup() { M5.begin(); delay(50); Serial.println(); InitI2SSpeakerOrMic(MODE_MIC); delay(2000); } void loop() { TouchPoint_t pos = M5.Touch.getPressPoint(); if (pos.x != -1) { size_t bytes_written; M5.Axp.SetSpkEnable(true); InitI2SSpeakerOrMic(MODE_SPK); // Random Play int wav = random(5); // Write Speaker i2s_write(SPEAKER_I2S_NUMBER, wavList[wav], wavSize[wav], &bytes_written, portMAX_DELAY); i2s_zero_dma_buffer(SPEAKER_I2S_NUMBER); // Set Mic Mode InitI2SSpeakerOrMic(MODE_MIC); M5.Axp.SetSpkEnable(false); } }
コードは以下のGitHubに音声データ付きでおいてあります。
音声データはATOM Echoと同じものになります。
- GPIOの変更
- ボタンから画面タッチに変更
- LED制御を削除
- AXP192経由でスピーカーの有効、無効化
ATOM Echoとの変更点は上記になります。割と簡単に移植できますね。音質もノイズもなく非常にクリアです。
まとめ
あっさりと使うことができました。M5Liteライブラリでもラッパークラスを作って、M5Stack Fireなどのアナログスピーカーと、M5Stack Core2のI2Sスピーカーで同じ関数で再生できるようなものを今後作っていきたいと思っています。
ただ、M5StickCにスピーカーHATが接続されているかの確認と、ATOMがEchoなのかそれ以外かの区別ができないので、そこはどうしようか悩んでいます、、、
マイクも同じように使えそうですね!
コメント