MAX98357 & PCM5102
2023.01.16
YouTube でも紹介しています。画像をクリックすると再生できます。
以前に、ラズベリーパイからI2S接続により、デジタルオーディオ変換モジュール(DAC)PCM5101を介してし、ハイレゾ音源の再生を行いました。
I2S通信によるハイレゾ音源再生
今回は、ESP32からI2S接続により、MAX98357AあるいはPCM5102Aを用いて、WAV音源の再生を行います。
MAX98357Aはアンプ内蔵のモノラルDAC、PCM5102AはステレオDACですが別途アンプを必要とします。
いずれも5W未満の小さなスピーカーを駆動する際に有用です。
WAV音源再生にあたっては、配線の違いだけで、MAX98357A、PCM5102Aともに同じコードが使用できます。
■Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT
使用するマイコンボードです。
●ESP32-S2 240MHz
●4 MB Flash & 2 MB PSRAM
●2.4 GHz Wi-Fi (SoC)
●Two I2C ports
●Hardware UART
●Hardware SPI
●Hardware I2S on any pins
●3.3V regulator with 600mA peak output
Ref.Adafruit QT Py ESP32-S2
Qt Py Pinout
QT Py ESP32-S2 の詳細は下記をご覧ください。
Adafruit QT Py + XIAO Expansion board
■SPI Flash SD / SD CARD MODULE
音源はSPI Flash SDあるいはSDカードから読みだして再生します。
Adafruit SPI Flash SD Card
容量:4Gbit(512MByte)
最大 50Mhz のクロック周波数をサポート
組み込みの HW ECC エンジンと信頼性の高い NAND 管理メカニズム
クラス8までの書き込み速度
SPI Flash SDの詳細は下記を参考にしてください。
FTP Server & SPI Flash SD
■MAX98357A搭載 I2S 3W D級アンプボード
・ピンでゲインを3 dB、6 dB、9 dB、12 dB、15 dBの5段階に選択可能
・過熱シャットダウン機能
・出力:3.2 W(4 Ω時) / 1.8 W(8 Ω、5 V電源電圧時)
・I²Sサンプルレート:8-96 kHz
・PSRR: 77 dB typ @ 1 KHz
・MCLK不要
・クリック/ポップを低減
●GAIN
音量はGAINとVIN端子あるいはGND端子の間に抵抗を挟むことで5段階の調整が可能です。
・3dB(GAIN→100KΩ→VIN)
・6dB(GAIN→VIN)
・9dB(未接続:default)
・12dB(GAIN→GND)
・15dB(GAIN→100KΩ→GND)
●SD / MODE
SD(MODE)端子に掛ける電圧で、アンプの停止あるいは出力制御を行います。
・アンプ停止(SD→GND)
・ステレオ音源左右の平均をモノラル出力(Vin→(0.16V~0.77V)→SD)
・右チャンネルのみを出力(Vin→(0.77V~1.4V)→SD)
・左チャンネルのみを出力(Vin→(1.4V~)→SD)
SD端子は100KΩの内部プルダウン抵抗を有しているので、VinとSD端子の間に挟む抵抗との分圧を計算します。
Adafruit MAX98357 I2S Class-D Mono Amp / Pinouts
●配線
上記の設定をもとにした配線です
FlashSD/microSD | - | ESP32-S2 | - | MAX98357 |
| - | A0 | - | BCLK |
| - | A1 | - | LRC |
| - | A2 | - | DIN |
CS | - | A3 | | |
(RasPi)RX | - | TX | | |
(RasPi)TX | - | RX | | |
SCK | - | SCK | | |
MISO | - | MISO | | |
MOSI | - | MOSI | | |
Vin | - | 3.3V | -100KΩ- -1MΩ- - | GAIN SD Vin |
GND | - | GND | - | GND |
画面中央にある2枚のモジュールは下が SPI FLASH SD、上が microSDカードモジュールです。チップセレクトピンを差し替えてどちらでも使えるようにしてあります。
8Ω1.5Wのスピーカーに、ヘッダーピンをはんだ付けしてブレッドボードに挿しています。
●ノイズ対策
ローパスフィルタ回路を組込みました。100μHのマイクロインダクタと220pFのキャパシタを使っています。
これでかなりノイズが軽減されました。
貧相なスピーカーを使っているので、GAIN端子とVDDの間に100KΩの抵抗を挟んで3dBに設定しています。
また、ステレオ音源を使用するので、SD端子とVDDの間に1MΩの抵抗を設置して、左右の平均をモノラルで出力する設定にしています。
AliExpress - MAX98357
ローパスフィルタ(LPF)
直流や低周波の信号を通過させ、高周波の信号をカットするフィルタ回路です。主に高周波ノイズのカットに使用されます。
またオーディオでは低音用スピーカーの高音/中音成分カットに使用されます。
インダクタは高周波になるほど高いインピーダンスを持ちます。
このため、高周波電流を阻止するローパスフィルタとして働き、高周波ノイズを減衰させることができます。
インダクタに電流が流れると磁束が発生して電流のエネルギーが磁気のエネルギーに変化されますが、電流の変化に伴ってこの磁束は再び電磁誘導によって電流に変換されます。このとき、磁束のエネルギーのすべてが電流のエネルギーに戻るのではなく、一部は磁気損失として失われます。
LCフィルタの種類とローパスフィルタにおける部品選定事例
■音楽CDのリッピング
音楽CDリッピングとは音楽CDに入っている音声データを読み取って音楽ファイルに変換することをいいます。
Windows Media Player を使って簡単にリッピングできます。ここでは、WAVファイルとして書き出しています。
ここで取得したWAVファイルを、SPI FLASH SDに保存して使用します。
■I2S設定
I2S設定に関しては、「よみやチャンネル」さんで詳しく説明されていますので、そちらをご覧ください。
高性能DAC PCM5102をESP32で使ってみる
I2Sヘッダファイルの内容は下記をご覧ください。
esp32_MusicPlayer
I2S設定の中で下記の赤文字の部分を、音源であるWAVファイルのヘッダー情報を解析して動的に設定しています。
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = sampleRate,
.bits_per_sample = i2s_bitPerSample,
.channel_format = i2s_channelFormat,
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S | I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = 0
};
~
i2s_set_clk((i2s_port_t)I2S_CH_NUM, sampleRate, (i2s_bits_per_sample_t)bitPerSample, (i2s_channel_t)numChannels);
もっともシンプルなWAVファイルは下記の通りです。バイナリ・エディタでWAVファイルを開いています。
1番目のサブチャンクIDが「fmt 」、2番目のサブチャンクIDが「data」です。
Windows Media PlayerでリッピングしたWAVファイルにはLISTという名前の楽曲情報が格納されているサブチャンクが存在します。
さらに、WAV書式が拡張されていて、PCM形式のWAVファイルでは必要のないcbSize(赤枠部分)という属性が追加されています。
WAVEFORMATEX 構造体
Arduino言語はいわばC言語なので、構造体を使って、簡単にヘッダー情報の解析が可能です。
また、ヘッダー情報中の数値はリトルエンディアンの並びで、ESP32もリトルエンディアンなので、そのまま使用できます。
ラズベリーパイにインストールしたPlatformIOのデバイスモニターでESP32とシリアル通信してヘッダー情報の解析結果を表示してみました。
ここで取得したチャンネル数(NumChannels)、サンプリング周波数(SampleRate)、解像度(BitPerSample)を、先ほどのi2s設定に反映させます。
また、音源の演奏データサイズは、Subchunk2Sizeになります。
WAVファイルのヘッダー情報解析に関しては、下記も参考にしてください。
音声ファイルの切貼り
■プログラミング
I2Sの設定さえしてしまえば、あとは簡単です。
I2S_Init(pwf->SampleRate,pwf->BitPerSample, pwf->NumChannels);
long len = pwf->Subchunk2Size;
while(len>0) {
if (len>I2S_BUFFER_SIZE) {
file.readBytes(i2s_buf, I2S_BUFFER_SIZE);
I2S_Write(i2s_buf, I2S_BUFFER_SIZE);
} else {
file.readBytes(i2s_buf, len);
I2S_Write(i2s_buf, len);
break;
}
len -= I2S_BUFFER_SIZE;
}
演奏データをI2Sバッファサイズ単位でMAX98357に流し込んで演奏させています。
●ソースコード
2週間ごとに動画作成と解説記事を作成しているので、ソースコードはかなり雑です。適当に編集して使ってください。
#include <Arduino.h>
#include <FS.h>
#include <SD.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
#include "esp_system.h"
#define I2S_OUT_BCK A0
#define I2S_OUT_LCK A1
#define I2S_OUT_DIN A2
#define I2S_CH_NUM I2S_NUM_0
#define I2S_BUFFER_COUNT 4
#define I2S_BUFFER_SIZE 512
char i2s_buf[I2S_BUFFER_SIZE];
#define SD_CS A3
#define SDSPEED 40000000
// The Canonical WAVE file format
typedef struct {
uint8_t ChunkID[4];
uint32_t ChunkSize;
uint8_t Format[4];
uint8_t Subchunk1ID[4];
uint32_t Subchunk1Size;
uint16_t AudioFormat;
uint16_t NumChannels;
uint32_t SampleRate;
uint32_t ByteRate;
uint16_t BlockAlign;
uint16_t BitPerSample;
uint8_t Subchunk2ID[4];
uint32_t Subchunk2Size;
uint8_t *wavdata;
} WAV_FORMAT;
File file;
size_t i2s_bytes_write = 0;
void I2S_Init(uint32_t sampleRate, uint16_t bitPerSample, uint16_t numChannels) {
i2s_bits_per_sample_t i2s_bitPerSample;
i2s_channel_fmt_t i2s_channelFormat;
switch(bitPerSample) {
case 8: i2s_bitPerSample = I2S_BITS_PER_SAMPLE_8BIT; break;
case 16: i2s_bitPerSample = I2S_BITS_PER_SAMPLE_16BIT; break;
case 24: i2s_bitPerSample = I2S_BITS_PER_SAMPLE_24BIT; break;
case 32: i2s_bitPerSample = I2S_BITS_PER_SAMPLE_32BIT; break;
}
switch(numChannels) {
case 1: i2s_channelFormat = I2S_CHANNEL_FMT_ONLY_LEFT; break;
case 2: i2s_channelFormat = I2S_CHANNEL_FMT_RIGHT_LEFT; break;
}
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = sampleRate,
.bits_per_sample = i2s_bitPerSample,
.channel_format = i2s_channelFormat,
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S | I2S_COMM_FORMAT_STAND_MSB),
.intr_alloc_flags = 0,
.dma_buf_count = I2S_BUFFER_COUNT,
.dma_buf_len = I2S_BUFFER_SIZE,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_OUT_BCK,
.ws_io_num = I2S_OUT_LCK,
.data_out_num = I2S_OUT_DIN,
.data_in_num = -1 //Not used
};
i2s_driver_install((i2s_port_t)I2S_CH_NUM, &i2s_config, 0, NULL);
i2s_set_pin((i2s_port_t)I2S_CH_NUM, &pin_config);
i2s_set_clk((i2s_port_t)I2S_CH_NUM, sampleRate, (i2s_bits_per_sample_t)bitPerSample, (i2s_channel_t)numChannels);
}
void I2S_Write(char* data, int numData) {
i2s_write((i2s_port_t)0, (const char *)data, numData, &i2s_bytes_write, portMAX_DELAY);
}
boolean getWavFormat(WAV_FORMAT *pwf) {
long len;
short cbsize;
if (file.read((uint8_t *)pwf,20) == -1) return false;
if (memcmp(pwf->Subchunk1ID,"fmt ",4)==0) {
if((len = file.read((uint8_t *)pwf+20,24))==-1) return false;
} else if (memcmp(pwf->Subchunk1ID,"LIST",4)==0) {
if (file.seek(20+pwf->Subchunk1Size)) {
if((len = file.read((uint8_t *)pwf+12,24))==-1) return false;
if (pwf->Subchunk1Size == 18) {
// skip cbsize on WAVEFORMATEX
if((len = file.read((uint8_t *)&cbsize,2))==-1) return false;
}
if((len = file.read((uint8_t *)pwf+36,8))==-1) return false;
} else {
return false;
}
} else {
return false;
}
if( memcmp(pwf->ChunkID, "RIFF", 4)
||memcmp(pwf->Format, "WAVE", 4)
||memcmp(pwf->Subchunk1ID, "fmt ", 4)
||memcmp(pwf->Subchunk2ID, "data", 4))
return false;
else return true;
}
boolean play(WAV_FORMAT *pwf, char *filename) {
if(!(file = SD.open(filename))) return false;
if (getWavFormat(pwf)) {
I2S_Init(pwf->SampleRate,pwf->BitPerSample, pwf->NumChannels);
long len = pwf->Subchunk2Size;
while(len>0) {
if (len>I2S_BUFFER_SIZE) {
file.readBytes(i2s_buf, I2S_BUFFER_SIZE);
I2S_Write(i2s_buf, I2S_BUFFER_SIZE);
} else {
file.readBytes(i2s_buf, len);
I2S_Write(i2s_buf, len);
break;
}
len -= I2S_BUFFER_SIZE;
}
file.close();
}
return true;
}
void setup() {
WAV_FORMAT *pwf[1];
if (SD.begin( SD_CS, SPI, SDSPEED)) {
pwf[0] = (WAV_FORMAT *)malloc(sizeof(WAV_FORMAT));
play(pwf[0],"/sound/03_toccatina_low.wav");
}
}
void loop() {}
■ビルド環境
ソースコードのビルドには、PlatformIOを使用しています。
Arduino開発環境構築 PlatformIO
ビルドには、Raspberry Pi 3 model B、Raspberry Pi OS を使用しています。ラズベリーパイに Nano HAT Hacker を挟んで、GPIOを分岐させ、Piano Hat を被せています。
●電磁波の影響
ブレッドボード上に構築したので、シールドしていません。
ノートパソコンなどの近くで再生すると、電磁波の影響を受けてノイズが発生してしまいます。
■補足:PCM5102A I2C DAC
PCM5102Aの場合も、配線を変えるだけで、上記のソースコードがそのまま使えます。
PCM5102Aにはアンプが内蔵されていないので、外部アンプを取り付けてください。
モジュール供給電圧: dc3.3v
信号対ノイズ比snr: 112db
ダイナミックレンジ: 112dB
フルスケールシングルエンド出力: 2.1vrms
サンプリング周波数: 8KHz〜384KHz
メインクロック周波数: 50mhz
オーディオデータ数: 16、24、32
作業環境温度: -40 ° c〜85 ° c
オーディオデータ形式: iis,左揃え
全調波歪み (-1dbfsでのthd + n): -93db
●配線
FlashSD/microSD | - | ESP32-S2 | - | PCM5102A |
| - | A0 | - | BCK |
| - | A1 | - | LCK |
| - | A2 | - | DIN |
CS | - | A3 | | |
(RasPi)RX | - | TX | | |
(RasPi)TX | - | RX | | |
SCK | - | SCK | | |
MISO | - | MISO | | |
MOSI | - | MOSI | | |
Vin | - | 3.3V | | |
GND | - | GND | - | SCK/GND |
| - | 5V | - | VCC |
|
Raspberry Pi(ラズベリー パイ)は、ARMプロセッサを搭載したシングルボードコンピュータ。イギリスのラズベリーパイ財団によって開発されている。
Arduinoで学ぶ組込みシステム入門(第2版)
●Arduinoを使って組込みシステム開発を理解する
・ハードウェアやソフトウェアなどの基礎知識/
・設計から実装までを系統的に説明するモデルベース開発/
・Arduinoを用いた実際の開発例
最新 使える! MATLAB 第3版
◆◆すぐに「使える!」 全ページフルカラー!◆◆
・MATLAB R2022bに対応し、解説もより詳しく!/
・コマンド・スクリプトの例が豊富で、動かして学べる!/
・超基本から解説。これから使いはじめる人にぴったり!/
・全編フルカラー、スクリーンショットも豊富!
Amazon Web Services基礎からのネットワーク&サーバー構築改訂4版
1.システム構築をインフラから始めるには/
2.ネットワークを構築する/
3.サーバーを構築する/
4.Webサーバーソフトをインストールする/
5.HTTPの動きを確認する/
6.プライベートサブネットを構築する/
7.NATを構築する/
8.DBを用いたブログシステムの構築/
9.TCP/IPによる通信の仕組みを理解する
C言語は第二の母国語: 独学学生時代から企業内IT職人時代に培った、独立のための技術とノウハウ 平田豊著
学生時代から独学でプログラミングをはじめ、企業内でデバイスドライバを開発し、そして独立後もたくさんのアプリケーション開発や技術書制作に携わってきた著者。その筆者が大事に使い続ける「C言語」の“昔と今”について、気づいたことや役立つ知識、使ってきたツールなどについて、これまで記してきたことを整理してまとめました。
本書では、現役プログラマーだけでなく、これからプログラミングを学ぶ学生などにも有益な情報やノウハウを、筆者の経験を元に紹介しています。
1冊ですべて身につくJavaScript入門講座
・最初の一歩が踏み出せる! 初心者に寄り添うやさしい解説
・最新の技術が身につく! 今のJavaScriptの書き方・使い方
・絶対に知っておきたい! アニメーションとイベントの知識
・プログラミングの基本から実装方法まですべて学べる
図解! Git & GitHubのツボとコツがゼッタイにわかる本
ソフトウェア開発では欠かすことのできないGit、GitHub。
これからGit、GitHubを使いたいという入門者の方でも、実際に手を動かしながら使い方を学べます。
C自作の鉄則!2023 (日経BPパソコンベストムック)
メーカー製のパソコンはスペックが中途半端で、自分が本当に欲しい機種がない――。そう思っている人には、ぜひ自作パソコンをお薦めします。自作パソコンのパーツは進化が速く、しかも驚くほど種類が豊富。価格も性能も、幅広く用意されているため、満足度100%の“自分だけの1台”を手に入れることができます。
Interface 2023年6月号
特集:第1部 フィルタ設計 基礎の基礎/
第2部 係数アプリや波形観測アプリで合点!FIR&IIRフィルタ作り/
第3部 配布プリント基板で体験!マイコンで動くフィルタ作り
日経Linux 2023年5月号
【特集 1】 AI時代の最強フリーソフト ~ 25のやりたいを実現!
【特集 2】 AWS、Azureのうまみを無料で体感!面倒なことはクラウドに任せよう
【特集 3】 新しいRaspberry Pi Cameraで遊んでみよう
【特集 4】 Linuxで旧型PCを復活! 1kg切るモバイルPCを「ChromeOS Flex」でChromebook化
ラズパイマガジン2022年秋号
特集:5大人気ボード 電子工作超入門
「半導体不足で在庫が不足し、電子工作のボードがなかなか買えない…」。そんな今にふさわしい特集を企画しました。5種の人気ボードにすべて対応した電子工作の入門特集です。「GPIO」や「I2C」を使った電子パーツの制御方法は、どのボードでも同じです。手に入れられたボードを使って、今こそ電子工作を始めましょう。
地方で稼ぐ! ITエンジニアのすすめ
学歴、理系の知識、専門スキル……全部なくてもITエンジニアになれる!
地方でも高収入でやりがいをもって働ける!ITエンジニアの魅力を一挙大公開
Raspberry Piのはじめ方2022
本書は、ラズパイやPicoの買い方やインストール、初期設定といった基本から、サーバー、電子工作、IoT、AIといったラズパイならではの活用方法まで、1冊でお届けします。
ラズパイをこれから始める方向けに、全36ページの入門マンガ「女子高生とラズベリーパイ」も巻末に掲載。これを読むだけでラズパイがどんなものなのか、すぐに分かって触れるようになります。
ハッカーの学校 IoTハッキングの教科書
生活にとけこみ、家電機器を便利にするIoT技術。
Webカメラなど、便利の裏側に潜むセキュリティの危険性をハッキングで検証。
専門家がパケットキャプチャからハードウェアハッキングまで、その攻撃と防御を徹底解説。
本書は2018年7月に刊行された「ハッカーの学校IoTハッキングの教科書」に一部修正を加えた第2版です。
攻撃手法を学んで防御せよ! 押さえておくべきIoTハッキング
本書は、経済産業省から2021年4月にリリースされた、IoTセキュリティを対象とした『機器のサイバーセキュリティ確保のためのセキュリティ検証の手引き』の『別冊2 機器メーカに向けた脅威分析及びセキュリティ検証の解説書』をもとに、IoT機器の開発者や品質保証の担当者が、攻撃者の視点に立ってセキュリティ検証を実践するための手法を、事例とともに詳細に解説しました。
ポチらせる文章術
販売サイト・ネット広告・メルマガ・ブログ・ホームページ・SNS…
全WEB媒体で効果バツグン!
カリスマコピーライターが教える「見てもらう」「買ってもらう」「共感してもらう」すべてに効くネット文章術
プログラマーは世界をどう見ているのか 西村博之著
イーロン・マスク(テスラ)、ジェフ・べゾス(Amazon)、ラリー・ペイジ(Google)…etc.
世界のトップはなぜプログラマーなのか?
ニーア オートマタ PLAY ARTS改 <ヨルハ 二号 B型 DX版> PVC製 塗装済み可動フィギュア
「NieR:Automata」より、ヨルハ二号B型こと2BがPLAY ARTS改に新たに登場!
高級感の感じられるコスチュームや髪の質感、洗練されたボディバランス、細かなデティールに至るまでこだわり抜かれた逸品。
DX版には通常版のラインナップに加え2Bの随行支援ユニット ポッド042などをはじめ“純白の美しい太刀"白の約定やエフェクトパーツ、自爆モードを再現できる換装用ボディパーツ、シーンに合わせて変えられる顔パーツ2種も付属する豪華な仕様に。
作中のあらゆるシーンを再現することが可能なファン必見の一品となっている。
Newtonライト2.0 ベイズ統計
ベイズ統計は,結果から原因を推定する統計学です。AIや医療などの幅広い分野で応用されています。その基礎となるのは18世紀に考えだされた「ベイズの定理」です。
この本では,ベイズ統計学のきほんをやさしく紹介していきます。
白光(HAKKO) ダイヤル式温度制御はんだ吸取器 ハンディタイプ FR301-81
無水エタノールP 500mlx2個パック(掃除)
ケイバ(KEIBA) マイクロニッパー MN-A04
サンハヤト SAD-101 ニューブレッドボード
白光(HAKKO) HEXSOL 巻はんだ 精密プリント基板用 150g FS402-02
[Amazon限定ブランド]【指定第2類医薬品】PHARMA CHOICE 解熱鎮痛薬 解熱鎮痛錠IP 100錠
|